383 lines
9.8 KiB
Text
383 lines
9.8 KiB
Text
/**
|
|
* 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."
|
|
*
|
|
* @file dcPackerInterface.I
|
|
* @author drose
|
|
* @date 2004-06-18
|
|
*/
|
|
|
|
/**
|
|
* Returns the name of this field, or empty string if the field is unnamed.
|
|
*/
|
|
INLINE const std::string &DCPackerInterface::
|
|
get_name() const {
|
|
return _name;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* Returns the type of value expected by this field.
|
|
*/
|
|
INLINE DCPackType DCPackerInterface::
|
|
get_pack_type() const {
|
|
return _pack_type;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
do_pack_int8(char *buffer, int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
do_pack_int16(char *buffer, int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
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);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
do_pack_int64(char *buffer, int64_t 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);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
do_pack_uint8(char *buffer, unsigned int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
do_pack_uint16(char *buffer, unsigned int value) {
|
|
buffer[0] = (char)(value & 0xff);
|
|
buffer[1] = (char)((value >> 8) & 0xff);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
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);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
do_pack_uint64(char *buffer, uint64_t 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);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
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
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE int DCPackerInterface::
|
|
do_unpack_int8(const char *buffer) {
|
|
return (int)(signed char)buffer[0];
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE int DCPackerInterface::
|
|
do_unpack_int16(const char *buffer) {
|
|
return (int)((unsigned int)(unsigned char)buffer[0] |
|
|
((int)(signed char)buffer[1] << 8));
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
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));
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE int64_t DCPackerInterface::
|
|
do_unpack_int64(const char *buffer) {
|
|
return (int64_t)((uint64_t)(unsigned char)buffer[0] |
|
|
((uint64_t)(unsigned char)buffer[1] << 8) |
|
|
((uint64_t)(unsigned char)buffer[2] << 16) |
|
|
((uint64_t)(unsigned char)buffer[3] << 24) |
|
|
((uint64_t)(unsigned char)buffer[4] << 32) |
|
|
((uint64_t)(unsigned char)buffer[5] << 40) |
|
|
((uint64_t)(unsigned char)buffer[6] << 48) |
|
|
((int64_t)(signed char)buffer[7] << 54));
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
INLINE unsigned int DCPackerInterface::
|
|
do_unpack_uint8(const char *buffer) {
|
|
return (unsigned int)(unsigned char)buffer[0];
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE unsigned int DCPackerInterface::
|
|
do_unpack_uint16(const char *buffer) {
|
|
return ((unsigned int)(unsigned char)buffer[0] |
|
|
((unsigned int)(unsigned char)buffer[1] << 8));
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
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));
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
INLINE uint64_t DCPackerInterface::
|
|
do_unpack_uint64(const char *buffer) {
|
|
return ((uint64_t)(unsigned char)buffer[0] |
|
|
((uint64_t)(unsigned char)buffer[1] << 8) |
|
|
((uint64_t)(unsigned char)buffer[2] << 16) |
|
|
((uint64_t)(unsigned char)buffer[3] << 24) |
|
|
((uint64_t)(unsigned char)buffer[4] << 32) |
|
|
((uint64_t)(unsigned char)buffer[5] << 40) |
|
|
((uint64_t)(unsigned char)buffer[6] << 48) |
|
|
((int64_t)(signed char)buffer[7] << 54));
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
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
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Confirms that the signed value fits within num_bits bits. Sets range_error
|
|
* true if it does not.
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
validate_int64_limits(int64_t value, int num_bits, bool &range_error) {
|
|
int64_t mask = ((int64_t)1 << (num_bits - 1)) - 1;
|
|
value |= mask;
|
|
|
|
if (value != mask && value != -1) {
|
|
range_error = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Confirms that the unsigned value fits within num_bits bits. Sets
|
|
* range_error true if it does not.
|
|
*/
|
|
INLINE void DCPackerInterface::
|
|
validate_uint64_limits(uint64_t value, int num_bits, bool &range_error) {
|
|
uint64_t mask = ((uint64_t)1 << num_bits) - 1;
|
|
value &= ~mask;
|
|
|
|
if (value != 0) {
|
|
range_error = true;
|
|
}
|
|
}
|