Panda3D
Loading...
Searching...
No Matches
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 */
17INLINE const std::string &DCPackerInterface::
18get_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 */
28check_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 */
37has_fixed_byte_size() const {
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 */
46get_fixed_byte_size() const {
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 */
59has_fixed_structure() const {
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 */
69has_range_limits() const {
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 */
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 */
91has_nested_fields() const {
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 */
101get_num_nested_fields() const {
102 return _num_nested_fields;
103}
104
105/**
106 * Returns the type of value expected by this field.
107 */
108INLINE DCPackType DCPackerInterface::
109get_pack_type() const {
110 return _pack_type;
111}
112
113/**
114 *
115 */
116INLINE void DCPackerInterface::
117do_pack_int8(char *buffer, int value) {
118 buffer[0] = (char)(value & 0xff);
119}
120
121/**
122 *
123 */
124INLINE void DCPackerInterface::
125do_pack_int16(char *buffer, int value) {
126 buffer[0] = (char)(value & 0xff);
127 buffer[1] = (char)((value >> 8) & 0xff);
128}
129
130/**
131 *
132 */
133INLINE void DCPackerInterface::
134do_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 */
144INLINE void DCPackerInterface::
145do_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 */
159INLINE void DCPackerInterface::
160do_pack_uint8(char *buffer, unsigned int value) {
161 buffer[0] = (char)(value & 0xff);
162}
163
164/**
165 *
166 */
167INLINE void DCPackerInterface::
168do_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 */
176INLINE void DCPackerInterface::
177do_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 */
187INLINE void DCPackerInterface::
188do_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 */
202INLINE void DCPackerInterface::
203do_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 */
219INLINE int DCPackerInterface::
220do_unpack_int8(const char *buffer) {
221 return (int)(signed char)buffer[0];
222}
223
224/**
225 *
226 */
227INLINE int DCPackerInterface::
228do_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 */
236INLINE int DCPackerInterface::
237do_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 */
247INLINE int64_t DCPackerInterface::
248do_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] << 56));
257}
258
259/**
260 *
261 */
262INLINE unsigned int DCPackerInterface::
263do_unpack_uint8(const char *buffer) {
264 return (unsigned int)(unsigned char)buffer[0];
265}
266
267/**
268 *
269 */
270INLINE unsigned int DCPackerInterface::
271do_unpack_uint16(const char *buffer) {
272 return ((unsigned int)(unsigned char)buffer[0] |
273 ((unsigned int)(unsigned char)buffer[1] << 8));
274}
275
276/**
277 *
278 */
279INLINE unsigned int DCPackerInterface::
280do_unpack_uint32(const char *buffer) {
281 return ((unsigned int)(unsigned char)buffer[0] |
282 ((unsigned int)(unsigned char)buffer[1] << 8) |
283 ((unsigned int)(unsigned char)buffer[2] << 16) |
284 ((unsigned int)(unsigned char)buffer[3] << 24));
285}
286
287/**
288 *
289 */
290INLINE uint64_t DCPackerInterface::
291do_unpack_uint64(const char *buffer) {
292 return ((uint64_t)(unsigned char)buffer[0] |
293 ((uint64_t)(unsigned char)buffer[1] << 8) |
294 ((uint64_t)(unsigned char)buffer[2] << 16) |
295 ((uint64_t)(unsigned char)buffer[3] << 24) |
296 ((uint64_t)(unsigned char)buffer[4] << 32) |
297 ((uint64_t)(unsigned char)buffer[5] << 40) |
298 ((uint64_t)(unsigned char)buffer[6] << 48) |
299 ((uint64_t)(unsigned char)buffer[7] << 56));
300}
301
302/**
303 *
304 */
305INLINE double DCPackerInterface::
306do_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 */
325validate_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 */
345validate_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 */
359validate_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 */
376validate_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}
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.
bool has_fixed_structure() const
Returns true if this field type always has the same structure regardless of the data in the stream,...
const std::string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
bool has_nested_fields() const
Returns true if this field type has any nested fields (and thus expects a push() .
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.
int get_num_nested_fields() const
Returns the number of nested fields required by this field type.
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.
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_int_limits(int value, int num_bits, bool &range_error)
Confirms that the signed value fits within num_bits bits.
static void validate_uint64_limits(uint64_t value, int num_bits, bool &range_error)
Confirms that the unsigned value fits within num_bits bits.
static void validate_int64_limits(int64_t value, int num_bits, bool &range_error)
Confirms that the signed value fits within num_bits bits.
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 ...
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...
DCPackType get_pack_type() const
Returns the type of value expected by this field.