unpack to python object

This commit is contained in:
David Rose 2004-06-25 00:39:33 +00:00
parent faf063cbf8
commit 6845758d2b
9 changed files with 182 additions and 1 deletions

View File

@ -223,6 +223,19 @@ is_bogus_class() const {
return _bogus_class;
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: DCClass::has_class_def
// Access: Published
// Description: Returns true if the DCClass object has an associated
// Python class definition, false otherwise.
////////////////////////////////////////////////////////////////////
bool DCClass::
has_class_def() const {
return (_class_def != NULL);
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: DCClass::set_class_def

View File

@ -55,6 +55,7 @@ PUBLISHED:
bool is_bogus_class() const;
#ifdef HAVE_PYTHON
bool has_class_def() const;
void set_class_def(PyObject *class_def);
PyObject *get_class_def() const;

View File

@ -60,6 +60,16 @@ get_number() const {
return _number;
}
////////////////////////////////////////////////////////////////////
// Function: DCField::as_field
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DCField *DCField::
as_field() {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: DCField::as_atomic_field
// Access: Published, Virtual

View File

@ -42,6 +42,7 @@ public:
PUBLISHED:
int get_number() const;
virtual DCField *as_field();
virtual DCAtomicField *as_atomic_field();
virtual DCMolecularField *as_molecular_field();
virtual DCParameter *as_parameter();

View File

@ -20,6 +20,8 @@
#include "dcSwitch.h"
#include "dcParserDefs.h"
#include "dcLexerDefs.h"
#include "dcClassParameter.h"
#include "dcClass.h"
////////////////////////////////////////////////////////////////////
// Function: DCPacker::Constructor
@ -217,6 +219,9 @@ begin_repack(const char *data, size_t length,
_root = root;
_catalog = _root->get_catalog();
_live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
if (_live_catalog == NULL) {
_pack_error = true;
}
// We don't begin at the first field in repack mode. Instead, you
// must explicitly call seek().
@ -268,6 +273,10 @@ seek(const string &field_name) {
_live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
}
nassertr(_catalog != (DCPackerCatalog *)NULL, false);
if (_live_catalog == NULL) {
_pack_error = true;
return false;
}
int entry_index = _live_catalog->find_entry_by_name(field_name);
if (entry_index < 0) {
@ -305,6 +314,10 @@ seek(const string &field_name) {
_pack_error = true;
return false;
}
if (_live_catalog == NULL) {
_pack_error = true;
return false;
}
int entry_index = _live_catalog->find_entry_by_name(field_name);
if (entry_index < 0) {
@ -338,6 +351,11 @@ seek(const string &field_name) {
_catalog->release_live_catalog(_live_catalog);
_live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
if (_live_catalog == NULL) {
_pack_error = true;
return false;
}
begin = _live_catalog->get_begin(entry_index);
}
@ -696,6 +714,22 @@ unpack_object() {
}
break;
case PT_class:
{
const DCClassParameter *class_param = ((DCPackerInterface *)get_current_field())->as_class_parameter();
if (class_param != (DCClassParameter *)NULL) {
DCClass *dclass = class_param->get_class();
if (dclass->has_class_def()) {
// If we know what kind of class object this is and it has a
// valid constructor, create the class object instead of
// just a tuple.
object = unpack_class_object(dclass);
break;
}
}
}
// If we don't know what kind of class object it is, or it doesn't
// have a constructor, fall through and make a tuple.
default:
{
// First, build up a list from the nested objects.
@ -994,3 +1028,92 @@ set_unpack_data(const char *unpack_data, size_t unpack_length,
_unpack_length = unpack_length;
_owns_unpack_data = owns_unpack_data;
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: DCPacker::unpack_class_object
// Access: Private
// Description: Given that the current element is a ClassParameter
// for a Python class for which we have a valid
// constructor, unpack it and fill in its values.
////////////////////////////////////////////////////////////////////
PyObject *DCPacker::
unpack_class_object(DCClass *dclass) {
PyObject *class_def = dclass->get_class_def();
nassertr(class_def != (PyObject *)NULL, NULL);
PyObject *object = PyObject_CallObject(class_def, NULL);
if (object == (PyObject *)NULL) {
return NULL;
}
push();
while (more_nested_fields()) {
const DCField *field = ((DCPackerInterface *)get_current_field())->as_field();
nassertr(field != (DCField *)NULL, object);
set_class_element(object, field);
}
pop();
return object;
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: DCPacker::set_class_element
// Access: Private
// Description: Unpacks the current element and stuffs it on the
// Python class object in whatever way is appopriate.
////////////////////////////////////////////////////////////////////
void DCPacker::
set_class_element(PyObject *object, const DCField *field) {
string field_name = field->get_name();
DCPackType pack_type = get_pack_type();
if (field_name.empty()) {
switch (pack_type) {
case PT_class:
case PT_switch:
// If the field has no name, but it is one of these container
// objects, we want to unpack its nested objects directly into
// the class.
push();
while (more_nested_fields()) {
const DCField *field = ((DCPackerInterface *)get_current_field())->as_field();
nassertv(field != (DCField *)NULL);
set_class_element(object, field);
}
pop();
break;
default:
// Otherwise, we just skip over the field.
unpack_skip();
}
} else {
// If the field does have a name, we will want to store it on the
// class, either by calling a method (for a PT_field pack_type) or
// by setting a value (for any other kind of pack_type).
PyObject *element = unpack_object();
if (pack_type == PT_field) {
PyObject *func = PyObject_GetAttrString(object, (char *)field_name.c_str());
if (func != (PyObject *)NULL) {
PyObject *result = PyObject_CallObject(func, element);
Py_XDECREF(result);
}
Py_DECREF(func);
} else {
PyObject_SetAttrString(object, (char *)field_name.c_str(), element);
}
Py_DECREF(element);
}
}
#endif // HAVE_PYTHON

View File

@ -26,6 +26,7 @@
#include "dcPackerCatalog.h"
#include "dcPython.h"
class DCClass;
class DCSwitch;
////////////////////////////////////////////////////////////////////
@ -134,6 +135,11 @@ private:
void set_unpack_data(const char *unpack_data, size_t unpack_length,
bool owns_unpack_data);
#ifdef HAVE_PYTHON
PyObject *unpack_class_object(DCClass *dclass);
void set_class_element(PyObject *object, const DCField *field);
#endif
private:
enum Mode {
M_idle,

View File

@ -138,7 +138,10 @@ get_live_catalog(const char *data, size_t length) const {
r_fill_live_catalog(live_catalog, packer, last_switch);
bool okflag = packer.end_unpack();
nassertr(okflag, live_catalog);
if (!okflag) {
delete live_catalog;
return NULL;
}
if (_root->has_fixed_structure()) {
// If our root field has a fixed structure, then the live catalog

View File

@ -69,6 +69,16 @@ DCPackerInterface::
}
}
////////////////////////////////////////////////////////////////////
// Function: DCPackerInterface::as_field
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DCField *DCPackerInterface::
as_field() {
return (DCField *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DCPackerInterface::as_switch
// Access: Published, Virtual
@ -79,6 +89,16 @@ as_switch() {
return (DCSwitch *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DCPackerInterface::as_class_parameter
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DCClassParameter *DCPackerInterface::
as_class_parameter() {
return (DCClassParameter *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DCPackerInterface::calc_num_nested_fields
// Access: Public, Virtual

View File

@ -22,7 +22,9 @@
#include "dcbase.h"
#include "dcSubatomicType.h"
class DCField;
class DCSwitch;
class DCClassParameter;
class DCPackData;
class DCPackerCatalog;
@ -74,7 +76,9 @@ public:
PUBLISHED:
INLINE const string &get_name() const;
virtual DCField *as_field();
virtual DCSwitch *as_switch();
virtual DCClassParameter *as_class_parameter();
public:
INLINE void set_name(const string &name);