python packer uses new DCPacker

This commit is contained in:
David Rose 2004-06-16 22:12:31 +00:00
parent 96e4161169
commit 866807b44e
16 changed files with 351 additions and 175 deletions

View File

@ -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
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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
////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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());
}
}

View File

@ -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

View File

@ -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;