Explorar el Código

unpack to python object

David Rose hace 21 años
padre
commit
6845758d2b

+ 13 - 0
direct/src/dcparser/dcClass.cxx

@@ -223,6 +223,19 @@ is_bogus_class() const {
   return _bogus_class;
   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
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::set_class_def
 //     Function: DCClass::set_class_def

+ 1 - 0
direct/src/dcparser/dcClass.h

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

+ 10 - 0
direct/src/dcparser/dcField.cxx

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

+ 1 - 0
direct/src/dcparser/dcField.h

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

+ 123 - 0
direct/src/dcparser/dcPacker.cxx

@@ -20,6 +20,8 @@
 #include "dcSwitch.h"
 #include "dcSwitch.h"
 #include "dcParserDefs.h"
 #include "dcParserDefs.h"
 #include "dcLexerDefs.h"
 #include "dcLexerDefs.h"
+#include "dcClassParameter.h"
+#include "dcClass.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::Constructor
 //     Function: DCPacker::Constructor
@@ -217,6 +219,9 @@ begin_repack(const char *data, size_t length,
   _root = root;
   _root = root;
   _catalog = _root->get_catalog();
   _catalog = _root->get_catalog();
   _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
   _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
   // We don't begin at the first field in repack mode.  Instead, you
   // must explicitly call seek().
   // must explicitly call seek().
@@ -268,6 +273,10 @@ seek(const string &field_name) {
       _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
       _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
     }
     }
     nassertr(_catalog != (DCPackerCatalog *)NULL, false);
     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);
     int entry_index = _live_catalog->find_entry_by_name(field_name);
     if (entry_index < 0) {
     if (entry_index < 0) {
@@ -305,6 +314,10 @@ seek(const string &field_name) {
       _pack_error = true;
       _pack_error = true;
       return false;
       return false;
     }
     }
+    if (_live_catalog == NULL) {
+      _pack_error = true;
+      return false;
+    }
 
 
     int entry_index = _live_catalog->find_entry_by_name(field_name);
     int entry_index = _live_catalog->find_entry_by_name(field_name);
     if (entry_index < 0) {
     if (entry_index < 0) {
@@ -338,6 +351,11 @@ seek(const string &field_name) {
       _catalog->release_live_catalog(_live_catalog);
       _catalog->release_live_catalog(_live_catalog);
       _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
       _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);
       begin = _live_catalog->get_begin(entry_index);
     }
     }
 
 
@@ -696,6 +714,22 @@ unpack_object() {
     }
     }
     break;
     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:
   default:
     {
     {
       // First, build up a list from the nested objects.
       // 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;
   _unpack_length = unpack_length;
   _owns_unpack_data = owns_unpack_data;
   _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

+ 6 - 0
direct/src/dcparser/dcPacker.h

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

+ 4 - 1
direct/src/dcparser/dcPackerCatalog.cxx

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

+ 20 - 0
direct/src/dcparser/dcPackerInterface.cxx

@@ -69,6 +69,16 @@ DCPackerInterface::
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::as_field
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCField *DCPackerInterface::
+as_field() {
+  return (DCField *)NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::as_switch
 //     Function: DCPackerInterface::as_switch
 //       Access: Published, Virtual
 //       Access: Published, Virtual
@@ -79,6 +89,16 @@ as_switch() {
   return (DCSwitch *)NULL;
   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
 //     Function: DCPackerInterface::calc_num_nested_fields
 //       Access: Public, Virtual
 //       Access: Public, Virtual

+ 4 - 0
direct/src/dcparser/dcPackerInterface.h

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