mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
add unpack seeking
This commit is contained in:
parent
38690f1522
commit
d61f2fcfa4
@ -22,6 +22,7 @@
|
||||
dcSubatomicType.h \
|
||||
dcPackData.h dcPackData.I \
|
||||
dcPacker.h dcPacker.I \
|
||||
dcPackerCatalog.h dcPackerCatalog.I \
|
||||
dcPackerInterface.h dcPackerInterface.I \
|
||||
dcParameter.h dcClassParameter.h dcArrayParameter.h dcSimpleParameter.h \
|
||||
dcTypedef.h \
|
||||
@ -35,6 +36,7 @@
|
||||
dcMolecularField.cxx dcSubatomicType.cxx \
|
||||
dcPackData.cxx \
|
||||
dcPacker.cxx \
|
||||
dcPackerCatalog.cxx \
|
||||
dcPackerInterface.cxx \
|
||||
dcParameter.cxx dcClassParameter.cxx \
|
||||
dcArrayParameter.cxx dcSimpleParameter.cxx \
|
||||
|
@ -444,6 +444,12 @@ void DCAtomicField::
|
||||
add_element(const DCAtomicField::ElementType &element) {
|
||||
_elements.push_back(element);
|
||||
_num_nested_fields = (int)_elements.size();
|
||||
|
||||
// See if we still have a fixed byte size.
|
||||
if (_has_fixed_byte_size) {
|
||||
_has_fixed_byte_size = element._param->has_fixed_byte_size();
|
||||
_fixed_byte_size += element._param->get_fixed_byte_size();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -22,6 +22,16 @@
|
||||
#include "dcindent.h"
|
||||
#include "dcmsgtypes.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCClass::get_name
|
||||
// Access: Published
|
||||
// Description: Returns the name of this class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &DCClass::
|
||||
get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCClass::get_number
|
||||
// Access: Published
|
||||
@ -628,7 +638,7 @@ ai_format_generate(PyObject *distobj, int do_id,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DCClass::
|
||||
DCClass(const string &name, bool is_struct, bool bogus_class) :
|
||||
DCPackerInterface(name),
|
||||
_name(name),
|
||||
_is_struct(is_struct),
|
||||
_bogus_class(bogus_class)
|
||||
{
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include "dcbase.h"
|
||||
#include "dcField.h"
|
||||
#include "dcPackerInterface.h"
|
||||
#include "dcDeclaration.h"
|
||||
|
||||
class HashGenerator;
|
||||
@ -32,8 +31,9 @@ class DCParameter;
|
||||
// Description : Defines a particular DistributedClass as read from an
|
||||
// input .dc file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT DCClass : public DCPackerInterface, public DCDeclaration {
|
||||
class EXPCL_DIRECT DCClass : public DCDeclaration {
|
||||
PUBLISHED:
|
||||
const string &get_name() const;
|
||||
int get_number() const;
|
||||
|
||||
bool has_parent() const;
|
||||
@ -94,6 +94,7 @@ public:
|
||||
void set_number(int number);
|
||||
|
||||
private:
|
||||
string _name;
|
||||
bool _is_struct;
|
||||
bool _bogus_class;
|
||||
int _number;
|
||||
|
@ -35,6 +35,17 @@ DCClassParameter(DCClass *dclass) :
|
||||
_num_fields = _dclass->get_num_inherited_fields();
|
||||
_num_nested_fields = _num_fields + _dclass->get_num_inherited_parameters();
|
||||
_pack_type = PT_class;
|
||||
|
||||
// If all of the nested fields have a fixed byte size, then so does
|
||||
// the class (and its byte size is the sum of all of the nested
|
||||
// fields).
|
||||
_has_fixed_byte_size = true;
|
||||
_fixed_byte_size = 0;
|
||||
for (int i = 0; i < _num_nested_fields && _has_fixed_byte_size; i++) {
|
||||
DCPackerInterface *field = get_nested_field(i);
|
||||
_has_fixed_byte_size = field->has_fixed_byte_size();
|
||||
_fixed_byte_size += field->get_fixed_byte_size();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -130,7 +130,7 @@ pack_args(Datagram &datagram, PyObject *sequence) const {
|
||||
PyObject *str = PyObject_Str(tuple);
|
||||
|
||||
ostringstream strm;
|
||||
strm << "Incorrect arguments to field: " << get_name()
|
||||
strm << "Incorrect arguments or value too large on field: " << get_name()
|
||||
<< PyString_AsString(str);
|
||||
|
||||
Py_DECREF(str);
|
||||
@ -257,6 +257,9 @@ DCField(const string &name) : DCPackerInterface(name) {
|
||||
_has_nested_fields = true;
|
||||
_num_nested_fields = 0;
|
||||
_pack_type = PT_field;
|
||||
|
||||
_has_fixed_byte_size = true;
|
||||
_fixed_byte_size = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -75,7 +75,10 @@ DCMolecularField(const string &name) : DCField(name) {
|
||||
// Description: Adds the indicated atomic field to the end of the
|
||||
// list of atomic fields that make up the molecular
|
||||
// field. This is normally called only during parsing
|
||||
// of the dc file.
|
||||
// of the dc file. The atomic field should be fully
|
||||
// defined by this point; you should not modify the
|
||||
// atomic field (e.g. by adding more elements) after
|
||||
// adding it to a molecular field.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCMolecularField::
|
||||
add_atomic(DCAtomicField *atomic) {
|
||||
@ -87,6 +90,12 @@ add_atomic(DCAtomicField *atomic) {
|
||||
}
|
||||
|
||||
_num_nested_fields = _nested_fields.size();
|
||||
|
||||
// See if we still have a fixed byte size.
|
||||
if (_has_fixed_byte_size) {
|
||||
_has_fixed_byte_size = atomic->has_fixed_byte_size();
|
||||
_fixed_byte_size += atomic->get_fixed_byte_size();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -63,6 +63,19 @@ more_nested_fields() const {
|
||||
return (_current_field != (DCPackerInterface *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::get_current_field
|
||||
// Access: Published
|
||||
// Description: Returns the field that will be referenced by the next
|
||||
// call to pack_*() or unpack_*(). This will be NULL if
|
||||
// we have unpacked (or packed) all fields, or if it is
|
||||
// time to call pop().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const DCPackerInterface *DCPacker::
|
||||
get_current_field() const {
|
||||
return _current_field;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::get_pack_type
|
||||
// Access: Published
|
||||
@ -355,6 +368,21 @@ unpack_string() {
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::unpack_literal_value
|
||||
// Access: Published
|
||||
// Description: Returns the literal string that represents the packed
|
||||
// value of the current field, and advances the field
|
||||
// pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string DCPacker::
|
||||
unpack_literal_value() {
|
||||
size_t start = _unpack_p;
|
||||
unpack_skip();
|
||||
nassertr(_unpack_p >= start, string());
|
||||
return string(_unpack_data + start, _unpack_p - start);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::had_pack_error
|
||||
// Access: Published
|
||||
|
@ -31,6 +31,9 @@ DCPacker() {
|
||||
_unpack_data = NULL;
|
||||
_unpack_length = 0;
|
||||
_unpack_p = 0;
|
||||
_root = NULL;
|
||||
_catalog = NULL;
|
||||
_live_catalog = NULL;
|
||||
_current_field = NULL;
|
||||
_current_parent = NULL;
|
||||
_current_field_index = 0;
|
||||
@ -45,6 +48,7 @@ DCPacker() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DCPacker::
|
||||
~DCPacker() {
|
||||
clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -62,7 +66,10 @@ begin_pack(const DCPackerInterface *root) {
|
||||
_pack_error = false;
|
||||
_pack_data.clear();
|
||||
|
||||
_stack.clear();
|
||||
_root = root;
|
||||
_catalog = NULL;
|
||||
_live_catalog = NULL;
|
||||
|
||||
_current_field = root;
|
||||
_current_parent = NULL;
|
||||
_current_field_index = 0;
|
||||
@ -85,13 +92,10 @@ end_pack() {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
return !_pack_error;
|
||||
}
|
||||
|
||||
@ -127,7 +131,10 @@ begin_unpack(const char *data, size_t length,
|
||||
_unpack_length = length;
|
||||
_unpack_p = 0;
|
||||
|
||||
_stack.clear();
|
||||
_root = root;
|
||||
_catalog = NULL;
|
||||
_live_catalog = NULL;
|
||||
|
||||
_current_field = root;
|
||||
_current_parent = NULL;
|
||||
_current_field_index = 0;
|
||||
@ -140,7 +147,8 @@ begin_unpack(const char *data, size_t length,
|
||||
// Description: Finishes the unpacking session.
|
||||
//
|
||||
// The return value is true on success, or false if
|
||||
// there has been some error during unpacking.
|
||||
// there has been some error during unpacking (or if all
|
||||
// fields have not been unpacked).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCPacker::
|
||||
end_unpack() {
|
||||
@ -149,17 +157,69 @@ end_unpack() {
|
||||
_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;
|
||||
// This happens if we have not unpacked all of the fields.
|
||||
// However, this is not an error if we have called seek() during
|
||||
// the unpack session (in which case the _catalog will be
|
||||
// non-NULL). On the other hand, if the catalog is still NULL,
|
||||
// then we have never called seek() and it is an error not to
|
||||
// unpack all values.
|
||||
if (_catalog == (DCPackerCatalog *)NULL) {
|
||||
_pack_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
return !_pack_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::seek
|
||||
// Access: Published
|
||||
// Description: Sets the current unpack (or repack) position to the
|
||||
// named field. In unpack mode, the next call to
|
||||
// unpack_*() or push() will begin to read the named
|
||||
// field. In repack mode, the next call to pack_*() or
|
||||
// push() will modify the named field.
|
||||
//
|
||||
// Returns true if successful, false if the field is not
|
||||
// known (or if the packer is in an invalid mode).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCPacker::
|
||||
seek(const string &field_name) {
|
||||
if (_mode == M_unpack) {
|
||||
if (_catalog == (DCPackerCatalog *)NULL) {
|
||||
_catalog = _root->get_catalog();
|
||||
_live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
|
||||
}
|
||||
nassertr(_catalog != (DCPackerCatalog *)NULL, false);
|
||||
|
||||
int entry_index = _catalog->find_entry_by_name(field_name);
|
||||
if (entry_index < 0) {
|
||||
// The field was not known.
|
||||
_pack_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const DCPackerCatalog::Entry &entry = _catalog->get_entry(entry_index);
|
||||
|
||||
// If we are seeking, we don't need to remember our current stack
|
||||
// position.
|
||||
_stack.clear();
|
||||
_current_field = entry._field;
|
||||
_current_parent = entry._parent;
|
||||
_current_field_index = entry._field_index;
|
||||
_num_nested_fields = _current_parent->get_num_nested_fields();
|
||||
_unpack_p = _live_catalog->get_unpack_p(entry_index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invalid mode.
|
||||
_pack_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::push
|
||||
// Access: Published
|
||||
@ -281,10 +341,12 @@ pop() {
|
||||
size_t length = _pack_data.get_length() - _push_marker - length_bytes;
|
||||
if (length_bytes == 4) {
|
||||
DCPackerInterface::do_pack_uint32
|
||||
(_pack_data.get_rewrite_pointer(_push_marker, 4), length);
|
||||
(_pack_data.get_rewrite_pointer(_push_marker, 4), length,
|
||||
_pack_error);
|
||||
} else {
|
||||
DCPackerInterface::do_pack_uint16
|
||||
(_pack_data.get_rewrite_pointer(_push_marker, 2), length);
|
||||
(_pack_data.get_rewrite_pointer(_push_marker, 2), length,
|
||||
_pack_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,6 +362,37 @@ pop() {
|
||||
advance();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::unpack_skip
|
||||
// Access: Published
|
||||
// Description: Skips the current field without unpacking it and
|
||||
// advances to the next field.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPacker::
|
||||
unpack_skip() {
|
||||
nassertv(_mode == M_unpack);
|
||||
if (_current_field == NULL) {
|
||||
_pack_error = true;
|
||||
|
||||
} else if (_current_field->has_fixed_byte_size()) {
|
||||
_unpack_p += _current_field->get_fixed_byte_size();
|
||||
advance();
|
||||
|
||||
} else {
|
||||
if (_current_field->unpack_skip(_unpack_data, _unpack_length, _unpack_p)) {
|
||||
advance();
|
||||
|
||||
} else {
|
||||
// If the single field couldn't be skipped, try skipping nested fields.
|
||||
push();
|
||||
while (more_nested_fields()) {
|
||||
unpack_skip();
|
||||
}
|
||||
pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::pack_object
|
||||
@ -363,6 +456,11 @@ unpack_object() {
|
||||
DCPackType pack_type = get_pack_type();
|
||||
|
||||
switch (pack_type) {
|
||||
case PT_invalid:
|
||||
object = Py_None;
|
||||
unpack_skip();
|
||||
break;
|
||||
|
||||
case PT_double:
|
||||
{
|
||||
double value = unpack_double();
|
||||
@ -566,3 +664,25 @@ unpack_and_format(ostream &out) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPacker::clear
|
||||
// Access: Private
|
||||
// Description: Resets the data structures after a pack or unpack
|
||||
// sequence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCPacker::
|
||||
clear() {
|
||||
_stack.clear();
|
||||
_current_field = NULL;
|
||||
_current_parent = NULL;
|
||||
_current_field_index = 0;
|
||||
_num_nested_fields = 0;
|
||||
|
||||
if (_live_catalog != (DCPackerCatalog::LiveCatalog *)NULL) {
|
||||
_catalog->release_live_catalog(_live_catalog);
|
||||
_live_catalog = NULL;
|
||||
}
|
||||
_catalog = NULL;
|
||||
_root = NULL;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "dcPackerInterface.h"
|
||||
#include "dcSubatomicType.h"
|
||||
#include "dcPackData.h"
|
||||
#include "dcPackerCatalog.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DCPacker
|
||||
@ -45,10 +46,13 @@ PUBLISHED:
|
||||
void begin_unpack(const string &data, const DCPackerInterface *root);
|
||||
bool end_unpack();
|
||||
|
||||
bool seek(const string &field_name);
|
||||
|
||||
INLINE bool has_nested_fields() const;
|
||||
INLINE int get_num_nested_fields() const;
|
||||
INLINE bool more_nested_fields() const;
|
||||
|
||||
INLINE const DCPackerInterface *get_current_field() const;
|
||||
INLINE DCPackType get_pack_type() const;
|
||||
|
||||
void push();
|
||||
@ -68,6 +72,8 @@ PUBLISHED:
|
||||
INLINE PN_int64 unpack_int64();
|
||||
INLINE PN_uint64 unpack_uint64();
|
||||
INLINE string unpack_string();
|
||||
INLINE string unpack_literal_value();
|
||||
void unpack_skip();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
void pack_object(PyObject *object);
|
||||
@ -89,6 +95,7 @@ public:
|
||||
|
||||
private:
|
||||
INLINE void advance();
|
||||
void clear();
|
||||
|
||||
private:
|
||||
enum Mode {
|
||||
@ -104,6 +111,10 @@ private:
|
||||
size_t _unpack_length;
|
||||
size_t _unpack_p;
|
||||
|
||||
const DCPackerInterface *_root;
|
||||
const DCPackerCatalog *_catalog;
|
||||
const DCPackerCatalog::LiveCatalog *_live_catalog;
|
||||
|
||||
class StackElement {
|
||||
public:
|
||||
const DCPackerInterface *_current_parent;
|
||||
|
50
direct/src/dcparser/dcPackerCatalog.I
Normal file
50
direct/src/dcparser/dcPackerCatalog.I
Normal file
@ -0,0 +1,50 @@
|
||||
// Filename: dcPackerCatalog.I
|
||||
// Created by: drose (21Jun04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::LiveCatalog::get_unpack_p
|
||||
// Access: Public
|
||||
// Description: Returns the beginning of the indicated field within
|
||||
// the live data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t DCPackerCatalog::LiveCatalog::
|
||||
get_unpack_p(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_live_entries.size(), 0);
|
||||
return _live_entries[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::get_num_entries
|
||||
// Access: Public
|
||||
// Description: Returns the number of entries in the catalog.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int DCPackerCatalog::
|
||||
get_num_entries() const {
|
||||
return _entries.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::get_entry
|
||||
// Access: Public
|
||||
// Description: Returns the nth entry in the catalog.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const DCPackerCatalog::Entry &DCPackerCatalog::
|
||||
get_entry(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_entries.size(), _entries[0]);
|
||||
return _entries[n];
|
||||
}
|
191
direct/src/dcparser/dcPackerCatalog.cxx
Normal file
191
direct/src/dcparser/dcPackerCatalog.cxx
Normal file
@ -0,0 +1,191 @@
|
||||
// Filename: dcPackerCatalog.cxx
|
||||
// Created by: drose (21Jun04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dcPackerCatalog.h"
|
||||
#include "dcPackerInterface.h"
|
||||
#include "dcPacker.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::Constructor
|
||||
// Access: Private
|
||||
// Description: The catalog is created only by
|
||||
// DCPackerInterface::get_catalog().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DCPackerCatalog::
|
||||
DCPackerCatalog(const DCPackerInterface *root) : _root(root) {
|
||||
_live_catalog = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::Destructor
|
||||
// Access: Private
|
||||
// Description: The catalog is destroyed only by
|
||||
// ~DCPackerInterface().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DCPackerCatalog::
|
||||
~DCPackerCatalog() {
|
||||
if (_live_catalog != (LiveCatalog *)NULL) {
|
||||
delete _live_catalog;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::find_entry_by_name
|
||||
// Access: Public
|
||||
// Description: Returns the index number of the entry with the
|
||||
// indicated name, or -1 if no entry has the indicated
|
||||
// name. The return value is suitable for passing to
|
||||
// get_entry().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int DCPackerCatalog::
|
||||
find_entry_by_name(const string &name) const {
|
||||
EntriesByName::const_iterator ni;
|
||||
ni = _entries_by_name.find(name);
|
||||
if (ni != _entries_by_name.end()) {
|
||||
return (*ni).second;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::find_entry_by_field
|
||||
// Access: Public
|
||||
// Description: Returns the index number of the entry with the
|
||||
// indicated field, or -1 if no entry has the indicated
|
||||
// field. The return value is suitable for passing to
|
||||
// get_entry().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int DCPackerCatalog::
|
||||
find_entry_by_field(const DCPackerInterface *field) const {
|
||||
EntriesByField::const_iterator ni;
|
||||
ni = _entries_by_field.find(field);
|
||||
if (ni != _entries_by_field.end()) {
|
||||
return (*ni).second;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::get_live_catalog
|
||||
// Access: Public
|
||||
// Description: Returns a LiveCatalog object indicating the positions
|
||||
// within the indicated data record of each field within
|
||||
// the catalog. If the catalog's fields are all
|
||||
// fixed-width, this may return a statically-allocated
|
||||
// LiveCatalog object that is the same for all data
|
||||
// records; otherwise, it will allocate a new
|
||||
// LiveCatalog object that must be freed with a later
|
||||
// call to release_live_catalog().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const DCPackerCatalog::LiveCatalog *DCPackerCatalog::
|
||||
get_live_catalog(const char *data, size_t length) const {
|
||||
if (_live_catalog != (LiveCatalog *)NULL) {
|
||||
// Return the previously-allocated static catalog.
|
||||
return _live_catalog;
|
||||
}
|
||||
|
||||
LiveCatalog *live_catalog = new LiveCatalog;
|
||||
live_catalog->_live_entries.reserve(_entries.size());
|
||||
for (size_t i = 0; i < _entries.size(); i++) {
|
||||
live_catalog->_live_entries.push_back(0);
|
||||
}
|
||||
|
||||
DCPacker packer;
|
||||
packer.begin_unpack(data, length, _root);
|
||||
r_fill_live_catalog(live_catalog, packer);
|
||||
bool okflag = packer.end_unpack();
|
||||
|
||||
nassertr(okflag, live_catalog);
|
||||
|
||||
if (_root->has_fixed_byte_size()) {
|
||||
// If our root field has a fixed byte size, then the live catalog
|
||||
// will always be the same every time, so we might as well keep
|
||||
// this one around as an optimization.
|
||||
((DCPackerCatalog *)this)->_live_catalog = live_catalog;
|
||||
}
|
||||
|
||||
return live_catalog;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::release_live_catalog
|
||||
// Access: Public
|
||||
// Description: Releases the LiveCatalog object that was returned by
|
||||
// an earlier call to get_live_catalog(). If this
|
||||
// represents a newly-allocated live catalog, it will
|
||||
// free it; otherwise, it will do nothing.
|
||||
//
|
||||
// It is therefore always correct (and necessary) to
|
||||
// match a call to get_live_catalog() with a later call
|
||||
// to release_live_catalog().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCPackerCatalog::
|
||||
release_live_catalog(const DCPackerCatalog::LiveCatalog *live_catalog) const {
|
||||
if (live_catalog != _live_catalog) {
|
||||
delete (LiveCatalog *)live_catalog;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::add_entry
|
||||
// Access: Private
|
||||
// Description: Called only by DCPackerInterface::r_fill_catalog(),
|
||||
// this adds a new entry to the catalog.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCPackerCatalog::
|
||||
add_entry(const string &name, const DCPackerInterface *field,
|
||||
const DCPackerInterface *parent, int field_index) {
|
||||
Entry entry;
|
||||
entry._name = name;
|
||||
entry._field = field;
|
||||
entry._parent = parent;
|
||||
entry._field_index = field_index;
|
||||
|
||||
int entry_index = (int)_entries.size();
|
||||
_entries.push_back(entry);
|
||||
_entries_by_name.insert(EntriesByName::value_type(name, entry_index));
|
||||
_entries_by_field.insert(EntriesByField::value_type(field, entry_index));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerCatalog::r_fill_live_catalog
|
||||
// Access: Private
|
||||
// Description: Recursively walks through all of the fields on the
|
||||
// catalog and fills the live catalog with the
|
||||
// appropriate offsets.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCPackerCatalog::
|
||||
r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer) const {
|
||||
const DCPackerInterface *current_field = packer.get_current_field();
|
||||
|
||||
int field_index = find_entry_by_field(current_field);
|
||||
if (field_index >= 0) {
|
||||
live_catalog->_live_entries[field_index] = packer.get_num_unpacked_bytes();
|
||||
}
|
||||
|
||||
if (packer.has_nested_fields() && packer.get_pack_type() != PT_string) {
|
||||
packer.push();
|
||||
while (packer.more_nested_fields()) {
|
||||
r_fill_live_catalog(live_catalog, packer);
|
||||
}
|
||||
packer.pop();
|
||||
|
||||
} else {
|
||||
packer.unpack_skip();
|
||||
}
|
||||
}
|
95
direct/src/dcparser/dcPackerCatalog.h
Normal file
95
direct/src/dcparser/dcPackerCatalog.h
Normal file
@ -0,0 +1,95 @@
|
||||
// Filename: dcPackerCatalog.h
|
||||
// Created by: drose (21Jun04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DCPACKERCATALOG_H
|
||||
#define DCPACKERCATALOG_H
|
||||
|
||||
#include "dcbase.h"
|
||||
|
||||
class DCPackerInterface;
|
||||
class DCPacker;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DCPackerCatalog
|
||||
// Description : This object contains the names of all of the nested
|
||||
// fields available within a particular field. It is
|
||||
// created on demand when a catalog is first requested
|
||||
// from a particular field; its ownership is retained by
|
||||
// the field so it must not be deleted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT DCPackerCatalog {
|
||||
private:
|
||||
DCPackerCatalog(const DCPackerInterface *root);
|
||||
~DCPackerCatalog();
|
||||
|
||||
public:
|
||||
// The Entry class records the static catalog data: the name of each
|
||||
// field and its relationship to its parent.
|
||||
class Entry {
|
||||
public:
|
||||
string _name;
|
||||
const DCPackerInterface *_field;
|
||||
const DCPackerInterface *_parent;
|
||||
int _field_index;
|
||||
};
|
||||
|
||||
// The LiveCatalog class adds the dynamic catalog data: the actual
|
||||
// location of each field within the data record. This might be
|
||||
// different for different data records (since some data fields have
|
||||
// a dynamic length).
|
||||
class LiveCatalog {
|
||||
public:
|
||||
INLINE size_t get_unpack_p(int n) const;
|
||||
|
||||
private:
|
||||
typedef pvector<size_t> LiveEntries;
|
||||
LiveEntries _live_entries;
|
||||
friend class DCPackerCatalog;
|
||||
};
|
||||
|
||||
INLINE int get_num_entries() const;
|
||||
INLINE const Entry &get_entry(int n) const;
|
||||
int find_entry_by_name(const string &name) const;
|
||||
int find_entry_by_field(const DCPackerInterface *field) const;
|
||||
|
||||
const LiveCatalog *get_live_catalog(const char *data, size_t length) const;
|
||||
void release_live_catalog(const LiveCatalog *live_catalog) const;
|
||||
|
||||
private:
|
||||
void add_entry(const string &name, const DCPackerInterface *field,
|
||||
const DCPackerInterface *parent, int field_index);
|
||||
void r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer) const;
|
||||
|
||||
const DCPackerInterface *_root;
|
||||
LiveCatalog *_live_catalog;
|
||||
|
||||
typedef pvector<Entry> Entries;
|
||||
Entries _entries;
|
||||
|
||||
typedef pmap<string, int> EntriesByName;
|
||||
EntriesByName _entries_by_name;
|
||||
|
||||
typedef pmap<const DCPackerInterface *, int> EntriesByField;
|
||||
EntriesByField _entries_by_field;
|
||||
|
||||
friend class DCPackerInterface;
|
||||
};
|
||||
|
||||
#include "dcPackerCatalog.I"
|
||||
|
||||
#endif
|
@ -17,14 +17,111 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_name
|
||||
// Access: Published
|
||||
// Description: Returns the name of this field, or empty string
|
||||
// if the field is unnamed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &DCPackerInterface::
|
||||
get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::set_name
|
||||
// Access: Public
|
||||
// Description: Sets the name of this field.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
set_name(const string &name) {
|
||||
_name = name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::has_fixed_byte_size
|
||||
// Access: Public
|
||||
// Description: Returns true if this field type always packs to the
|
||||
// same number of bytes, false if it is variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DCPackerInterface::
|
||||
has_fixed_byte_size() const {
|
||||
return _has_fixed_byte_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_fixed_byte_size
|
||||
// Access: Public
|
||||
// Description: If has_fixed_byte_size() returns true, this returns
|
||||
// the number of bytes this field type will use.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t DCPackerInterface::
|
||||
get_fixed_byte_size() const {
|
||||
return _fixed_byte_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_num_length_bytes
|
||||
// Access: Public
|
||||
// Description: Returns the number of bytes that should be written
|
||||
// into the stream on a push() to record the number of
|
||||
// bytes in the record up until the next pop(). This is
|
||||
// only meaningful if _has_nested_fields is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t DCPackerInterface::
|
||||
get_num_length_bytes() const {
|
||||
return _num_length_bytes;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::has_nested_fields
|
||||
// Access: Public
|
||||
// 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.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DCPackerInterface::
|
||||
has_nested_fields() const {
|
||||
return _has_nested_fields;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_num_nested_fields
|
||||
// Access: Public
|
||||
// Description: Returns the number of nested fields required by this
|
||||
// field type. These may be array elements or structure
|
||||
// elements. The return value may be -1 to indicate the
|
||||
// number of nested fields is variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int DCPackerInterface::
|
||||
get_num_nested_fields() const {
|
||||
return _num_nested_fields;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_pack_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of value expected by this field.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DCPackType DCPackerInterface::
|
||||
get_pack_type() const {
|
||||
return _pack_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::do_pack_int8
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_int8(char *buffer, int value) {
|
||||
do_pack_int8(char *buffer, int value, bool &pack_error) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
if ((abs(value) & ~0xff) != 0) {
|
||||
pack_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -33,9 +130,12 @@ do_pack_int8(char *buffer, int value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_int16(char *buffer, int value) {
|
||||
do_pack_int16(char *buffer, int value, bool &pack_error) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
buffer[1] = (char)((value >> 8) & 0xff);
|
||||
if ((abs(value) & ~0xffff) != 0) {
|
||||
pack_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -44,7 +144,7 @@ do_pack_int16(char *buffer, int value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_int32(char *buffer, int value) {
|
||||
do_pack_int32(char *buffer, int value, bool &) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
buffer[1] = (char)((value >> 8) & 0xff);
|
||||
buffer[2] = (char)((value >> 16) & 0xff);
|
||||
@ -57,7 +157,7 @@ do_pack_int32(char *buffer, int value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_int64(char *buffer, PN_int64 value) {
|
||||
do_pack_int64(char *buffer, PN_int64 value, bool &) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
buffer[1] = (char)((value >> 8) & 0xff);
|
||||
buffer[2] = (char)((value >> 16) & 0xff);
|
||||
@ -74,8 +174,11 @@ do_pack_int64(char *buffer, PN_int64 value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_uint8(char *buffer, unsigned int value) {
|
||||
do_pack_uint8(char *buffer, unsigned int value, bool &pack_error) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
if ((value & ~0xff) != 0) {
|
||||
pack_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -84,9 +187,12 @@ do_pack_uint8(char *buffer, unsigned int value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_uint16(char *buffer, unsigned int value) {
|
||||
do_pack_uint16(char *buffer, unsigned int value, bool &pack_error) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
buffer[1] = (char)((value >> 8) & 0xff);
|
||||
if ((value & ~0xffff) != 0) {
|
||||
pack_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -95,7 +201,7 @@ do_pack_uint16(char *buffer, unsigned int value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_uint32(char *buffer, unsigned int value) {
|
||||
do_pack_uint32(char *buffer, unsigned int value, bool &) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
buffer[1] = (char)((value >> 8) & 0xff);
|
||||
buffer[2] = (char)((value >> 16) & 0xff);
|
||||
@ -108,7 +214,7 @@ do_pack_uint32(char *buffer, unsigned int value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_uint64(char *buffer, PN_uint64 value) {
|
||||
do_pack_uint64(char *buffer, PN_uint64 value, bool &) {
|
||||
buffer[0] = (char)(value & 0xff);
|
||||
buffer[1] = (char)((value >> 8) & 0xff);
|
||||
buffer[2] = (char)((value >> 16) & 0xff);
|
||||
@ -125,7 +231,7 @@ do_pack_uint64(char *buffer, PN_uint64 value) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DCPackerInterface::
|
||||
do_pack_float64(char *buffer, double value) {
|
||||
do_pack_float64(char *buffer, double value, bool &) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
// Reverse the byte ordering for big-endian machines.
|
||||
char *p = (char *)value;
|
||||
|
@ -17,6 +17,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dcPackerInterface.h"
|
||||
#include "dcPackerCatalog.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::Constructor
|
||||
@ -33,6 +34,7 @@ DCPackerInterface(const string &name) :
|
||||
_has_nested_fields = false;
|
||||
_num_nested_fields = -1;
|
||||
_pack_type = PT_invalid;
|
||||
_catalog = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -50,6 +52,7 @@ DCPackerInterface(const DCPackerInterface ©) :
|
||||
_num_nested_fields(copy._num_nested_fields),
|
||||
_pack_type(copy._pack_type)
|
||||
{
|
||||
_catalog = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -59,90 +62,9 @@ DCPackerInterface(const DCPackerInterface ©) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DCPackerInterface::
|
||||
~DCPackerInterface() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_name
|
||||
// Access: Published
|
||||
// Description: Returns the name of this field, or empty string
|
||||
// if the field is unnamed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &DCPackerInterface::
|
||||
get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::set_name
|
||||
// Access: Published
|
||||
// Description: Sets the name of this field.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCPackerInterface::
|
||||
set_name(const string &name) {
|
||||
_name = name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::has_fixed_byte_size
|
||||
// Access: Public
|
||||
// Description: Returns true if this field type always packs to the
|
||||
// same number of bytes, false if it is variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCPackerInterface::
|
||||
has_fixed_byte_size() const {
|
||||
return _has_fixed_byte_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_fixed_byte_size
|
||||
// Access: Public
|
||||
// Description: If has_fixed_byte_size() returns true, this returns
|
||||
// the number of bytes this field type will use.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t DCPackerInterface::
|
||||
get_fixed_byte_size() const {
|
||||
return _fixed_byte_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_num_length_bytes
|
||||
// Access: Public
|
||||
// Description: Returns the number of bytes that should be written
|
||||
// into the stream on a push() to record the number of
|
||||
// bytes in the record up until the next pop(). This is
|
||||
// only meaningful if _has_nested_fields is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t DCPackerInterface::
|
||||
get_num_length_bytes() const {
|
||||
return _num_length_bytes;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::has_nested_fields
|
||||
// Access: Public
|
||||
// Description: Returns true if this field type has any nested fields
|
||||
// (and thus expects a push() .. pop() interface to the
|
||||
// DCPacker), or false otherwise. If this returns true,
|
||||
// get_num_nested_fields() may be called to determine
|
||||
// how many nested fields are expected.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCPackerInterface::
|
||||
has_nested_fields() const {
|
||||
return _has_nested_fields;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_num_nested_fields
|
||||
// Access: Public
|
||||
// Description: Returns the number of nested fields required by this
|
||||
// field type. These may be array elements or structure
|
||||
// elements. The return value may be -1 to indicate the
|
||||
// number of nested fields is variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int DCPackerInterface::
|
||||
get_num_nested_fields() const {
|
||||
return _num_nested_fields;
|
||||
if (_catalog != (DCPackerCatalog *)NULL) {
|
||||
delete _catalog;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -173,16 +95,6 @@ get_nested_field(int n) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_pack_type
|
||||
// Access: Public
|
||||
// Description: Returns the type of value expected by this field.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DCPackType DCPackerInterface::
|
||||
get_pack_type() const {
|
||||
return _pack_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::pack_double
|
||||
// Access: Public, Virtual
|
||||
@ -314,3 +226,87 @@ bool DCPackerInterface::
|
||||
unpack_string(const char *, size_t, size_t &, string &) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::unpack_skip
|
||||
// Access: Public, Virtual
|
||||
// Description: Increments p to the end of the current field without
|
||||
// actually unpacking any data. Returns true on
|
||||
// success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCPackerInterface::
|
||||
unpack_skip(const char *, size_t, size_t &) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::get_catalog
|
||||
// Access: Public
|
||||
// Description: Returns the DCPackerCatalog associated with this
|
||||
// field, listing all of the nested fields by name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const DCPackerCatalog *DCPackerInterface::
|
||||
get_catalog() const {
|
||||
if (_catalog == (DCPackerCatalog *)NULL) {
|
||||
((DCPackerInterface *)this)->make_catalog();
|
||||
}
|
||||
return _catalog;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::make_catalog
|
||||
// Access: Private
|
||||
// Description: Called internally to create a new DCPackerCatalog
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCPackerInterface::
|
||||
make_catalog() {
|
||||
nassertv(_catalog == (DCPackerCatalog *)NULL);
|
||||
_catalog = new DCPackerCatalog(this);
|
||||
|
||||
if (has_nested_fields()) {
|
||||
int num_nested = get_num_nested_fields();
|
||||
// num_nested might be -1, indicating there are a dynamic number
|
||||
// of fields (e.g. an array). But in that case, none of the
|
||||
// fields will be named anyway, so we don't care about them, so
|
||||
// it's ok that the following loop will not visit any fields.
|
||||
for (int i = 0; i < num_nested; i++) {
|
||||
DCPackerInterface *nested = get_nested_field(i);
|
||||
if (nested != (DCPackerInterface *)NULL) {
|
||||
nested->r_fill_catalog(_catalog, "", this, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCPackerInterface::r_fill_catalog
|
||||
// Access: Private
|
||||
// Description: Called internally to recursively fill up the new
|
||||
// DCPackerCatalog object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DCPackerInterface::
|
||||
r_fill_catalog(DCPackerCatalog *catalog, const string &name_prefix,
|
||||
DCPackerInterface *parent, int field_index) {
|
||||
string next_name_prefix = name_prefix;
|
||||
|
||||
if (!get_name().empty()) {
|
||||
// Record this entry in the catalog.
|
||||
next_name_prefix += get_name();
|
||||
catalog->add_entry(next_name_prefix, this, parent, field_index);
|
||||
|
||||
next_name_prefix += ".";
|
||||
}
|
||||
|
||||
// Add any children.
|
||||
if (has_nested_fields()) {
|
||||
int num_nested = get_num_nested_fields();
|
||||
// As above, it's ok if num_nested is -1.
|
||||
for (int i = 0; i < num_nested; i++) {
|
||||
DCPackerInterface *nested = get_nested_field(i);
|
||||
if (nested != (DCPackerInterface *)NULL) {
|
||||
nested->r_fill_catalog(catalog, next_name_prefix, this, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "dcSubatomicType.h"
|
||||
|
||||
class DCPackData;
|
||||
class DCPackerCatalog;
|
||||
|
||||
BEGIN_PUBLISH
|
||||
// This enumerated type is returned by get_pack_type() and represents
|
||||
@ -67,20 +68,20 @@ public:
|
||||
virtual ~DCPackerInterface();
|
||||
|
||||
PUBLISHED:
|
||||
const string &get_name() const;
|
||||
void set_name(const string &name);
|
||||
INLINE const string &get_name() const;
|
||||
|
||||
public:
|
||||
bool has_fixed_byte_size() const;
|
||||
size_t get_fixed_byte_size() const;
|
||||
size_t get_num_length_bytes() const;
|
||||
INLINE void set_name(const string &name);
|
||||
INLINE bool has_fixed_byte_size() const;
|
||||
INLINE size_t get_fixed_byte_size() const;
|
||||
INLINE size_t get_num_length_bytes() const;
|
||||
|
||||
bool has_nested_fields() const;
|
||||
int get_num_nested_fields() const;
|
||||
INLINE bool has_nested_fields() const;
|
||||
INLINE int get_num_nested_fields() const;
|
||||
virtual int calc_num_nested_fields(size_t length_bytes) const;
|
||||
virtual DCPackerInterface *get_nested_field(int n) const;
|
||||
|
||||
DCPackType get_pack_type() const;
|
||||
INLINE DCPackType get_pack_type() const;
|
||||
|
||||
virtual bool pack_double(DCPackData &pack_data, double value) const;
|
||||
virtual bool pack_int(DCPackData &pack_data, int value) const;
|
||||
@ -95,19 +96,20 @@ public:
|
||||
virtual bool unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value) const;
|
||||
virtual bool unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value) const;
|
||||
virtual bool unpack_string(const char *data, size_t length, size_t &p, string &value) const;
|
||||
virtual bool unpack_skip(const char *data, size_t length, size_t &p) const;
|
||||
|
||||
// These are the low-level interfaces for packing and unpacking
|
||||
// numbers from a buffer. You're responsible for making sure the
|
||||
// buffer has enough room, and for incrementing the pointer.
|
||||
INLINE static void do_pack_int8(char *buffer, int value);
|
||||
INLINE static void do_pack_int16(char *buffer, int value);
|
||||
INLINE static void do_pack_int32(char *buffer, int value);
|
||||
INLINE static void do_pack_int64(char *buffer, PN_int64 value);
|
||||
INLINE static void do_pack_uint8(char *buffer, unsigned int value);
|
||||
INLINE static void do_pack_uint16(char *buffer, unsigned int value);
|
||||
INLINE static void do_pack_uint32(char *buffer, unsigned int value);
|
||||
INLINE static void do_pack_uint64(char *buffer, PN_uint64 value);
|
||||
INLINE static void do_pack_float64(char *buffer, double value);
|
||||
INLINE static void do_pack_int8(char *buffer, int value, bool &pack_error);
|
||||
INLINE static void do_pack_int16(char *buffer, int value, bool &pack_error);
|
||||
INLINE static void do_pack_int32(char *buffer, int value, bool &pack_error);
|
||||
INLINE static void do_pack_int64(char *buffer, PN_int64 value, bool &pack_error);
|
||||
INLINE static void do_pack_uint8(char *buffer, unsigned int value, bool &pack_error);
|
||||
INLINE static void do_pack_uint16(char *buffer, unsigned int value, bool &pack_error);
|
||||
INLINE static void do_pack_uint32(char *buffer, unsigned int value, bool &pack_error);
|
||||
INLINE static void do_pack_uint64(char *buffer, PN_uint64 value, bool &pack_error);
|
||||
INLINE static void do_pack_float64(char *buffer, double value, bool &pack_error);
|
||||
|
||||
INLINE static int do_unpack_int8(const char *buffer);
|
||||
INLINE static int do_unpack_int16(const char *buffer);
|
||||
@ -119,6 +121,8 @@ public:
|
||||
INLINE static PN_uint64 do_unpack_uint64(const char *buffer);
|
||||
INLINE static double do_unpack_float64(const char *buffer);
|
||||
|
||||
const DCPackerCatalog *get_catalog() const;
|
||||
|
||||
protected:
|
||||
string _name;
|
||||
bool _has_fixed_byte_size;
|
||||
@ -127,6 +131,14 @@ protected:
|
||||
bool _has_nested_fields;
|
||||
int _num_nested_fields;
|
||||
DCPackType _pack_type;
|
||||
|
||||
private:
|
||||
void make_catalog();
|
||||
void r_fill_catalog(DCPackerCatalog *catalog, const string &name_prefix,
|
||||
DCPackerInterface *parent, int field_index);
|
||||
|
||||
|
||||
DCPackerCatalog *_catalog;
|
||||
};
|
||||
|
||||
#include "dcPackerInterface.I"
|
||||
|
@ -318,58 +318,59 @@ get_nested_field(int) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
pack_double(DCPackData &pack_data, double value) const {
|
||||
bool pack_error = false;
|
||||
double real_value = value * _divisor;
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
do_pack_int8(pack_data.get_write_pointer(1),
|
||||
(int)floor(real_value + 0.5));
|
||||
(int)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
case ST_int16:
|
||||
do_pack_int16(pack_data.get_write_pointer(2),
|
||||
(int)floor(real_value + 0.5));
|
||||
(int)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
|
||||
case ST_int32:
|
||||
do_pack_int32(pack_data.get_write_pointer(4),
|
||||
(int)floor(real_value + 0.5));
|
||||
(int)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
|
||||
case ST_int64:
|
||||
do_pack_int64(pack_data.get_write_pointer(8),
|
||||
(PN_int64)floor(real_value + 0.5));
|
||||
(PN_int64)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
|
||||
case ST_uint8:
|
||||
do_pack_uint8(pack_data.get_write_pointer(1),
|
||||
(unsigned int)floor(real_value + 0.5));
|
||||
(unsigned int)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
|
||||
case ST_uint16:
|
||||
do_pack_uint16(pack_data.get_write_pointer(2),
|
||||
(unsigned int)floor(real_value + 0.5));
|
||||
(unsigned int)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
|
||||
case ST_uint32:
|
||||
do_pack_uint32(pack_data.get_write_pointer(4),
|
||||
(unsigned int)floor(real_value + 0.5));
|
||||
(unsigned int)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
|
||||
case ST_uint64:
|
||||
do_pack_uint64(pack_data.get_write_pointer(8),
|
||||
(PN_uint64)floor(real_value + 0.5));
|
||||
(PN_uint64)floor(real_value + 0.5), pack_error);
|
||||
break;
|
||||
|
||||
case ST_float64:
|
||||
do_pack_float64(pack_data.get_write_pointer(8), real_value);
|
||||
do_pack_float64(pack_data.get_write_pointer(8), real_value, pack_error);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !pack_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -380,50 +381,51 @@ pack_double(DCPackData &pack_data, double value) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
pack_int(DCPackData &pack_data, int value) const {
|
||||
bool pack_error = false;
|
||||
int int_value = value * _divisor;
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
do_pack_int8(pack_data.get_write_pointer(1), int_value);
|
||||
do_pack_int8(pack_data.get_write_pointer(1), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int16:
|
||||
do_pack_int16(pack_data.get_write_pointer(2), int_value);
|
||||
do_pack_int16(pack_data.get_write_pointer(2), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int32:
|
||||
do_pack_int32(pack_data.get_write_pointer(4), int_value);
|
||||
do_pack_int32(pack_data.get_write_pointer(4), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int64:
|
||||
do_pack_int64(pack_data.get_write_pointer(8), int_value);
|
||||
do_pack_int64(pack_data.get_write_pointer(8), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint8:
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint16:
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint32:
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint64:
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), (unsigned int)int_value);
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), (unsigned int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_float64:
|
||||
do_pack_float64(pack_data.get_write_pointer(8), int_value);
|
||||
do_pack_float64(pack_data.get_write_pointer(8), int_value, pack_error);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !pack_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -434,50 +436,51 @@ pack_int(DCPackData &pack_data, int value) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
pack_uint(DCPackData &pack_data, unsigned int value) const {
|
||||
bool pack_error = false;
|
||||
unsigned int int_value = value * _divisor;
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
|
||||
do_pack_int8(pack_data.get_write_pointer(1), (int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int16:
|
||||
do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
|
||||
do_pack_int16(pack_data.get_write_pointer(2), (int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int32:
|
||||
do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
|
||||
do_pack_int32(pack_data.get_write_pointer(4), (int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int64:
|
||||
do_pack_int64(pack_data.get_write_pointer(8), (int)int_value);
|
||||
do_pack_int64(pack_data.get_write_pointer(8), (int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint8:
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), int_value);
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint16:
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), int_value);
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint32:
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), int_value);
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint64:
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), int_value);
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_float64:
|
||||
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
|
||||
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value, pack_error);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !pack_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -488,50 +491,51 @@ pack_uint(DCPackData &pack_data, unsigned int value) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
pack_int64(DCPackData &pack_data, PN_int64 value) const {
|
||||
bool pack_error = false;
|
||||
PN_int64 int_value = value * _divisor;
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
|
||||
do_pack_int8(pack_data.get_write_pointer(1), (int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int16:
|
||||
do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
|
||||
do_pack_int16(pack_data.get_write_pointer(2), (int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int32:
|
||||
do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
|
||||
do_pack_int32(pack_data.get_write_pointer(4), (int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int64:
|
||||
do_pack_int64(pack_data.get_write_pointer(8), int_value);
|
||||
do_pack_int64(pack_data.get_write_pointer(8), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint8:
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)(PN_uint64)int_value);
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)(PN_uint64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint16:
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)(PN_uint64)int_value);
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)(PN_uint64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint32:
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)(PN_uint64)int_value);
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)(PN_uint64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint64:
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), (PN_uint64)int_value);
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), (PN_uint64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_float64:
|
||||
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
|
||||
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value, pack_error);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !pack_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -542,50 +546,51 @@ pack_int64(DCPackData &pack_data, PN_int64 value) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
pack_uint64(DCPackData &pack_data, PN_uint64 value) const {
|
||||
bool pack_error = false;
|
||||
PN_uint64 int_value = value * _divisor;
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
do_pack_int8(pack_data.get_write_pointer(1), (int)(PN_int64)int_value);
|
||||
do_pack_int8(pack_data.get_write_pointer(1), (int)(PN_int64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int16:
|
||||
do_pack_int16(pack_data.get_write_pointer(2), (int)(PN_int64)int_value);
|
||||
do_pack_int16(pack_data.get_write_pointer(2), (int)(PN_int64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int32:
|
||||
do_pack_int32(pack_data.get_write_pointer(4), (int)(PN_int64)int_value);
|
||||
do_pack_int32(pack_data.get_write_pointer(4), (int)(PN_int64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_int64:
|
||||
do_pack_int64(pack_data.get_write_pointer(8), (PN_int64)int_value);
|
||||
do_pack_int64(pack_data.get_write_pointer(8), (PN_int64)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint8:
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
|
||||
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint16:
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint32:
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_uint64:
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), int_value);
|
||||
do_pack_uint64(pack_data.get_write_pointer(8), int_value, pack_error);
|
||||
break;
|
||||
|
||||
case ST_float64:
|
||||
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
|
||||
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value, pack_error);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !pack_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -596,15 +601,19 @@ pack_uint64(DCPackData &pack_data, PN_uint64 value) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
pack_string(DCPackData &pack_data, const string &value) const {
|
||||
bool pack_error = false;
|
||||
|
||||
switch (_type) {
|
||||
case ST_string:
|
||||
case ST_blob:
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), value.length());
|
||||
do_pack_uint16(pack_data.get_write_pointer(2), value.length(),
|
||||
pack_error);
|
||||
pack_data.append_data(value.data(), value.length());
|
||||
break;
|
||||
|
||||
case ST_blob32:
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), value.length());
|
||||
do_pack_uint32(pack_data.get_write_pointer(4), value.length(),
|
||||
pack_error);
|
||||
pack_data.append_data(value.data(), value.length());
|
||||
break;
|
||||
|
||||
@ -612,7 +621,7 @@ pack_string(DCPackData &pack_data, const string &value) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !pack_error;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1116,6 +1125,67 @@ unpack_string(const char *data, size_t length, size_t &p, string &value) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::unpack_skip
|
||||
// Access: Public, Virtual
|
||||
// Description: Increments p to the end of the current field without
|
||||
// actually unpacking any data. Returns true on
|
||||
// success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DCSimpleParameter::
|
||||
unpack_skip(const char *data, size_t length, size_t &p) const {
|
||||
size_t string_length;
|
||||
|
||||
switch (_type) {
|
||||
case ST_int8:
|
||||
case ST_uint8:
|
||||
p++;
|
||||
break;
|
||||
|
||||
case ST_int16:
|
||||
case ST_uint16:
|
||||
p += 2;
|
||||
break;
|
||||
|
||||
case ST_int32:
|
||||
case ST_uint32:
|
||||
p += 4;
|
||||
break;
|
||||
|
||||
case ST_int64:
|
||||
case ST_uint64:
|
||||
case ST_float64:
|
||||
p += 8;
|
||||
break;
|
||||
|
||||
case ST_string:
|
||||
case ST_blob:
|
||||
if (p + 2 > length) {
|
||||
return false;
|
||||
}
|
||||
string_length = do_unpack_uint16(data + p);
|
||||
p += 2 + string_length;
|
||||
break;
|
||||
|
||||
case ST_blob32:
|
||||
if (p + 4 > length) {
|
||||
return false;
|
||||
}
|
||||
string_length = do_unpack_uint32(data + p);
|
||||
p += 4 + string_length;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p > length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DCSimpleParameter::output_instance
|
||||
// Access: Public, Virtual
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
virtual bool unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value) const;
|
||||
virtual bool unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value) const;
|
||||
virtual bool unpack_string(const char *data, size_t length, size_t &p, string &value) const;
|
||||
virtual bool unpack_skip(const char *data, size_t length, size_t &p) const;
|
||||
|
||||
virtual void output_instance(ostream &out, const string &prename,
|
||||
const string &name, const string &postname) const;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "dcDeclaration.cxx"
|
||||
#include "dcPackData.cxx"
|
||||
#include "dcPacker.cxx"
|
||||
#include "dcPackerCatalog.cxx"
|
||||
#include "dcPackerInterface.cxx"
|
||||
#include "dcindent.cxx"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user