mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
python unpacking
This commit is contained in:
parent
dd5ba8f3b6
commit
aff151835d
@ -407,20 +407,6 @@ generate_hash(HashGenerator &hashgen) const {
|
|||||||
hashgen.add_int(_flags);
|
hashgen.add_int(_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: DCAtomicField::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 DCAtomicField::
|
|
||||||
has_nested_fields() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCAtomicField::get_num_nested_fields
|
// Function: DCAtomicField::get_num_nested_fields
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -447,30 +433,3 @@ get_nested_field(int n) const {
|
|||||||
nassertr(n >= 0 && n < (int)_elements.size(), NULL);
|
nassertr(n >= 0 && n < (int)_elements.size(), NULL);
|
||||||
return _elements[n]._type;
|
return _elements[n]._type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: DCAtomicField::do_unpack_args
|
|
||||||
// Access: Public, Virtual
|
|
||||||
// Description: Unpacks the values from the datagram, beginning at
|
|
||||||
// the current point in the interator, into a vector of
|
|
||||||
// Python objects (each with its own reference count).
|
|
||||||
// Returns true if there are enough values in the
|
|
||||||
// datagram, false otherwise.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool DCAtomicField::
|
|
||||||
do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const {
|
|
||||||
Elements::const_iterator ei;
|
|
||||||
for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
|
|
||||||
const ElementType &element = (*ei);
|
|
||||||
PyObject *item = element._type->unpack_arg(iterator);
|
|
||||||
if (item == (PyObject *)NULL) {
|
|
||||||
// Ran out of datagram bytes.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
args.push_back(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // HAVE_PYTHON
|
|
||||||
|
@ -64,15 +64,9 @@ public:
|
|||||||
virtual void write(ostream &out, bool brief, int indent_level) const;
|
virtual void write(ostream &out, bool brief, int indent_level) const;
|
||||||
virtual void generate_hash(HashGenerator &hash) const;
|
virtual void generate_hash(HashGenerator &hash) const;
|
||||||
|
|
||||||
virtual bool has_nested_fields() const;
|
|
||||||
virtual int get_num_nested_fields() const;
|
virtual int get_num_nested_fields() const;
|
||||||
virtual DCPackerInterface *get_nested_field(int n) const;
|
virtual DCPackerInterface *get_nested_field(int n) const;
|
||||||
|
|
||||||
public:
|
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
virtual bool do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// These members define the primary interface to the atomic field
|
// These members define the primary interface to the atomic field
|
||||||
// definition as read from the file.
|
// definition as read from the file.
|
||||||
|
@ -239,7 +239,7 @@ receive_update(PyObject *distobj, DatagramIterator &iterator) const {
|
|||||||
void DCClass::
|
void DCClass::
|
||||||
receive_update_broadcast_required(PyObject *distobj, DatagramIterator &iterator) const {
|
receive_update_broadcast_required(PyObject *distobj, DatagramIterator &iterator) const {
|
||||||
int num_fields = get_num_inherited_fields();
|
int num_fields = get_num_inherited_fields();
|
||||||
for (int i = 0; i < num_fields; i++) {
|
for (int i = 0; i < num_fields && !PyErr_Occurred(); i++) {
|
||||||
DCField *field = get_inherited_field(i);
|
DCField *field = get_inherited_field(i);
|
||||||
DCAtomicField *atom = field->as_atomic_field();
|
DCAtomicField *atom = field->as_atomic_field();
|
||||||
if (atom != (DCAtomicField *)NULL &&
|
if (atom != (DCAtomicField *)NULL &&
|
||||||
@ -262,7 +262,7 @@ receive_update_broadcast_required(PyObject *distobj, DatagramIterator &iterator)
|
|||||||
void DCClass::
|
void DCClass::
|
||||||
receive_update_all_required(PyObject *distobj, DatagramIterator &iterator) const {
|
receive_update_all_required(PyObject *distobj, DatagramIterator &iterator) const {
|
||||||
int num_fields = get_num_inherited_fields();
|
int num_fields = get_num_inherited_fields();
|
||||||
for (int i = 0; i < num_fields; i++) {
|
for (int i = 0; i < num_fields && !PyErr_Occurred(); i++) {
|
||||||
DCField *field = get_inherited_field(i);
|
DCField *field = get_inherited_field(i);
|
||||||
DCAtomicField *atom = field->as_atomic_field();
|
DCAtomicField *atom = field->as_atomic_field();
|
||||||
if (atom != (DCAtomicField *)NULL && atom->is_required()) {
|
if (atom != (DCAtomicField *)NULL && atom->is_required()) {
|
||||||
@ -282,7 +282,7 @@ receive_update_all_required(PyObject *distobj, DatagramIterator &iterator) const
|
|||||||
void DCClass::
|
void DCClass::
|
||||||
receive_update_other(PyObject *distobj, DatagramIterator &iterator) const {
|
receive_update_other(PyObject *distobj, DatagramIterator &iterator) const {
|
||||||
int num_fields = iterator.get_uint16();
|
int num_fields = iterator.get_uint16();
|
||||||
for (int i = 0; i < num_fields; i++) {
|
for (int i = 0; i < num_fields && !PyErr_Occurred(); i++) {
|
||||||
receive_update(distobj, iterator);
|
receive_update(distobj, iterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,10 +79,17 @@ bool DCField::
|
|||||||
pack_args(Datagram &datagram, PyObject *sequence) const {
|
pack_args(Datagram &datagram, PyObject *sequence) const {
|
||||||
nassertr(PySequence_Check(sequence), false);
|
nassertr(PySequence_Check(sequence), false);
|
||||||
DCPacker packer;
|
DCPacker packer;
|
||||||
packer.begin(this);
|
packer.begin_pack(this);
|
||||||
packer.pack_object(sequence);
|
packer.pack_object(sequence);
|
||||||
if (packer.end()) {
|
if (packer.end_pack()) {
|
||||||
datagram.append_data(packer.get_data(), packer.get_length());
|
datagram.append_data(packer.get_data(), packer.get_length());
|
||||||
|
|
||||||
|
/*
|
||||||
|
PyObject *str = PyObject_Str(sequence);
|
||||||
|
cerr << "pack " << get_name() << PyString_AsString(str) << "\n";
|
||||||
|
Py_DECREF(str);
|
||||||
|
*/
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,16 +120,29 @@ pack_args(Datagram &datagram, PyObject *sequence) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PyObject *DCField::
|
PyObject *DCField::
|
||||||
unpack_args(DatagramIterator &iterator) const {
|
unpack_args(DatagramIterator &iterator) const {
|
||||||
pvector<PyObject *> args;
|
DCPacker packer;
|
||||||
bool enough_data = do_unpack_args(args, iterator);
|
packer.begin_unpack(iterator.get_remaining_bytes(), this);
|
||||||
nassertr(enough_data, NULL);
|
|
||||||
|
|
||||||
PyObject *tuple = PyTuple_New(args.size());
|
PyObject *object = packer.unpack_object();
|
||||||
for (size_t i = 0; i < args.size(); i++) {
|
|
||||||
PyTuple_SET_ITEM(tuple, i, args[i]);
|
if (packer.end_unpack()) {
|
||||||
|
// Successfully unpacked.
|
||||||
|
iterator.skip_bytes(packer.get_num_unpacked_bytes());
|
||||||
|
|
||||||
|
/*
|
||||||
|
PyObject *str = PyObject_Str(object);
|
||||||
|
cerr << "recv " << get_name() << PyString_AsString(str) << "\n";
|
||||||
|
Py_DECREF(str);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tuple;
|
ostringstream strm;
|
||||||
|
strm << "Error unpacking field " << get_name();
|
||||||
|
|
||||||
|
nassert_raise(strm.str());
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
@ -146,6 +166,7 @@ receive_update(PyObject *distobj, DatagramIterator &iterator) const {
|
|||||||
Py_XDECREF(result);
|
Py_XDECREF(result);
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
}
|
}
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
@ -225,3 +246,27 @@ generate_hash(HashGenerator &hashgen) const {
|
|||||||
// redundant. However, the field name is significant.
|
// redundant. However, the field name is significant.
|
||||||
hashgen.add_string(_name);
|
hashgen.add_string(_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCField::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 DCField::
|
||||||
|
has_nested_fields() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCField::get_pack_type
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Returns the type of value expected by this field.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
DCPackType DCField::
|
||||||
|
get_pack_type() const {
|
||||||
|
return PT_field;
|
||||||
|
}
|
||||||
|
@ -66,15 +66,13 @@ public:
|
|||||||
virtual void write(ostream &out, bool brief, int indent_level) const=0;
|
virtual void write(ostream &out, bool brief, int indent_level) const=0;
|
||||||
virtual void generate_hash(HashGenerator &hash) const;
|
virtual void generate_hash(HashGenerator &hash) const;
|
||||||
|
|
||||||
|
virtual bool has_nested_fields() const;
|
||||||
|
virtual DCPackType get_pack_type() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _number;
|
int _number;
|
||||||
string _name;
|
string _name;
|
||||||
|
|
||||||
public:
|
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
virtual bool do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const=0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
friend class DCClass;
|
friend class DCClass;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,20 +132,6 @@ generate_hash(HashGenerator &hashgen) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: DCMolecularField::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 DCMolecularField::
|
|
||||||
has_nested_fields() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCMolecularField::get_num_nested_fields
|
// Function: DCMolecularField::get_num_nested_fields
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -172,26 +158,3 @@ get_nested_field(int n) const {
|
|||||||
nassertr(n >= 0 && n < (int)_nested_fields.size(), NULL);
|
nassertr(n >= 0 && n < (int)_nested_fields.size(), NULL);
|
||||||
return _nested_fields[n];
|
return _nested_fields[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: DCMolecularField::do_unpack_args
|
|
||||||
// Access: Public, Virtual
|
|
||||||
// Description: Unpacks the values from the datagram, beginning at
|
|
||||||
// the current point in the interator, into a vector of
|
|
||||||
// Python objects (each with its own reference count).
|
|
||||||
// Returns true if there are enough values in the
|
|
||||||
// datagram, false otherwise.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool DCMolecularField::
|
|
||||||
do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const {
|
|
||||||
Fields::const_iterator fi;
|
|
||||||
for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
|
|
||||||
if (!(*fi)->do_unpack_args(args, iterator)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // HAVE_PYTHON
|
|
||||||
|
@ -46,15 +46,9 @@ public:
|
|||||||
virtual void write(ostream &out, bool brief, int indent_level) const;
|
virtual void write(ostream &out, bool brief, int indent_level) const;
|
||||||
virtual void generate_hash(HashGenerator &hash) const;
|
virtual void generate_hash(HashGenerator &hash) const;
|
||||||
|
|
||||||
virtual bool has_nested_fields() const;
|
|
||||||
virtual int get_num_nested_fields() const;
|
virtual int get_num_nested_fields() const;
|
||||||
virtual DCPackerInterface *get_nested_field(int n) const;
|
virtual DCPackerInterface *get_nested_field(int n) const;
|
||||||
|
|
||||||
public:
|
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
virtual bool do_unpack_args(pvector<PyObject *> &args, DatagramIterator &iterator) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// These members define the primary interface to the molecular field
|
// These members define the primary interface to the molecular field
|
||||||
// definition as read from the file.
|
// definition as read from the file.
|
||||||
|
@ -51,18 +51,35 @@ get_num_nested_fields() const {
|
|||||||
return _num_nested_fields;
|
return _num_nested_fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::more_nested_fields
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if there are more nested fields to pack
|
||||||
|
// or unpack in the current push sequence, false if it
|
||||||
|
// is time to call pop().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool DCPacker::
|
||||||
|
more_nested_fields() const {
|
||||||
|
return (_current_field != (DCPackerInterface *)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPacker::get_pack_type
|
// Function: DCPacker::get_pack_type
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Returns the type of value expected by the current
|
// Description: Returns the type of value expected by the current
|
||||||
// field, or ST_invalid if it is not correct to call
|
// field. See the enumerated type definition at the top
|
||||||
// pack_value() at this point (e.g. the current field is
|
// of DCPackerInterface.h. If this returns one of
|
||||||
// an array, not the element of an array).
|
// PT_double, PT_int, PT_int64, or PT_string, then you
|
||||||
|
// should call the corresponding pack_double(),
|
||||||
|
// pack_int() function (or unpack_double(),
|
||||||
|
// unpack_int(), etc.) to transfer data. Otherwise, you
|
||||||
|
// should call push() and begin packing or unpacking the
|
||||||
|
// nested fields.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE DCSubatomicType DCPacker::
|
INLINE DCPackType DCPacker::
|
||||||
get_pack_type() const {
|
get_pack_type() const {
|
||||||
if (_current_field == NULL) {
|
if (_current_field == NULL) {
|
||||||
return ST_invalid;
|
return PT_invalid;
|
||||||
} else {
|
} else {
|
||||||
return _current_field->get_pack_type();
|
return _current_field->get_pack_type();
|
||||||
}
|
}
|
||||||
@ -76,6 +93,7 @@ get_pack_type() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void DCPacker::
|
INLINE void DCPacker::
|
||||||
pack_double(double value) {
|
pack_double(double value) {
|
||||||
|
nassertv(_mode == M_pack);
|
||||||
if (_current_field == NULL) {
|
if (_current_field == NULL) {
|
||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
} else {
|
} else {
|
||||||
@ -94,6 +112,7 @@ pack_double(double value) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void DCPacker::
|
INLINE void DCPacker::
|
||||||
pack_int(int value) {
|
pack_int(int value) {
|
||||||
|
nassertv(_mode == M_pack);
|
||||||
if (_current_field == NULL) {
|
if (_current_field == NULL) {
|
||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
} else {
|
} else {
|
||||||
@ -112,6 +131,7 @@ pack_int(int value) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void DCPacker::
|
INLINE void DCPacker::
|
||||||
pack_int64(PN_int64 value) {
|
pack_int64(PN_int64 value) {
|
||||||
|
nassertv(_mode == M_pack);
|
||||||
if (_current_field == NULL) {
|
if (_current_field == NULL) {
|
||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
} else {
|
} else {
|
||||||
@ -130,6 +150,7 @@ pack_int64(PN_int64 value) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void DCPacker::
|
INLINE void DCPacker::
|
||||||
pack_string(const string &value) {
|
pack_string(const string &value) {
|
||||||
|
nassertv(_mode == M_pack);
|
||||||
if (_current_field == NULL) {
|
if (_current_field == NULL) {
|
||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
} else {
|
} else {
|
||||||
@ -149,6 +170,7 @@ pack_string(const string &value) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void DCPacker::
|
INLINE void DCPacker::
|
||||||
pack_literal_value(const string &value) {
|
pack_literal_value(const string &value) {
|
||||||
|
nassertv(_mode == M_pack);
|
||||||
if (_current_field == NULL) {
|
if (_current_field == NULL) {
|
||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
} else {
|
} else {
|
||||||
@ -157,6 +179,98 @@ pack_literal_value(const string &value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::unpack_double
|
||||||
|
// Access: Published
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE double DCPacker::
|
||||||
|
unpack_double() {
|
||||||
|
double value = 0.0;
|
||||||
|
nassertr(_mode == M_unpack, value);
|
||||||
|
if (_current_field == NULL) {
|
||||||
|
_pack_error = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (!_current_field->unpack_double(_unpack_data, _unpack_length, _unpack_p, value)) {
|
||||||
|
_pack_error = true;
|
||||||
|
}
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::unpack_int
|
||||||
|
// Access: Published
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE int DCPacker::
|
||||||
|
unpack_int() {
|
||||||
|
int value = 0;
|
||||||
|
nassertr(_mode == M_unpack, value);
|
||||||
|
if (_current_field == NULL) {
|
||||||
|
_pack_error = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (!_current_field->unpack_int(_unpack_data, _unpack_length, _unpack_p, value)) {
|
||||||
|
_pack_error = true;
|
||||||
|
}
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::unpack_int64
|
||||||
|
// Access: Published
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE PN_int64 DCPacker::
|
||||||
|
unpack_int64() {
|
||||||
|
PN_int64 value = 0;
|
||||||
|
nassertr(_mode == M_unpack, value);
|
||||||
|
if (_current_field == NULL) {
|
||||||
|
_pack_error = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (!_current_field->unpack_int64(_unpack_data, _unpack_length, _unpack_p, value)) {
|
||||||
|
_pack_error = true;
|
||||||
|
}
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::unpack_string
|
||||||
|
// Access: Published
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE string DCPacker::
|
||||||
|
unpack_string() {
|
||||||
|
string value;
|
||||||
|
nassertr(_mode == M_unpack, value);
|
||||||
|
if (_current_field == NULL) {
|
||||||
|
_pack_error = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (!_current_field->unpack_string(_unpack_data, _unpack_length, _unpack_p, value)) {
|
||||||
|
_pack_error = true;
|
||||||
|
}
|
||||||
|
advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPacker::had_pack_error
|
// Function: DCPacker::had_pack_error
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -170,6 +284,21 @@ had_pack_error() const {
|
|||||||
return _pack_error;
|
return _pack_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::get_num_unpacked_bytes
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the number of bytes that have been unpacked
|
||||||
|
// so far, or after unpack_end(), the total number of
|
||||||
|
// bytes that were unpacked at all. This can be used to
|
||||||
|
// validate that all of the bytes in the buffer were
|
||||||
|
// actually unpacked (which is not otherwise considered
|
||||||
|
// an error).
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE size_t DCPacker::
|
||||||
|
get_num_unpacked_bytes() const {
|
||||||
|
return _unpack_p;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPacker::get_string
|
// Function: DCPacker::get_string
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -222,6 +351,12 @@ advance() {
|
|||||||
// call pop().
|
// call pop().
|
||||||
_current_field = NULL;
|
_current_field = NULL;
|
||||||
|
|
||||||
|
} else if (_mode == M_unpack && _push_marker != 0 &&
|
||||||
|
_unpack_p >= _push_marker) {
|
||||||
|
// Done with all the fields on this parent. The caller must now
|
||||||
|
// call pop().
|
||||||
|
_current_field = NULL;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// We have another field to advance to.
|
// We have another field to advance to.
|
||||||
_current_field = _current_parent->get_nested_field(_current_field_index);
|
_current_field = _current_parent->get_nested_field(_current_field_index);
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
DCPacker::
|
DCPacker::
|
||||||
DCPacker() {
|
DCPacker() {
|
||||||
|
_mode = M_idle;
|
||||||
|
_unpack_data = NULL;
|
||||||
|
_unpack_length = 0;
|
||||||
|
_unpack_p = 0;
|
||||||
_current_field = NULL;
|
_current_field = NULL;
|
||||||
_current_parent = NULL;
|
_current_parent = NULL;
|
||||||
_current_field_index = 0;
|
_current_field_index = 0;
|
||||||
@ -42,19 +46,17 @@ DCPacker::
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPacker::begin
|
// Function: DCPacker::begin_pack
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Begins a packing session. The parameter is the DC
|
// Description: Begins a packing session. The parameter is the DC
|
||||||
// object that describes the packing format; it may be a
|
// object that describes the packing format; it may be a
|
||||||
// DCType or DCField.
|
// DCType or DCField.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void DCPacker::
|
void DCPacker::
|
||||||
begin(const DCPackerInterface *root) {
|
begin_pack(const DCPackerInterface *root) {
|
||||||
// If this assertion fails, we didn't match begin() up with end().
|
nassertv(_mode == M_idle);
|
||||||
nassertv(_stack.empty() &&
|
|
||||||
_current_field == NULL &&
|
|
||||||
_current_parent == NULL);
|
|
||||||
|
|
||||||
|
_mode = M_pack;
|
||||||
_pack_error = false;
|
_pack_error = false;
|
||||||
_pack_data.clear();
|
_pack_data.clear();
|
||||||
|
|
||||||
@ -66,7 +68,7 @@ begin(const DCPackerInterface *root) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPacker::end
|
// Function: DCPacker::end_pack
|
||||||
// Access: Published, Virtual
|
// Access: Published, Virtual
|
||||||
// Description: Finishes a packing session.
|
// Description: Finishes a packing session.
|
||||||
//
|
//
|
||||||
@ -74,7 +76,76 @@ begin(const DCPackerInterface *root) {
|
|||||||
// there has been some error during packing.
|
// there has been some error during packing.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool DCPacker::
|
bool DCPacker::
|
||||||
end() {
|
end_pack() {
|
||||||
|
nassertr(_mode == M_pack, false);
|
||||||
|
|
||||||
|
_mode = M_idle;
|
||||||
|
|
||||||
|
if (!_stack.empty() || _current_field != NULL || _current_parent != NULL) {
|
||||||
|
_pack_error = true;
|
||||||
|
_stack.clear();
|
||||||
|
_current_field = NULL;
|
||||||
|
_current_parent = NULL;
|
||||||
|
_current_field_index = 0;
|
||||||
|
_num_nested_fields = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !_pack_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::begin_unpack
|
||||||
|
// Access: Published
|
||||||
|
// Description: Begins an unpacking session. Unlike the other
|
||||||
|
// version of begin_unpack(), this version makes a copy
|
||||||
|
// of the data string.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void DCPacker::
|
||||||
|
begin_unpack(const string &data, const DCPackerInterface *root) {
|
||||||
|
_unpack_str = data;
|
||||||
|
begin_unpack(data.data(), data.length(), root);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::begin_unpack
|
||||||
|
// Access: Public
|
||||||
|
// Description: Begins an unpacking session. The data pointer is
|
||||||
|
// used directly; the data buffer is not copied.
|
||||||
|
// Therefore, you must not delete or modify the data
|
||||||
|
// pointer until you call end_unpack().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void DCPacker::
|
||||||
|
begin_unpack(const char *data, size_t length,
|
||||||
|
const DCPackerInterface *root) {
|
||||||
|
nassertv(_mode == M_idle);
|
||||||
|
|
||||||
|
_mode = M_unpack;
|
||||||
|
_pack_error = false;
|
||||||
|
_unpack_data = data;
|
||||||
|
_unpack_length = length;
|
||||||
|
_unpack_p = 0;
|
||||||
|
|
||||||
|
_stack.clear();
|
||||||
|
_current_field = root;
|
||||||
|
_current_parent = NULL;
|
||||||
|
_current_field_index = 0;
|
||||||
|
_num_nested_fields = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::end_unpack
|
||||||
|
// Access: Published
|
||||||
|
// Description: Finishes the unpacking session.
|
||||||
|
//
|
||||||
|
// The return value is true on success, or false if
|
||||||
|
// there has been some error during unpacking.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool DCPacker::
|
||||||
|
end_unpack() {
|
||||||
|
nassertr(_mode == M_unpack, false);
|
||||||
|
|
||||||
|
_mode = M_idle;
|
||||||
|
|
||||||
if (!_stack.empty() || _current_field != NULL || _current_parent != NULL) {
|
if (!_stack.empty() || _current_field != NULL || _current_parent != NULL) {
|
||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
_stack.clear();
|
_stack.clear();
|
||||||
@ -105,14 +176,59 @@ push() {
|
|||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int num_nested_fields = _current_field->get_num_nested_fields();
|
|
||||||
StackElement element;
|
StackElement element;
|
||||||
element._current_parent = _current_parent;
|
element._current_parent = _current_parent;
|
||||||
element._current_field_index = _current_field_index;
|
element._current_field_index = _current_field_index;
|
||||||
element._push_start = _push_start;
|
element._push_marker = _push_marker;
|
||||||
_stack.push_back(element);
|
_stack.push_back(element);
|
||||||
|
|
||||||
_current_parent = _current_field;
|
_current_parent = _current_field;
|
||||||
|
|
||||||
|
|
||||||
|
// Now deal with the length prefix that might or might not be
|
||||||
|
// before a sequence of nested fields.
|
||||||
|
int num_nested_fields = _current_parent->get_num_nested_fields();
|
||||||
|
size_t length_bytes = _current_parent->get_length_bytes();
|
||||||
|
|
||||||
|
if (_mode == M_pack) {
|
||||||
|
// Reserve length_bytes for when we figure out what the length
|
||||||
|
// is.
|
||||||
|
_push_marker = _pack_data.get_length();
|
||||||
|
_pack_data.append_junk(length_bytes);
|
||||||
|
|
||||||
|
} else { // _mode == M_unpack
|
||||||
|
// Read length_bytes to determine the end of this nested
|
||||||
|
// sequence.
|
||||||
|
_push_marker = 0;
|
||||||
|
|
||||||
|
if (length_bytes != 0) {
|
||||||
|
if (_unpack_p + length_bytes > _unpack_length) {
|
||||||
|
_pack_error = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
size_t length;
|
||||||
|
if (length_bytes == 4) {
|
||||||
|
length = ((size_t)(unsigned char)_unpack_data[_unpack_p + 0] |
|
||||||
|
((size_t)(unsigned char)_unpack_data[_unpack_p + 1] << 8) |
|
||||||
|
((size_t)(unsigned char)_unpack_data[_unpack_p + 2] << 16) |
|
||||||
|
((size_t)(unsigned char)_unpack_data[_unpack_p + 3] << 24));
|
||||||
|
_unpack_p += 4;
|
||||||
|
_push_marker = _unpack_p + length;
|
||||||
|
} else {
|
||||||
|
length = ((size_t)(unsigned char)_unpack_data[_unpack_p + 0] |
|
||||||
|
((size_t)(unsigned char)_unpack_data[_unpack_p + 1] << 8));
|
||||||
|
_unpack_p += 2;
|
||||||
|
}
|
||||||
|
_push_marker = _unpack_p + length;
|
||||||
|
|
||||||
|
// The explicit length trumps the number of nested fields
|
||||||
|
// reported by get_num_nested_fields().
|
||||||
|
num_nested_fields = _current_parent->get_num_nested_fields(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now point to the first field in the nested range.
|
||||||
_num_nested_fields = num_nested_fields;
|
_num_nested_fields = num_nested_fields;
|
||||||
_current_field_index = 0;
|
_current_field_index = 0;
|
||||||
|
|
||||||
@ -124,11 +240,6 @@ push() {
|
|||||||
_current_field = _current_parent->get_nested_field(_current_field_index);
|
_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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +256,12 @@ push() {
|
|||||||
void DCPacker::
|
void DCPacker::
|
||||||
pop() {
|
pop() {
|
||||||
if (_current_field != NULL && _num_nested_fields >= 0) {
|
if (_current_field != NULL && _num_nested_fields >= 0) {
|
||||||
// Oops, didn't pack enough values.
|
// Oops, didn't pack or unpack enough values.
|
||||||
|
_pack_error = true;
|
||||||
|
|
||||||
|
} else if (_mode == M_unpack && _push_marker != 0 &&
|
||||||
|
_unpack_p != _push_marker) {
|
||||||
|
// Didn't unpack the right number of values.
|
||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,28 +270,30 @@ pop() {
|
|||||||
_pack_error = true;
|
_pack_error = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (_mode == M_pack) {
|
||||||
size_t length_bytes = _current_parent->get_length_bytes();
|
size_t length_bytes = _current_parent->get_length_bytes();
|
||||||
if (length_bytes != 0) {
|
if (length_bytes != 0) {
|
||||||
// Now go back and fill in the length of the array.
|
// Now go back and fill in the length of the array.
|
||||||
char buffer[4];
|
char buffer[4];
|
||||||
size_t length = _pack_data.get_length() - _push_start - length_bytes;
|
size_t length = _pack_data.get_length() - _push_marker - length_bytes;
|
||||||
if (length_bytes == 4) {
|
if (length_bytes == 4) {
|
||||||
buffer[0] = (char)(length & 0xff);
|
buffer[0] = (char)(length & 0xff);
|
||||||
buffer[1] = (char)((length >> 8) & 0xff);
|
buffer[1] = (char)((length >> 8) & 0xff);
|
||||||
buffer[2] = (char)((length >> 16) & 0xff);
|
buffer[2] = (char)((length >> 16) & 0xff);
|
||||||
buffer[3] = (char)((length >> 24) & 0xff);
|
buffer[3] = (char)((length >> 24) & 0xff);
|
||||||
_pack_data.rewrite_data(_push_start, buffer, 4);
|
_pack_data.rewrite_data(_push_marker, buffer, 4);
|
||||||
} else {
|
} else {
|
||||||
buffer[0] = (char)(length & 0xff);
|
buffer[0] = (char)(length & 0xff);
|
||||||
buffer[1] = (char)((length >> 8) & 0xff);
|
buffer[1] = (char)((length >> 8) & 0xff);
|
||||||
_pack_data.rewrite_data(_push_start, buffer, 2);
|
_pack_data.rewrite_data(_push_marker, buffer, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_current_field = _current_parent;
|
_current_field = _current_parent;
|
||||||
_current_parent = _stack.back()._current_parent;
|
_current_parent = _stack.back()._current_parent;
|
||||||
_current_field_index = _stack.back()._current_field_index;
|
_current_field_index = _stack.back()._current_field_index;
|
||||||
_push_start = _stack.back()._push_start;
|
_push_marker = _stack.back()._push_marker;
|
||||||
_num_nested_fields = (_current_parent == NULL) ? 0 : _current_parent->get_num_nested_fields();
|
_num_nested_fields = (_current_parent == NULL) ? 0 : _current_parent->get_num_nested_fields();
|
||||||
_stack.pop_back();
|
_stack.pop_back();
|
||||||
}
|
}
|
||||||
@ -195,6 +313,7 @@ pop() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void DCPacker::
|
void DCPacker::
|
||||||
pack_object(PyObject *object) {
|
pack_object(PyObject *object) {
|
||||||
|
nassertv(_mode == M_pack);
|
||||||
PyObject *str = PyObject_Str(object);
|
PyObject *str = PyObject_Str(object);
|
||||||
Py_DECREF(str);
|
Py_DECREF(str);
|
||||||
|
|
||||||
@ -227,3 +346,76 @@ pack_object(PyObject *object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPacker::unpack_object
|
||||||
|
// Access: Published
|
||||||
|
// Description: Unpacks a Python object of the appropriate type from
|
||||||
|
// the stream for the current field. This may be an
|
||||||
|
// integer or a string for a simple field object; if the
|
||||||
|
// current field represents a list of fields it will be
|
||||||
|
// a tuple.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PyObject *DCPacker::
|
||||||
|
unpack_object() {
|
||||||
|
PyObject *object = NULL;
|
||||||
|
|
||||||
|
DCPackType pack_type = get_pack_type();
|
||||||
|
|
||||||
|
switch (pack_type) {
|
||||||
|
case PT_double:
|
||||||
|
{
|
||||||
|
double value = unpack_double();
|
||||||
|
object = PyFloat_FromDouble(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PT_int:
|
||||||
|
{
|
||||||
|
int value = unpack_int();
|
||||||
|
object = PyInt_FromLong(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PT_int64:
|
||||||
|
{
|
||||||
|
PN_int64 value = unpack_int64();
|
||||||
|
object = PyLong_FromLongLong(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PT_string:
|
||||||
|
{
|
||||||
|
string str = unpack_string();
|
||||||
|
object = PyString_FromStringAndSize(str.data(), str.size());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// First, build up a list from the nested objects.
|
||||||
|
object = PyList_New(0);
|
||||||
|
|
||||||
|
push();
|
||||||
|
while (more_nested_fields()) {
|
||||||
|
PyObject *element = unpack_object();
|
||||||
|
PyList_Append(object, element);
|
||||||
|
Py_DECREF(element);
|
||||||
|
}
|
||||||
|
pop();
|
||||||
|
|
||||||
|
if (pack_type != PT_array) {
|
||||||
|
// For these other kinds of objects, we'll convert the list
|
||||||
|
// into a tuple.
|
||||||
|
PyObject *tuple = PyList_AsTuple(object);
|
||||||
|
Py_DECREF(object);
|
||||||
|
object = tuple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
@ -35,26 +35,42 @@ PUBLISHED:
|
|||||||
DCPacker();
|
DCPacker();
|
||||||
~DCPacker();
|
~DCPacker();
|
||||||
|
|
||||||
void begin(const DCPackerInterface *root);
|
void begin_pack(const DCPackerInterface *root);
|
||||||
bool end();
|
bool end_pack();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void begin_unpack(const char *data, size_t length,
|
||||||
|
const DCPackerInterface *root);
|
||||||
|
PUBLISHED:
|
||||||
|
void begin_unpack(const string &data, const DCPackerInterface *root);
|
||||||
|
bool end_unpack();
|
||||||
|
|
||||||
INLINE bool has_nested_fields() const;
|
INLINE bool has_nested_fields() const;
|
||||||
INLINE int get_num_nested_fields() const;
|
INLINE int get_num_nested_fields() const;
|
||||||
|
INLINE bool more_nested_fields() const;
|
||||||
|
|
||||||
void push();
|
void push();
|
||||||
void pop();
|
void pop();
|
||||||
|
|
||||||
INLINE DCSubatomicType get_pack_type() const;
|
INLINE DCPackType get_pack_type() const;
|
||||||
INLINE void pack_double(double value);
|
INLINE void pack_double(double value);
|
||||||
INLINE void pack_int(int value);
|
INLINE void pack_int(int value);
|
||||||
INLINE void pack_int64(PN_int64 value);
|
INLINE void pack_int64(PN_int64 value);
|
||||||
INLINE void pack_string(const string &value);
|
INLINE void pack_string(const string &value);
|
||||||
INLINE void pack_literal_value(const string &value);
|
INLINE void pack_literal_value(const string &value);
|
||||||
|
|
||||||
|
INLINE double unpack_double();
|
||||||
|
INLINE int unpack_int();
|
||||||
|
INLINE PN_int64 unpack_int64();
|
||||||
|
INLINE string unpack_string();
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
void pack_object(PyObject *object);
|
void pack_object(PyObject *object);
|
||||||
|
PyObject *unpack_object();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
INLINE bool had_pack_error() const;
|
INLINE bool had_pack_error() const;
|
||||||
|
INLINE size_t get_num_unpacked_bytes() const;
|
||||||
|
|
||||||
INLINE string get_string() const;
|
INLINE string get_string() const;
|
||||||
INLINE size_t get_length() const;
|
INLINE size_t get_length() const;
|
||||||
@ -65,13 +81,24 @@ private:
|
|||||||
INLINE void advance();
|
INLINE void advance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum Mode {
|
||||||
|
M_idle,
|
||||||
|
M_pack,
|
||||||
|
M_unpack,
|
||||||
|
};
|
||||||
|
Mode _mode;
|
||||||
|
|
||||||
DCPackData _pack_data;
|
DCPackData _pack_data;
|
||||||
|
string _unpack_str;
|
||||||
|
const char *_unpack_data;
|
||||||
|
size_t _unpack_length;
|
||||||
|
size_t _unpack_p;
|
||||||
|
|
||||||
class StackElement {
|
class StackElement {
|
||||||
public:
|
public:
|
||||||
const DCPackerInterface *_current_parent;
|
const DCPackerInterface *_current_parent;
|
||||||
int _current_field_index;
|
int _current_field_index;
|
||||||
size_t _push_start;
|
size_t _push_marker;
|
||||||
};
|
};
|
||||||
typedef pvector<StackElement> Stack;
|
typedef pvector<StackElement> Stack;
|
||||||
|
|
||||||
@ -79,12 +106,15 @@ private:
|
|||||||
const DCPackerInterface *_current_field;
|
const DCPackerInterface *_current_field;
|
||||||
const DCPackerInterface *_current_parent;
|
const DCPackerInterface *_current_parent;
|
||||||
int _current_field_index;
|
int _current_field_index;
|
||||||
size_t _push_start;
|
|
||||||
|
// In pack mode, _push_marker marks the beginning of the push record
|
||||||
|
// (so we can go back and write in the length later). In unpack
|
||||||
|
// mode, it marks the end of the push record (so we know when we've
|
||||||
|
// reached the end).
|
||||||
|
size_t _push_marker;
|
||||||
int _num_nested_fields;
|
int _num_nested_fields;
|
||||||
|
|
||||||
bool _pack_error;
|
bool _pack_error;
|
||||||
|
|
||||||
friend class DCPackerInterface;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "dcPacker.I"
|
#include "dcPacker.I"
|
||||||
|
@ -54,6 +54,21 @@ get_num_nested_fields() const {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPackerInterface::get_num_nested_fields
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: This flavor of get_num_nested_fields is used during
|
||||||
|
// unpacking. It returns the number of nested fields to
|
||||||
|
// expect, given a certain length in bytes (as read from
|
||||||
|
// the get_length_bytes() stored in the stream on the
|
||||||
|
// pack). This will only be called if
|
||||||
|
// get_length_bytes() returns nonzero.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int DCPackerInterface::
|
||||||
|
get_num_nested_fields(size_t length_bytes) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPackerInterface::get_nested_field
|
// Function: DCPackerInterface::get_nested_field
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -84,13 +99,11 @@ get_length_bytes() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DCPackerInterface::get_pack_type
|
// Function: DCPackerInterface::get_pack_type
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
// Description: Returns the type of value expected by this field, or
|
// Description: Returns the type of value expected by this field.
|
||||||
// ST_invalid if this field cannot accept simple value
|
|
||||||
// types.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
DCSubatomicType DCPackerInterface::
|
DCPackType DCPackerInterface::
|
||||||
get_pack_type() const {
|
get_pack_type() const {
|
||||||
return ST_invalid;
|
return PT_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -136,3 +149,47 @@ bool DCPackerInterface::
|
|||||||
pack_string(DCPackData &, const string &) const {
|
pack_string(DCPackData &, const string &) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPackerInterface::unpack_double
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool DCPackerInterface::
|
||||||
|
unpack_double(const char *, size_t, size_t &, double &) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPackerInterface::unpack_int
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool DCPackerInterface::
|
||||||
|
unpack_int(const char *, size_t, size_t &, int &) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPackerInterface::unpack_int64
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool DCPackerInterface::
|
||||||
|
unpack_int64(const char *, size_t, size_t &, PN_int64 &) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DCPackerInterface::unpack_string
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: Unpacks the current numeric or string value from the
|
||||||
|
// stream. Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool DCPackerInterface::
|
||||||
|
unpack_string(const char *, size_t, size_t &, string &) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -24,6 +24,30 @@
|
|||||||
|
|
||||||
class DCPackData;
|
class DCPackData;
|
||||||
|
|
||||||
|
BEGIN_PUBLISH
|
||||||
|
// This enumerated type is returned by get_pack_type() and represents
|
||||||
|
// the best choice for a subsequent call to pack_*() or unpack_*().
|
||||||
|
enum DCPackType {
|
||||||
|
// This one should never be returned in a normal situation.
|
||||||
|
PT_invalid,
|
||||||
|
|
||||||
|
// These PackTypes are all fundamental types, and should be packed
|
||||||
|
// (or unpacked) with the corresponding call to pack_double(),
|
||||||
|
// pack_int(), etc.
|
||||||
|
PT_double,
|
||||||
|
PT_int,
|
||||||
|
PT_int64,
|
||||||
|
PT_string,
|
||||||
|
|
||||||
|
// The remaining PackTypes imply a need to call push() and pop().
|
||||||
|
// They are all variants on the same thing: a list of nested fields,
|
||||||
|
// but the PackType provides a bit of a semantic context.
|
||||||
|
PT_array,
|
||||||
|
PT_field,
|
||||||
|
PT_struct,
|
||||||
|
};
|
||||||
|
END_PUBLISH
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : DCPackerInterface
|
// Class : DCPackerInterface
|
||||||
// Description : This defines the internal interface for packing
|
// Description : This defines the internal interface for packing
|
||||||
@ -40,14 +64,20 @@ public:
|
|||||||
|
|
||||||
virtual bool has_nested_fields() const;
|
virtual bool has_nested_fields() const;
|
||||||
virtual int get_num_nested_fields() const;
|
virtual int get_num_nested_fields() const;
|
||||||
|
virtual int get_num_nested_fields(size_t length_bytes) const;
|
||||||
virtual DCPackerInterface *get_nested_field(int n) const;
|
virtual DCPackerInterface *get_nested_field(int n) const;
|
||||||
virtual size_t get_length_bytes() const;
|
virtual size_t get_length_bytes() const;
|
||||||
|
|
||||||
virtual DCSubatomicType get_pack_type() const;
|
virtual DCPackType get_pack_type() const;
|
||||||
virtual bool pack_double(DCPackData &pack_data, double 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_int(DCPackData &pack_data, int value) const;
|
||||||
virtual bool pack_int64(DCPackData &pack_data, PN_int64 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 bool pack_string(DCPackData &pack_data, const string &value) const;
|
||||||
|
|
||||||
|
virtual bool unpack_double(const char *data, size_t length, size_t &p, double &value) const;
|
||||||
|
virtual bool unpack_int(const char *data, size_t length, size_t &p, int &value) const;
|
||||||
|
virtual bool unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value) const;
|
||||||
|
virtual bool unpack_string(const char *data, size_t length, size_t &p, string &value) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1182,13 +1182,13 @@ case 38:
|
|||||||
case 39:
|
case 39:
|
||||||
#line 271 "dcParser.yxx"
|
#line 271 "dcParser.yxx"
|
||||||
{
|
{
|
||||||
default_value_packer.begin(atomic_element._type);
|
default_value_packer.begin_pack(atomic_element._type);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 40:
|
case 40:
|
||||||
#line 275 "dcParser.yxx"
|
#line 275 "dcParser.yxx"
|
||||||
{
|
{
|
||||||
if (!default_value_packer.end()) {
|
if (!default_value_packer.end_pack()) {
|
||||||
yyerror("Invalid default value for type");
|
yyerror("Invalid default value for type");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -269,11 +269,11 @@ atomic_element_definition:
|
|||||||
}
|
}
|
||||||
| atomic_element_definition '='
|
| atomic_element_definition '='
|
||||||
{
|
{
|
||||||
default_value_packer.begin(atomic_element._type);
|
default_value_packer.begin_pack(atomic_element._type);
|
||||||
}
|
}
|
||||||
default_value
|
default_value
|
||||||
{
|
{
|
||||||
if (!default_value_packer.end()) {
|
if (!default_value_packer.end_pack()) {
|
||||||
yyerror("Invalid default value for type");
|
yyerror("Invalid default value for type");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -47,15 +47,21 @@ PUBLISHED:
|
|||||||
public:
|
public:
|
||||||
virtual bool has_nested_fields() const;
|
virtual bool has_nested_fields() const;
|
||||||
virtual int get_num_nested_fields() const;
|
virtual int get_num_nested_fields() const;
|
||||||
|
virtual int get_num_nested_fields(size_t length_bytes) const;
|
||||||
virtual DCPackerInterface *get_nested_field(int n) const;
|
virtual DCPackerInterface *get_nested_field(int n) const;
|
||||||
virtual size_t get_length_bytes() const;
|
virtual size_t get_length_bytes() const;
|
||||||
|
|
||||||
virtual DCSubatomicType get_pack_type() const;
|
virtual DCPackType get_pack_type() const;
|
||||||
virtual bool pack_double(DCPackData &pack_data, double 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_int(DCPackData &pack_data, int value) const;
|
||||||
virtual bool pack_int64(DCPackData &pack_data, PN_int64 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 bool pack_string(DCPackData &pack_data, const string &value) const;
|
||||||
|
|
||||||
|
virtual bool unpack_double(const char *data, size_t length, size_t &p, double &value) const;
|
||||||
|
virtual bool unpack_int(const char *data, size_t length, size_t &p, int &value) const;
|
||||||
|
virtual bool unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value) const;
|
||||||
|
virtual bool unpack_string(const char *data, size_t length, size_t &p, string &value) const;
|
||||||
|
|
||||||
virtual void output(ostream &out, const string ¶meter_name,
|
virtual void output(ostream &out, const string ¶meter_name,
|
||||||
bool brief) const;
|
bool brief) const;
|
||||||
virtual void generate_hash(HashGenerator &hash) const;
|
virtual void generate_hash(HashGenerator &hash) const;
|
||||||
@ -64,23 +70,15 @@ private:
|
|||||||
static DCSimpleType *create_nested_field(DCSubatomicType type, int divisor);
|
static DCSimpleType *create_nested_field(DCSubatomicType type, int divisor);
|
||||||
static DCPackerInterface *create_uint32uint8_type();
|
static DCPackerInterface *create_uint32uint8_type();
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
public:
|
|
||||||
virtual void pack_arg(Datagram &datagram, PyObject *item) const;
|
|
||||||
virtual PyObject *unpack_arg(DatagramIterator &iterator) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void do_pack_arg(Datagram &datagram, PyObject *item, DCSubatomicType type) const;
|
|
||||||
PyObject *do_unpack_arg(DatagramIterator &iterator, DCSubatomicType type) const;
|
|
||||||
#endif // HAVE_PYTHON
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DCSubatomicType _type;
|
DCSubatomicType _type;
|
||||||
int _divisor;
|
int _divisor;
|
||||||
|
|
||||||
|
DCPackType _pack_type;
|
||||||
bool _is_array;
|
bool _is_array;
|
||||||
DCSubatomicType _nested_type;
|
DCSubatomicType _nested_type;
|
||||||
DCPackerInterface *_nested_field;
|
DCPackerInterface *_nested_field;
|
||||||
|
size_t _bytes_per_element;
|
||||||
|
|
||||||
// The rest of this is to maintain the static list of
|
// The rest of this is to maintain the static list of
|
||||||
// DCPackerInterface objects for _nested_field, above. We allocate
|
// DCPackerInterface objects for _nested_field, above. We allocate
|
||||||
@ -95,6 +93,7 @@ private:
|
|||||||
virtual bool has_nested_fields() const;
|
virtual bool has_nested_fields() const;
|
||||||
virtual int get_num_nested_fields() const;
|
virtual int get_num_nested_fields() const;
|
||||||
virtual DCPackerInterface *get_nested_field(int n) const;
|
virtual DCPackerInterface *get_nested_field(int n) const;
|
||||||
|
virtual DCPackType get_pack_type() const;
|
||||||
|
|
||||||
DCSimpleType *_uint32_type;
|
DCSimpleType *_uint32_type;
|
||||||
DCSimpleType *_uint8_type;
|
DCSimpleType *_uint8_type;
|
||||||
|
@ -70,12 +70,6 @@ public:
|
|||||||
virtual void output(ostream &out, const string ¶meter_name,
|
virtual void output(ostream &out, const string ¶meter_name,
|
||||||
bool brief) const=0;
|
bool brief) const=0;
|
||||||
virtual void generate_hash(HashGenerator &hash) const;
|
virtual void generate_hash(HashGenerator &hash) const;
|
||||||
|
|
||||||
#ifdef HAVE_PYTHON
|
|
||||||
virtual void pack_arg(Datagram &datagram, PyObject *item) const=0;
|
|
||||||
virtual PyObject *unpack_arg(DatagramIterator &iterator) const=0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user