459 lines
18 KiB
Plaintext
459 lines
18 KiB
Plaintext
// Filename: dcPackerInterface.I
|
|
// Created by: drose (18Jun04)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// 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::check_match
|
|
// Access: Published
|
|
// Description: Returns true if the other interface is bitwise the
|
|
// same as this one--that is, a uint32 only matches a
|
|
// uint32, etc. Names of components, and range limits,
|
|
// are not compared.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool DCPackerInterface::
|
|
check_match(const DCPackerInterface *other) const {
|
|
return do_check_match(other);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// 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::has_fixed_structure
|
|
// Access: Public
|
|
// Description: Returns true if this field type always has the same
|
|
// structure regardless of the data in the stream, or
|
|
// false if its structure may vary. This is almost, but
|
|
// not quite, the same thing as has_fixed_byte_size.
|
|
// The difference is that a DCSwitch may have multiple
|
|
// cases all with the same byte size, but they will
|
|
// still (presumably) have different structures, in the
|
|
// sense that the actual list of fields varies according
|
|
// to the live data.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool DCPackerInterface::
|
|
has_fixed_structure() const {
|
|
return _has_fixed_structure;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::has_range_limits
|
|
// Access: Public
|
|
// Description: Returns true if this field, or any sub-field of this
|
|
// field, has a limit imposed in the DC file on its
|
|
// legal values. If this is false, then
|
|
// unpack_validate() is trivial.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool DCPackerInterface::
|
|
has_range_limits() const {
|
|
return _has_range_limits;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// 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) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_int16
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_int16(char *buffer, int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_int32
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_int32(char *buffer, int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
buffer[2] = (char)((value >> 16) & 0xff);
|
|
buffer[3] = (char)((value >> 24) & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_int64
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_int64(char *buffer, PN_int64 value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
buffer[2] = (char)((value >> 16) & 0xff);
|
|
buffer[3] = (char)((value >> 24) & 0xff);
|
|
buffer[4] = (char)((value >> 32) & 0xff);
|
|
buffer[5] = (char)((value >> 40) & 0xff);
|
|
buffer[6] = (char)((value >> 48) & 0xff);
|
|
buffer[7] = (char)((value >> 56) & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_uint8
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_uint8(char *buffer, unsigned int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_uint16
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_uint16(char *buffer, unsigned int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_uint32
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_uint32(char *buffer, unsigned int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
buffer[2] = (char)((value >> 16) & 0xff);
|
|
buffer[3] = (char)((value >> 24) & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_uint64
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_uint64(char *buffer, PN_uint64 value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
buffer[2] = (char)((value >> 16) & 0xff);
|
|
buffer[3] = (char)((value >> 24) & 0xff);
|
|
buffer[4] = (char)((value >> 32) & 0xff);
|
|
buffer[5] = (char)((value >> 40) & 0xff);
|
|
buffer[6] = (char)((value >> 48) & 0xff);
|
|
buffer[7] = (char)((value >> 56) & 0xff);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_pack_float64
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
do_pack_float64(char *buffer, double value) {
|
|
#ifdef WORDS_BIGENDIAN
|
|
// Reverse the byte ordering for big-endian machines.
|
|
char *p = (char *)&value;
|
|
for (size_t i = 0; i < 8; i++) {
|
|
buffer[i] = p[7 - i];
|
|
}
|
|
#else
|
|
memcpy(buffer, &value, 8);
|
|
#endif
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_int8
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int DCPackerInterface::
|
|
do_unpack_int8(const char *buffer) {
|
|
return (int)(signed char)buffer[0];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_int16
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int DCPackerInterface::
|
|
do_unpack_int16(const char *buffer) {
|
|
return (int)((unsigned int)(unsigned char)buffer[0] |
|
|
((int)(signed char)buffer[1] << 8));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_int32
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int DCPackerInterface::
|
|
do_unpack_int32(const char *buffer) {
|
|
return (int)((unsigned int)(unsigned char)buffer[0] |
|
|
((unsigned int)(unsigned char)buffer[1] << 8) |
|
|
((unsigned int)(unsigned char)buffer[2] << 16) |
|
|
((int)(signed char)buffer[3] << 24));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_int64
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE PN_int64 DCPackerInterface::
|
|
do_unpack_int64(const char *buffer) {
|
|
return (PN_int64)((PN_uint64)(unsigned char)buffer[0] |
|
|
((PN_uint64)(unsigned char)buffer[1] << 8) |
|
|
((PN_uint64)(unsigned char)buffer[2] << 16) |
|
|
((PN_uint64)(unsigned char)buffer[3] << 24) |
|
|
((PN_uint64)(unsigned char)buffer[4] << 32) |
|
|
((PN_uint64)(unsigned char)buffer[5] << 40) |
|
|
((PN_uint64)(unsigned char)buffer[6] << 48) |
|
|
((PN_int64)(signed char)buffer[7] << 54));
|
|
}
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_uint8
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE unsigned int DCPackerInterface::
|
|
do_unpack_uint8(const char *buffer) {
|
|
return (unsigned int)(unsigned char)buffer[0];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_uint16
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE unsigned int DCPackerInterface::
|
|
do_unpack_uint16(const char *buffer) {
|
|
return ((unsigned int)(unsigned char)buffer[0] |
|
|
((unsigned int)(unsigned char)buffer[1] << 8));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_uint32
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE unsigned int DCPackerInterface::
|
|
do_unpack_uint32(const char *buffer) {
|
|
return ((unsigned int)(unsigned char)buffer[0] |
|
|
((unsigned int)(unsigned char)buffer[1] << 8) |
|
|
((unsigned int)(unsigned char)buffer[2] << 16) |
|
|
((unsigned int)(unsigned char)buffer[3] << 24));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_uint64
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE PN_uint64 DCPackerInterface::
|
|
do_unpack_uint64(const char *buffer) {
|
|
return ((PN_uint64)(unsigned char)buffer[0] |
|
|
((PN_uint64)(unsigned char)buffer[1] << 8) |
|
|
((PN_uint64)(unsigned char)buffer[2] << 16) |
|
|
((PN_uint64)(unsigned char)buffer[3] << 24) |
|
|
((PN_uint64)(unsigned char)buffer[4] << 32) |
|
|
((PN_uint64)(unsigned char)buffer[5] << 40) |
|
|
((PN_uint64)(unsigned char)buffer[6] << 48) |
|
|
((PN_int64)(signed char)buffer[7] << 54));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::do_unpack_float64
|
|
// Access: Public, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double DCPackerInterface::
|
|
do_unpack_float64(const char *buffer) {
|
|
#ifdef WORDS_BIGENDIAN
|
|
char reverse[8];
|
|
|
|
// Reverse the byte ordering for big-endian machines.
|
|
for (size_t i = 0; i < 8; i++) {
|
|
reverse[i] = buffer[7 - i];
|
|
}
|
|
return *(double *)reverse;
|
|
#else
|
|
return *(double *)buffer;
|
|
#endif // WORDS_BIGENDIAN
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::validate_int_limits
|
|
// Access: Public, Static
|
|
// Description: Confirms that the signed value fits within num_bits
|
|
// bits. Sets range_error true if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
validate_int_limits(int value, int num_bits, bool &range_error) {
|
|
// What we're really checking is that all of the bits above the
|
|
// lower (num_bits - 1) bits are the same--either all 1 or all 0.
|
|
|
|
// First, turn on the lower (num_bits - 1).
|
|
int mask = ((int)1 << (num_bits - 1)) - 1;
|
|
value |= mask;
|
|
|
|
// The result should be either mask (all high bits are 0) or -1 (all
|
|
// high bits are 1). If it is anything else we have a range error.
|
|
if (value != mask && value != -1) {
|
|
range_error = true;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::validate_int64_limits
|
|
// Access: Public, Static
|
|
// Description: Confirms that the signed value fits within num_bits
|
|
// bits. Sets range_error true if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
validate_int64_limits(PN_int64 value, int num_bits, bool &range_error) {
|
|
PN_int64 mask = ((PN_int64)1 << (num_bits - 1)) - 1;
|
|
value |= mask;
|
|
|
|
if (value != mask && value != -1) {
|
|
range_error = true;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::validate_uint_limits
|
|
// Access: Public, Static
|
|
// Description: Confirms that the unsigned value fits within num_bits
|
|
// bits. Sets range_error true if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
validate_uint_limits(unsigned int value, int num_bits, bool &range_error) {
|
|
// Here we're really checking that all of the bits above the lower
|
|
// num_bits bits are all 0.
|
|
|
|
unsigned int mask = ((unsigned int)1 << num_bits) - 1;
|
|
value &= ~mask;
|
|
|
|
if (value != 0) {
|
|
range_error = true;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCPackerInterface::validate_uint64_limits
|
|
// Access: Public, Static
|
|
// Description: Confirms that the unsigned value fits within num_bits
|
|
// bits. Sets range_error true if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void DCPackerInterface::
|
|
validate_uint64_limits(PN_uint64 value, int num_bits, bool &range_error) {
|
|
PN_uint64 mask = ((PN_uint64)1 << num_bits) - 1;
|
|
value &= ~mask;
|
|
|
|
if (value != 0) {
|
|
range_error = true;
|
|
}
|
|
}
|