python packer uses new DCPacker
This commit is contained in:
parent
96e4161169
commit
866807b44e
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue