historical/toontown-classic.git/panda/include/dcPackerInterface.I
2024-01-16 11:20:27 -06:00

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