Panda3D
dcPacker.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 dcPacker.I
10  * @author drose
11  * @date 2004-06-15
12  */
13 
14 /**
15  * Empties the data in the pack buffer and unpack buffer. This should be
16  * called between calls to begin_pack(), unless you want to concatenate all of
17  * the pack results together.
18  */
19 INLINE void DCPacker::
21  _pack_data.clear();
22 
23  if (_owns_unpack_data) {
24  delete[] _unpack_data;
25  _owns_unpack_data = false;
26  }
27  _unpack_data = nullptr;
28 }
29 
30 /**
31  * Returns true if the current field has any nested fields (and thus expects a
32  * push() .. pop() interface), or false otherwise. If this returns true,
33  * get_num_nested_fields() may be called to determine how many nested fields
34  * are expected.
35  */
36 INLINE bool DCPacker::
38  if (_current_field == nullptr) {
39  return false;
40  } else {
41  return _current_field->has_nested_fields();
42  }
43 }
44 
45 /**
46  * Returns the number of nested fields associated with the current field, if
47  * has_nested_fields() returned true.
48  *
49  * The return value may be -1 to indicate that a variable number of nested
50  * fields are accepted by this field type (e.g. a variable-length array).
51  *
52  * Note that this method is unreliable to determine how many fields you must
53  * traverse before you can call pop(), since particularly in the presence of a
54  * DCSwitch, it may change during traversal. Use more_nested_fields()
55  * instead.
56  */
57 INLINE int DCPacker::
59  return _num_nested_fields;
60 }
61 
62 /**
63  * Returns true if there are more nested fields to pack or unpack in the
64  * current push sequence, false if it is time to call pop().
65  */
66 INLINE bool DCPacker::
68  return (_current_field != nullptr && !_pack_error);
69 }
70 
71 /**
72  * Returns the field that we left in our last call to push(): the owner of the
73  * current level of fields. This may be NULL at the beginning of the pack
74  * operation.
75  */
76 INLINE const DCPackerInterface *DCPacker::
78  return _current_parent;
79 }
80 
81 /**
82  * Returns the field that will be referenced by the next call to pack_*() or
83  * unpack_*(). This will be NULL if we have unpacked (or packed) all fields,
84  * or if it is time to call pop().
85  */
86 INLINE const DCPackerInterface *DCPacker::
88  return _current_field;
89 }
90 
91 /**
92  * Returns a pointer to the last DCSwitch instance that we have passed by and
93  * selected one case of during the pack/unpack process. Each time we
94  * encounter a new DCSwitch and select a case, this will change state.
95  *
96  * This may be used to detect when a DCSwitch has been selected. At the
97  * moment this changes state, get_current_parent() will contain the particular
98  * SwitchCase that was selected by the switch.
99  */
100 INLINE const DCSwitchParameter *DCPacker::
102  return _last_switch;
103 }
104 
105 /**
106  * Returns the type of value expected by the current field. See the
107  * enumerated type definition at the top of DCPackerInterface.h. If this
108  * returns one of PT_double, PT_int, PT_int64, or PT_string, then you should
109  * call the corresponding pack_double(), pack_int() function (or
110  * unpack_double(), unpack_int(), etc.) to transfer data. Otherwise, you
111  * should call push() and begin packing or unpacking the nested fields.
112  */
113 INLINE DCPackType DCPacker::
114 get_pack_type() const {
115  if (_current_field == nullptr) {
116  return PT_invalid;
117  } else {
118  return _current_field->get_pack_type();
119  }
120 }
121 
122 /**
123  * Returns the name of the current field, if it has a name, or the empty
124  * string if the field does not have a name or there is no current field.
125  */
126 INLINE std::string DCPacker::
128  if (_current_field == nullptr) {
129  return std::string();
130  } else {
131  return _current_field->get_name();
132  }
133 }
134 
135 /**
136  * Packs the indicated numeric or string value into the stream.
137  */
138 INLINE void DCPacker::
139 pack_double(double value) {
140  nassertv(_mode == M_pack || _mode == M_repack);
141  if (_current_field == nullptr) {
142  _pack_error = true;
143  } else {
144  _current_field->pack_double(_pack_data, value, _pack_error, _range_error);
145  advance();
146  }
147 }
148 
149 /**
150  * Packs the indicated numeric or string value into the stream.
151  */
152 INLINE void DCPacker::
153 pack_int(int value) {
154  nassertv(_mode == M_pack || _mode == M_repack);
155  if (_current_field == nullptr) {
156  _pack_error = true;
157  } else {
158  _current_field->pack_int(_pack_data, value, _pack_error, _range_error);
159  advance();
160  }
161 }
162 
163 /**
164  * Packs the indicated numeric or string value into the stream.
165  */
166 INLINE void DCPacker::
167 pack_uint(unsigned int value) {
168  nassertv(_mode == M_pack || _mode == M_repack);
169  if (_current_field == nullptr) {
170  _pack_error = true;
171  } else {
172  _current_field->pack_uint(_pack_data, value, _pack_error, _range_error);
173  advance();
174  }
175 }
176 
177 /**
178  * Packs the indicated numeric or string value into the stream.
179  */
180 INLINE void DCPacker::
181 pack_int64(int64_t value) {
182  nassertv(_mode == M_pack || _mode == M_repack);
183  if (_current_field == nullptr) {
184  _pack_error = true;
185  } else {
186  _current_field->pack_int64(_pack_data, value, _pack_error, _range_error);
187  advance();
188  }
189 }
190 
191 /**
192  * Packs the indicated numeric or string value into the stream.
193  */
194 INLINE void DCPacker::
195 pack_uint64(uint64_t value) {
196  nassertv(_mode == M_pack || _mode == M_repack);
197  if (_current_field == nullptr) {
198  _pack_error = true;
199  } else {
200  _current_field->pack_uint64(_pack_data, value, _pack_error, _range_error);
201  advance();
202  }
203 }
204 
205 /**
206  * Packs the indicated numeric or string value into the stream.
207  */
208 INLINE void DCPacker::
209 pack_string(const std::string &value) {
210  nassertv(_mode == M_pack || _mode == M_repack);
211  if (_current_field == nullptr) {
212  _pack_error = true;
213  } else {
214  _current_field->pack_string(_pack_data, value, _pack_error, _range_error);
215  advance();
216  }
217 }
218 
219 /**
220  * Packs the indicated numeric or string value into the stream.
221  */
222 INLINE void DCPacker::
223 pack_blob(const vector_uchar &value) {
224  nassertv(_mode == M_pack || _mode == M_repack);
225  if (_current_field == nullptr) {
226  _pack_error = true;
227  } else {
228  _current_field->pack_blob(_pack_data, value, _pack_error, _range_error);
229  advance();
230  }
231 }
232 
233 /**
234  * Adds the indicated string value into the stream, representing a single pre-
235  * packed field element, or a whole group of field elements at once.
236  */
237 INLINE void DCPacker::
238 pack_literal_value(const vector_uchar &value) {
239  nassertv(_mode == M_pack || _mode == M_repack);
240  if (_current_field == nullptr) {
241  _pack_error = true;
242  } else {
243  _pack_data.append_data((const char *)value.data(), value.size());
244  advance();
245  }
246 }
247 
248 /**
249  * Unpacks the current numeric or string value from the stream.
250  */
251 INLINE double DCPacker::
253  double value = 0.0;
254  nassertr(_mode == M_unpack, value);
255  if (_current_field == nullptr) {
256  _pack_error = true;
257 
258  } else {
259  _current_field->unpack_double(_unpack_data, _unpack_length, _unpack_p,
260  value, _pack_error, _range_error);
261  advance();
262  }
263 
264  return value;
265 }
266 
267 /**
268  * Unpacks the current numeric or string value from the stream.
269  */
270 INLINE int DCPacker::
272  int value = 0;
273  nassertr(_mode == M_unpack, value);
274  if (_current_field == nullptr) {
275  _pack_error = true;
276 
277  } else {
278  _current_field->unpack_int(_unpack_data, _unpack_length, _unpack_p,
279  value, _pack_error, _range_error);
280  advance();
281  }
282 
283  return value;
284 }
285 
286 /**
287  * Unpacks the current numeric or string value from the stream.
288  */
289 INLINE unsigned int DCPacker::
291  unsigned int value = 0;
292  nassertr(_mode == M_unpack, value);
293  if (_current_field == nullptr) {
294  _pack_error = true;
295 
296  } else {
297  _current_field->unpack_uint(_unpack_data, _unpack_length, _unpack_p,
298  value, _pack_error, _range_error);
299  advance();
300  }
301 
302  return value;
303 }
304 
305 /**
306  * Unpacks the current numeric or string value from the stream.
307  */
308 INLINE int64_t DCPacker::
310  int64_t value = 0;
311  nassertr(_mode == M_unpack, value);
312  if (_current_field == nullptr) {
313  _pack_error = true;
314 
315  } else {
316  _current_field->unpack_int64(_unpack_data, _unpack_length, _unpack_p,
317  value, _pack_error, _range_error);
318  advance();
319  }
320 
321  return value;
322 }
323 
324 /**
325  * Unpacks the current numeric or string value from the stream.
326  */
327 INLINE uint64_t DCPacker::
329  uint64_t value = 0;
330  nassertr(_mode == M_unpack, value);
331  if (_current_field == nullptr) {
332  _pack_error = true;
333 
334  } else {
335  _current_field->unpack_uint64(_unpack_data, _unpack_length, _unpack_p,
336  value, _pack_error, _range_error);
337  advance();
338  }
339 
340  return value;
341 }
342 
343 /**
344  * Unpacks the current numeric or string value from the stream.
345  */
346 INLINE std::string DCPacker::
348  std::string value;
349  nassertr(_mode == M_unpack, value);
350  if (_current_field == nullptr) {
351  _pack_error = true;
352 
353  } else {
354  _current_field->unpack_string(_unpack_data, _unpack_length, _unpack_p,
355  value, _pack_error, _range_error);
356  advance();
357  }
358 
359  return value;
360 }
361 
362 /**
363  * Unpacks the current binary data value from the stream.
364  */
365 INLINE vector_uchar DCPacker::
367  vector_uchar value;
368  nassertr(_mode == M_unpack, value);
369  if (_current_field == nullptr) {
370  _pack_error = true;
371 
372  } else {
373  _current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
374  value, _pack_error, _range_error);
375  advance();
376  }
377 
378  return value;
379 }
380 
381 /**
382  * Returns the literal string that represents the packed value of the current
383  * field, and advances the field pointer.
384  */
385 INLINE vector_uchar DCPacker::
387  size_t start = _unpack_p;
388  unpack_skip();
389  nassertr(_unpack_p >= start, vector_uchar());
390  return vector_uchar((const unsigned char *)_unpack_data + start,
391  (const unsigned char *)_unpack_data + _unpack_p);
392 }
393 
394 /**
395  * Unpacks the current numeric or string value from the stream.
396  */
397 INLINE void DCPacker::
398 unpack_double(double &value) {
399  nassertv(_mode == M_unpack);
400  if (_current_field == nullptr) {
401  _pack_error = true;
402 
403  } else {
404  _current_field->unpack_double(_unpack_data, _unpack_length, _unpack_p,
405  value, _pack_error, _range_error);
406  advance();
407  }
408 }
409 
410 /**
411  * Unpacks the current numeric or string value from the stream.
412  */
413 INLINE void DCPacker::
414 unpack_int(int &value) {
415  nassertv(_mode == M_unpack);
416  if (_current_field == nullptr) {
417  _pack_error = true;
418 
419  } else {
420  _current_field->unpack_int(_unpack_data, _unpack_length, _unpack_p,
421  value, _pack_error, _range_error);
422  advance();
423  }
424 }
425 
426 /**
427  * Unpacks the current numeric or string value from the stream.
428  */
429 INLINE void DCPacker::
430 unpack_uint(unsigned int &value) {
431  nassertv(_mode == M_unpack);
432  if (_current_field == nullptr) {
433  _pack_error = true;
434 
435  } else {
436  _current_field->unpack_uint(_unpack_data, _unpack_length, _unpack_p,
437  value, _pack_error, _range_error);
438  advance();
439  }
440 }
441 
442 /**
443  * Unpacks the current numeric or string value from the stream.
444  */
445 INLINE void DCPacker::
446 unpack_int64(int64_t &value) {
447  nassertv(_mode == M_unpack);
448  if (_current_field == nullptr) {
449  _pack_error = true;
450 
451  } else {
452  _current_field->unpack_int64(_unpack_data, _unpack_length, _unpack_p,
453  value, _pack_error, _range_error);
454  advance();
455  }
456 }
457 
458 /**
459  * Unpacks the current numeric or string value from the stream.
460  */
461 INLINE void DCPacker::
462 unpack_uint64(uint64_t &value) {
463  nassertv(_mode == M_unpack);
464  if (_current_field == nullptr) {
465  _pack_error = true;
466 
467  } else {
468  _current_field->unpack_uint64(_unpack_data, _unpack_length, _unpack_p,
469  value, _pack_error, _range_error);
470  advance();
471  }
472 }
473 
474 /**
475  * Unpacks the current numeric or string value from the stream.
476  */
477 INLINE void DCPacker::
478 unpack_string(std::string &value) {
479  nassertv(_mode == M_unpack);
480  if (_current_field == nullptr) {
481  _pack_error = true;
482 
483  } else {
484  _current_field->unpack_string(_unpack_data, _unpack_length, _unpack_p,
485  value, _pack_error, _range_error);
486  advance();
487  }
488 }
489 
490 /**
491  * Unpacks the current numeric or string value from the stream.
492  */
493 INLINE void DCPacker::
494 unpack_blob(vector_uchar &value) {
495  nassertv(_mode == M_unpack);
496  if (_current_field == nullptr) {
497  _pack_error = true;
498 
499  } else {
500  _current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
501  value, _pack_error, _range_error);
502  advance();
503  }
504 }
505 
506 /**
507  * Returns the literal string that represents the packed value of the current
508  * field, and advances the field pointer.
509  */
510 INLINE void DCPacker::
511 unpack_literal_value(vector_uchar &value) {
512  size_t start = _unpack_p;
513  unpack_skip();
514  nassertv(_unpack_p >= start);
515  value = vector_uchar((const unsigned char *)_unpack_data + start,
516  (const unsigned char *)_unpack_data + _unpack_p);
517 }
518 
519 /**
520  * Returns true if there has been an parse error since the most recent call to
521  * begin(); this can only happen if you call parse_and_pack().
522  */
523 INLINE bool DCPacker::
525  return _parse_error;
526 }
527 
528 /**
529  * Returns true if there has been an packing error since the most recent call
530  * to begin(); in particular, this may be called after end() has returned
531  * false to determine the nature of the failure.
532  *
533  * A return value of true indicates there was a push/pop mismatch, or the
534  * push/pop structure did not match the data structure, or there were the
535  * wrong number of elements in a nested push/pop structure, or on unpack that
536  * the data stream was truncated.
537  */
538 INLINE bool DCPacker::
539 had_pack_error() const {
540  return _pack_error;
541 }
542 
543 /**
544  * Returns true if there has been an range validation error since the most
545  * recent call to begin(); in particular, this may be called after end() has
546  * returned false to determine the nature of the failure.
547  *
548  * A return value of true indicates a value that was packed or unpacked did
549  * not fit within the specified legal range for a parameter, or within the
550  * limits of the field size.
551  */
552 INLINE bool DCPacker::
554  return _range_error;
555 }
556 
557 /**
558  * Returns true if there has been any error (either a pack error or a range
559  * error) since the most recent call to begin(). If this returns true, then
560  * the matching call to end() will indicate an error (false).
561  */
562 INLINE bool DCPacker::
563 had_error() const {
564  return _range_error || _pack_error || _parse_error;
565 }
566 
567 /**
568  * Returns the number of bytes that have been unpacked so far, or after
569  * unpack_end(), the total number of bytes that were unpacked at all. This
570  * can be used to validate that all of the bytes in the buffer were actually
571  * unpacked (which is not otherwise considered an error).
572  */
573 INLINE size_t DCPacker::
575  return _unpack_p;
576 }
577 
578 /**
579  * Returns the current length of the buffer. This is the number of useful
580  * bytes stored in the buffer, not the amount of memory it takes up.
581  */
582 INLINE size_t DCPacker::
583 get_length() const {
584  return _pack_data.get_length();
585 }
586 
587 /**
588  * Returns the packed data buffer as a string. Also see get_data().
589  */
590 INLINE std::string DCPacker::
591 get_string() const {
592  return _pack_data.get_string();
593 }
594 
595 /**
596  * Returns the packed data buffer as a bytes object. Also see get_data().
597  */
598 INLINE vector_uchar DCPacker::
599 get_bytes() const {
600  const unsigned char *p = (const unsigned char *)_pack_data.get_data();
601  return vector_uchar(p, p + _pack_data.get_length());
602 }
603 
604 /**
605  * Returns the total number of bytes in the unpack data buffer. This is the
606  * buffer used when unpacking; it is separate from the pack data returned by
607  * get_length(), which is filled during packing.
608  */
609 INLINE size_t DCPacker::
611  return _unpack_length;
612 }
613 
614 /**
615  * Returns the unpack data buffer, as a string. This is the buffer used when
616  * unpacking; it is separate from the pack data returned by get_string(),
617  * which is filled during packing. Also see get_unpack_data().
618  */
619 INLINE std::string DCPacker::
621  return std::string(_unpack_data, _unpack_length);
622 }
623 
624 /**
625  * Copies the packed data into the indicated string. Also see get_data().
626  */
627 INLINE void DCPacker::
628 get_string(std::string &data) const {
629  data.assign(_pack_data.get_data(), _pack_data.get_length());
630 }
631 
632 /**
633  * Returns the beginning of the data buffer. The buffer is not null-
634  * terminated, but see also get_string().
635  *
636  * This may be used in conjunction with get_length() to copy all of the bytes
637  * out of the buffer. Also see take_data() to get the packed data without a
638  * copy operation.
639  */
640 INLINE const char *DCPacker::
641 get_data() const {
642  return _pack_data.get_data();
643 }
644 
645 /**
646  * Returns the pointer to the beginning of the data buffer, and transfers
647  * ownership of the buffer to the caller. The caller is now responsible for
648  * ultimately freeing the returned pointer with delete[], if it is non-NULL.
649  * This may (or may not) return NULL if the buffer is empty.
650  *
651  * This also empties the DCPackData structure, and sets its length to zero (so
652  * you should call get_length() before calling this method).
653  */
654 INLINE char *DCPacker::
656  return _pack_data.take_data();
657 }
658 
659 /**
660  * Adds the indicated bytes to the end of the data. This may only be called
661  * between packing sessions.
662  */
663 INLINE void DCPacker::
664 append_data(const unsigned char *buffer, size_t size) {
665  nassertv(_mode == M_idle);
666  _pack_data.append_data((const char *)buffer, size);
667 }
668 
669 /**
670  * Adds the indicated number of bytes to the end of the data without
671  * initializing them, and returns a pointer to the beginning of the new data.
672  * This may only be called between packing sessions.
673  */
674 INLINE char *DCPacker::
675 get_write_pointer(size_t size) {
676  nassertr(_mode == M_idle, nullptr);
677  return _pack_data.get_write_pointer(size);
678 }
679 
680 /**
681  * Returns a read pointer to the unpack data buffer. This is the buffer used
682  * when unpacking; it is separate from the pack data returned by get_data(),
683  * which is filled during packing.
684  */
685 INLINE const char *DCPacker::
687  return _unpack_data;
688 }
689 
690 /**
691  * Returns the number of DCPacker::StackElement pointers ever simultaneously
692  * allocated; these are now either in active use or have been recycled into
693  * the deleted DCPacker::StackElement pool to be used again.
694  */
695 INLINE int DCPacker::
697  return StackElement::_num_ever_allocated;
698 }
699 
700 /**
701  * Packs the data into the buffer between packing sessions.
702  */
703 INLINE void DCPacker::
704 raw_pack_int8(int value) {
705  nassertv(_mode == M_idle);
706  DCPackerInterface::do_pack_int8(_pack_data.get_write_pointer(1), value);
707 }
708 
709 /**
710  * Packs the data into the buffer between packing sessions.
711  */
712 INLINE void DCPacker::
713 raw_pack_int16(int value) {
714  nassertv(_mode == M_idle);
715  DCPackerInterface::do_pack_int16(_pack_data.get_write_pointer(2), value);
716 }
717 
718 /**
719  * Packs the data into the buffer between packing sessions.
720  */
721 INLINE void DCPacker::
722 raw_pack_int32(int value) {
723  nassertv(_mode == M_idle);
724  DCPackerInterface::do_pack_int32(_pack_data.get_write_pointer(4), value);
725 }
726 
727 /**
728  * Packs the data into the buffer between packing sessions.
729  */
730 INLINE void DCPacker::
731 raw_pack_int64(int64_t value) {
732  nassertv(_mode == M_idle);
733  DCPackerInterface::do_pack_int64(_pack_data.get_write_pointer(8), value);
734 }
735 
736 /**
737  * Packs the data into the buffer between packing sessions.
738  */
739 INLINE void DCPacker::
740 raw_pack_uint8(unsigned int value) {
741  nassertv(_mode == M_idle);
742  DCPackerInterface::do_pack_uint8(_pack_data.get_write_pointer(1), value);
743 }
744 
745 /**
746  * Packs the data into the buffer between packing sessions.
747  */
748 INLINE void DCPacker::
749 raw_pack_uint16(unsigned int value) {
750  nassertv(_mode == M_idle);
751  DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value);
752 }
753 
754 /**
755  * Packs the data into the buffer between packing sessions.
756  */
757 INLINE void DCPacker::
758 raw_pack_uint32(unsigned int value) {
759  nassertv(_mode == M_idle);
760  DCPackerInterface::do_pack_uint32(_pack_data.get_write_pointer(4), value);
761 }
762 
763 /**
764  * Packs the data into the buffer between packing sessions.
765  */
766 INLINE void DCPacker::
767 raw_pack_uint64(uint64_t value) {
768  nassertv(_mode == M_idle);
769  DCPackerInterface::do_pack_uint64(_pack_data.get_write_pointer(8), value);
770 }
771 
772 /**
773  * Packs the data into the buffer between packing sessions.
774  */
775 INLINE void DCPacker::
776 raw_pack_float64(double value) {
777  nassertv(_mode == M_idle);
778  DCPackerInterface::do_pack_float64(_pack_data.get_write_pointer(8), value);
779 }
780 
781 /**
782  * Packs the data into the buffer between packing sessions.
783  */
784 INLINE void DCPacker::
785 raw_pack_string(const std::string &value) {
786  nassertv(_mode == M_idle);
787  DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value.length());
788  _pack_data.append_data(value.data(), value.length());
789 }
790 
791 /**
792  * Packs the data into the buffer between packing sessions.
793  */
794 INLINE void DCPacker::
795 raw_pack_blob(const vector_uchar &value) {
796  nassertv(_mode == M_idle);
797  DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value.size());
798  _pack_data.append_data((const char *)value.data(), value.size());
799 }
800 
801 /**
802  * Unpacks the data from the buffer between unpacking sessions.
803  */
804 INLINE int DCPacker::
806  int value = 0;
807  raw_unpack_int8(value);
808  return value;
809 }
810 
811 /**
812  * Unpacks the data from the buffer between unpacking sessions.
813  */
814 INLINE int DCPacker::
816  int value = 0;
817  raw_unpack_int16(value);
818  return value;
819 }
820 
821 /**
822  * Unpacks the data from the buffer between unpacking sessions.
823  */
824 INLINE int DCPacker::
826  int value = 0;
827  raw_unpack_int32(value);
828  return value;
829 }
830 
831 /**
832  * Unpacks the data from the buffer between unpacking sessions.
833  */
834 INLINE int64_t DCPacker::
836  int64_t value = 0;
837  raw_unpack_int64(value);
838  return value;
839 }
840 
841 /**
842  * Unpacks the data from the buffer between unpacking sessions.
843  */
844 INLINE void DCPacker::
845 raw_unpack_int8(int &value) {
846  nassertv(_mode == M_idle && _unpack_data != nullptr);
847  if (_unpack_p + 1 > _unpack_length) {
848  _pack_error = true;
849  return;
850  }
851  value = DCPackerInterface::do_unpack_int8(_unpack_data + _unpack_p);
852  _unpack_p++;
853 }
854 
855 /**
856  * Unpacks the data from the buffer between unpacking sessions.
857  */
858 INLINE void DCPacker::
859 raw_unpack_int16(int &value) {
860  nassertv(_mode == M_idle && _unpack_data != nullptr);
861  if (_unpack_p + 2 > _unpack_length) {
862  _pack_error = true;
863  return;
864  }
865  value = DCPackerInterface::do_unpack_int16(_unpack_data + _unpack_p);
866  _unpack_p += 2;
867 }
868 
869 /**
870  * Unpacks the data from the buffer between unpacking sessions.
871  */
872 INLINE void DCPacker::
873 raw_unpack_int32(int &value) {
874  nassertv(_mode == M_idle && _unpack_data != nullptr);
875  if (_unpack_p + 4 > _unpack_length) {
876  _pack_error = true;
877  return;
878  }
879  value = DCPackerInterface::do_unpack_int32(_unpack_data + _unpack_p);
880  _unpack_p += 4;
881 }
882 
883 /**
884  * Unpacks the data from the buffer between unpacking sessions.
885  */
886 INLINE unsigned int DCPacker::
888  unsigned int value = 0;
889  raw_unpack_uint8(value);
890  return value;
891 }
892 
893 /**
894  * Unpacks the data from the buffer between unpacking sessions.
895  */
896 INLINE unsigned int DCPacker::
898  unsigned int value = 0;
899  raw_unpack_uint16(value);
900  return value;
901 }
902 
903 /**
904  * Unpacks the data from the buffer between unpacking sessions.
905  */
906 INLINE unsigned int DCPacker::
908  unsigned int value = 0;
909  raw_unpack_uint32(value);
910  return value;
911 }
912 
913 /**
914  * Unpacks the data from the buffer between unpacking sessions.
915  */
916 INLINE uint64_t DCPacker::
918  uint64_t value = 0;
919  raw_unpack_uint64(value);
920  return value;
921 }
922 
923 /**
924  * Unpacks the data from the buffer between unpacking sessions.
925  */
926 INLINE double DCPacker::
928  double value = 0;
929  raw_unpack_float64(value);
930  return value;
931 }
932 
933 /**
934  * Unpacks the data from the buffer between unpacking sessions.
935  */
936 INLINE std::string DCPacker::
938  std::string value;
939  raw_unpack_string(value);
940  return value;
941 }
942 
943 /**
944  * Unpacks the data from the buffer between unpacking sessions.
945  */
946 INLINE vector_uchar DCPacker::
948  vector_uchar value;
949  raw_unpack_blob(value);
950  return value;
951 }
952 
953 /**
954  * Unpacks the data from the buffer between unpacking sessions.
955  */
956 INLINE void DCPacker::
957 raw_unpack_int64(int64_t &value) {
958  nassertv(_mode == M_idle && _unpack_data != nullptr);
959  if (_unpack_p + 8 > _unpack_length) {
960  _pack_error = true;
961  return;
962  }
963  value = DCPackerInterface::do_unpack_int64(_unpack_data + _unpack_p);
964  _unpack_p += 8;
965 }
966 
967 /**
968  * Unpacks the data from the buffer between unpacking sessions.
969  */
970 INLINE void DCPacker::
971 raw_unpack_uint8(unsigned int &value) {
972  nassertv(_mode == M_idle && _unpack_data != nullptr);
973  if (_unpack_p + 1 > _unpack_length) {
974  _pack_error = true;
975  return;
976  }
977  value = DCPackerInterface::do_unpack_uint8(_unpack_data + _unpack_p);
978  _unpack_p++;
979 }
980 
981 /**
982  * Unpacks the data from the buffer between unpacking sessions.
983  */
984 INLINE void DCPacker::
985 raw_unpack_uint16(unsigned int &value) {
986  nassertv(_mode == M_idle && _unpack_data != nullptr);
987  if (_unpack_p + 2 > _unpack_length) {
988  _pack_error = true;
989  return;
990  }
991  value = DCPackerInterface::do_unpack_uint16(_unpack_data + _unpack_p);
992  _unpack_p += 2;
993 }
994 
995 /**
996  * Unpacks the data from the buffer between unpacking sessions.
997  */
998 INLINE void DCPacker::
999 raw_unpack_uint32(unsigned int &value) {
1000  nassertv(_mode == M_idle && _unpack_data != nullptr);
1001  if (_unpack_p + 4 > _unpack_length) {
1002  _pack_error = true;
1003  return;
1004  }
1005  value = DCPackerInterface::do_unpack_uint32(_unpack_data + _unpack_p);
1006  _unpack_p += 4;
1007 }
1008 
1009 /**
1010  * Unpacks the data from the buffer between unpacking sessions.
1011  */
1012 INLINE void DCPacker::
1013 raw_unpack_uint64(uint64_t &value) {
1014  nassertv(_mode == M_idle && _unpack_data != nullptr);
1015  if (_unpack_p + 8 > _unpack_length) {
1016  _pack_error = true;
1017  return;
1018  }
1019  value = DCPackerInterface::do_unpack_uint64(_unpack_data + _unpack_p);
1020  _unpack_p += 8;
1021 }
1022 
1023 /**
1024  * Unpacks the data from the buffer between unpacking sessions.
1025  */
1026 INLINE void DCPacker::
1027 raw_unpack_float64(double &value) {
1028  nassertv(_mode == M_idle && _unpack_data != nullptr);
1029  if (_unpack_p + 8 > _unpack_length) {
1030  _pack_error = true;
1031  return;
1032  }
1033  value = DCPackerInterface::do_unpack_float64(_unpack_data + _unpack_p);
1034  _unpack_p += 8;
1035 }
1036 
1037 /**
1038  * Unpacks the data from the buffer between unpacking sessions.
1039  */
1040 INLINE void DCPacker::
1041 raw_unpack_string(std::string &value) {
1042  nassertv(_mode == M_idle && _unpack_data != nullptr);
1043  unsigned int string_length = raw_unpack_uint16();
1044 
1045  if (_unpack_p + string_length > _unpack_length) {
1046  _pack_error = true;
1047  return;
1048  }
1049 
1050  value.assign(_unpack_data + _unpack_p, string_length);
1051  _unpack_p += string_length;
1052 }
1053 
1054 /**
1055  * Unpacks the data from the buffer between unpacking sessions.
1056  */
1057 INLINE void DCPacker::
1058 raw_unpack_blob(vector_uchar &value) {
1059  nassertv(_mode == M_idle && _unpack_data != nullptr);
1060  unsigned int blob_size = raw_unpack_uint16();
1061 
1062  if (_unpack_p + blob_size > _unpack_length) {
1063  _pack_error = true;
1064  return;
1065  }
1066 
1067  const unsigned char *p = (const unsigned char *)_unpack_data + _unpack_p;
1068  value = vector_uchar(p, p + blob_size);
1069  _unpack_p += blob_size;
1070 }
1071 
1072 /**
1073  * Advances to the next field after a call to pack_value() or pop().
1074  */
1075 INLINE void DCPacker::
1076 advance() {
1077  _current_field_index++;
1078  if (_num_nested_fields >= 0 &&
1079  _current_field_index >= _num_nested_fields) {
1080  // Done with all the fields on this parent. The caller must now call
1081  // pop().
1082  _current_field = nullptr;
1083 
1084  // But if the parent is a switch record, we make a special case so we can
1085  // get the alternate fields.
1086  if (_current_parent != nullptr) {
1087  const DCSwitchParameter *switch_parameter = ((DCPackerInterface *)_current_parent)->as_switch_parameter();
1088  if (switch_parameter != nullptr) {
1089  handle_switch(switch_parameter);
1090  }
1091  }
1092 
1093  } else if (_pop_marker != 0 && _unpack_p >= _pop_marker) {
1094  // Done with all the fields on this parent. The caller must now call
1095  // pop().
1096  _current_field = nullptr;
1097 
1098  } else {
1099  // We have another field to advance to.
1100  _current_field = _current_parent->get_nested_field(_current_field_index);
1101  }
1102 }
1103 
1104 /**
1105  * Allocates the memory for a new DCPacker::StackElement. This is specialized
1106  * here to provide for fast allocation of these things.
1107  */
1108 INLINE void *DCPacker::StackElement::
1109 operator new(size_t size) {
1110  if (_deleted_chain != nullptr) {
1111  StackElement *obj = _deleted_chain;
1112  _deleted_chain = _deleted_chain->_next;
1113  return obj;
1114  }
1115 #ifndef NDEBUG
1116  _num_ever_allocated++;
1117 #endif // NDEBUG
1118  return ::operator new(size);
1119 }
1120 
1121 /**
1122  * Frees the memory for a deleted DCPacker::StackElement. This is specialized
1123  * here to provide for fast allocation of these things.
1124  */
1125 INLINE void DCPacker::StackElement::
1126 operator delete(void *ptr) {
1127  StackElement *obj = (StackElement *)ptr;
1128  obj->_next = _deleted_chain;
1129  _deleted_chain = obj;
1130 }
char * get_write_pointer(size_t size)
Adds the indicated number of bytes to the end of the data without initializing them,...
Definition: dcPackData.I:57
uint64_t unpack_uint64()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:328
bool had_range_error() const
Returns true if there has been an range validation error since the most recent call to begin(); in pa...
Definition: dcPacker.I:553
void raw_pack_uint64(uint64_t value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:767
bool had_error() const
Returns true if there has been any error (either a pack error or a range error) since the most recent...
Definition: dcPacker.I:563
uint64_t raw_unpack_uint64()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:917
DCPackType get_pack_type() const
Returns the type of value expected by the current field.
Definition: dcPacker.I:114
static int get_num_stack_elements_ever_allocated()
Returns the number of DCPacker::StackElement pointers ever simultaneously allocated; these are now ei...
Definition: dcPacker.I:696
void append_data(const char *buffer, size_t size)
Adds the indicated bytes to the end of the data.
Definition: dcPackData.I:47
void pack_int(int value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:153
void raw_pack_int16(int value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:713
const std::string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
virtual void pack_uint(DCPackData &pack_data, unsigned int value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
void pack_blob(const vector_uchar &value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:223
bool has_nested_fields() const
Returns true if this field type has any nested fields (and thus expects a push() .
size_t get_num_unpacked_bytes() const
Returns the number of bytes that have been unpacked so far, or after unpack_end(),...
Definition: dcPacker.I:574
void clear()
Empties the contents of the data (without necessarily freeing its allocated memory).
Definition: dcPackData.I:39
int raw_unpack_int16()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:815
const DCPackerInterface * get_current_field() const
Returns the field that will be referenced by the next call to pack_*() or unpack_*().
Definition: dcPacker.I:87
unsigned int raw_unpack_uint16()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:897
int raw_unpack_int8()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:805
void raw_pack_uint8(unsigned int value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:740
bool had_parse_error() const
Returns true if there has been an parse error since the most recent call to begin(); this can only ha...
Definition: dcPacker.I:524
vector_uchar raw_unpack_blob()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:947
std::string get_string() const
Returns the packed data buffer as a string.
Definition: dcPacker.I:591
virtual void unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
int get_num_nested_fields() const
Returns the number of nested fields associated with the current field, if has_nested_fields() returne...
Definition: dcPacker.I:58
This represents a switch object used as a parameter itself, which packs the appropriate fields of the...
unsigned int unpack_uint()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:290
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.
void pack_uint(unsigned int value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:167
bool had_pack_error() const
Returns true if there has been an packing error since the most recent call to begin(); in particular,...
Definition: dcPacker.I:539
void pack_uint64(uint64_t value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:195
int64_t unpack_int64()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:309
void raw_pack_int64(int64_t value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:731
size_t get_length() const
Returns the current length of the buffer.
Definition: dcPacker.I:583
double unpack_double()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:252
std::string get_current_field_name() const
Returns the name of the current field, if it has a name, or the empty string if the field does not ha...
Definition: dcPacker.I:127
void raw_pack_uint32(unsigned int value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:758
size_t get_unpack_length() const
Returns the total number of bytes in the unpack data buffer.
Definition: dcPacker.I:610
std::string get_string() const
Returns the data buffer as a string.
Definition: dcPackData.I:93
void raw_pack_float64(double value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:776
std::string get_unpack_string() const
Returns the unpack data buffer, as a string.
Definition: dcPacker.I:620
bool has_nested_fields() const
Returns true if the current field has any nested fields (and thus expects a push() .
Definition: dcPacker.I:37
char * get_write_pointer(size_t size)
Adds the indicated number of bytes to the end of the data without initializing them,...
Definition: dcPacker.I:675
virtual void pack_uint64(DCPackData &pack_data, uint64_t value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
char * take_data()
Returns the pointer to the beginning of the data buffer, and transfers ownership of the buffer to the...
Definition: dcPacker.I:655
unsigned int raw_unpack_uint8()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:887
const DCPackerInterface * get_current_parent() const
Returns the field that we left in our last call to push(): the owner of the current level of fields.
Definition: dcPacker.I:77
virtual void pack_int64(DCPackData &pack_data, int64_t value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
unsigned int raw_unpack_uint32()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:907
int raw_unpack_int32()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:825
void append_data(const unsigned char *buffer, size_t size)
Adds the indicated bytes to the end of the data.
Definition: dcPacker.I:664
void raw_pack_int8(int value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:704
void raw_pack_uint16(unsigned int value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:749
bool more_nested_fields() const
Returns true if there are more nested fields to pack or unpack in the current push sequence,...
Definition: dcPacker.I:67
virtual void unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
char * take_data()
Returns the pointer to the beginning of the data buffer, and transfers ownership of the buffer to the...
Definition: dcPackData.I:129
int64_t raw_unpack_int64()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:835
const char * get_data() const
Returns the beginning of the data buffer.
Definition: dcPacker.I:641
size_t get_length() const
Returns the current length of the buffer.
Definition: dcPackData.I:102
const DCSwitchParameter * get_last_switch() const
Returns a pointer to the last DCSwitch instance that we have passed by and selected one case of durin...
Definition: dcPacker.I:101
std::string unpack_string()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:347
void raw_pack_string(const std::string &value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:785
DCPackType get_pack_type() const
Returns the type of value expected by this field.
virtual void unpack_int(const char *data, size_t length, size_t &p, int &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
virtual void unpack_string(const char *data, size_t length, size_t &p, std::string &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
void pack_literal_value(const vector_uchar &value)
Adds the indicated string value into the stream, representing a single pre- packed field element,...
Definition: dcPacker.I:238
vector_uchar unpack_blob()
Unpacks the current binary data value from the stream.
Definition: dcPacker.I:366
int unpack_int()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:271
const char * get_data() const
Returns the beginning of the data buffer.
Definition: dcPackData.I:115
std::string raw_unpack_string()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:937
void raw_pack_int32(int value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:722
virtual void pack_string(DCPackData &pack_data, const std::string &value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
void raw_pack_blob(const vector_uchar &value)
Packs the data into the buffer between packing sessions.
Definition: dcPacker.I:795
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
void unpack_skip()
Skips the current field without unpacking it and advances to the next field.
Definition: dcPacker.cxx:604
double raw_unpack_float64()
Unpacks the data from the buffer between unpacking sessions.
Definition: dcPacker.I:927
virtual void unpack_double(const char *data, size_t length, size_t &p, double &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
vector_uchar unpack_literal_value()
Returns the literal string that represents the packed value of the current field, and advances the fi...
Definition: dcPacker.I:386
vector_uchar get_bytes() const
Returns the packed data buffer as a bytes object.
Definition: dcPacker.I:599
const char * get_unpack_data() const
Returns a read pointer to the unpack data buffer.
Definition: dcPacker.I:686
virtual void unpack_int64(const char *data, size_t length, size_t &p, int64_t &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
void pack_double(double value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:139
virtual void pack_double(DCPackData &pack_data, double value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
This defines the internal interface for packing values into a DCField.
virtual void pack_int(DCPackData &pack_data, int value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
void pack_string(const std::string &value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:209
void clear_data()
Empties the data in the pack buffer and unpack buffer.
Definition: dcPacker.I:20
virtual void unpack_uint64(const char *data, size_t length, size_t &p, uint64_t &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
void pack_int64(int64_t value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:181