소스 검색

python packer uses new DCPacker

David Rose 21 년 전
부모
커밋
866807b44e

+ 33 - 24
direct/src/dcparser/dcAtomicField.cxx

@@ -407,37 +407,46 @@ generate_hash(HashGenerator &hashgen) const {
   hashgen.add_int(_flags);
 }
 
-#ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::do_pack_args
+//     Function: DCAtomicField::has_nested_fields
 //       Access: Public, Virtual
-//  Description: Packs the Python arguments beginning from the
-//               indicated index of the indicated tuple into the
-//               datagram, appending to the end of the datagram.
-//               Increments index according to the number of arguments
-//               packed.  Returns true if the tuple contained at least
-//               enough arguments to match the field, false otherwise.
+//  Description: Returns true if this field type has any nested fields
+//               (and thus expects a push() .. pop() interface to the
+//               DCPacker), or false otherwise.  If this returns true,
+//               get_num_nested_fields() may be called to determine
+//               how many nested fields are expected.
 ////////////////////////////////////////////////////////////////////
 bool DCAtomicField::
-do_pack_args(Datagram &datagram, PyObject *tuple, int &index) const {
-  int size = PySequence_Size(tuple);
+has_nested_fields() const {
+  return true;
+}
 
-  Elements::const_iterator ei;
-  for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
-    const ElementType &element = (*ei);
-    if (index >= size) {
-      // Not enough elements in the tuple.
-      return false;
-    }
-    PyObject *item = PySequence_GetItem(tuple, index);
-    index++;
-    element._type->pack_arg(datagram, item);
-    Py_DECREF(item);
-  }
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::get_num_nested_fields
+//       Access: Public, Virtual
+//  Description: Returns the number of nested fields required by this
+//               field type.  These may be array elements or structure
+//               elements.  The return value may be -1 to indicate the
+//               number of nested fields is variable.
+////////////////////////////////////////////////////////////////////
+int DCAtomicField::
+get_num_nested_fields() const {
+  return _elements.size();
+}
 
-  return true;
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::get_nested_field
+//       Access: Public, Virtual
+//  Description: Returns the DCPackerInterface object that represents
+//               the nth nested field.  This may return NULL if there
+//               is no such field (but it shouldn't do this if n is in
+//               the range 0 <= n < get_num_nested_fields()).
+////////////////////////////////////////////////////////////////////
+DCPackerInterface *DCAtomicField::
+get_nested_field(int n) const {
+  nassertr(n >= 0 && n < (int)_elements.size(), NULL);
+  return _elements[n]._type;
 }
-#endif  // HAVE_PYTHON
 
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////

+ 4 - 2
direct/src/dcparser/dcAtomicField.h

@@ -64,9 +64,12 @@ public:
   virtual void write(ostream &out, bool brief, int indent_level) const;
   virtual void generate_hash(HashGenerator &hash) const;
 
+  virtual bool has_nested_fields() const;
+  virtual int get_num_nested_fields() const;
+  virtual DCPackerInterface *get_nested_field(int n) const;
+
 public:
 #ifdef HAVE_PYTHON
-  virtual bool do_pack_args(Datagram &datagram, PyObject *tuple, int &index) const;
   virtual bool do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const;
 #endif
 
@@ -106,7 +109,6 @@ public:
   };
 
   int _flags;  // A bitmask union of any of the above values.
-  size_t _pack_index;
 };
 
 #endif

+ 18 - 10
direct/src/dcparser/dcClass.cxx

@@ -330,8 +330,10 @@ direct_update(PyObject *distobj, const string &field_name,
 //               presumably either a required field or a specified
 //               optional field, and we are building up a datagram for
 //               the generate-with-required message.
+//
+//               Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
-void DCClass::
+bool DCClass::
 pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
   DCAtomicField *atom = field->as_atomic_field();
   if (atom == (DCAtomicField *)NULL) {
@@ -339,7 +341,7 @@ pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
     strm << "Cannot pack non-atomic field " << field->get_name()
          << " for generate";
     nassert_raise(strm.str());
-    return;
+    return false;
   }
 
   // We need to get the initial value of this field.  There isn't a
@@ -354,7 +356,7 @@ pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
     ostringstream strm;
     strm << "Required field " << set_name << " has no parameters!";
     nassert_raise(strm.str());
-    return;
+    return false;
   }
   
   if (set_name.substr(0, 3) != string("set")) {
@@ -362,7 +364,7 @@ pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
     ostringstream strm;
     strm << "Required field " << set_name << " does not begin with 'set'";
     nassert_raise(strm.str());
-    return;
+    return false;
   }
   string get_name = set_name;
   get_name[0] = 'g';
