Panda3D
Loading...
Searching...
No Matches
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 */
19INLINE void DCPacker::
20clear_data() {
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 */
36INLINE bool DCPacker::
37has_nested_fields() const {
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 */
57INLINE 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 */
66INLINE bool DCPacker::
67more_nested_fields() const {
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 */
77get_current_parent() const {
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 */
87get_current_field() const {
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 */
101get_last_switch() const {
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 */
113INLINE DCPackType DCPacker::
114get_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 */
126INLINE 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 */
138INLINE void DCPacker::
139pack_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 */
152INLINE void DCPacker::
153pack_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 */
166INLINE void DCPacker::
167pack_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 */
180INLINE void DCPacker::
181pack_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 */
194INLINE void DCPacker::
195pack_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 */
208INLINE void DCPacker::
209pack_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 */
222INLINE void DCPacker::
223pack_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 */
237INLINE void DCPacker::
238pack_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 */
251INLINE 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 */
270INLINE int DCPacker::
271unpack_int() {
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 */
289INLINE unsigned int DCPacker::
290unpack_uint() {
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 */
308INLINE int64_t DCPacker::
309unpack_int64() {
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 */
327INLINE 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 */
346INLINE 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 */
365INLINE vector_uchar DCPacker::
366unpack_blob() {
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 */
385INLINE 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 */
397INLINE void DCPacker::
398unpack_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 */
413INLINE void DCPacker::
414unpack_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 */
429INLINE void DCPacker::
430unpack_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 */
445INLINE void DCPacker::
446unpack_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 */
461INLINE void DCPacker::
462unpack_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 */
477INLINE void DCPacker::
478unpack_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 */
493INLINE void DCPacker::
494unpack_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 */
510INLINE void DCPacker::
511unpack_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 */
523INLINE bool DCPacker::
524had_parse_error() const {
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 */
538INLINE bool DCPacker::
539had_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 */
552INLINE bool DCPacker::
553had_range_error() const {
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 */
562INLINE bool DCPacker::
563had_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 */
573INLINE 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 */
582INLINE size_t DCPacker::
583get_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 */
590INLINE std::string DCPacker::
591get_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 */
598INLINE vector_uchar DCPacker::
599get_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 */
609INLINE size_t DCPacker::
610get_unpack_length() const {
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 */
619INLINE std::string DCPacker::
620get_unpack_string() const {
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 */
627INLINE void DCPacker::
628get_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 */
640INLINE const char *DCPacker::
641get_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 */
654INLINE char *DCPacker::
655take_data() {
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 */
663INLINE void DCPacker::
664append_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 */
674INLINE char *DCPacker::
675get_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 */
685INLINE const char *DCPacker::
686get_unpack_data() const {
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 */
695INLINE int DCPacker::
697 return StackElement::_num_ever_allocated;
698}
699
700/**
701 * Packs the data into the buffer between packing sessions.
702 */
703INLINE void DCPacker::
704raw_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 */
712INLINE void DCPacker::
713raw_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 */
721INLINE void DCPacker::
722raw_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 */
730INLINE void DCPacker::
731raw_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 */
739INLINE void DCPacker::
740raw_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 */
748INLINE void DCPacker::
749raw_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 */
757INLINE void DCPacker::
758raw_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 */
766INLINE void DCPacker::
767raw_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 */
775INLINE void DCPacker::
776raw_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 */
784INLINE void DCPacker::
785raw_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 */
794INLINE void DCPacker::
795raw_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 */
804INLINE 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 */
814INLINE 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 */
824INLINE 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 */
834INLINE 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 */
844INLINE void DCPacker::
845raw_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 */
858INLINE void DCPacker::
859raw_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 */
872INLINE void DCPacker::
873raw_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 */
886INLINE 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 */
896INLINE 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 */
906INLINE 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 */
916INLINE 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 */
926INLINE 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 */
936INLINE 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 */
946INLINE 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 */
956INLINE void DCPacker::
957raw_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 */
970INLINE void DCPacker::
971raw_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 */
984INLINE void DCPacker::
985raw_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 */
998INLINE void DCPacker::
999raw_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 */
1012INLINE void DCPacker::
1013raw_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 */
1026INLINE void DCPacker::
1027raw_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 */
1040INLINE void DCPacker::
1041raw_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 */
1057INLINE void DCPacker::
1058raw_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 */
1075INLINE void DCPacker::
1076advance() {
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 */
1108INLINE void *DCPacker::StackElement::
1109operator 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 */
1125INLINE void DCPacker::StackElement::
1126operator delete(void *ptr) {
1127 if (ptr != nullptr) {
1128 StackElement *obj = (StackElement *)ptr;
1129 obj->_next = _deleted_chain;
1130 _deleted_chain = obj;
1131 }
1132}
const char * get_data() const
Returns the beginning of the data buffer.
Definition dcPackData.I:115
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
void append_data(const char *buffer, size_t size)
Adds the indicated bytes to the end of the data.
Definition dcPackData.I:47
size_t get_length() const
Returns the current length of the buffer.
Definition dcPackData.I:102
void clear()
Empties the contents of the data (without necessarily freeing its allocated memory).
Definition dcPackData.I:39
std::string get_string() const
Returns the data buffer as a string.
Definition dcPackData.I:93
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
This defines the internal interface for packing values into a DCField.
const std::string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
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.
virtual void unpack_blob(const char *data, size_t length, size_t &p, std::vector< unsigned char > &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
bool has_nested_fields() const
Returns true if this field type has any nested fields (and thus expects a push() .
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.
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.
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.
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.
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.
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.
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.
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 pack_int(DCPackData &pack_data, int value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
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.
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.
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.
DCPackType get_pack_type() const
Returns the type of value expected by this field.
virtual void pack_blob(DCPackData &pack_data, const std::vector< unsigned char > &value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
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
int raw_unpack_int32()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:825
std::vector< unsigned char > get_bytes() const
Returns the packed data buffer as a bytes object.
Definition dcPacker.I:599
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
void raw_pack_int8(int value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:704
unsigned int raw_unpack_uint32()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:907
std::string unpack_string()
Unpacks the current numeric or string value from the stream.
Definition dcPacker.I:347
std::string raw_unpack_string()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:937
void clear_data()
Empties the data in the pack buffer and unpack buffer.
Definition dcPacker.I:20
void pack_blob(const std::vector< unsigned char > &value)
Packs the indicated numeric or string value into the stream.
Definition dcPacker.I:223
int unpack_int()
Unpacks the current numeric or string value from the stream.
Definition dcPacker.I:271
std::string get_string() const
Returns the packed data buffer as a string.
Definition dcPacker.I:591
std::vector< unsigned char > raw_unpack_blob()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:947
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 pack_uint(unsigned int value)
Packs the indicated numeric or string value into the stream.
Definition dcPacker.I:167
std::vector< unsigned char > unpack_literal_value()
Returns the literal string that represents the packed value of the current field, and advances the fi...
Definition dcPacker.I:386
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 pack_int(int value)
Packs the indicated numeric or string value into the stream.
Definition dcPacker.I:153
void raw_pack_string(const std::string &value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:785
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
DCPackType get_pack_type() const
Returns the type of value expected by the current field.
Definition dcPacker.I:114
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
void raw_pack_float64(double value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:776
bool has_nested_fields() const
Returns true if the current field has any nested fields (and thus expects a push() .
Definition dcPacker.I:37
uint64_t raw_unpack_uint64()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:917
void raw_pack_uint32(unsigned int value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:758
void pack_uint64(uint64_t value)
Packs the indicated numeric or string value into the stream.
Definition dcPacker.I:195
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
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
void raw_pack_uint16(unsigned int value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:749
double unpack_double()
Unpacks the current numeric or string value from the stream.
Definition dcPacker.I:252
void raw_pack_uint8(unsigned int value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:740
size_t get_unpack_length() const
Returns the total number of bytes in the unpack data buffer.
Definition dcPacker.I:610
void pack_literal_value(const std::vector< unsigned char > &value)
Adds the indicated string value into the stream, representing a single pre- packed field element,...
Definition dcPacker.I:238
std::string get_unpack_string() const
Returns the unpack data buffer, as a string.
Definition dcPacker.I:620
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_int64(int64_t value)
Packs the indicated numeric or string value into the stream.
Definition dcPacker.I:181
const char * get_data() const
Returns the beginning of the data buffer.
Definition dcPacker.I:641
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
int raw_unpack_int16()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:815
double raw_unpack_float64()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:927
void unpack_skip()
Skips the current field without unpacking it and advances to the next field.
Definition dcPacker.cxx:604
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
int64_t raw_unpack_int64()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:835
void raw_pack_int64(int64_t value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:731
const char * get_unpack_data() const
Returns a read pointer to the unpack data buffer.
Definition dcPacker.I:686
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
unsigned int raw_unpack_uint8()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:887
std::vector< unsigned char > unpack_blob()
Unpacks the current binary data value from the stream.
Definition dcPacker.I:366
unsigned int raw_unpack_uint16()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:897
void pack_double(double value)
Packs the indicated numeric or string value into the stream.
Definition dcPacker.I:139
size_t get_length() const
Returns the current length of the buffer.
Definition dcPacker.I:583
int64_t unpack_int64()
Unpacks the current numeric or string value from the stream.
Definition dcPacker.I:309
void raw_pack_blob(const std::vector< unsigned char > &value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:795
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 raw_pack_uint64(uint64_t value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:767
int raw_unpack_int8()
Unpacks the data from the buffer between unpacking sessions.
Definition dcPacker.I:805
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
unsigned int unpack_uint()
Unpacks the current numeric or string value from the stream.
Definition dcPacker.I:290
uint64_t unpack_uint64()
Unpacks the current numeric or string value from the stream.
Definition dcPacker.I:328
void raw_pack_int32(int value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:722
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
void raw_pack_int16(int value)
Packs the data into the buffer between packing sessions.
Definition dcPacker.I:713
void pack_string(const std::string &value)
Packs the indicated numeric or string value into the stream.
Definition dcPacker.I:209
This represents a switch object used as a parameter itself, which packs the appropriate fields of the...