diff --git a/direct/src/dcparser/dcAtomicField.cxx b/direct/src/dcparser/dcAtomicField.cxx index 8755253fb9..ebca8a1b8d 100644 --- a/direct/src/dcparser/dcAtomicField.cxx +++ b/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); - - 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); - } - +has_nested_fields() const { return true; } -#endif // HAVE_PYTHON + +//////////////////////////////////////////////////////////////////// +// 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(); +} + +//////////////////////////////////////////////////////////////////// +// 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; +} #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// diff --git a/direct/src/dcparser/dcAtomicField.h b/direct/src/dcparser/dcAtomicField.h index 721b9d4282..4e70471638 100644 --- a/direct/src/dcparser/dcAtomicField.h +++ b/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 &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 diff --git a/direct/src/dcparser/dcClass.cxx b/direct/src/dcparser/dcClass.cxx index 2bf6c29dca..cfd00a630e 100644 --- a/direct/src/dcparser/dcClass.cxx +++ b/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(); + } } } diff --git a/direct/src/dcparser/dcClass.h b/direct/src/dcparser/dcClass.h index d2616567b8..1a39e76aa6 100644 --- a/direct/src/dcparser/dcClass.h +++ b/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; diff --git a/direct/src/dcparser/dcField.cxx b/direct/src/dcparser/dcField.cxx index ab7d62c25e..be6c04b0a0 100644 --- a/direct/src/dcparser/dcField.cxx +++ b/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. +// datagram. Returns true on success, false on failure. //////////////////////////////////////////////////////////////////// -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; +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 diff --git a/direct/src/dcparser/dcField.h b/direct/src/dcparser/dcField.h index d13674ecbe..4dc541439e 100644 --- a/direct/src/dcparser/dcField.h +++ b/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 &args, DatagramIterator &iterator) const=0; #endif diff --git a/direct/src/dcparser/dcMolecularField.cxx b/direct/src/dcparser/dcMolecularField.cxx index 23ab09bc9e..830b2119ae 100644 --- a/direct/src/dcparser/dcMolecularField.cxx +++ b/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 //////////////////////////////////////////////////////////////////// diff --git a/direct/src/dcparser/dcMolecularField.h b/direct/src/dcparser/dcMolecularField.h index 5e2a7d20f7..a54ccbf4c6 100644 --- a/direct/src/dcparser/dcMolecularField.h +++ b/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 &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 Fields; Fields _fields; -private: DCType *get_next_pack_element(); - size_t _pack_field_index; - size_t _pack_element_index; + typedef pvector NestedFields; + NestedFields _nested_fields; }; #endif diff --git a/direct/src/dcparser/dcPacker.I b/direct/src/dcparser/dcPacker.I index d6c383db0a..aeae8b8db2 100755 --- a/direct/src/dcparser/dcPacker.I +++ b/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); } } diff --git a/direct/src/dcparser/dcPacker.cxx b/direct/src/dcparser/dcPacker.cxx index b0aed1d379..6100153cab 100755 --- a/direct/src/dcparser/dcPacker.cxx +++ b/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 diff --git a/direct/src/dcparser/dcPacker.h b/direct/src/dcparser/dcPacker.h index c0c38b3bf5..4e6f776da1 100755 --- a/direct/src/dcparser/dcPacker.h +++ b/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 Stack; + typedef pvector 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; diff --git a/direct/src/dcparser/dcPackerInterface.cxx b/direct/src/dcparser/dcPackerInterface.cxx index 51b357091d..7b0fb126c4 100755 --- a/direct/src/dcparser/dcPackerInterface.cxx +++ b/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; } diff --git a/direct/src/dcparser/dcPackerInterface.h b/direct/src/dcparser/dcPackerInterface.h index 2206dd343d..0c2341d2ed 100755 --- a/direct/src/dcparser/dcPackerInterface.h +++ b/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 diff --git a/direct/src/dcparser/dcParser.yxx b/direct/src/dcparser/dcParser.yxx index 3d8172af23..e1ed3c97ec 100644 --- a/direct/src/dcparser/dcParser.yxx +++ b/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()); } } diff --git a/direct/src/dcparser/dcSimpleType.cxx b/direct/src/dcparser/dcSimpleType.cxx index 834d6356f5..9de9c69bbd 100755 --- a/direct/src/dcparser/dcSimpleType.cxx +++ b/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 diff --git a/direct/src/dcparser/dcSimpleType.h b/direct/src/dcparser/dcSimpleType.h index 03dd8f0e7d..a6762e4798 100755 --- a/direct/src/dcparser/dcSimpleType.h +++ b/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 ¶meter_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 DivisorMap; - typedef map NestedFieldMap; + typedef pmap DivisorMap; + typedef pmap 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;