@@ -374,11 +376,11 @@ pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
     strm << "Required field " << set_name
          << " doesn't have matching field named " << get_name;
     nassert_raise(strm.str());
-    return;
+    return false;
   }
   PyObject *func = 
     PyObject_GetAttrString(distobj, (char *)get_name.c_str());
-  nassertv(func != (PyObject *)NULL);
+  nassertr(func != (PyObject *)NULL, false);
   
   PyObject *empty_args = PyTuple_New(0);
   PyObject *result = PyObject_CallObject(func, empty_args);
@@ -386,7 +388,7 @@ pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
   Py_DECREF(func);
   if (result == (PyObject *)NULL) {
     cerr << "Error when calling " << get_name << "\n";
-    return;
+    return false;
   }
   
   if (atom->get_num_elements() == 1) {
@@ -398,8 +400,10 @@ pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
   }        
   
   // Now pack the arguments into the datagram.
-  atom->pack_args(dg, result);
+  bool pack_ok = atom->pack_args(dg, result);
   Py_DECREF(result);
+
+  return pack_ok;
 }
 #endif  // HAVE_PYTHON
 
@@ -488,7 +492,9 @@ ai_format_generate(PyObject *distobj, int do_id,
     DCField *field = get_inherited_field(i);
     DCAtomicField *atom = field->as_atomic_field();
     if (atom != (DCAtomicField *)NULL && atom->is_required()) {
-      pack_required_field(dg, distobj, atom);
+      if (!pack_required_field(dg, distobj, atom)) {
+        return Datagram();
+      }
     }
   }
 
@@ -511,7 +517,9 @@ ai_format_generate(PyObject *distobj, int do_id,
         return Datagram();
       }
 
-      pack_required_field(dg, distobj, field);
+      if (!pack_required_field(dg, distobj, field)) {
+        return Datagram();
+      }
     }
   }
 

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

@@ -58,7 +58,7 @@ PUBLISHED:
                      const string &value_blob);
   void direct_update(PyObject *distobj, const string &field_name, 
                      const Datagram &datagram);
