Panda3D
dcPackerInterface.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file dcPackerInterface.I
10  * @author drose
11  * @date 2004-06-18
12  */
13 
14 /**
15  * Returns the name of this field, or empty string if the field is unnamed.
16  */
17 INLINE const std::string &DCPackerInterface::
18 get_name() const {
19  return _name;
20 }
21 
22 /**
23  * Returns true if the other interface is bitwise the same as this one--that
24  * is, a uint32 only matches a uint32, etc. Names of components, and range
25  * limits, are not compared.
26  */
27 INLINE bool DCPackerInterface::
28 check_match(const DCPackerInterface *other) const {
29  return do_check_match(other);
30 }
31 
32 /**
33  * Returns true if this field type always packs to the same number of bytes,
34  * false if it is variable.
35  */
36 INLINE bool DCPackerInterface::
38  return _has_fixed_byte_size;
39 }
40 
41 /**
42  * If has_fixed_byte_size() returns true, this returns the number of bytes
43  * this field type will use.
44  */
45 INLINE size_t DCPackerInterface::
47  return _fixed_byte_size;
48 }
49 
50 /**
51  * Returns true if this field type always has the same structure regardless of
52  * the data in the stream, or false if its structure may vary. This is
53  * almost, but not quite, the same thing as has_fixed_byte_size. The
54  * difference is that a DCSwitch may have multiple cases all with the same
55  * byte size, but they will still (presumably) have different structures, in
56  * the sense that the actual list of fields varies according to the live data.
57  */
58 INLINE bool DCPackerInterface::
60  return _has_fixed_structure;
61 }
62 
63 /**
64  * Returns true if this field, or any sub-field of this field, has a limit
65  * imposed in the DC file on its legal values. If this is false, then
66  * unpack_validate() is trivial.
67  */
68 INLINE bool DCPackerInterface::
70  return _has_range_limits;
71 }
72 
73 /**
74  * Returns the number of bytes that should be written into the stream on a
75  * push() to record the number of bytes in the record up until the next pop().
76  * This is only meaningful if _has_nested_fields is true.
77  */
78 INLINE size_t DCPackerInterface::
80  return _num_length_bytes;
81 }
82 
83 
84 /**
85  * Returns true if this field type has any nested fields (and thus expects a
86  * push() .. pop() interface to the DCPacker), or false otherwise. If this
87  * returns true, get_num_nested_fields() may be called to determine how many
88  * nested fields are expected.
89  */
90 INLINE bool DCPackerInterface::
92  return _has_nested_fields;
93 }
94 
95 /**
96  * Returns the number of nested fields required by this field type. These may
97  * be array elements or structure elements. The return value may be -1 to
98  * indicate the number of nested fields is variable.
99  */
100 INLINE int DCPackerInterface::
102  return _num_nested_fields;
103 }
104 
105 /**
106  * Returns the type of value expected by this field.
107  */
108 INLINE DCPackType DCPackerInterface::
109 get_pack_type() const {
110  return _pack_type;
111 }
112 
113 /**
114  *
115  */
116 INLINE void DCPackerInterface::
117 do_pack_int8(char *buffer, int value) {
118  buffer[0] = (char)(value & 0xff);
119 }
120 
121 /**
122  *
123  */
124 INLINE void DCPackerInterface::
125 do_pack_int16(char *buffer, int value) {
126  buffer[0] = (char)(value & 0xff);
127  buffer[1] = (char)((value >> 8) & 0xff);
128 }
129 
130 /**
131  *
132  */
133 INLINE void DCPackerInterface::
134 do_pack_int32(char *buffer, int value) {
135  buffer[0] = (char)(value & 0xff);
136  buffer[1] = (char)((value >> 8) & 0xff);
137  buffer[2] = (char)((value >> 16) & 0xff);
138  buffer[3] = (char)((value >> 24) & 0xff);
139 }
140 
141 /**
142  *
143  */
144 INLINE void DCPackerInterface::
145 do_pack_int64(char *buffer, int64_t value) {
146  buffer[0] = (char)(value & 0xff);
147  buffer[1] = (char)((value >> 8) & 0xff);
148  buffer[2] = (char)((value >> 16) & 0xff);
149  buffer[3] = (char)((value >> 24) & 0xff);
150  buffer[4] = (char)((value >> 32) & 0xff);
151  buffer[5] = (char)((value >> 40) & 0xff);
152  buffer[6] = (char)((value >> 48) & 0xff);
153  buffer[7] = (char)((value >> 56) & 0xff);
154 }
155 
156 /**
157  *
158  */
159 INLINE void DCPackerInterface::
160 do_pack_uint8(char *buffer, unsigned int value) {
161  buffer[0] = (char)(value & 0xff);
162 }
163 
164 /**
165  *
166  */
167 INLINE void DCPackerInterface::
168 do_pack_uint16(char *buffer, unsigned int value) {
169  buffer[0] = (char)(value & 0xff);
170  buffer[1] = (char)((value >> 8) & 0xff);
171 }
172 
173 /**
174  *
175  */
176 INLINE void DCPackerInterface::
177 do_pack_uint32(char *buffer, unsigned int value) {
178  buffer[0] = (char)(value & 0xff);
179  buffer[1] = (char)((value >> 8) & 0xff);
180  buffer[2] = (char)((value >> 16) & 0xff);
181  buffer[3] = (char)((value >> 24) & 0xff);
182 }
183 
184 /**
185  *
186  */
187 INLINE void DCPackerInterface::
188 do_pack_uint64(char *buffer, uint64_t value) {
189  buffer[0] = (char)(value & 0xff);
190  buffer[1] = (char)((value >> 8) & 0xff);
191  buffer[2] = (char)((value >> 16) & 0xff);
192  buffer[3] = (char)((value >> 24) & 0xff);
193  buffer[4] = (char)((value >> 32) & 0xff);
194  buffer[5] = (char)((value >> 40) & 0xff);
195  buffer[6] = (char)((value >> 48) & 0xff);
196  buffer[7] = (char)((value >> 56) & 0xff);
197 }
198 
199 /**
200  *
201  */
202 INLINE void DCPackerInterface::
203 do_pack_float64(char *buffer, double value) {
204 #ifdef WORDS_BIGENDIAN
205  // Reverse the byte ordering for big-endian machines.
206  char *p = (char *)&value;
207  for (size_t i = 0; i < 8; i++) {
208  buffer[i] = p[7 - i];
209  }
210 #else
211  memcpy(buffer, &value, 8);
212 #endif
213 }
214 
215 
216 /**
217  *
218  */
219 INLINE int DCPackerInterface::
220 do_unpack_int8(const char *buffer) {
221  return (int)(signed char)buffer[0];
222 }
223 
224 /**
225  *
226  */
227 INLINE int DCPackerInterface::
228 do_unpack_int16(const char *buffer) {
229  return (int)((unsigned int)(unsigned char)buffer[0] |
230  ((int)(signed char)buffer[1] << 8));
231 }
232 
233 /**
234  *
235  */
236 INLINE int DCPackerInterface::
237 do_unpack_int32(const char *buffer) {
238  return (int)((unsigned int)(unsigned char)buffer[0] |
239  ((unsigned int)(unsigned char)buffer[1] << 8) |
240  ((unsigned int)(unsigned char)buffer[2] << 16) |
241  ((int)(signed char)buffer[3] << 24));
242 }
243 
244 /**
245  *
246  */
247 INLINE int64_t DCPackerInterface::
248 do_unpack_int64(const char *buffer) {
249  return (int64_t)((uint64_t)(unsigned char)buffer[0] |
250  ((uint64_t)(unsigned char)buffer[1] << 8) |
251  ((uint64_t)(unsigned char)buffer[2] << 16) |
252  ((uint64_t)(unsigned char)buffer[3] << 24) |
253  ((uint64_t)(unsigned char)buffer[4] << 32) |
254  ((uint64_t)(unsigned char)buffer[5] << 40) |
255  ((uint64_t)(unsigned char)buffer[6] << 48) |
256  ((int64_t)(signed char)buffer[7] << 54));
257 }
258 /**
259  *
260  */
261 INLINE unsigned int DCPackerInterface::
262 do_unpack_uint8(const char *buffer) {
263  return (unsigned int)(unsigned char)buffer[0];
264 }
265 
266 /**
267  *
268  */
269 INLINE unsigned int DCPackerInterface::
270 do_unpack_uint16(const char *buffer) {
271  return ((unsigned int)(unsigned char)buffer[0] |
272  ((unsigned int)(unsigned char)buffer[1] << 8));
273 }
274 
275 /**
276  *
277  */
278 INLINE unsigned int DCPackerInterface::
279 do_unpack_uint32(const char *buffer) {
280  return ((unsigned int)(unsigned char)buffer[0] |
281  ((unsigned int)(unsigned char)buffer[1] << 8) |
282  ((unsigned int)(unsigned char)buffer[2] << 16) |
283  ((unsigned int)(unsigned char)buffer[3] << 24));
284 }
285 
286 /**
287  *
288  */
289 INLINE uint64_t DCPackerInterface::
290 do_unpack_uint64(const char *buffer) {
291  return ((uint64_t)(unsigned char)buffer[0] |
292  ((uint64_t)(unsigned char)buffer[1] << 8) |
293  ((uint64_t)(unsigned char)buffer[2] << 16) |
294  ((uint64_t)(unsigned char)buffer[3] << 24) |
295  ((uint64_t)(unsigned char)buffer[4] << 32) |
296  ((uint64_t)(unsigned char)buffer[5] << 40) |
297  ((uint64_t)(unsigned char)buffer[6] << 48) |
298  ((int64_t)(signed char)buffer[7] << 54));
299 }
300 
301 
302 /**
303  *
304  */
305 INLINE double DCPackerInterface::
306 do_unpack_float64(const char *buffer) {
307 #ifdef WORDS_BIGENDIAN
308  char reverse[8];
309 
310  // Reverse the byte ordering for big-endian machines.
311  for (size_t i = 0; i < 8; i++) {
312  reverse[i] = buffer[7 - i];
313  }
314  return *(double *)reverse;
315 #else
316  return *(double *)buffer;
317 #endif // WORDS_BIGENDIAN
318 }
319 
320 /**
321  * Confirms that the signed value fits within num_bits bits. Sets range_error
322  * true if it does not.
323  */
324 INLINE void DCPackerInterface::
325 validate_int_limits(int value, int num_bits, bool &range_error) {
326  // What we're really checking is that all of the bits above the lower
327  // (num_bits - 1) bits are the same--either all 1 or all 0.
328 
329  // First, turn on the lower (num_bits - 1).
330  int mask = ((int)1 << (num_bits - 1)) - 1;
331  value |= mask;
332 
333  // The result should be either mask (all high bits are 0) or -1 (all high
334  // bits are 1). If it is anything else we have a range error.
335  if (value != mask && value != -1) {
336  range_error = true;
337  }
338 }
339 
340 /**
341  * Confirms that the signed value fits within num_bits bits. Sets range_error
342  * true if it does not.
343  */
344 INLINE void DCPackerInterface::
345 validate_int64_limits(int64_t value, int num_bits, bool &range_error) {
346  int64_t mask = ((int64_t)1 << (num_bits - 1)) - 1;
347  value |= mask;
348 
349  if (value != mask && value != -1) {
350  range_error = true;
351  }
352 }
353 
354 /**
355  * Confirms that the unsigned value fits within num_bits bits. Sets
356  * range_error true if it does not.
357  */
358 INLINE void DCPackerInterface::
359 validate_uint_limits(unsigned int value, int num_bits, bool &range_error) {
360  // Here we're really checking that all of the bits above the lower num_bits
361  // bits are all 0.
362 
363  unsigned int mask = ((unsigned int)1 << num_bits) - 1;
364  value &= ~mask;
365 
366  if (value != 0) {
367  range_error = true;
368  }
369 }
370 
371 /**
372  * Confirms that the unsigned value fits within num_bits bits. Sets
373  * range_error true if it does not.
374  */
375 INLINE void DCPackerInterface::
376 validate_uint64_limits(uint64_t value, int num_bits, bool &range_error) {
377  uint64_t mask = ((uint64_t)1 << num_bits) - 1;
378  value &= ~mask;
379 
380  if (value != 0) {
381  range_error = true;
382  }
383 }
static void validate_uint64_limits(uint64_t value, int num_bits, bool &range_error)
Confirms that the unsigned value fits within num_bits bits.
const std::string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
bool has_fixed_structure() const
Returns true if this field type always has the same structure regardless of the data in the stream,...
bool has_nested_fields() const
Returns true if this field type has any nested fields (and thus expects a push() .
static void validate_int_limits(int value, int num_bits, bool &range_error)
Confirms that the signed value fits within num_bits bits.
bool has_fixed_byte_size() const
Returns true if this field type always packs to the same number of bytes, false if it is variable.
int get_num_nested_fields() const
Returns the number of nested fields required by this field type.
size_t get_fixed_byte_size() const
If has_fixed_byte_size() returns true, this returns the number of bytes this field type will use.
bool has_range_limits() const
Returns true if this field, or any sub-field of this field, has a limit imposed in the DC file on its...
bool check_match(const DCPackerInterface *other) const
Returns true if the other interface is bitwise the same as this oneā€“that is, a uint32 only matches a ...
size_t get_num_length_bytes() const
Returns the number of bytes that should be written into the stream on a push() to record the number o...
static void validate_int64_limits(int64_t value, int num_bits, bool &range_error)
Confirms that the signed value fits within num_bits bits.
DCPackType get_pack_type() const
Returns the type of value expected by this field.
This defines the internal interface for packing values into a DCField.
static void validate_uint_limits(unsigned int value, int num_bits, bool &range_error)
Confirms that the unsigned value fits within num_bits bits.