panda3d/direct/src/dcparser/dcSimpleParameter.cxx
2004-06-19 00:03:15 +00:00

1226 lines
31 KiB
C++

// Filename: dcSimpleParameter.cxx
// Created by: drose (15Jun04)
//
////////////////////////////////////////////////////////////////////
//
// 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 "dcSimpleParameter.h"
#include "dcPackData.h"
#include "dcTypedef.h"
#include "hashGenerator.h"
#include <math.h>
DCSimpleParameter::NestedFieldMap DCSimpleParameter::_nested_field_map;
DCSimpleParameter::Uint32Uint8Type *DCSimpleParameter::_uint32uint8_type = NULL;
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DCSimpleParameter::
DCSimpleParameter(DCSubatomicType type, int divisor) :
_type(type),
_divisor(1)
{
_pack_type = PT_invalid;
_nested_type = ST_invalid;
_has_nested_fields = false;
_bytes_per_element = 0;
_num_length_bytes = 2;
// Check for one of the built-in array types. For these types, we
// must present a packing interface that has a variable number of
// nested fields of the appropriate type.
switch (_type) {
case ST_int8array:
_pack_type = PT_array;
_nested_type = ST_int8;
_has_nested_fields = true;
_bytes_per_element = 1;
break;
case ST_int16array:
_pack_type = PT_array;
_nested_type = ST_int16;
_has_nested_fields = true;
_bytes_per_element = 2;
break;
case ST_int32array:
_pack_type = PT_array;
_nested_type = ST_int32;
_has_nested_fields = true;
_bytes_per_element = 4;
break;
case ST_uint8array:
_pack_type = PT_array;
_nested_type = ST_uint8;
_has_nested_fields = true;
_bytes_per_element = 1;
break;
case ST_uint16array:
_pack_type = PT_array;
_nested_type = ST_uint16;
_has_nested_fields = true;
_bytes_per_element = 2;
break;
case ST_uint32array:
_pack_type = PT_array;
_nested_type = ST_uint32;
_has_nested_fields = true;
_bytes_per_element = 4;
break;
case ST_uint32uint8array:
_pack_type = PT_array;
_has_nested_fields = true;
_bytes_per_element = 5;
break;
case ST_blob32:
_num_length_bytes = 4;
// fall through
case ST_blob:
case ST_string:
// For these types, we will present an array interface as an array
// of uint8, but we will also accept a set_value() with a string
// parameter.
_pack_type = PT_string;
_nested_type = ST_uint8;
_has_nested_fields = true;
_bytes_per_element = 1;
break;
// The simple types can be packed directly.
case ST_int8:
_pack_type = PT_int;
_has_fixed_byte_size = true;
_fixed_byte_size = 1;
break;
case ST_int16:
_pack_type = PT_int;
_has_fixed_byte_size = true;
_fixed_byte_size = 2;
break;
case ST_int32:
_pack_type = PT_int;
_has_fixed_byte_size = true;
_fixed_byte_size = 4;
break;
case ST_int64:
_pack_type = PT_int64;
_has_fixed_byte_size = true;
_fixed_byte_size = 8;
break;
case ST_uint8:
_pack_type = PT_uint;
_has_fixed_byte_size = true;
_fixed_byte_size = 1;
break;
case ST_uint16:
_pack_type = PT_uint;
_has_fixed_byte_size = true;
_fixed_byte_size = 2;
break;
case ST_uint32:
_pack_type = PT_uint;
_has_fixed_byte_size = true;
_fixed_byte_size = 4;
break;
case ST_uint64:
_pack_type = PT_uint64;
_has_fixed_byte_size = true;
_fixed_byte_size = 8;
break;
case ST_float64:
_pack_type = PT_double;
_has_fixed_byte_size = true;
_fixed_byte_size = 8;
break;
case ST_invalid:
break;
}
set_divisor(divisor);
if (_nested_type != ST_invalid) {
_nested_field = create_nested_field(_nested_type, _divisor);
} else if (_type == ST_uint32uint8array) {
// This one is a special case. We must create a special nested
// type that accepts a uint32 followed by a uint8 for each
// element.
_nested_field = create_uint32uint8_type();
} else {
_nested_field = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
DCSimpleParameter::
DCSimpleParameter(const DCSimpleParameter &copy) :
DCParameter(copy),
_type(copy._type),
_divisor(copy._divisor),
_nested_field(copy._nested_field),
_bytes_per_element(copy._bytes_per_element)
{
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::as_simple_parameter
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DCSimpleParameter *DCSimpleParameter::
as_simple_parameter() {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::make_copy
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DCParameter *DCSimpleParameter::
make_copy() const {
return new DCSimpleParameter(*this);
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::is_valid
// Access: Published, Virtual
// Description: Returns false if the type is an invalid type
// (e.g. declared from an undefined typedef), true if
// it is valid.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
is_valid() const {
return _type != ST_invalid;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::get_type
// Access: Published
// Description: Returns the particular subatomic type represented by
// this instance.
////////////////////////////////////////////////////////////////////
DCSubatomicType DCSimpleParameter::
get_type() const {
return _type;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::get_divisor
// Access: Published
// Description: Returns the divisor associated with this type. This
// is 1 by default, but if this is other than one it
// represents the scale to apply when packing and
// unpacking numeric values (to store fixed-point values
// in an integer field). It is only meaningful for
// numeric-type fields.
////////////////////////////////////////////////////////////////////
int DCSimpleParameter::
get_divisor() const {
return _divisor;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::set_divisor
// Access: Public
// Description: Assigns the indicated divisor to the simple type.
// Returns true if assigned, false if this type cannot
// accept a divisor.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
set_divisor(int divisor) {
if (_pack_type == PT_string || divisor == 0) {
return false;
}
_divisor = divisor;
if ((_divisor != 1) &&
(_pack_type == PT_int || _pack_type == PT_int64 ||
_pack_type == PT_uint || _pack_type == PT_uint64)) {
_pack_type = PT_double;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::calc_num_nested_fields
// Access: Public, Virtual
// Description: This flavor of get_num_nested_fields is used during
// unpacking. It returns the number of nested fields to
// expect, given a certain length in bytes (as read from
// the _num_length_bytes stored in the stream on the
// push). This will only be called if _num_length_bytes
// is nonzero.
////////////////////////////////////////////////////////////////////
int DCSimpleParameter::
calc_num_nested_fields(size_t length_bytes) const {
if (_bytes_per_element != 0) {
return length_bytes / _bytes_per_element;
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::get_nested_field
// Access: Public, Virtual
// Description: Returns the DCPackerInterface object that represents
// the nth nested field. This may return NULL if there
// is no such field (but it shouldn't do this if n is in
// the range 0 <= n < get_num_nested_fields()).
////////////////////////////////////////////////////////////////////
DCPackerInterface *DCSimpleParameter::
get_nested_field(int) const {
return _nested_field;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::pack_double
// Access: Published, Virtual
// Description: Packs the indicated numeric or string value into the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
pack_double(DCPackData &pack_data, double value) const {
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));
break;
case ST_int16:
do_pack_int16(pack_data.get_write_pointer(2),
(int)floor(real_value + 0.5));
break;
case ST_int32:
do_pack_int32(pack_data.get_write_pointer(4),
(int)floor(real_value + 0.5));
break;
case ST_int64:
do_pack_int64(pack_data.get_write_pointer(8),
(PN_int64)floor(real_value + 0.5));
break;
case ST_uint8:
do_pack_uint8(pack_data.get_write_pointer(1),
(unsigned int)floor(real_value + 0.5));
break;
case ST_uint16:
do_pack_uint16(pack_data.get_write_pointer(2),
(unsigned int)floor(real_value + 0.5));
break;
case ST_uint32:
do_pack_uint32(pack_data.get_write_pointer(4),
(unsigned int)floor(real_value + 0.5));
break;
case ST_uint64:
do_pack_uint64(pack_data.get_write_pointer(8),
(PN_uint64)floor(real_value + 0.5));
break;
case ST_float64:
do_pack_float64(pack_data.get_write_pointer(8), real_value);
break;
default:
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::pack_int
// Access: Published, Virtual
// Description: Packs the indicated numeric or string value into the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
pack_int(DCPackData &pack_data, int value) const {
int int_value = value * _divisor;
switch (_type) {
case ST_int8:
do_pack_int8(pack_data.get_write_pointer(1), int_value);
break;
case ST_int16:
do_pack_int16(pack_data.get_write_pointer(2), int_value);
break;
case ST_int32:
do_pack_int32(pack_data.get_write_pointer(4), int_value);
break;
case ST_int64:
do_pack_int64(pack_data.get_write_pointer(8), int_value);
break;
case ST_uint8:
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
break;
case ST_uint16:
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
break;
case ST_uint32:
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
break;
case ST_uint64:
do_pack_uint64(pack_data.get_write_pointer(8), (unsigned int)int_value);
break;
case ST_float64:
do_pack_float64(pack_data.get_write_pointer(8), int_value);
break;
default:
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::pack_uint
// Access: Published, Virtual
// Description: Packs the indicated numeric or string value into the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
pack_uint(DCPackData &pack_data, unsigned int value) const {
unsigned int int_value = value * _divisor;
switch (_type) {
case ST_int8:
do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
break;
case ST_int16:
do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
break;
case ST_int32:
do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
break;
case ST_int64:
do_pack_int64(pack_data.get_write_pointer(8), (int)int_value);
break;
case ST_uint8:
do_pack_uint8(pack_data.get_write_pointer(1), int_value);
break;
case ST_uint16:
do_pack_uint16(pack_data.get_write_pointer(2), int_value);
break;
case ST_uint32:
do_pack_uint32(pack_data.get_write_pointer(4), int_value);
break;
case ST_uint64:
do_pack_uint64(pack_data.get_write_pointer(8), int_value);
break;
case ST_float64:
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
break;
default:
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::pack_int64
// Access: Published, Virtual
// Description: Packs the indicated numeric or string value into the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
pack_int64(DCPackData &pack_data, PN_int64 value) const {
PN_int64 int_value = value * _divisor;
switch (_type) {
case ST_int8:
do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
break;
case ST_int16:
do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
break;
case ST_int32:
do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
break;
case ST_int64:
do_pack_int64(pack_data.get_write_pointer(8), int_value);
break;
case ST_uint8:
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)(PN_uint64)int_value);
break;
case ST_uint16:
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)(PN_uint64)int_value);
break;
case ST_uint32:
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)(PN_uint64)int_value);
break;
case ST_uint64:
do_pack_uint64(pack_data.get_write_pointer(8), (PN_uint64)int_value);
break;
case ST_float64:
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
break;
default:
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::pack_uint64
// Access: Published, Virtual
// Description: Packs the indicated numeric or string value into the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
pack_uint64(DCPackData &pack_data, PN_uint64 value) const {
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);
break;
case ST_int16:
do_pack_int16(pack_data.get_write_pointer(2), (int)(PN_int64)int_value);
break;
case ST_int32:
do_pack_int32(pack_data.get_write_pointer(4), (int)(PN_int64)int_value);
break;
case ST_int64:
do_pack_int64(pack_data.get_write_pointer(8), (PN_int64)int_value);
break;
case ST_uint8:
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
break;
case ST_uint16:
do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
break;
case ST_uint32:
do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
break;
case ST_uint64:
do_pack_uint64(pack_data.get_write_pointer(8), int_value);
break;
case ST_float64:
do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
break;
default:
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::pack_string
// Access: Published, Virtual
// Description: Packs the indicated numeric or string value into the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
pack_string(DCPackData &pack_data, const string &value) const {
switch (_type) {
case ST_string:
case ST_blob:
do_pack_uint16(pack_data.get_write_pointer(2), value.length());
pack_data.append_data(value.data(), value.length());
break;
case ST_blob32:
do_pack_uint32(pack_data.get_write_pointer(4), value.length());
pack_data.append_data(value.data(), value.length());
break;
default:
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::unpack_double
// Access: Public, Virtual
// Description: Unpacks the current numeric or string value from the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
unpack_double(const char *data, size_t length, size_t &p, double &value) const {
switch (_type) {
case ST_int8:
if (p + 1 > length) {
return false;
}
value = do_unpack_int8(data + p);
p++;
break;
case ST_int16:
if (p + 2 > length) {
return false;
}
value = do_unpack_int16(data + p);
p += 2;
break;
case ST_int32:
if (p + 4 > length) {
return false;
}
value = do_unpack_int32(data + p);
p += 4;
break;
case ST_int64:
if (p + 8 > length) {
return false;
}
value = (double)do_unpack_int64(data + p);
p += 8;
break;
case ST_uint8:
if (p + 1 > length) {
return false;
}
value = do_unpack_uint8(data + p);
p++;
break;
case ST_uint16:
if (p + 2 > length) {
return false;
}
value = do_unpack_uint16(data + p);
p += 2;
break;
case ST_uint32:
if (p + 4 > length) {
return false;
}
value = do_unpack_uint32(data + p);
p += 4;
break;
case ST_uint64:
if (p + 8 > length) {
return false;
}
value = (double)do_unpack_uint64(data + p);
p += 8;
break;
case ST_float64:
if (p + 8 > length) {
return false;
}
value = do_unpack_float64(data + p);
p += 8;
break;
default:
return false;
}
if (_divisor != 1) {
value = value / _divisor;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::unpack_int
// Access: Public, Virtual
// Description: Unpacks the current numeric or string value from the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
unpack_int(const char *data, size_t length, size_t &p, int &value) const {
switch (_type) {
case ST_int8:
if (p + 1 > length) {
return false;
}
value = do_unpack_int8(data + p);
p++;
break;
case ST_int16:
if (p + 2 > length) {
return false;
}
value = do_unpack_int16(data + p);
p += 2;
break;
case ST_int32:
if (p + 4 > length) {
return false;
}
value = do_unpack_int32(data + p);
p += 4;
break;
case ST_int64:
if (p + 8 > length) {
return false;
}
value = (int)do_unpack_int64(data + p);
p += 8;
break;
case ST_uint8:
if (p + 1 > length) {
return false;
}
value = (int)do_unpack_uint8(data + p);
p++;
break;
case ST_uint16:
if (p + 2 > length) {
return false;
}
value = (int)do_unpack_uint16(data + p);
p += 2;
break;
case ST_uint32:
if (p + 4 > length) {
return false;
}
value = (int)do_unpack_uint32(data + p);
p += 4;
break;
case ST_uint64:
if (p + 8 > length) {
return false;
}
value = (int)(unsigned int)do_unpack_uint64(data + p);
p += 8;
break;
case ST_float64:
if (p + 8 > length) {
return false;
}
value = (int)do_unpack_float64(data + p);
p += 8;
break;
default:
return false;
}
if (_divisor != 1) {
value = value / _divisor;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::unpack_uint
// Access: Public, Virtual
// Description: Unpacks the current numeric or string value from the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value) const {
switch (_type) {
case ST_int8:
if (p + 1 > length) {
return false;
}
value = (unsigned int)do_unpack_int8(data + p);
p++;
break;
case ST_int16:
if (p + 2 > length) {
return false;
}
value = (unsigned int)do_unpack_int16(data + p);
p += 2;
break;
case ST_int32:
if (p + 4 > length) {
return false;
}
value = (unsigned int)do_unpack_int32(data + p);
p += 4;
break;
case ST_int64:
if (p + 8 > length) {
return false;
}
value = (unsigned int)do_unpack_int64(data + p);
p += 8;
break;
case ST_uint8:
if (p + 1 > length) {
return false;
}
value = do_unpack_uint8(data + p);
p++;
break;
case ST_uint16:
if (p + 2 > length) {
return false;
}
value = do_unpack_uint16(data + p);
p += 2;
break;
case ST_uint32:
if (p + 4 > length) {
return false;
}
value = do_unpack_uint32(data + p);
p += 4;
break;
case ST_uint64:
if (p + 8 > length) {
return false;
}
value = (unsigned int)do_unpack_uint64(data + p);
p += 8;
break;
case ST_float64:
if (p + 8 > length) {
return false;
}
value = (unsigned int)do_unpack_float64(data + p);
p += 8;
break;
default:
return false;
}
if (_divisor != 1) {
value = value / _divisor;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::unpack_int64
// Access: Public, Virtual
// Description: Unpacks the current numeric or string value from the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value) const {
switch (_type) {
case ST_int8:
if (p + 1 > length) {
return false;
}
value = do_unpack_int8(data + p);
p++;
break;
case ST_int16:
if (p + 2 > length) {
return false;
}
value = do_unpack_int16(data + p);
p += 2;
break;
case ST_int32:
if (p + 4 > length) {
return false;
}
value = do_unpack_int32(data + p);
p += 4;
break;
case ST_int64:
if (p + 8 > length) {
return false;
}
value = do_unpack_int64(data + p);
p += 8;
break;
case ST_uint8:
if (p + 1 > length) {
return false;
}
value = (int)do_unpack_uint8(data + p);
p++;
break;
case ST_uint16:
if (p + 2 > length) {
return false;
}
value = (int)do_unpack_uint16(data + p);
p += 2;
break;
case ST_uint32:
if (p + 4 > length) {
return false;
}
value = (int)do_unpack_uint32(data + p);
p += 4;
break;
case ST_uint64:
if (p + 8 > length) {
return false;
}
value = (PN_int64)do_unpack_uint64(data + p);
p += 8;
break;
case ST_float64:
if (p + 8 > length) {
return false;
}
value = (PN_int64)do_unpack_float64(data + p);
p += 8;
break;
default:
return false;
}
if (_divisor != 1) {
value = value / _divisor;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::unpack_uint64
// Access: Public, Virtual
// Description: Unpacks the current numeric or string value from the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value) const {
switch (_type) {
case ST_int8:
if (p + 1 > length) {
return false;
}
value = (unsigned int)do_unpack_int8(data + p);
p++;
break;
case ST_int16:
if (p + 2 > length) {
return false;
}
value = (unsigned int)do_unpack_int16(data + p);
p += 2;
break;
case ST_int32:
if (p + 4 > length) {
return false;
}
value = (unsigned int)do_unpack_int32(data + p);
p += 4;
break;
case ST_int64:
if (p + 8 > length) {
return false;
}
value = (PN_uint64)do_unpack_int64(data + p);
p += 8;
break;
case ST_uint8:
if (p + 1 > length) {
return false;
}
value = do_unpack_uint8(data + p);
p++;
break;
case ST_uint16:
if (p + 2 > length) {
return false;
}
value = do_unpack_uint16(data + p);
p += 2;
break;
case ST_uint32:
if (p + 4 > length) {
return false;
}
value = do_unpack_uint32(data + p);
p += 4;
break;
case ST_uint64:
if (p + 8 > length) {
return false;
}
value = do_unpack_uint64(data + p);
p += 8;
break;
case ST_float64:
if (p + 8 > length) {
return false;
}
value = (PN_uint64)do_unpack_float64(data + p);
p += 8;
break;
default:
return false;
}
if (_divisor != 1) {
value = value / _divisor;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::unpack_string
// Access: Public, Virtual
// Description: Unpacks the current numeric or string value from the
// stream. Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool DCSimpleParameter::
unpack_string(const char *data, size_t length, size_t &p, string &value) const {
size_t string_length;
switch (_type) {
case ST_string:
case ST_blob:
if (p + 2 > length) {
return false;
}
string_length = do_unpack_uint16(data + p);
p += 2;
break;
case ST_blob32:
if (p + 4 > length) {
return false;
}
string_length = do_unpack_uint32(data + p);
p += 4;
break;
default:
return false;
}
if (p + string_length > length) {
return false;
}
value = string(data + p, string_length);
p += string_length;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::output_instance
// Access: Public, Virtual
// Description: Formats the parameter in the C++-like dc syntax as a
// typename and identifier.
////////////////////////////////////////////////////////////////////
void DCSimpleParameter::
output_instance(ostream &out, const string &prename, const string &name,
const string &postname) const {
if (get_typedef() != (DCTypedef *)NULL) {
out << get_typedef()->get_name();
} else {
out << _type;
}
if (_divisor != 1) {
out << "/" << _divisor;
}
if (!prename.empty() || !name.empty() || !postname.empty()) {
out << " " << prename << name << postname;
}
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::generate_hash
// Access: Public, Virtual
// Description: Accumulates the properties of this type into the
// hash.
////////////////////////////////////////////////////////////////////
void DCSimpleParameter::
generate_hash(HashGenerator &hashgen) const {
DCParameter::generate_hash(hashgen);
hashgen.add_int(_type);
hashgen.add_int(_divisor);
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::create_nested_field
// Access: Private, Static
// Description: Creates the one instance of the DCSimpleParameter
// corresponding to this combination of type and divisor
// if it is not already created.
////////////////////////////////////////////////////////////////////
DCSimpleParameter *DCSimpleParameter::
create_nested_field(DCSubatomicType type, int divisor) {
DivisorMap divisor_map = _nested_field_map[type];
DivisorMap::iterator di;
di = divisor_map.find(divisor);
if (di != divisor_map.end()) {
return (*di).second;
}
DCSimpleParameter *nested_field = new DCSimpleParameter(type, divisor);
divisor_map[divisor] = nested_field;
return nested_field;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::create_uint32uint8_type
// Access: Private, Static
// Description: Creates the one instance of the Uint32Uint8Type
// object if it is not already created.
////////////////////////////////////////////////////////////////////
DCPackerInterface *DCSimpleParameter::
create_uint32uint8_type() {
if (_uint32uint8_type == NULL) {
_uint32uint8_type = new Uint32Uint8Type;
}
return _uint32uint8_type;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::Uint32Uint8Type::Constructor
// Access: Public
// Description: This special packer interface is provided just to
// implement uint32uint8array, which is a special kind
// of array that consists of nested pairs of (uint32,
// uint8) values.
////////////////////////////////////////////////////////////////////
DCSimpleParameter::Uint32Uint8Type::
Uint32Uint8Type() {
_uint32_type = new DCSimpleParameter(ST_uint32);
_uint8_type = new DCSimpleParameter(ST_uint8);
_has_nested_fields = true;
_num_nested_fields = 2;
_pack_type = PT_class;
}
////////////////////////////////////////////////////////////////////
// Function: DCSimpleParameter::Uint32Uint8Type::get_nested_field
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
DCPackerInterface *DCSimpleParameter::Uint32Uint8Type::
get_nested_field(int n) const {
switch (n) {
case 0:
return _uint32_type;
case 1:
return _uint8_type;
default:
return NULL;
}
}