-  void pack_required_field(Datagram &dg, PyObject *distobj, 
+  bool pack_required_field(Datagram &dg, PyObject *distobj, 
                            DCField *field) const;
 
 

+ 25 - 12
direct/src/dcparser/dcField.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "dcField.h"
+#include "dcPacker.h"
 #include "hashGenerator.h"
 #include "dcmsgtypes.h"
 
@@ -72,19 +73,31 @@ as_molecular_field() {
 //       Access: Published
 //  Description: Packs the Python arguments from the indicated tuple
 //               into the datagram, appending to the end of the
-//               datagram.
-////////////////////////////////////////////////////////////////////
-void DCField::
-pack_args(Datagram &datagram, PyObject *tuple) const {
-  nassertv(PySequence_Check(tuple));
-  int index = 0;
-  bool enough_args = do_pack_args(datagram, tuple, index);
-  if (!enough_args || index != PySequence_Size(tuple)) {
-    ostringstream strm;
-    strm << "Wrong number of arguments to field " << get_name();
-    nassert_raise(strm.str());
-    return;
+//               datagram.  Returns true on success, false on failure.
+////////////////////////////////////////////////////////////////////
+bool DCField::
+pack_args(Datagram &datagram, PyObject *sequence) const {
+  nassertr(PySequence_Check(sequence), false);
+  DCPacker packer;
+  packer.begin(this);
+  packer.pack_object(sequence);
+  if (packer.end()) {
+    datagram.append_data(packer.get_data(), packer.get_length());
+    return true;
   }
+
+  PyObject *tuple = PySequence_Tuple(sequence);
+  PyObject *str = PyObject_Str(tuple);
+  
+  ostringstream strm;
+  strm << "Incorrect arguments to field: " << get_name()
+       << PyString_AsString(str);
+
+  Py_DECREF(str);
+  Py_DECREF(tuple);
+    
+  nassert_raise(strm.str());
+  return false;
 }
 #endif  // HAVE_PYTHON
 

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

@@ -51,7 +51,7 @@ PUBLISHED:
   virtual DCMolecularField *as_molecular_field();
 
 #ifdef HAVE_PYTHON
-  void pack_args(Datagram &datagram, PyObject *tuple) const;
+  bool pack_args(Datagram &datagram, PyObject *sequence) const;
   PyObject *unpack_args(DatagramIterator &iterator) const;
 
   void receive_update(PyObject *distobj, DatagramIterator &iterator) const;
@@ -72,7 +72,6 @@ protected:
 
 public:
 #ifdef HAVE_PYTHON
-  virtual bool do_pack_args(Datagram &datagram, PyObject *tuple, int &index) const=0;
   virtual bool do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const=0;
 #endif
 

+ 52 - 18
direct/src/dcparser/dcMolecularField.cxx

@@ -69,6 +69,24 @@ DCMolecularField::
 DCMolecularField(const string &name) : DCField(name) {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCMolecularField::add_atomic
+//       Access: Public
+//  Description: Adds the indicated atomic field to the end of the
+//               list of atomic fields that make up the molecular
+//               field.  This is normally called only during parsing
+//               of the dc file.
+////////////////////////////////////////////////////////////////////
+void DCMolecularField::
+add_atomic(DCAtomicField *atomic) {
+  _fields.push_back(atomic);
+
+  int num_nested_fields = atomic->get_num_nested_fields();
+  for (int i = 0; i < num_nested_fields; i++) {
+    _nested_fields.push_back(atomic->get_nested_field(i));
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCMolecularField::write
 //       Access: Public, Virtual
@@ -114,30 +132,46 @@ generate_hash(HashGenerator &hashgen) const {
   }
 }
 
-#ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
-//     Function: DCMolecularField::do_pack_args
+//     Function: DCMolecularField::has_nested_fields
 //       Access: Public, Virtual
-//  Description: Packs the Python arguments beginning from the
-//               indicated index of the indicated tuple into the
-//               datagram, appending to the end of the datagram.
-//               Increments index according to the number of arguments
-//               packed.  Returns true if the tuple contained at least
-//               enough arguments to match the field, false otherwise.
+//  Description: Returns true if this field type has any nested fields
+//               (and thus expects a push() .. pop() interface to the
+//               DCPacker), or false otherwise.  If this returns true,
+//               get_num_nested_fields() may be called to determine
+//               how many nested fields are expected.
 ////////////////////////////////////////////////////////////////////
 bool DCMolecularField::
-do_pack_args(Datagram &datagram, PyObject *tuple, int &index) const {
-  Fields::const_iterator fi;
-  for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
-    DCField *field = (*fi);
-    if (!field->do_pack_args(datagram, tuple, index)) {
-      return false;
-    }
-  }
-
+has_nested_fields() const {
   return true;
 }
-#endif  // HAVE_PYTHON
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCMolecularField::get_num_nested_fields
+//       Access: Public, Virtual
+//  Description: Returns the number of nested fields required by this
+//               field type.  These may be array elements or structure
+//               elements.  The return value may be -1 to indicate the
+//               number of nested fields is variable.
+////////////////////////////////////////////////////////////////////
+int DCMolecularField::
+get_num_nested_fields() const {
+  return _nested_fields.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCMolecularField::get_nested_field
+//       Access: Public, Virtual
+//  Description: Returns the DCPackerInterface object that represents
+//               the nth nested field.  This may return NULL if there
+//               is no such field (but it shouldn't do this if n is in
+//               the range 0 <= n < get_num_nested_fields()).
+////////////////////////////////////////////////////////////////////
+DCPackerInterface *DCMolecularField::
+get_nested_field(int n) const {
+  nassertr(n >= 0 && n < (int)_nested_fields.size(), NULL);
+  return _nested_fields[n];
+}
 
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////

+ 10 - 5
direct/src/dcparser/dcMolecularField.h

@@ -40,26 +40,31 @@ PUBLISHED:
 
 public:
   DCMolecularField(const string &name);
+
+  void add_atomic(DCAtomicField *atomic);
+
   virtual void write(ostream &out, bool brief, int indent_level) const;
   virtual void generate_hash(HashGenerator &hash) const;
 
+  virtual bool has_nested_fields() const;
+  virtual int get_num_nested_fields() const;
+  virtual DCPackerInterface *get_nested_field(int n) const;
+
 public:
 #ifdef HAVE_PYTHON
-  virtual bool do_pack_args(Datagram &datagram, PyObject *tuple, int &index) const;
   virtual bool do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const;
 #endif
 
-public:
+private:
   // These members define the primary interface to the molecular field
   // definition as read from the file.
   typedef pvector<DCAtomicField *> Fields;
   Fields _fields;
 
-private:
   DCType *get_next_pack_element();
 
-  size_t _pack_field_index;
-  size_t _pack_element_index;
+  typedef pvector<DCPackerInterface *> NestedFields;
+  NestedFields _nested_fields;
 };
 
 #endif

+ 34 - 17
direct/src/dcparser/dcPacker.I

@@ -17,15 +17,32 @@
 ////////////////////////////////////////////////////////////////////
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::has_nested_fields
+//       Access: Public, Virtual
+//  Description: Returns true if the current field has any nested
+//               fields (and thus expects a push() .. pop()
+//               interface), or false otherwise.  If this returns
+//               true, get_num_nested_fields() may be called to
+//               determine how many nested fields are expected.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCPacker::
+has_nested_fields() const {
+  if (_current_field == NULL) {
+    return false;
+  } else {
+    return _current_field->has_nested_fields();
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::get_num_nested_fields
 //       Access: Published
 //  Description: Returns the number of nested fields associated with
-//               the current field.  If this returns nonzero, it will
-//               be necessary to call push(), followed by pack_value()
-//               the indicated number of times, followed by pop().
+//               the current field, if has_nested_fields() returned
+//               true.
 //
-//               The return value may also be -1 to indicate that a
+//               The return value may be -1 to indicate that a
 //               variable number of nested fields are accepted by this
 //               field type (e.g. a variable-length array).
 ////////////////////////////////////////////////////////////////////
@@ -52,17 +69,17 @@ get_pack_type() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPacker::pack_value
+//     Function: DCPacker::pack_double
 //       Access: Published
 //  Description: Packs the indicated numeric or string value into the
 //               stream.
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPacker::
-pack_value(double value) {
+pack_double(double value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_value(_pack_data, value)) {
+    if (!_current_field->pack_double(_pack_data, value)) {
       _pack_error = true;
     }
     advance();
@@ -70,17 +87,17 @@ pack_value(double value) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPacker::pack_value
+//     Function: DCPacker::pack_int
 //       Access: Published
 //  Description: Packs the indicated numeric or string value into the
 //               stream.
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPacker::
-pack_value(int value) {
+pack_int(int value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_value(_pack_data, value)) {
+    if (!_current_field->pack_int(_pack_data, value)) {
       _pack_error = true;
     }
     advance();
@@ -88,17 +105,17 @@ pack_value(int value) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPacker::pack_value
+//     Function: DCPacker::pack_int64
 //       Access: Published
 //  Description: Packs the indicated numeric or string value into the
 //               stream.
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPacker::
-pack_value(PN_int64 value) {
+pack_int64(PN_int64 value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_value(_pack_data, value)) {
+    if (!_current_field->pack_int64(_pack_data, value)) {
       _pack_error = true;
     }
     advance();
@@ -106,17 +123,17 @@ pack_value(PN_int64 value) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPacker::pack_value
+//     Function: DCPacker::pack_string
 //       Access: Published
 //  Description: Packs the indicated numeric or string value into the
 //               stream.
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPacker::
-pack_value(const string &value) {
+pack_string(const string &value) {
   if (_current_field == NULL) {
     _pack_error = true;
   } else {
-    if (!_current_field->pack_value(_pack_data, value)) {
+    if (!_current_field->pack_string(_pack_data, value)) {
       _pack_error = true;
     }
     advance();
@@ -198,6 +215,7 @@ get_data() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DCPacker::
 advance() {
+  _current_field_index++;
   if (_num_nested_fields >= 0 &&
       _current_field_index >= _num_nested_fields) {
     // Done with all the fields on this parent.  The caller must now
@@ -206,7 +224,6 @@ advance() {
 
   } else {
     // We have another field to advance to.
-    _current_field_index++;
     _current_field = _current_parent->get_nested_field(_current_field_index);
   }
 }

+ 69 - 22
direct/src/dcparser/dcPacker.cxx

@@ -49,7 +49,7 @@ DCPacker::
 //               DCType or DCField.
 ////////////////////////////////////////////////////////////////////
 void DCPacker::
-begin(DCPackerInterface *root) {
+begin(const DCPackerInterface *root) {
   // If this assertion fails, we didn't match begin() up with end().
   nassertv(_stack.empty() && 
            _current_field == NULL &&
@@ -96,37 +96,39 @@ end() {
 //               array or the individual fields in a structure field.
 //               It must also be balanced by a matching pop().
 //
-//               It is necessary to use push() / pop() if and only if
-//               get_num_nested_fields() returns nonzero.
+//               It is necessary to use push() / pop() only if
+//               has_nested_fields() returns true.
 ////////////////////////////////////////////////////////////////////
 void DCPacker::
 push() {
-  if (_current_field == NULL) {
+  if (!has_nested_fields()) {
     _pack_error = true;
 
   } else {
     int num_nested_fields = _current_field->get_num_nested_fields();
-    if (num_nested_fields == 0) {
-      _pack_error = true;
+    StackElement element;
+    element._current_parent = _current_parent;
+    element._current_field_index = _current_field_index;
+    element._push_start = _push_start;
+    _stack.push_back(element);
+    
+    _current_parent = _current_field;
+    _num_nested_fields = num_nested_fields;
+    _current_field_index = 0;
 
+    if (_num_nested_fields >= 0 &&
+        _current_field_index >= _num_nested_fields) {
+      _current_field = NULL;
+      
     } else {
-      StackElement element;
-      element._current_parent = _current_parent;
-      element._current_field_index = _current_field_index;
-      element._push_start = _push_start;
-      _stack.push_back(element);
-
-      _current_parent = _current_field;
-      _current_field_index = 0;
-      _current_field = _current_parent->get_nested_field(0);
-      _num_nested_fields = num_nested_fields;
-
-      // Reserve length_bytes for when we figure out what the length
-      // is.
-      _push_start = _pack_data.get_length();
-      size_t length_bytes = _current_parent->get_length_bytes();
-      _pack_data.append_junk(length_bytes);
+      _current_field = _current_parent->get_nested_field(_current_field_index);
     }
+    
+    // Reserve length_bytes for when we figure out what the length
+    // is.
+    _push_start = _pack_data.get_length();
+    size_t length_bytes = _current_parent->get_length_bytes();
+    _pack_data.append_junk(length_bytes);
   }
 }
 
@@ -180,3 +182,48 @@ pop() {
 
   advance();
 }
+
+#ifdef HAVE_PYTHON
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::pack_object
+//       Access: Published
+//  Description: Packs the Python object of whatever type into the
+//               packer.  Each numeric object and string object maps
+//               to the corresponding pack_value() call; a tuple or
+//               sequence maps to a push() followed by all of the
+//               tuple's contents followed by a pop().
+////////////////////////////////////////////////////////////////////
+void DCPacker::
+pack_object(PyObject *object) {
+  PyObject *str = PyObject_Str(object);
+  Py_DECREF(str);
+
+  if (PyInt_Check(object)) {
+    pack_int(PyInt_AS_LONG(object));
+
+  } else if (PyFloat_Check(object)) {
+    pack_double(PyFloat_AS_DOUBLE(object));
+
+  } else if (PyLong_Check(object)) {
+    pack_int64(PyLong_AsLongLong(object));
+
+  } else if (PyString_Check(object) || PyUnicode_Check(object)) {
+    char *buffer;
+    int length;
+    PyString_AsStringAndSize(object, &buffer, &length);
+    if (buffer) {
+      pack_string(string(buffer, length));
+    }
+
+  } else if (PySequence_Check(object)) {
+    push();
+    int size = PySequence_Size(object);
+    for (int i = 0; i < size; i++) {
+      PyObject *element = PySequence_GetItem(object, i);
+      pack_object(element);
+      Py_DECREF(element);
+    }
+    pop();
+  }
+}
+#endif  // HAVE_PYTHON

+ 14 - 9
direct/src/dcparser/dcPacker.h

@@ -35,20 +35,25 @@ PUBLISHED:
   DCPacker();
   ~DCPacker();
 
-  void begin(DCPackerInterface *root);
+  void begin(const DCPackerInterface *root);
   bool end();
 
+  INLINE bool has_nested_fields() const;
   INLINE int get_num_nested_fields() const;
   void push();
   void pop();
 
   INLINE DCSubatomicType get_pack_type() const;
-  INLINE void pack_value(double value);
-  INLINE void pack_value(int value);
-  INLINE void pack_value(PN_int64 value);
-  INLINE void pack_value(const string &value);
+  INLINE void pack_double(double value);
+  INLINE void pack_int(int value);
+  INLINE void pack_int64(PN_int64 value);
+  INLINE void pack_string(const string &value);
   INLINE void pack_literal_value(const string &value);
 
+#ifdef HAVE_PYTHON
+  void pack_object(PyObject *object);
+#endif
+
   INLINE bool had_pack_error() const;
 
   INLINE string get_string() const;
@@ -64,15 +69,15 @@ private:
 
   class StackElement {
   public:
-    DCPackerInterface *_current_parent;
+    const DCPackerInterface *_current_parent;
     int _current_field_index;
     size_t _push_start;
   };
-  typedef vector<StackElement> Stack;
+  typedef pvector<StackElement> Stack;
 
   Stack _stack;
-  DCPackerInterface *_current_field;
-  DCPackerInterface *_current_parent;
+  const DCPackerInterface *_current_field;
+  const DCPackerInterface *_current_parent;
   int _current_field_index;
   size_t _push_start;
   int _num_nested_fields;

+ 29 - 17
direct/src/dcparser/dcPackerInterface.cxx

@@ -27,15 +27,27 @@ DCPackerInterface::
 ~DCPackerInterface() {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::has_nested_fields
+//       Access: Public, Virtual
+//  Description: Returns true if this field type has any nested fields
+//               (and thus expects a push() .. pop() interface to the
+//               DCPacker), or false otherwise.  If this returns true,
+//               get_num_nested_fields() may be called to determine
+//               how many nested fields are expected.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+has_nested_fields() const {
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::get_num_nested_fields
 //       Access: Public, Virtual
 //  Description: Returns the number of nested fields required by this
 //               field type.  These may be array elements or structure
-//               elements.  The return value should be 0 if the field
-//               type does not have any nested fields.  It may also be
-//               -1 to indicate the number of nested fields is
-//               variable.
+//               elements.  The return value may be -1 to indicate the
+//               number of nested fields is variable.
 ////////////////////////////////////////////////////////////////////
 int DCPackerInterface::
 get_num_nested_fields() const {
@@ -58,11 +70,11 @@ get_nested_field(int n) const {
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::get_length_bytes
 //       Access: Public, Virtual
-//  Description: If get_num_nested_fields() returns non-zero, this
-//               should return either 0, 2, or 4, indicating the
-//               number of bytes this field's data should be prefixed
-//               with to record its length.  This is respected by
-//               push() and pop().
+//  Description: If has_nested_fields() returns true, this should
+//               return either 0, 2, or 4, indicating the number of
+//               bytes this field's data should be prefixed with to
+//               record its length.  This is respected by push() and
+//               pop().
 ////////////////////////////////////////////////////////////////////
 size_t DCPackerInterface::
 get_length_bytes() const {
@@ -82,45 +94,45 @@ get_pack_type() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPackerInterface::pack_value
+//     Function: DCPackerInterface::pack_double
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCPackerInterface::
-pack_value(DCPackData &, double) const {
+pack_double(DCPackData &, double) const {
   return false;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPackerInterface::pack_value
+//     Function: DCPackerInterface::pack_int
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCPackerInterface::
-pack_value(DCPackData &, int) const {
+pack_int(DCPackData &, int) const {
   return false;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPackerInterface::pack_value
+//     Function: DCPackerInterface::pack_int64
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCPackerInterface::
-pack_value(DCPackData &, PN_int64) const {
+pack_int64(DCPackData &, PN_int64) const {
   return false;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCPackerInterface::pack_value
+//     Function: DCPackerInterface::pack_string
 //       Access: Public, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCPackerInterface::
-pack_value(DCPackData &, const string &) const {
+pack_string(DCPackData &, const string &) const {
   return false;
 }

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

@@ -38,15 +38,16 @@ class EXPCL_DIRECT DCPackerInterface {
 public:
   virtual ~DCPackerInterface();
 
+  virtual bool has_nested_fields() const;
   virtual int get_num_nested_fields() const;
   virtual DCPackerInterface *get_nested_field(int n) const;
   virtual size_t get_length_bytes() const;
 
   virtual DCSubatomicType get_pack_type() const;
-  virtual bool pack_value(DCPackData &pack_data, double value) const;
-  virtual bool pack_value(DCPackData &pack_data, int value) const;
-  virtual bool pack_value(DCPackData &pack_data, PN_int64 value) const;
-  virtual bool pack_value(DCPackData &pack_data, const string &value) const;
+  virtual bool pack_double(DCPackData &pack_data, double value) const;
+  virtual bool pack_int(DCPackData &pack_data, int value) const;
+  virtual bool pack_int64(DCPackData &pack_data, PN_int64 value) const;
+  virtual bool pack_string(DCPackData &pack_data, const string &value) const;
 };
 
 #endif

+ 9 - 9
direct/src/dcparser/dcParser.yxx

@@ -285,15 +285,15 @@ atomic_element_definition:
 default_value:
 	INTEGER
 {
-  default_value_packer.pack_value($1);
+  default_value_packer.pack_int($1);
 }
         | REAL
 {
-  default_value_packer.pack_value($1);
+  default_value_packer.pack_double($1);
 }
         | STRING
 {
-  default_value_packer.pack_value($1);
+  default_value_packer.pack_string($1);
 }
         | HEX_STRING
 {
@@ -310,13 +310,13 @@ default_value:
         | INTEGER '*' INTEGER
 {
   for (int i = 0; i < $3; i++) {
-    default_value_packer.pack_value($1);
+    default_value_packer.pack_int($1);
   }
 }
         | REAL '*' INTEGER
 {
   for (int i = 0; i < $3; i++) {
-    default_value_packer.pack_value($1);
+    default_value_packer.pack_double($1);
   }
 }
         | HEX_STRING '*' INTEGER
@@ -476,16 +476,16 @@ molecular_atom_list:
         atomic_name
 {
   if ($1 != (DCAtomicField *)NULL) {
-    current_molecular->_fields.push_back($1);
+    current_molecular->add_atomic($1);
   }
 }
         | molecular_atom_list ',' atomic_name
 {
   if ($3 != (DCAtomicField *)NULL) {
-    current_molecular->_fields.push_back($3);
-    if (current_molecular->_fields[0]->_flags != $3->_flags) {
+    current_molecular->add_atomic($3);
+    if (current_molecular->get_atomic(0)->_flags != $3->_flags) {
       yyerror("Mismatched flags in molecule between " + 
-              current_molecular->_fields[0]->get_name() + " and " +
+              current_molecular->get_atomic(0)->get_name() + " and " +
               $3->get_name());
     }
   }

+ 39 - 17
direct/src/dcparser/dcSimpleType.cxx

@@ -157,15 +157,27 @@ set_divisor(int divisor) {
   _divisor = divisor;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSimpleType::has_nested_fields
+//       Access: Public, Virtual
+//  Description: Returns true if this field type has any nested fields
+//               (and thus expects a push() .. pop() interface to the
+//               DCPacker), or false otherwise.  If this returns true,
+//               get_num_nested_fields() may be called to determine
+//               how many nested fields are expected.
+////////////////////////////////////////////////////////////////////
+bool DCSimpleType::
+has_nested_fields() const {
+  return _is_array;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSimpleType::get_num_nested_fields
 //       Access: Public, Virtual
 //  Description: Returns the number of nested fields required by this
 //               field type.  These may be array elements or structure
-//               elements.  The return value should be 0 if the field
-//               type does not have any nested fields.  It may also be
-//               -1 to indicate the number of nested fields is
-//               variable.
+//               elements.  The return value may be -1 to indicate the
+//               number of nested fields is variable.
 ////////////////////////////////////////////////////////////////////
 int DCSimpleType::
 get_num_nested_fields() const {
@@ -188,11 +200,11 @@ get_nested_field(int n) const {
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSimpleType::get_length_bytes
 //       Access: Public, Virtual
-//  Description: If get_num_nested_fields() returns non-zero, this
-//               should return either 0, 2, or 4, indicating the
-//               number of bytes this field's data should be prefixed
-//               with to record its length.  This is respected by
-//               push() and pop().
+//  Description: If has_nested_fields() returns true, this should
+//               return either 0, 2, or 4, indicating the number of
+//               bytes this field's data should be prefixed with to
+//               record its length.  This is respected by push() and
+//               pop().
 ////////////////////////////////////////////////////////////////////
 size_t DCSimpleType::
 get_length_bytes() const {
@@ -212,13 +224,13 @@ get_pack_type() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCSimpleType::pack_value
+//     Function: DCSimpleType::pack_double
 //       Access: Published, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCSimpleType::
-pack_value(DCPackData &pack_data, double value) const {
+pack_double(DCPackData &pack_data, double value) const {
   double real_value = value * _divisor;
   int int_value = (int)floor(real_value + 0.5);
 
@@ -286,13 +298,13 @@ pack_value(DCPackData &pack_data, double value) const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCSimpleType::pack_value
+//     Function: DCSimpleType::pack_int
 //       Access: Published, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCSimpleType::
-pack_value(DCPackData &pack_data, int value) const {
+pack_int(DCPackData &pack_data, int value) const {
   int int_value = value * _divisor;
 
   char buffer[8];
@@ -369,13 +381,13 @@ pack_value(DCPackData &pack_data, int value) const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCSimpleType::pack_value
+//     Function: DCSimpleType::pack_int64
 //       Access: Published, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCSimpleType::
-pack_value(DCPackData &pack_data, PN_int64 value) const {
+pack_int64(DCPackData &pack_data, PN_int64 value) const {
   PN_int64 int_value = value * _divisor;
 
   char buffer[8];
@@ -445,13 +457,13 @@ pack_value(DCPackData &pack_data, PN_int64 value) const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCSimpleType::pack_value
+//     Function: DCSimpleType::pack_string
 //       Access: Published, Virtual
 //  Description: Packs the indicated numeric or string value into the
 //               stream.  Returns true on success, false on failure.
 ////////////////////////////////////////////////////////////////////
 bool DCSimpleType::
-pack_value(DCPackData &pack_data, const string &value) const {
+pack_string(DCPackData &pack_data, const string &value) const {
   char buffer[4];
 
   switch (_type) {
@@ -948,6 +960,16 @@ Uint32Uint8Type() {
   _uint8_type = new DCSimpleType(ST_uint8);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSimpleType::Uint32Uint8Type::has_nested_fields
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool DCSimpleType::Uint32Uint8Type::
+has_nested_fields() const {
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSimpleType::Uint32Uint8Type::get_num_nested_fields
 //       Access: Public, Virtual

+ 8 - 6
direct/src/dcparser/dcSimpleType.h

@@ -45,15 +45,16 @@ PUBLISHED:
   void set_divisor(int divisor);
 
 public:
+  virtual bool has_nested_fields() const;
   virtual int get_num_nested_fields() const;
   virtual DCPackerInterface *get_nested_field(int n) const;
   virtual size_t get_length_bytes() const;
 
   virtual DCSubatomicType get_pack_type() const;
-  virtual bool pack_value(DCPackData &pack_data, double value) const;
-  virtual bool pack_value(DCPackData &pack_data, int value) const;
-  virtual bool pack_value(DCPackData &pack_data, PN_int64 value) const;
-  virtual bool pack_value(DCPackData &pack_data, const string &value) const;
+  virtual bool pack_double(DCPackData &pack_data, double value) const;
+  virtual bool pack_int(DCPackData &pack_data, int value) const;
+  virtual bool pack_int64(DCPackData &pack_data, PN_int64 value) const;
+  virtual bool pack_string(DCPackData &pack_data, const string &value) const;
 
   virtual void output(ostream &out, const string &parameter_name, 
                       bool brief) const;
@@ -84,13 +85,14 @@ private:
   // The rest of this is to maintain the static list of
   // DCPackerInterface objects for _nested_field, above.  We allocate
   // each possible object once, and don't delete it.
-  typedef map<int, DCSimpleType *> DivisorMap;
-  typedef map<DCSubatomicType, DivisorMap> NestedFieldMap;
+  typedef pmap<int, DCSimpleType *> DivisorMap;
+  typedef pmap<DCSubatomicType, DivisorMap> NestedFieldMap;
   static NestedFieldMap _nested_field_map;
 
   class Uint32Uint8Type : public DCPackerInterface {
   public:
     Uint32Uint8Type();
+    virtual bool has_nested_fields() const;
     virtual int get_num_nested_fields() const;
     virtual DCPackerInterface *get_nested_field(int n) const;