add unpack seeking

This commit is contained in:
David Rose 2004-06-21 23:51:59 +00:00
parent 38690f1522
commit d61f2fcfa4
19 changed files with 923 additions and 200 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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];
}

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

View 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

View File

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

View File

@ -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 &copy) :
_num_nested_fields(copy._num_nested_fields),
_pack_type(copy._pack_type)
{
_catalog = NULL;
}
////////////////////////////////////////////////////////////////////
@ -59,90 +62,9 @@ DCPackerInterface(const DCPackerInterface &copy) :
////////////////////////////////////////////////////////////////////
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);
}
}
}
}

View File

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

View File

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

View File

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

View File

@ -6,6 +6,7 @@
#include "dcDeclaration.cxx"
#include "dcPackData.cxx"
#include "dcPacker.cxx"
#include "dcPackerCatalog.cxx"
#include "dcPackerInterface.cxx"
#include "dcindent.cxx"