allow serial pack/unpack sessions

This commit is contained in:
David Rose 2004-06-25 21:22:16 +00:00
parent 6845758d2b
commit 4b15c13cc0
11 changed files with 701 additions and 167 deletions

View File

@ -459,7 +459,8 @@ output(ostream &out, bool brief) const {
if (!brief && _has_default_value) {
out << " = ";
DCPacker packer;
packer.begin_unpack(_default_value, _param);
packer.set_unpack_data(_default_value);
packer.begin_unpack(_param);
packer.unpack_and_format(out);
packer.end_unpack();
}

View File

@ -275,16 +275,21 @@ get_class_def() const {
////////////////////////////////////////////////////////////////////
// Function: DCClass::receive_update
// Access: Published
// Description: Extracts the update message out of the datagram and
// Description: Extracts the update message out of the packer and
// applies it to the indicated object by calling the
// appropriate method.
////////////////////////////////////////////////////////////////////
void DCClass::
receive_update(PyObject *distobj, DatagramIterator &iterator) const {
int field_id = iterator.get_uint16();
receive_update(PyObject *distobj, DatagramIterator &di) const {
DCPacker packer;
packer.set_unpack_data(di.get_remaining_bytes());
int field_id = packer.raw_unpack_uint16();
DCField *field = get_inherited_field(field_id);
nassertv_always(field != NULL);
field->receive_update(distobj, iterator);
field->receive_update(packer, distobj);
di.skip_bytes(packer.get_num_unpacked_bytes());
}
#endif // HAVE_PYTHON
@ -298,16 +303,21 @@ receive_update(PyObject *distobj, DatagramIterator &iterator) const {
// atomic fields that are marked "broadcast required".
////////////////////////////////////////////////////////////////////
void DCClass::
receive_update_broadcast_required(PyObject *distobj, DatagramIterator &iterator) const {
receive_update_broadcast_required(PyObject *distobj, DatagramIterator &di) const {
DCPacker packer;
packer.set_unpack_data(di.get_remaining_bytes());
int num_fields = get_num_inherited_fields();
for (int i = 0; i < num_fields && !PyErr_Occurred(); i++) {
DCField *field = get_inherited_field(i);
DCAtomicField *atom = field->as_atomic_field();
if (atom != (DCAtomicField *)NULL &&
atom->is_required() && atom->is_broadcast()) {
atom->receive_update(distobj, iterator);
atom->receive_update(packer, distobj);
}
}
di.skip_bytes(packer.get_num_unpacked_bytes());
}
#endif // HAVE_PYTHON
@ -321,15 +331,20 @@ receive_update_broadcast_required(PyObject *distobj, DatagramIterator &iterator)
// marked "required", whether they are broadcast or not.
////////////////////////////////////////////////////////////////////
void DCClass::
receive_update_all_required(PyObject *distobj, DatagramIterator &iterator) const {
receive_update_all_required(PyObject *distobj, DatagramIterator &di) const {
DCPacker packer;
packer.set_unpack_data(di.get_remaining_bytes());
int num_fields = get_num_inherited_fields();
for (int i = 0; i < num_fields && !PyErr_Occurred(); i++) {
DCField *field = get_inherited_field(i);
DCAtomicField *atom = field->as_atomic_field();
if (atom != (DCAtomicField *)NULL && atom->is_required()) {
atom->receive_update(distobj, iterator);
atom->receive_update(packer, distobj);
}
}
di.skip_bytes(packer.get_num_unpacked_bytes());
}
#endif // HAVE_PYTHON
@ -341,10 +356,10 @@ receive_update_all_required(PyObject *distobj, DatagramIterator &iterator) const
// fields that are broadcast in one chunk.
////////////////////////////////////////////////////////////////////
void DCClass::
receive_update_other(PyObject *distobj, DatagramIterator &iterator) const {
int num_fields = iterator.get_uint16();
receive_update_other(PyObject *distobj, DatagramIterator &di) const {
int num_fields = di.get_uint16();
for (int i = 0; i < num_fields && !PyErr_Occurred(); i++) {
receive_update(distobj, iterator);
receive_update(distobj, di);
}
}
#endif // HAVE_PYTHON
@ -359,8 +374,12 @@ receive_update_other(PyObject *distobj, DatagramIterator &iterator) const {
void DCClass::
direct_update(PyObject *distobj, const string &field_name,
const string &value_blob) {
Datagram datagram(value_blob);
direct_update(distobj, field_name, datagram);
DCField *field = get_field_by_name(field_name);
nassertv_always(field != NULL);
DCPacker packer;
packer.set_unpack_data(value_blob);
field->receive_update(packer, distobj);
}
#endif // HAVE_PYTHON
@ -374,10 +393,7 @@ direct_update(PyObject *distobj, const string &field_name,
void DCClass::
direct_update(PyObject *distobj, const string &field_name,
const Datagram &datagram) {
DCField *field = get_field_by_name(field_name);
nassertv_always(field != NULL);
DatagramIterator iterator(datagram);
field->receive_update(distobj, iterator);
direct_update(distobj, field_name, datagram.get_message());
}
#endif // HAVE_PYTHON
@ -387,7 +403,7 @@ direct_update(PyObject *distobj, const string &field_name,
// Access: Published
// Description: Looks up the current value of the indicated field by
// calling the appropriate get*() function, then packs
// that value into the datagram. This field is
// that value into the packer. This field is
// presumably either a required field or a specified
// optional field, and we are building up a datagram for
// the generate-with-required message.
@ -395,7 +411,7 @@ direct_update(PyObject *distobj, const string &field_name,
// Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCClass::
pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
pack_required_field(DCPacker &packer, PyObject *distobj, DCField *field) const {
DCAtomicField *atom = field->as_atomic_field();
if (atom == (DCAtomicField *)NULL) {
ostringstream strm;
@ -461,7 +477,7 @@ pack_required_field(Datagram &dg, PyObject *distobj, DCField *field) const {
}
// Now pack the arguments into the datagram.
bool pack_ok = atom->pack_args(dg, result);
bool pack_ok = atom->pack_args(packer, result);
Py_DECREF(result);
return pack_ok;
@ -487,7 +503,10 @@ client_format_update(const string &field_name, int do_id,
nassert_raise(strm.str());
return Datagram();
}
return field->client_format_update(do_id, args);
DCPacker packer;
field->client_format_update(packer, do_id, args);
return Datagram(packer.get_data(), packer.get_length());
}
#endif // HAVE_PYTHON
@ -510,7 +529,10 @@ ai_format_update(const string &field_name, int do_id,
nassert_raise(strm.str());
return Datagram();
}
return field->ai_format_update(do_id, to_id, from_id, args);
DCPacker packer;
field->ai_format_update(packer, do_id, to_id, from_id, args);
return Datagram(packer.get_data(), packer.get_length());
}
#endif // HAVE_PYTHON
@ -530,22 +552,23 @@ Datagram DCClass::
ai_format_generate(PyObject *distobj, int do_id,
int zone_id, int district_id, int from_channel_id,
PyObject *optional_fields) const {
Datagram dg;
dg.add_uint32(district_id);
dg.add_uint32(from_channel_id);
dg.add_uint8('A');
DCPacker packer;
packer.raw_pack_uint32(district_id);
packer.raw_pack_uint32(from_channel_id);
packer.raw_pack_uint8('A');
bool has_optional_fields = (PyObject_IsTrue(optional_fields) != 0);
if (has_optional_fields) {
dg.add_uint16(STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER);
packer.raw_pack_uint16(STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER);
} else {
dg.add_uint16(STATESERVER_OBJECT_GENERATE_WITH_REQUIRED);
packer.raw_pack_uint16(STATESERVER_OBJECT_GENERATE_WITH_REQUIRED);
}
dg.add_uint32(zone_id);
dg.add_uint16(_number);
dg.add_uint32(do_id);
packer.raw_pack_uint32(zone_id);
packer.raw_pack_uint16(_number);
packer.raw_pack_uint32(do_id);
// Specify all of the required fields.
int num_fields = get_num_inherited_fields();
@ -553,7 +576,7 @@ 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()) {
if (!pack_required_field(dg, distobj, atom)) {
if (!pack_required_field(packer, distobj, atom)) {
return Datagram();
}
}
@ -562,7 +585,7 @@ ai_format_generate(PyObject *distobj, int do_id,
// Also specify the optional fields.
if (has_optional_fields) {
int num_optional_fields = PySequence_Size(optional_fields);
dg.add_uint16(num_optional_fields);
packer.raw_pack_uint16(num_optional_fields);
for (int i = 0; i < num_optional_fields; i++) {
PyObject *py_field_name = PySequence_GetItem(optional_fields, i);
@ -578,13 +601,13 @@ ai_format_generate(PyObject *distobj, int do_id,
return Datagram();
}
if (!pack_required_field(dg, distobj, field)) {
if (!pack_required_field(packer, distobj, field)) {
return Datagram();
}
}
}
return dg;
return Datagram(packer.get_data(), packer.get_length());
}
#endif // HAVE_PYTHON

View File

@ -59,20 +59,21 @@ PUBLISHED:
void set_class_def(PyObject *class_def);
PyObject *get_class_def() const;
void receive_update(PyObject *distobj, DatagramIterator &iterator) const;
void receive_update_broadcast_required(PyObject *distobj, DatagramIterator &iterator) const;
void receive_update_all_required(PyObject *distobj, DatagramIterator &iterator) const;
void receive_update_other(PyObject *distobj, DatagramIterator &iterator) const;
void receive_update(PyObject *distobj, DatagramIterator &di) const;
void receive_update_broadcast_required(PyObject *distobj, DatagramIterator &di) const;
void receive_update_all_required(PyObject *distobj, DatagramIterator &di) const;
void receive_update_other(PyObject *distobj, DatagramIterator &di) const;
void direct_update(PyObject *distobj, const string &field_name,
const string &value_blob);
void direct_update(PyObject *distobj, const string &field_name,
const Datagram &datagram);
bool pack_required_field(Datagram &dg, PyObject *distobj,
bool pack_required_field(DCPacker &packer, PyObject *distobj,
DCField *field) const;
Datagram client_format_update(const string &field_name, int do_id,
PyObject *args) const;
Datagram client_format_update(const string &field_name,
int do_id, PyObject *args) const;
Datagram ai_format_update(const string &field_name, int do_id,
int to_id, int from_id, PyObject *args) const;
Datagram ai_format_generate(PyObject *distobj, int do_id, int zone_id,

View File

@ -124,7 +124,8 @@ as_switch() {
string DCField::
format_data(const string &packed_data) {
DCPacker packer;
packer.begin_unpack(packed_data, this);
packer.set_unpack_data(packed_data);
packer.begin_unpack(this);
string result = packer.unpack_and_format();
if (!packer.end_unpack()) {
return string();
@ -168,7 +169,8 @@ parse_string(const string &formatted_string) {
bool DCField::
validate_ranges(const string &packed_data) const {
DCPacker packer;
packer.begin_unpack(packed_data, this);
packer.set_unpack_data(packed_data);
packer.begin_unpack(this);
packer.unpack_validate();
if (!packer.end_unpack()) {
return false;
@ -182,18 +184,15 @@ validate_ranges(const string &packed_data) const {
// Function: DCField::pack_args
// Access: Published
// Description: Packs the Python arguments from the indicated tuple
// into the datagram, appending to the end of the
// datagram. Returns true on success, false on failure.
// into the packer. Returns true on success, false on
// failure.
////////////////////////////////////////////////////////////////////
bool DCField::
pack_args(Datagram &datagram, PyObject *sequence) const {
pack_args(DCPacker &packer, PyObject *sequence) const {
nassertr(PySequence_Check(sequence), false);
DCPacker packer;
packer.begin_pack(this);
packer.pack_object(sequence);
if (packer.end_pack()) {
datagram.append_data(packer.get_data(), packer.get_length());
/*
PyObject *str = PyObject_Str(sequence);
cerr << "pack " << get_name() << PyString_AsString(str) << "\n";
@ -227,24 +226,20 @@ pack_args(Datagram &datagram, PyObject *sequence) const {
////////////////////////////////////////////////////////////////////
// Function: DCField::unpack_args
// Access: Published
// Description: Unpacks the values from the datagram, beginning at
// the current point in the interator, into a Python
// Description: Unpacks the values from the packer, beginning at
// the current point in the unpack_buffer, into a Python
// tuple and returns the tuple. If there are remaining
// bytes in the datagram, they are ignored (but the
// iterator is left at the first unread byte).
// bytes in the unpack buffer, they are ignored (but the
// packer is left at the first unread byte).
////////////////////////////////////////////////////////////////////
PyObject *DCField::
unpack_args(DatagramIterator &iterator) const {
DCPacker packer;
string data = iterator.get_remaining_bytes();
packer.begin_unpack(data, this);
unpack_args(DCPacker &packer) const {
packer.begin_unpack(this);
PyObject *object = packer.unpack_object();
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";
@ -283,8 +278,8 @@ unpack_args(DatagramIterator &iterator) const {
// appropriate method.
////////////////////////////////////////////////////////////////////
void DCField::
receive_update(PyObject *distobj, DatagramIterator &iterator) const {
PyObject *args = unpack_args(iterator);
receive_update(DCPacker &packer, PyObject *distobj) const {
PyObject *args = unpack_args(packer);
if (PyObject_HasAttrString(distobj, (char *)_name.c_str())) {
PyObject *func = PyObject_GetAttrString(distobj, (char *)_name.c_str());
@ -307,14 +302,12 @@ receive_update(PyObject *distobj, DatagramIterator &iterator) const {
// to send an update for the indicated distributed
// object from the client.
////////////////////////////////////////////////////////////////////
Datagram DCField::
client_format_update(int do_id, PyObject *args) const {
Datagram dg;
dg.add_uint16(CLIENT_OBJECT_UPDATE_FIELD);
dg.add_uint32(do_id);
dg.add_uint16(_number);
pack_args(dg, args);
return dg;
void DCField::
client_format_update(DCPacker &packer, int do_id, PyObject *args) const {
packer.raw_pack_uint16(CLIENT_OBJECT_UPDATE_FIELD);
packer.raw_pack_uint32(do_id);
packer.raw_pack_uint16(_number);
pack_args(packer, args);
}
#endif // HAVE_PYTHON
@ -326,17 +319,15 @@ client_format_update(int do_id, PyObject *args) const {
// to send an update for the indicated distributed
// object from the AI.
////////////////////////////////////////////////////////////////////
Datagram DCField::
ai_format_update(int do_id, int to_id, int from_id, PyObject *args) const {
Datagram dg;
dg.add_uint32(to_id);
dg.add_uint32(from_id);
dg.add_uint8('A');
dg.add_uint16(STATESERVER_OBJECT_UPDATE_FIELD);
dg.add_uint32(do_id);
dg.add_uint16(_number);
pack_args(dg, args);
return dg;
void DCField::
ai_format_update(DCPacker &packer, int do_id, int to_id, int from_id, PyObject *args) const {
packer.raw_pack_uint32(to_id);
packer.raw_pack_uint32(from_id);
packer.raw_pack_uint8('A');
packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD);
packer.raw_pack_uint32(do_id);
packer.raw_pack_uint16(_number);
pack_args(packer, args);
}
#endif // HAVE_PYTHON

View File

@ -23,6 +23,7 @@
#include "dcPackerInterface.h"
#include "dcPython.h"
class DCPacker;
class DCAtomicField;
class DCMolecularField;
class DCParameter;
@ -54,13 +55,13 @@ PUBLISHED:
bool validate_ranges(const string &packed_data) const;
#ifdef HAVE_PYTHON
bool pack_args(Datagram &datagram, PyObject *sequence) const;
PyObject *unpack_args(DatagramIterator &iterator) const;
bool pack_args(DCPacker &packer, PyObject *sequence) const;
PyObject *unpack_args(DCPacker &packer) const;
void receive_update(PyObject *distobj, DatagramIterator &iterator) const;
void receive_update(DCPacker &packer, PyObject *distobj) const;
Datagram client_format_update(int do_id, PyObject *args) const;
Datagram ai_format_update(int do_id, int to_id, int from_id, PyObject *args) const;
void client_format_update(DCPacker &packer, int do_id, PyObject *args) const;
void ai_format_update(DCPacker &packer, int do_id, int to_id, int from_id, PyObject *args) const;
#endif
public:

View File

@ -54,7 +54,7 @@ clear() {
////////////////////////////////////////////////////////////////////
// Function: DCPackData::append_data
// Access: Published
// Access: Public
// Description: Adds the indicated bytes to the end of the data.
////////////////////////////////////////////////////////////////////
INLINE void DCPackData::
@ -65,7 +65,7 @@ append_data(const char *buffer, size_t size) {
////////////////////////////////////////////////////////////////////
// Function: DCPackData::get_write_pointer
// Access: Published
// Access: Public
// Description: Adds the indicated number of bytes to the end of the
// data without initializing them, and returns a pointer
// to the beginning of the new data.
@ -78,7 +78,7 @@ get_write_pointer(size_t size) {
////////////////////////////////////////////////////////////////////
// Function: DCPackData::append_junk
// Access: Published
// Access: Public
// Description: Adds some uninitialized bytes to the end of the data.
////////////////////////////////////////////////////////////////////
INLINE void DCPackData::
@ -88,7 +88,7 @@ append_junk(size_t size) {
////////////////////////////////////////////////////////////////////
// Function: DCPackData::rewrite_data
// Access: Published
// Access: Public
// Description: Changes the data at the indicated position to the
// given value. It is an error if there are not at
// least position + size bytes in the data.
@ -101,7 +101,7 @@ rewrite_data(size_t position, const char *buffer, size_t size) {
////////////////////////////////////////////////////////////////////
// Function: DCPackData::get_rewrite_pointer
// Access: Published
// Access: Public
// Description: Returns a pointer into the middle of the data at the
// indicated point.
////////////////////////////////////////////////////////////////////

View File

@ -33,12 +33,14 @@ PUBLISHED:
INLINE void clear();
public:
INLINE void append_data(const char *buffer, size_t size);
INLINE char *get_write_pointer(size_t size);
INLINE void append_junk(size_t size);
INLINE void rewrite_data(size_t position, const char *buffer, size_t size);
INLINE char *get_rewrite_pointer(size_t position, size_t size);
PUBLISHED:
INLINE string get_string() const;
INLINE size_t get_length() const;
public:

View File

@ -17,9 +17,28 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: DCPacker::clear_data
// Access: Published
// Description: Empties the data in the pack buffer and unpack
// buffer. This should be called between calls to
// begin_pack(), unless you want to concatenate all of
// the pack results together.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
clear_data() {
_pack_data.clear();
if (_owns_unpack_data) {
delete[] _unpack_data;
_owns_unpack_data = false;
}
_unpack_data = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::has_nested_fields
// Access: Public, Virtual
// Access: Published
// Description: Returns true if the current field has any nested
// fields (and thus expects a push() .. pop()
// interface), or false otherwise. If this returns
@ -621,6 +640,456 @@ get_data() const {
return _pack_data.get_data();
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::append_data
// Access: Public
// Description: Adds the indicated bytes to the end of the data.
// This may only be called between packing sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
append_data(const char *buffer, size_t size) {
nassertv(_mode == M_idle);
_pack_data.append_data(buffer, size);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::get_write_pointer
// Access: Public
// Description: Adds the indicated number of bytes to the end of the
// data without initializing them, and returns a pointer
// to the beginning of the new data. This may only be
// called between packing sessions.
////////////////////////////////////////////////////////////////////
INLINE char *DCPacker::
get_write_pointer(size_t size) {
nassertr(_mode == M_idle, NULL);
return _pack_data.get_write_pointer(size);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_int8
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_int8(int value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_int8(_pack_data.get_write_pointer(1), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_int16
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_int16(int value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_int16(_pack_data.get_write_pointer(2), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_int32
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_int32(int value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_int32(_pack_data.get_write_pointer(4), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_int64
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_int64(PN_int64 value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_int64(_pack_data.get_write_pointer(8), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_uint8
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_uint8(unsigned int value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_uint8(_pack_data.get_write_pointer(1), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_uint16
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_uint16(unsigned int value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_uint32
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_uint32(unsigned int value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_uint32(_pack_data.get_write_pointer(4), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_uint64
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_uint64(PN_uint64 value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_uint64(_pack_data.get_write_pointer(8), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_float64
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_float64(double value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_float64(_pack_data.get_write_pointer(8), value);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_string
// Access: Published
// Description: Packs the data into the buffer between packing
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_pack_string(const string &value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value.length());
_pack_data.append_data(value.data(), value.length());
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int8
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE int DCPacker::
raw_unpack_int8() {
int value = 0;
raw_unpack_int8(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int16
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE int DCPacker::
raw_unpack_int16() {
int value = 0;
raw_unpack_int16(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int32
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE int DCPacker::
raw_unpack_int32() {
int value = 0;
raw_unpack_int32(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int64
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE PN_int64 DCPacker::
raw_unpack_int64() {
PN_int64 value = 0;
raw_unpack_int64(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int8
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_int8(int &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 1 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_int8(_unpack_data + _unpack_p);
_unpack_p++;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int16
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_int16(int &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 2 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_int16(_unpack_data + _unpack_p);
_unpack_p += 2;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int32
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_int32(int &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 4 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_int32(_unpack_data + _unpack_p);
_unpack_p += 4;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint8
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE unsigned int DCPacker::
raw_unpack_uint8() {
unsigned int value = 0;
raw_unpack_uint8(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint16
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE unsigned int DCPacker::
raw_unpack_uint16() {
unsigned int value = 0;
raw_unpack_uint16(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint32
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE unsigned int DCPacker::
raw_unpack_uint32() {
unsigned int value = 0;
raw_unpack_uint32(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint64
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE PN_uint64 DCPacker::
raw_unpack_uint64() {
PN_uint64 value = 0;
raw_unpack_uint64(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_float64
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE double DCPacker::
raw_unpack_float64() {
double value = 0;
raw_unpack_float64(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_string
// Access: Published
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE string DCPacker::
raw_unpack_string() {
string value;
raw_unpack_string(value);
return value;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_int64
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_int64(PN_int64 &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 8 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_int64(_unpack_data + _unpack_p);
_unpack_p += 8;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint8
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_uint8(unsigned int &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 1 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_uint8(_unpack_data + _unpack_p);
_unpack_p++;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint16
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_uint16(unsigned int &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 2 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_uint16(_unpack_data + _unpack_p);
_unpack_p += 2;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint32
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_uint32(unsigned int &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 4 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_uint32(_unpack_data + _unpack_p);
_unpack_p += 4;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_uint64
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_uint64(PN_uint64 &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 8 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_uint64(_unpack_data + _unpack_p);
_unpack_p += 8;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_float64
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_float64(double &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
if (_unpack_p + 8 > _unpack_length) {
_pack_error = true;
return;
}
value = DCPackerInterface::do_unpack_float64(_unpack_data + _unpack_p);
_unpack_p += 8;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_unpack_string
// Access: Public
// Description: Unpacks the data from the buffer between unpacking
// sessions.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::
raw_unpack_string(string &value) {
nassertv(_mode == M_idle && _unpack_data != NULL);
unsigned int string_length = raw_unpack_uint16();
if (_unpack_p + string_length > _unpack_length) {
_pack_error = true;
return;
}
value.assign(_unpack_data + _unpack_p, string_length);
_unpack_p += string_length;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::advance
// Access: Private

View File

@ -49,6 +49,7 @@ DCPacker() {
////////////////////////////////////////////////////////////////////
DCPacker::
~DCPacker() {
clear_data();
clear();
}
@ -58,6 +59,12 @@ DCPacker::
// Description: Begins a packing session. The parameter is the DC
// object that describes the packing format; it may be a
// DCParameter or DCField.
//
// Unless you call clear_data() between sessions,
// multiple packing sessions will be concatenated
// together into the same buffer. If you wish to add
// bytes to the buffer between packing sessions, use
// append_data() or get_write_pointer().
////////////////////////////////////////////////////////////////////
void DCPacker::
begin_pack(const DCPackerInterface *root) {
@ -66,7 +73,6 @@ begin_pack(const DCPackerInterface *root) {
_mode = M_pack;
_pack_error = false;
_range_error = false;
_pack_data.clear();
_root = root;
_catalog = NULL;
@ -102,36 +108,63 @@ end_pack() {
}
////////////////////////////////////////////////////////////////////
// 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.
// Function: DCPacker::set_unpack_data
// Access: Public
// Description: Sets up the unpack_data pointer. You may call this
// before calling the version of begin_unpack() that
// takes only one parameter.
////////////////////////////////////////////////////////////////////
void DCPacker::
begin_unpack(const string &data, const DCPackerInterface *root) {
_unpack_str = data;
begin_unpack(_unpack_str.data(), _unpack_str.length(), root);
set_unpack_data(const string &data) {
nassertv(_mode == M_idle);
char *buffer = new char[data.length()];
memcpy(buffer, data.data(), data.length());
set_unpack_data(buffer, data.length(), true);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::set_unpack_data
// Access: Public
// Description: Sets up the unpack_data pointer. You may call this
// before calling the version of begin_unpack() that
// takes only one parameter.
////////////////////////////////////////////////////////////////////
void DCPacker::
set_unpack_data(const char *unpack_data, size_t unpack_length,
bool owns_unpack_data) {
nassertv(_mode == M_idle);
if (_owns_unpack_data) {
delete[] _unpack_data;
}
_unpack_data = unpack_data;
_unpack_length = unpack_length;
_owns_unpack_data = owns_unpack_data;
_unpack_p = 0;
}
////////////////////////////////////////////////////////////////////
// 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().
// Description: Begins an unpacking session. You must have
// previously called set_unpack_data() to specify a
// buffer to unpack.
//
// If there was data left in the buffer after a previous
// begin_unpack() .. end_unpack() session, the new
// session will resume from the current point. This
// method may be used, therefore, to unpack a sequence
// of objects from the same buffer.
////////////////////////////////////////////////////////////////////
void DCPacker::
begin_unpack(const char *data, size_t length,
const DCPackerInterface *root) {
begin_unpack(const DCPackerInterface *root) {
nassertv(_mode == M_idle);
nassertv(_unpack_data != NULL);
_mode = M_unpack;
_pack_error = false;
_range_error = false;
set_unpack_data(data, length, false);
_unpack_p = 0;
_root = root;
_catalog = NULL;
@ -175,44 +208,34 @@ end_unpack() {
return !_pack_error && !_range_error;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::begin_repack
// Access: Published
// Description: Begins an repacking session. Unlike the other
// version of begin_repack(), this version makes a copy
// of the data string.
////////////////////////////////////////////////////////////////////
void DCPacker::
begin_repack(const string &data, const DCPackerInterface *root) {
_unpack_str = data;
begin_repack(_unpack_str.data(), _unpack_str.length(), root);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::begin_repack
// Access: Public
// Description: Begins an repacking 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_repack().
// Description: Begins a repacking session. You must have previously
// called set_unpack_data() to specify a buffer to
// unpack.
//
// When repacking, unlike in packing or unpacking modes,
// you may not walk through the fields from beginning to
// end, or even pack two consecutive fields at once.
// Instead, you must call seek() for each field you wish
// to modify and pack only that one field; then call
// seek() again to modify another field.
// Unlike begin_pack() or begin_unpack() you may not
// concatenate the results of multiple begin_repack()
// sessions in one buffer.
//
// Also, unlike in packing or unpacking modes, you may
// not walk through the fields from beginning to end, or
// even pack two consecutive fields at once. Instead,
// you must call seek() for each field you wish to
// modify and pack only that one field; then call seek()
// again to modify another field.
////////////////////////////////////////////////////////////////////
void DCPacker::
begin_repack(const char *data, size_t length,
const DCPackerInterface *root) {
begin_repack(const DCPackerInterface *root) {
nassertv(_mode == M_idle);
nassertv(_unpack_data != NULL);
nassertv(_unpack_p == 0);
_mode = M_repack;
_pack_error = false;
_range_error = false;
set_unpack_data(data, length, false);
_unpack_p = 0;
_pack_data.clear();
// In repack mode, we immediately get the catalog, since we know
// we'll need it.
@ -1009,24 +1032,6 @@ clear() {
}
_catalog = NULL;
_root = NULL;
set_unpack_data(NULL, 0, false);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::set_unpack_data
// Access: Private
// Description: Sets up the unpack_data pointer.
////////////////////////////////////////////////////////////////////
void DCPacker::
set_unpack_data(const char *unpack_data, size_t unpack_length,
bool owns_unpack_data) {
if (_owns_unpack_data) {
delete[] _unpack_data;
}
_unpack_data = unpack_data;
_unpack_length = unpack_length;
_owns_unpack_data = owns_unpack_data;
}
#ifdef HAVE_PYTHON

View File

@ -44,21 +44,21 @@ PUBLISHED:
DCPacker();
~DCPacker();
INLINE void clear_data();
void begin_pack(const DCPackerInterface *root);
bool end_pack();
void set_unpack_data(const string &data);
public:
void begin_unpack(const char *data, size_t length,
const DCPackerInterface *root);
void set_unpack_data(const char *unpack_data, size_t unpack_length,
bool owns_unpack_data);
PUBLISHED:
void begin_unpack(const string &data, const DCPackerInterface *root);
void begin_unpack(const DCPackerInterface *root);
bool end_unpack();
public:
void begin_repack(const char *data, size_t length,
const DCPackerInterface *root);
PUBLISHED:
void begin_repack(const string &data, const DCPackerInterface *root);
void begin_repack(const DCPackerInterface *root);
bool end_repack();
bool seek(const string &field_name);
@ -125,6 +125,49 @@ PUBLISHED:
public:
INLINE const char *get_data() const;
INLINE void append_data(const char *buffer, size_t size);
INLINE char *get_write_pointer(size_t size);
PUBLISHED:
// The following methods are used only for packing (or unpacking)
// raw data into the buffer between packing sessions (e.g. between
// calls to end_pack() and the next begin_pack()).
INLINE void raw_pack_int8(int value);
INLINE void raw_pack_int16(int value);
INLINE void raw_pack_int32(int value);
INLINE void raw_pack_int64(PN_int64 value);
INLINE void raw_pack_uint8(unsigned int value);
INLINE void raw_pack_uint16(unsigned int value);
INLINE void raw_pack_uint32(unsigned int value);
INLINE void raw_pack_uint64(PN_uint64 value);
INLINE void raw_pack_float64(double value);
INLINE void raw_pack_string(const string &value);
INLINE int raw_unpack_int8();
INLINE int raw_unpack_int16();
INLINE int raw_unpack_int32();
INLINE PN_int64 raw_unpack_int64();
INLINE unsigned int raw_unpack_uint8();
INLINE unsigned int raw_unpack_uint16();
INLINE unsigned int raw_unpack_uint32();
INLINE PN_uint64 raw_unpack_uint64();
INLINE double raw_unpack_float64();
INLINE string raw_unpack_string();
public:
INLINE void raw_unpack_int8(int &value);
INLINE void raw_unpack_int16(int &value);
INLINE void raw_unpack_int32(int &value);
INLINE void raw_unpack_int64(PN_int64 &value);
INLINE void raw_unpack_uint8(unsigned int &value);
INLINE void raw_unpack_uint16(unsigned int &value);
INLINE void raw_unpack_uint32(unsigned int &value);
INLINE void raw_unpack_uint64(PN_uint64 &value);
INLINE void raw_unpack_float64(double &value);
INLINE void raw_unpack_string(string &value);
public:
static void enquote_string(ostream &out, char quote_mark, const string &str);
static void output_hex_string(ostream &out, const string &str);
@ -132,8 +175,6 @@ private:
INLINE void advance();
void handle_switch(const DCSwitch *dswitch);
void clear();
void set_unpack_data(const char *unpack_data, size_t unpack_length,
bool owns_unpack_data);
#ifdef HAVE_PYTHON
PyObject *unpack_class_object(DCClass *dclass);
@ -150,7 +191,6 @@ private:
Mode _mode;
DCPackData _pack_data;
string _unpack_str;
const char *_unpack_data;
size_t _unpack_length;
bool _owns_unpack_data;

View File

@ -133,7 +133,8 @@ get_live_catalog(const char *data, size_t length) const {
}
DCPacker packer;
packer.begin_unpack(data, length, _root);
packer.set_unpack_data(data, length, false);
packer.begin_unpack(_root);
const DCSwitch *last_switch = NULL;
r_fill_live_catalog(live_catalog, packer, last_switch);
bool okflag = packer.end_unpack();