Panda3D
dcSimpleParameter.cxx
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 dcSimpleParameter.cxx
10  * @author drose
11  * @date 2004-06-15
12  */
13 
14 #include "dcSimpleParameter.h"
15 #include "dcPackData.h"
16 #include "dcTypedef.h"
17 #include "dcArrayParameter.h"
18 #include "dcClassParameter.h"
19 #include "dcClass.h"
20 #include "hashGenerator.h"
21 #include <math.h>
22 
23 using std::string;
24 
25 DCSimpleParameter::NestedFieldMap DCSimpleParameter::_nested_field_map;
26 DCClassParameter *DCSimpleParameter::_uint32uint8_type = nullptr;
27 
28 /**
29  *
30  */
31 DCSimpleParameter::
32 DCSimpleParameter(DCSubatomicType type, unsigned int divisor) :
33  _type(type),
34  _divisor(1),
35  _has_modulus(false)
36 {
37  _pack_type = PT_invalid;
38  _nested_type = ST_invalid;
39  _has_nested_fields = false;
40  _bytes_per_element = 0;
41  _num_length_bytes = 2;
42 
43  // Check for one of the built-in array types. For these types, we must
44  // present a packing interface that has a variable number of nested fields
45  // of the appropriate type.
46  switch (_type) {
47  case ST_int8array:
48  _pack_type = PT_array;
49  _nested_type = ST_int8;
50  _has_nested_fields = true;
51  _bytes_per_element = 1;
52  break;
53 
54  case ST_int16array:
55  _pack_type = PT_array;
56  _nested_type = ST_int16;
57  _has_nested_fields = true;
58  _bytes_per_element = 2;
59  break;
60 
61  case ST_int32array:
62  _pack_type = PT_array;
63  _nested_type = ST_int32;
64  _has_nested_fields = true;
65  _bytes_per_element = 4;
66  break;
67 
68  case ST_uint8array:
69  _pack_type = PT_array;
70  _nested_type = ST_uint8;
71  _has_nested_fields = true;
72  _bytes_per_element = 1;
73  break;
74 
75  case ST_uint16array:
76  _pack_type = PT_array;
77  _nested_type = ST_uint16;
78  _has_nested_fields = true;
79  _bytes_per_element = 2;
80  break;
81 
82  case ST_uint32array:
83  _pack_type = PT_array;
84  _nested_type = ST_uint32;
85  _has_nested_fields = true;
86  _bytes_per_element = 4;
87  break;
88 
89  case ST_uint32uint8array:
90  _pack_type = PT_array;
91  _has_nested_fields = true;
92  _bytes_per_element = 5;
93  break;
94 
95  case ST_blob32:
96  _num_length_bytes = 4;
97  // fall through
98  case ST_blob:
99  // For blob and string, we will present an array interface as an array of
100  // uint8, but we will also accept a set_value() with a string parameter.
101  _pack_type = PT_blob;
102  _nested_type = ST_uint8;
103  _has_nested_fields = true;
104  _bytes_per_element = 1;
105  break;
106 
107  case ST_string:
108  _pack_type = PT_string;
109  _nested_type = ST_char;
110  _has_nested_fields = true;
111  _bytes_per_element = 1;
112  break;
113 
114  // The simple types can be packed directly.
115  case ST_int8:
116  _pack_type = PT_int;
117  _has_fixed_byte_size = true;
118  _fixed_byte_size = 1;
119  break;
120 
121  case ST_int16:
122  _pack_type = PT_int;
123  _has_fixed_byte_size = true;
124  _fixed_byte_size = 2;
125  break;
126 
127  case ST_int32:
128  _pack_type = PT_int;
129  _has_fixed_byte_size = true;
130  _fixed_byte_size = 4;
131  break;
132 
133  case ST_int64:
134  _pack_type = PT_int64;
135  _has_fixed_byte_size = true;
136  _fixed_byte_size = 8;
137  break;
138 
139  case ST_char:
140  _pack_type = PT_string;
141  _has_fixed_byte_size = true;
142  _fixed_byte_size = 1;
143  break;
144 
145  case ST_uint8:
146  _pack_type = PT_uint;
147  _has_fixed_byte_size = true;
148  _fixed_byte_size = 1;
149  break;
150 
151  case ST_uint16:
152  _pack_type = PT_uint;
153  _has_fixed_byte_size = true;
154  _fixed_byte_size = 2;
155  break;
156 
157  case ST_uint32:
158  _pack_type = PT_uint;
159  _has_fixed_byte_size = true;
160  _fixed_byte_size = 4;
161  break;
162 
163  case ST_uint64:
164  _pack_type = PT_uint64;
165  _has_fixed_byte_size = true;
166  _fixed_byte_size = 8;
167  break;
168 
169  case ST_float64:
170  _pack_type = PT_double;
171  _has_fixed_byte_size = true;
172  _fixed_byte_size = 8;
173  break;
174 
175  case ST_invalid:
176  break;
177  }
178  _has_fixed_structure = _has_fixed_byte_size;
179 
180  set_divisor(divisor);
181 
182  if (_nested_type != ST_invalid) {
183  _nested_field = create_nested_field(_nested_type, _divisor);
184 
185  } else if (_type == ST_uint32uint8array) {
186  // This one is a special case. We must create a special nested type that
187  // accepts a uint32 followed by a uint8 for each element.
188  _nested_field = create_uint32uint8_type();
189 
190  } else {
191  _nested_field = nullptr;
192  }
193 }
194 
195 /**
196  *
197  */
198 DCSimpleParameter::
199 DCSimpleParameter(const DCSimpleParameter &copy) :
200  DCParameter(copy),
201  _type(copy._type),
202  _divisor(copy._divisor),
203  _nested_field(copy._nested_field),
204  _bytes_per_element(copy._bytes_per_element),
205  _orig_range(copy._orig_range),
206  _has_modulus(copy._has_modulus),
207  _orig_modulus(copy._orig_modulus),
208  _int_range(copy._int_range),
209  _uint_range(copy._uint_range),
210  _int64_range(copy._int64_range),
211  _uint64_range(copy._uint64_range),
212  _double_range(copy._double_range),
213  _uint_modulus(copy._uint_modulus),
214  _uint64_modulus(copy._uint64_modulus),
215  _double_modulus(copy._double_modulus)
216 {
217 }
218 
219 /**
220  *
221  */
222 DCSimpleParameter *DCSimpleParameter::
223 as_simple_parameter() {
224  return this;
225 }
226 
227 /**
228  *
229  */
230 const DCSimpleParameter *DCSimpleParameter::
231 as_simple_parameter() const {
232  return this;
233 }
234 
235 /**
236  *
237  */
238 DCParameter *DCSimpleParameter::
239 make_copy() const {
240  return new DCSimpleParameter(*this);
241 }
242 
243 /**
244  * Returns false if the type is an invalid type (e.g. declared from an
245  * undefined typedef), true if it is valid.
246  */
248 is_valid() const {
249  return _type != ST_invalid;
250 }
251 
252 /**
253  * Returns the particular subatomic type represented by this instance.
254  */
256 get_type() const {
257  return _type;
258 }
259 
260 /**
261  * Returns true if there is a modulus associated, false otherwise.,
262  */
264 has_modulus() const {
265  return _has_modulus;
266 }
267 
268 /**
269  * Returns the modulus associated with this type, if any. It is an error to
270  * call this if has_modulus() returned false.
271  *
272  * If present, this is the modulus that is used to constrain the numeric value
273  * of the field before it is packed (and range-checked).
274  */
275 double DCSimpleParameter::
276 get_modulus() const {
277  return _orig_modulus;
278 }
279 
280 /**
281  * Returns the divisor associated with this type. This is 1 by default, but
282  * if this is other than one it represents the scale to apply when packing and
283  * unpacking numeric values (to store fixed-point values in an integer field).
284  * It is only meaningful for numeric-type fields.
285  */
287 get_divisor() const {
288  return _divisor;
289 }
290 
291 /**
292  * Returns true if the type is a numeric type (and therefore can accept a
293  * divisor and/or a modulus), or false if it is some string-based type.
294  */
297  return !(_pack_type == PT_string || _pack_type == PT_blob);
298 }
299 
300 /**
301  * Assigns the indicated modulus to the simple type. Any packed value will be
302  * constrained to be within [0, modulus).
303  *
304  * Returns true if assigned, false if this type cannot accept a modulus or if
305  * the modulus is invalid.
306  */
308 set_modulus(double modulus) {
309  if (_pack_type == PT_string || _pack_type == PT_blob || modulus <= 0.0) {
310  return false;
311  }
312 
313  _has_modulus = true;
314  _orig_modulus = modulus;
315 
316  bool range_error = false;
317  _double_modulus = modulus * _divisor;
318  _uint64_modulus = (uint64_t)floor(_double_modulus + 0.5);
319  _uint_modulus = (unsigned int)_uint64_modulus;
320 
321  // Check the range. The legitimate range for a modulus value is 1 through
322  // (maximum_value + 1).
323  switch (_type) {
324  case ST_int8:
325  case ST_int8array:
326  validate_uint64_limits(_uint64_modulus - 1, 7, range_error);
327  break;
328 
329  case ST_int16:
330  case ST_int16array:
331  validate_uint64_limits(_uint64_modulus - 1, 15, range_error);
332  break;
333 
334  case ST_int32:
335  case ST_int32array:
336  validate_uint64_limits(_uint64_modulus - 1, 31, range_error);
337  break;
338 
339  case ST_int64:
340  validate_uint64_limits(_uint64_modulus - 1, 63, range_error);
341  break;
342 
343  case ST_char:
344  case ST_uint8:
345  case ST_uint8array:
346  validate_uint64_limits(_uint64_modulus - 1, 8, range_error);
347  break;
348 
349  case ST_uint16:
350  case ST_uint16array:
351  validate_uint64_limits(_uint64_modulus - 1, 16, range_error);
352  break;
353 
354  case ST_uint32:
355  case ST_uint32array:
356  validate_uint64_limits(_uint64_modulus - 1, 32, range_error);
357  break;
358 
359  case ST_uint64:
360  case ST_float64:
361  break;
362 
363  default:
364  return false;
365  }
366 
367  return !range_error;
368 }
369 
370 /**
371  * Assigns the indicated divisor to the simple type. Returns true if
372  * assigned, false if this type cannot accept a divisor or if the divisor is
373  * invalid.
374  */
376 set_divisor(unsigned int divisor) {
377  if (_pack_type == PT_string || _pack_type == PT_blob || divisor == 0) {
378  return false;
379  }
380 
381  _divisor = divisor;
382  if ((_divisor != 1) &&
383  (_pack_type == PT_int || _pack_type == PT_int64 ||
384  _pack_type == PT_uint || _pack_type == PT_uint64)) {
385  _pack_type = PT_double;
386  }
387 
388  if (_has_range_limits) {
389  set_range(_orig_range);
390  }
391  if (_has_modulus) {
392  set_modulus(_orig_modulus);
393  }
394 
395  return true;
396 }
397 
398 /**
399  * Sets the parameter with the indicated range. A DCDoubleRange is used for
400  * specification, since this is the most generic type; but it is converted to
401  * the appropriate type internally. The return value is true if successful,
402  * or false if the range is inappropriate for the type.
403  */
405 set_range(const DCDoubleRange &range) {
406  bool range_error = false;
407  int num_ranges = range.get_num_ranges();
408  int i;
409 
410  _has_range_limits = (num_ranges != 0);
411  _orig_range = range;
412 
413  switch (_type) {
414  case ST_int8:
415  case ST_int8array:
416  _int_range.clear();
417  for (i = 0; i < num_ranges; i++) {
418  int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5);
419  int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5);
420  validate_int64_limits(min, 8, range_error);
421  validate_int64_limits(max, 8, range_error);
422  _int_range.add_range((int)min, (int)max);
423  }
424  break;
425 
426  case ST_int16:
427  case ST_int16array:
428  _int_range.clear();
429  for (i = 0; i < num_ranges; i++) {
430  int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5);
431  int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5);
432  validate_int64_limits(min, 16, range_error);
433  validate_int64_limits(max, 16, range_error);
434  _int_range.add_range((int)min, (int)max);
435  }
436  break;
437 
438  case ST_int32:
439  case ST_int32array:
440  _int_range.clear();
441  for (i = 0; i < num_ranges; i++) {
442  int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5);
443  int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5);
444  validate_int64_limits(min, 32, range_error);
445  validate_int64_limits(max, 32, range_error);
446  _int_range.add_range((int)min, (int)max);
447  }
448  break;
449 
450  case ST_int64:
451  _int64_range.clear();
452  for (i = 0; i < num_ranges; i++) {
453  int64_t min = (int64_t)floor(range.get_min(i) * _divisor + 0.5);
454  int64_t max = (int64_t)floor(range.get_max(i) * _divisor + 0.5);
455  _int64_range.add_range(min, max);
456  }
457  break;
458 
459  case ST_char:
460  case ST_uint8:
461  case ST_uint8array:
462  _uint_range.clear();
463  for (i = 0; i < num_ranges; i++) {
464  uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5);
465  uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5);
466  validate_uint64_limits(min, 8, range_error);
467  validate_uint64_limits(max, 8, range_error);
468  _uint_range.add_range((unsigned int)min, (unsigned int)max);
469  }
470  break;
471 
472  case ST_uint16:
473  case ST_uint16array:
474  _uint_range.clear();
475  for (i = 0; i < num_ranges; i++) {
476  uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5);
477  uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5);
478  validate_uint64_limits(min, 16, range_error);
479  validate_uint64_limits(max, 16, range_error);
480  _uint_range.add_range((unsigned int)min, (unsigned int)max);
481  }
482  break;
483 
484  case ST_uint32:
485  case ST_uint32array:
486  _uint_range.clear();
487  for (i = 0; i < num_ranges; i++) {
488  uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5);
489  uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5);
490  validate_uint64_limits(min, 32, range_error);
491  validate_uint64_limits(max, 32, range_error);
492  _uint_range.add_range((unsigned int)min, (unsigned int)max);
493  }
494  break;
495 
496  case ST_uint64:
497  _uint64_range.clear();
498  for (i = 0; i < num_ranges; i++) {
499  uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5);
500  uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5);
501  _uint64_range.add_range(min, max);
502  }
503  break;
504 
505  case ST_float64:
506  _double_range.clear();
507  for (i = 0; i < num_ranges; i++) {
508  double min = range.get_min(i) * _divisor;
509  double max = range.get_max(i) * _divisor;
510  _double_range.add_range(min, max);
511  }
512  break;
513 
514  case ST_string:
515  case ST_blob:
516  _uint_range.clear();
517  for (i = 0; i < num_ranges; i++) {
518  uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5);
519  uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5);
520  validate_uint64_limits(min, 16, range_error);
521  validate_uint64_limits(max, 16, range_error);
522  _uint_range.add_range((unsigned int)min, (unsigned int)max);
523  }
524  if (_uint_range.has_one_value()) {
525  // If we now have a fixed-length string requirement, we don't need a
526  // leading number of bytes.
527  _num_length_bytes = 0;
528  _has_fixed_byte_size = true;
529  _fixed_byte_size = _uint_range.get_one_value();
530  _has_fixed_structure = true;
531  } else {
532  _num_length_bytes = 2;
533  _has_fixed_byte_size = false;
534  _has_fixed_structure = false;
535  }
536  break;
537 
538  case ST_blob32:
539  _uint_range.clear();
540  for (i = 0; i < num_ranges; i++) {
541  uint64_t min = (uint64_t)floor(range.get_min(i) * _divisor + 0.5);
542  uint64_t max = (uint64_t)floor(range.get_max(i) * _divisor + 0.5);
543  validate_uint64_limits(min, 32, range_error);
544  validate_uint64_limits(max, 32, range_error);
545  _uint_range.add_range((unsigned int)min, (unsigned int)max);
546  }
547  if (_uint_range.has_one_value()) {
548  // If we now have a fixed-length string requirement, we don't need a
549  // leading number of bytes.
550  _num_length_bytes = 0;
551  _has_fixed_byte_size = true;
552  _fixed_byte_size = _uint_range.get_one_value();
553  _has_fixed_structure = true;
554  } else {
555  _num_length_bytes = 4;
556  _has_fixed_byte_size = false;
557  _has_fixed_structure = false;
558  }
559  break;
560 
561  default:
562  return false;
563  }
564 
565  return !range_error;
566 }
567 
568 /**
569  * This flavor of get_num_nested_fields is used during unpacking. It returns
570  * the number of nested fields to expect, given a certain length in bytes (as
571  * read from the _num_length_bytes stored in the stream on the push). This
572  * will only be called if _num_length_bytes is nonzero.
573  */
575 calc_num_nested_fields(size_t length_bytes) const {
576  if (_bytes_per_element != 0) {
577  return length_bytes / _bytes_per_element;
578  }
579  return 0;
580 }
581 
582 /**
583  * Returns the DCPackerInterface object that represents the nth nested field.
584  * This may return NULL if there is no such field (but it shouldn't do this if
585  * n is in the range 0 <= n < get_num_nested_fields()).
586  */
588 get_nested_field(int) const {
589  return _nested_field;
590 }
591 
592 /**
593  * Packs the indicated numeric or string value into the stream.
594  */
596 pack_double(DCPackData &pack_data, double value,
597  bool &pack_error, bool &range_error) const {
598  double real_value = value * _divisor;
599  if (_has_modulus) {
600  if (real_value < 0.0) {
601  real_value = _double_modulus - fmod(-real_value, _double_modulus);
602  if (real_value == _double_modulus) {
603  real_value = 0.0;
604  }
605  } else {
606  real_value = fmod(real_value, _double_modulus);
607  }
608  }
609 
610  switch (_type) {
611  case ST_int8:
612  {
613  int int_value = (int)floor(real_value + 0.5);
614  _int_range.validate(int_value, range_error);
615  validate_int_limits(int_value, 8, range_error);
616  do_pack_int8(pack_data.get_write_pointer(1), int_value);
617  }
618  break;
619 
620  case ST_int16:
621  {
622  int int_value = (int)floor(real_value + 0.5);
623  _int_range.validate(int_value, range_error);
624  validate_int_limits(int_value, 16, range_error);
625  do_pack_int16(pack_data.get_write_pointer(2), int_value);
626  }
627  break;
628 
629  case ST_int32:
630  {
631  int int_value = (int)floor(real_value + 0.5);
632  _int_range.validate(int_value, range_error);
633  do_pack_int32(pack_data.get_write_pointer(4), int_value);
634  }
635  break;
636 
637  case ST_int64:
638  {
639  int64_t int64_value = (int64_t)floor(real_value + 0.5);
640  _int64_range.validate(int64_value, range_error);
641  do_pack_int64(pack_data.get_write_pointer(8), int64_value);
642  }
643  break;
644 
645  case ST_char:
646  case ST_uint8:
647  {
648  unsigned int int_value = (unsigned int)floor(real_value + 0.5);
649  _uint_range.validate(int_value, range_error);
650  validate_uint_limits(int_value, 8, range_error);
651  do_pack_uint8(pack_data.get_write_pointer(1), int_value);
652  }
653  break;
654 
655  case ST_uint16:
656  {
657  unsigned int int_value = (unsigned int)floor(real_value + 0.5);
658  _uint_range.validate(int_value, range_error);
659  validate_uint_limits(int_value, 16, range_error);
660  do_pack_uint16(pack_data.get_write_pointer(2), int_value);
661  }
662  break;
663 
664  case ST_uint32:
665  {
666  unsigned int int_value = (unsigned int)floor(real_value + 0.5);
667  _uint_range.validate(int_value, range_error);
668  do_pack_uint32(pack_data.get_write_pointer(4), int_value);
669  }
670  break;
671 
672  case ST_uint64:
673  {
674  uint64_t int64_value = (uint64_t)floor(real_value + 0.5);
675  _uint64_range.validate(int64_value, range_error);
676  do_pack_uint64(pack_data.get_write_pointer(8), int64_value);
677  }
678  break;
679 
680  case ST_float64:
681  _double_range.validate(real_value, range_error);
682  do_pack_float64(pack_data.get_write_pointer(8), real_value);
683  break;
684 
685  default:
686  pack_error = true;
687  }
688 }
689 
690 /**
691  * Packs the indicated numeric or string value into the stream.
692  */
694 pack_int(DCPackData &pack_data, int value,
695  bool &pack_error, bool &range_error) const {
696  int int_value = value * _divisor;
697 
698  if (value != 0 && (int_value / value) != (int)_divisor) {
699  // If we've experienced overflow after applying the divisor, pack it as an
700  // int64 instead.
701  pack_int64(pack_data, (int64_t)value, pack_error, range_error);
702  return;
703  }
704 
705  if (_has_modulus && _uint_modulus != 0) {
706  if (int_value < 0) {
707  int_value = _uint_modulus - 1 - (-int_value - 1) % _uint_modulus;
708  } else {
709  int_value = int_value % _uint_modulus;
710  }
711  }
712 
713  switch (_type) {
714  case ST_int8:
715  _int_range.validate(int_value, range_error);
716  validate_int_limits(int_value, 8, range_error);
717  do_pack_int8(pack_data.get_write_pointer(1), int_value);
718  break;
719 
720  case ST_int16:
721  _int_range.validate(int_value, range_error);
722  validate_int_limits(int_value, 16, range_error);
723  do_pack_int16(pack_data.get_write_pointer(2), int_value);
724  break;
725 
726  case ST_int32:
727  _int_range.validate(int_value, range_error);
728  do_pack_int32(pack_data.get_write_pointer(4), int_value);
729  break;
730 
731  case ST_int64:
732  _int64_range.validate(int_value, range_error);
733  do_pack_int64(pack_data.get_write_pointer(8), int_value);
734  break;
735 
736  case ST_char:
737  case ST_uint8:
738  if (int_value < 0) {
739  range_error = true;
740  }
741  _uint_range.validate((unsigned int)int_value, range_error);
742  validate_uint_limits((unsigned int)int_value, 8, range_error);
743  do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
744  break;
745 
746  case ST_uint16:
747  if (int_value < 0) {
748  range_error = true;
749  }
750  _uint_range.validate((unsigned int)int_value, range_error);
751  validate_uint_limits((unsigned int)int_value, 16, range_error);
752  do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
753  break;
754 
755  case ST_uint32:
756  if (int_value < 0) {
757  range_error = true;
758  }
759  _uint_range.validate((unsigned int)int_value, range_error);
760  do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
761  break;
762 
763  case ST_uint64:
764  if (int_value < 0) {
765  range_error = true;
766  }
767  _uint64_range.validate((unsigned int)int_value, range_error);
768  do_pack_uint64(pack_data.get_write_pointer(8), (unsigned int)int_value);
769  break;
770 
771  case ST_float64:
772  _double_range.validate(int_value, range_error);
773  do_pack_float64(pack_data.get_write_pointer(8), int_value);
774  break;
775 
776  default:
777  pack_error = true;
778  }
779 }
780 
781 /**
782  * Packs the indicated numeric or string value into the stream.
783  */
785 pack_uint(DCPackData &pack_data, unsigned int value,
786  bool &pack_error, bool &range_error) const {
787  unsigned int int_value = value * _divisor;
788  if (_has_modulus && _uint_modulus != 0) {
789  int_value = int_value % _uint_modulus;
790  }
791 
792  switch (_type) {
793  case ST_int8:
794  if ((int)int_value < 0) {
795  range_error = true;
796  }
797  _int_range.validate((int)int_value, range_error);
798  validate_int_limits((int)int_value, 8, range_error);
799  do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
800  break;
801 
802  case ST_int16:
803  if ((int)int_value < 0) {
804  range_error = true;
805  }
806  _int_range.validate((int)int_value, range_error);
807  validate_int_limits((int)int_value, 16, range_error);
808  do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
809  break;
810 
811  case ST_int32:
812  if ((int)int_value < 0) {
813  range_error = true;
814  }
815  _int_range.validate((int)int_value, range_error);
816  do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
817  break;
818 
819  case ST_int64:
820  if ((int)int_value < 0) {
821  range_error = true;
822  }
823  _int64_range.validate((int)int_value, range_error);
824  do_pack_int64(pack_data.get_write_pointer(8), (int)int_value);
825  break;
826 
827  case ST_char:
828  case ST_uint8:
829  _uint_range.validate(int_value, range_error);
830  validate_uint_limits(int_value, 8, range_error);
831  do_pack_uint8(pack_data.get_write_pointer(1), int_value);
832  break;
833 
834  case ST_uint16:
835  _uint_range.validate(int_value, range_error);
836  validate_uint_limits(int_value, 16, range_error);
837  do_pack_uint16(pack_data.get_write_pointer(2), int_value);
838  break;
839 
840  case ST_uint32:
841  _uint_range.validate(int_value, range_error);
842  do_pack_uint32(pack_data.get_write_pointer(4), int_value);
843  break;
844 
845  case ST_uint64:
846  _uint64_range.validate(int_value, range_error);
847  do_pack_uint64(pack_data.get_write_pointer(8), int_value);
848  break;
849 
850  case ST_float64:
851  _double_range.validate(int_value, range_error);
852  do_pack_float64(pack_data.get_write_pointer(8), int_value);
853  break;
854 
855  default:
856  pack_error = true;
857  }
858 }
859 
860 /**
861  * Packs the indicated numeric or string value into the stream.
862  */
864 pack_int64(DCPackData &pack_data, int64_t value,
865  bool &pack_error, bool &range_error) const {
866  int64_t int_value = value * _divisor;
867  if (_has_modulus && _uint64_modulus != 0) {
868  if (int_value < 0) {
869  int_value = _uint64_modulus - 1 - (-int_value - 1) % _uint64_modulus;
870  } else {
871  int_value = int_value % _uint64_modulus;
872  }
873  }
874 
875  switch (_type) {
876  case ST_int8:
877  _int_range.validate((int)int_value, range_error);
878  validate_int64_limits(int_value, 8, range_error);
879  do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
880  break;
881 
882  case ST_int16:
883  _int_range.validate((int)int_value, range_error);
884  validate_int64_limits(int_value, 16, range_error);
885  do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
886  break;
887 
888  case ST_int32:
889  _int_range.validate((int)int_value, range_error);
890  validate_int64_limits(int_value, 32, range_error);
891  do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
892  break;
893 
894  case ST_int64:
895  _int64_range.validate(int_value, range_error);
896  do_pack_int64(pack_data.get_write_pointer(8), int_value);
897  break;
898 
899  case ST_char:
900  case ST_uint8:
901  if (int_value < 0) {
902  range_error = true;
903  }
904  _uint_range.validate((unsigned int)(uint64_t)int_value, range_error);
905  validate_uint64_limits((uint64_t)int_value, 8, range_error);
906  do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)(uint64_t)int_value);
907  break;
908 
909  case ST_uint16:
910  if (int_value < 0) {
911  range_error = true;
912  }
913  _uint_range.validate((unsigned int)(uint64_t)int_value, range_error);
914  validate_uint64_limits((uint64_t)int_value, 16, range_error);
915  do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)(uint64_t)int_value);
916  break;
917 
918  case ST_uint32:
919  if (int_value < 0) {
920  range_error = true;
921  }
922  _uint_range.validate((unsigned int)(uint64_t)int_value, range_error);
923  validate_uint64_limits((uint64_t)int_value, 32, range_error);
924  do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)(uint64_t)int_value);
925  break;
926 
927  case ST_uint64:
928  if (int_value < 0) {
929  range_error = true;
930  }
931  _uint64_range.validate((uint64_t)int_value, range_error);
932  do_pack_uint64(pack_data.get_write_pointer(8), (uint64_t)int_value);
933  break;
934 
935  case ST_float64:
936  _double_range.validate((double)int_value, range_error);
937  do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
938  break;
939 
940  default:
941  pack_error = true;
942  }
943 }
944 
945 /**
946  * Packs the indicated numeric or string value into the stream.
947  */
949 pack_uint64(DCPackData &pack_data, uint64_t value,
950  bool &pack_error, bool &range_error) const {
951  uint64_t int_value = value * _divisor;
952  if (_has_modulus && _uint64_modulus != 0) {
953  int_value = int_value % _uint64_modulus;
954  }
955 
956  switch (_type) {
957  case ST_int8:
958  if ((int64_t)int_value < 0) {
959  range_error = true;
960  }
961  _int_range.validate((int)(int64_t)int_value, range_error);
962  validate_int64_limits((int64_t)int_value, 8, range_error);
963  do_pack_int8(pack_data.get_write_pointer(1), (int)(int64_t)int_value);
964  break;
965 
966  case ST_int16:
967  if ((int64_t)int_value < 0) {
968  range_error = true;
969  }
970  _int_range.validate((int)(int64_t)int_value, range_error);
971  validate_int64_limits((int64_t)int_value, 16, range_error);
972  do_pack_int16(pack_data.get_write_pointer(2), (int)(int64_t)int_value);
973  break;
974 
975  case ST_int32:
976  if ((int64_t)int_value < 0) {
977  range_error = true;
978  }
979  _int_range.validate((int)(int64_t)int_value, range_error);
980  validate_int64_limits((int64_t)int_value, 32, range_error);
981  do_pack_int32(pack_data.get_write_pointer(4), (int)(int64_t)int_value);
982  break;
983 
984  case ST_int64:
985  if ((int64_t)int_value < 0) {
986  range_error = true;
987  }
988  _int64_range.validate((int64_t)int_value, range_error);
989  do_pack_int64(pack_data.get_write_pointer(8), (int64_t)int_value);
990  break;
991 
992  case ST_char:
993  case ST_uint8:
994  _uint_range.validate((unsigned int)int_value, range_error);
995  validate_uint64_limits(int_value, 8, range_error);
996  do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
997  break;
998 
999  case ST_uint16:
1000  _uint_range.validate((unsigned int)int_value, range_error);
1001  validate_uint64_limits(int_value, 16, range_error);
1002  do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
1003  break;
1004 
1005  case ST_uint32:
1006  _uint_range.validate((unsigned int)int_value, range_error);
1007  validate_uint64_limits(int_value, 32, range_error);
1008  do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
1009  break;
1010 
1011  case ST_uint64:
1012  _uint64_range.validate(int_value, range_error);
1013  do_pack_uint64(pack_data.get_write_pointer(8), int_value);
1014  break;
1015 
1016  case ST_float64:
1017  _double_range.validate((double)int_value, range_error);
1018  do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
1019  break;
1020 
1021  default:
1022  pack_error = true;
1023  }
1024 }
1025 
1026 /**
1027  * Packs the indicated numeric or string value into the stream.
1028  */
1030 pack_string(DCPackData &pack_data, const string &value,
1031  bool &pack_error, bool &range_error) const {
1032  size_t string_length = value.length();
1033 
1034  switch (_type) {
1035  case ST_char:
1036  case ST_uint8:
1037  case ST_int8:
1038  if (string_length == 0) {
1039  pack_error = true;
1040  } else {
1041  if (string_length != 1) {
1042  range_error = true;
1043  }
1044  _uint_range.validate((unsigned int)value[0], range_error);
1045  do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)value[0]);
1046  }
1047  break;
1048 
1049  case ST_string:
1050  case ST_blob:
1051  _uint_range.validate(string_length, range_error);
1052  validate_uint_limits(string_length, 16, range_error);
1053  if (_num_length_bytes != 0) {
1054  do_pack_uint16(pack_data.get_write_pointer(2), string_length);
1055  }
1056  pack_data.append_data(value.data(), string_length);
1057  break;
1058 
1059  case ST_blob32:
1060  _uint_range.validate(string_length, range_error);
1061  if (_num_length_bytes != 0) {
1062  do_pack_uint32(pack_data.get_write_pointer(4), string_length);
1063  }
1064  pack_data.append_data(value.data(), string_length);
1065  break;
1066 
1067  default:
1068  pack_error = true;
1069  }
1070 }
1071 
1072 /**
1073  * Packs the indicated numeric or string value into the stream.
1074  */
1076 pack_blob(DCPackData &pack_data, const vector_uchar &value,
1077  bool &pack_error, bool &range_error) const {
1078  size_t blob_size = value.size();
1079 
1080  switch (_type) {
1081  case ST_char:
1082  case ST_uint8:
1083  case ST_int8:
1084  if (blob_size == 0) {
1085  pack_error = true;
1086  } else {
1087  if (blob_size != 1) {
1088  range_error = true;
1089  }
1090  _uint_range.validate((unsigned int)value[0], range_error);
1091  do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)value[0]);
1092  }
1093  break;
1094 
1095  case ST_string:
1096  case ST_blob:
1097  _uint_range.validate(blob_size, range_error);
1098  validate_uint_limits(blob_size, 16, range_error);
1099  if (_num_length_bytes != 0) {
1100  do_pack_uint16(pack_data.get_write_pointer(2), blob_size);
1101  }
1102  pack_data.append_data((const char *)value.data(), blob_size);
1103  break;
1104 
1105  case ST_blob32:
1106  _uint_range.validate(blob_size, range_error);
1107  if (_num_length_bytes != 0) {
1108  do_pack_uint32(pack_data.get_write_pointer(4), blob_size);
1109  }
1110  pack_data.append_data((const char *)value.data(), blob_size);
1111  break;
1112 
1113  default:
1114  pack_error = true;
1115  }
1116 }
1117 
1118 /**
1119  * Packs the simpleParameter's specified default value (or a sensible default
1120  * if no value is specified) into the stream. Returns true if the default
1121  * value is packed, false if the simpleParameter doesn't know how to pack its
1122  * default value.
1123  */
1125 pack_default_value(DCPackData &pack_data, bool &pack_error) const {
1126  if (has_default_value()) {
1127  return DCField::pack_default_value(pack_data, pack_error);
1128  }
1129 
1130  if (_has_nested_fields) {
1131  // If the simple type is an array (or string) type, pack the appropriate
1132  // length array, with code similar to
1133  // DCArrayParameter::pack_default_value().
1134 
1135  unsigned int minimum_length = 0;
1136  if (!_uint_range.is_empty()) {
1137  minimum_length = _uint_range.get_min(0);
1138  }
1139 
1140  DCPacker packer;
1141  packer.begin_pack(this);
1142  packer.push();
1143  for (unsigned int i = 0; i < minimum_length; i++) {
1144  packer.pack_default_value();
1145  }
1146  packer.pop();
1147  if (!packer.end_pack()) {
1148  pack_error = true;
1149 
1150  } else {
1151  pack_data.append_data(packer.get_data(), packer.get_length());
1152  }
1153 
1154  } else {
1155  // Otherwise, if it's just a simple numeric type, pack a zero or the
1156  // minimum value.
1157  switch (_type) {
1158  case ST_int8:
1159  case ST_int16:
1160  case ST_int32:
1161  if (_int_range.is_in_range(0)) {
1162  pack_int(pack_data, 0, pack_error, pack_error);
1163  } else {
1164  pack_int(pack_data, _int_range.get_min(0), pack_error, pack_error);
1165  }
1166  break;
1167 
1168  case ST_int64:
1169  if (_int64_range.is_in_range(0)) {
1170  pack_int64(pack_data, 0, pack_error, pack_error);
1171  } else {
1172  pack_int64(pack_data, _int64_range.get_min(0), pack_error, pack_error);
1173  }
1174  break;
1175 
1176  case ST_char:
1177  case ST_uint8:
1178  case ST_uint16:
1179  case ST_uint32:
1180  if (_uint_range.is_in_range(0)) {
1181  pack_uint(pack_data, 0, pack_error, pack_error);
1182  } else {
1183  pack_uint(pack_data, _uint_range.get_min(0), pack_error, pack_error);
1184  }
1185  break;
1186 
1187  case ST_uint64:
1188  if (_uint64_range.is_in_range(0)) {
1189  pack_uint64(pack_data, 0, pack_error, pack_error);
1190  } else {
1191  pack_uint64(pack_data, _uint64_range.get_min(0), pack_error, pack_error);
1192  }
1193  break;
1194 
1195  case ST_float64:
1196  if (_double_range.is_in_range(0.0)) {
1197  pack_double(pack_data, 0.0, pack_error, pack_error);
1198  } else {
1199  pack_double(pack_data, _double_range.get_min(0), pack_error, pack_error);
1200  }
1201  break;
1202 
1203  default:
1204  pack_error = true;
1205  }
1206  }
1207  return true;
1208 }
1209 
1210 
1211 
1212 /**
1213  * Unpacks the current numeric or string value from the stream.
1214  */
1216 unpack_double(const char *data, size_t length, size_t &p, double &value,
1217  bool &pack_error, bool &range_error) const {
1218  switch (_type) {
1219  case ST_int8:
1220  {
1221  if (p + 1 > length) {
1222  pack_error = true;
1223  return;
1224  }
1225  int int_value = do_unpack_int8(data + p);
1226  _int_range.validate(int_value, range_error);
1227  value = int_value;
1228  p++;
1229  }
1230  break;
1231 
1232  case ST_int16:
1233  {
1234  if (p + 2 > length) {
1235  pack_error = true;
1236  return;
1237  }
1238  int int_value = do_unpack_int16(data + p);
1239  _int_range.validate(int_value, range_error);
1240  value = int_value;
1241  p += 2;
1242  }
1243  break;
1244 
1245  case ST_int32:
1246  {
1247  if (p + 4 > length) {
1248  pack_error = true;
1249  return;
1250  }
1251  int int_value = do_unpack_int32(data + p);
1252  _int_range.validate(int_value, range_error);
1253  value = int_value;
1254  p += 4;
1255  }
1256  break;
1257 
1258  case ST_int64:
1259  {
1260  if (p + 8 > length) {
1261  pack_error = true;
1262  return;
1263  }
1264  int64_t int_value = do_unpack_int64(data + p);
1265  _int64_range.validate(int_value, range_error);
1266  value = (double)int_value;
1267  p += 8;
1268  }
1269  break;
1270 
1271  case ST_char:
1272  case ST_uint8:
1273  {
1274  if (p + 1 > length) {
1275  pack_error = true;
1276  return;
1277  }
1278  unsigned int uint_value = do_unpack_uint8(data + p);
1279  _uint_range.validate(uint_value, range_error);
1280  value = uint_value;
1281  p++;
1282  }
1283  break;
1284 
1285  case ST_uint16:
1286  {
1287  if (p + 2 > length) {
1288  pack_error = true;
1289  return;
1290  }
1291  unsigned int uint_value = do_unpack_uint16(data + p);
1292  _uint_range.validate(uint_value, range_error);
1293  value = uint_value;
1294  p += 2;
1295  }
1296  break;
1297 
1298  case ST_uint32:
1299  {
1300  if (p + 4 > length) {
1301  pack_error = true;
1302  return;
1303  }
1304  unsigned int uint_value = do_unpack_uint32(data + p);
1305  _uint_range.validate(uint_value, range_error);
1306  value = uint_value;
1307  p += 4;
1308  }
1309  break;
1310 
1311  case ST_uint64:
1312  {
1313  if (p + 8 > length) {
1314  pack_error = true;
1315  return;
1316  }
1317  uint64_t uint_value = do_unpack_uint64(data + p);
1318  _uint64_range.validate(uint_value, range_error);
1319  value = (double)uint_value;
1320  p += 8;
1321  }
1322  break;
1323 
1324  case ST_float64:
1325  {
1326  if (p + 8 > length) {
1327  pack_error = true;
1328  return;
1329  }
1330  value = do_unpack_float64(data + p);
1331  _double_range.validate(value, range_error);
1332  p += 8;
1333  }
1334  break;
1335 
1336  default:
1337  pack_error = true;
1338  return;
1339  }
1340 
1341  if (_divisor != 1) {
1342  value = value / _divisor;
1343  }
1344 
1345  return;
1346 }
1347 
1348 /**
1349  * Unpacks the current numeric or string value from the stream.
1350  */
1352 unpack_int(const char *data, size_t length, size_t &p, int &value,
1353  bool &pack_error, bool &range_error) const {
1354  switch (_type) {
1355  case ST_int8:
1356  if (p + 1 > length) {
1357  pack_error = true;
1358  return;
1359  }
1360  value = do_unpack_int8(data + p);
1361  _int_range.validate(value, range_error);
1362  p++;
1363  break;
1364 
1365  case ST_int16:
1366  if (p + 2 > length) {
1367  pack_error = true;
1368  return;
1369  }
1370  value = do_unpack_int16(data + p);
1371  _int_range.validate(value, range_error);
1372  p += 2;
1373  break;
1374 
1375  case ST_int32:
1376  if (p + 4 > length) {
1377  pack_error = true;
1378  return;
1379  }
1380  value = do_unpack_int32(data + p);
1381  _int_range.validate(value, range_error);
1382  p += 4;
1383  break;
1384 
1385  case ST_int64:
1386  {
1387  if (p + 8 > length) {
1388  pack_error = true;
1389  return;
1390  }
1391  int64_t int_value = do_unpack_uint64(data + p);
1392  _int64_range.validate(int_value, range_error);
1393  value = (int)int_value;
1394  if (value != int_value) {
1395  // uint exceeded the storage capacity of a signed int.
1396  pack_error = true;
1397  }
1398  p += 8;
1399  }
1400  break;
1401 
1402  case ST_char:
1403  case ST_uint8:
1404  {
1405  if (p + 1 > length) {
1406  pack_error = true;
1407  return;
1408  }
1409  unsigned int uint_value = do_unpack_uint8(data + p);
1410  _uint_range.validate(uint_value, range_error);
1411  value = uint_value;
1412  p++;
1413  }
1414  break;
1415 
1416  case ST_uint16:
1417  {
1418  if (p + 2 > length) {
1419  pack_error = true;
1420  return;
1421  }
1422  unsigned int uint_value = do_unpack_uint16(data + p);
1423  _uint_range.validate(uint_value, range_error);
1424  value = (int)uint_value;
1425  p += 2;
1426  }
1427  break;
1428 
1429  case ST_uint32:
1430  {
1431  if (p + 4 > length) {
1432  pack_error = true;
1433  return;
1434  }
1435  unsigned int uint_value = do_unpack_uint32(data + p);
1436  _uint_range.validate(uint_value, range_error);
1437  value = (int)uint_value;
1438  if (value < 0) {
1439  pack_error = true;
1440  }
1441  p += 4;
1442  }
1443  break;
1444 
1445  case ST_uint64:
1446  {
1447  if (p + 8 > length) {
1448  pack_error = true;
1449  return;
1450  }
1451  uint64_t uint_value = do_unpack_uint64(data + p);
1452  _uint64_range.validate(uint_value, range_error);
1453  value = (int)(unsigned int)uint_value;
1454  if ((unsigned int)value != uint_value || value < 0) {
1455  pack_error = true;
1456  }
1457  p += 8;
1458  }
1459  break;
1460 
1461  case ST_float64:
1462  {
1463  if (p + 8 > length) {
1464  pack_error = true;
1465  return;
1466  }
1467  double real_value = do_unpack_float64(data + p);
1468  _double_range.validate(real_value, range_error);
1469  value = (int)real_value;
1470  p += 8;
1471  }
1472  break;
1473 
1474  default:
1475  pack_error = true;
1476  return;
1477  }
1478 
1479  if (_divisor != 1) {
1480  value = value / _divisor;
1481  }
1482 
1483  return;
1484 }
1485 
1486 /**
1487  * Unpacks the current numeric or string value from the stream.
1488  */
1490 unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value,
1491  bool &pack_error, bool &range_error) const {
1492  switch (_type) {
1493  case ST_int8:
1494  {
1495  if (p + 1 > length) {
1496  pack_error = true;
1497  return;
1498  }
1499  int int_value = do_unpack_int8(data + p);
1500  _int_range.validate(int_value, range_error);
1501  if (int_value < 0) {
1502  pack_error = true;
1503  }
1504  value = (unsigned int)int_value;
1505  p++;
1506  }
1507  break;
1508 
1509  case ST_int16:
1510  {
1511  if (p + 2 > length) {
1512  pack_error = true;
1513  return;
1514  }
1515  int int_value = do_unpack_int16(data + p);
1516  _int_range.validate(int_value, range_error);
1517  if (int_value < 0) {
1518  pack_error = true;
1519  }
1520  value = (unsigned int)int_value;
1521  p += 2;
1522  }
1523  break;
1524 
1525  case ST_int32:
1526  {
1527  if (p + 4 > length) {
1528  pack_error = true;
1529  return;
1530  }
1531  int int_value = do_unpack_int32(data + p);
1532  _int_range.validate(int_value, range_error);
1533  if (int_value < 0) {
1534  pack_error = true;
1535  }
1536  value = (unsigned int)int_value;
1537  p += 4;
1538  }
1539  break;
1540 
1541  case ST_int64:
1542  {
1543  if (p + 8 > length) {
1544  pack_error = true;
1545  return;
1546  }
1547  int64_t int_value = do_unpack_int64(data + p);
1548  _int64_range.validate(int_value, range_error);
1549  if (int_value < 0) {
1550  pack_error = true;
1551  }
1552  value = (unsigned int)(int)int_value;
1553  if (value != int_value) {
1554  pack_error = true;
1555  }
1556  p += 8;
1557  }
1558  break;
1559 
1560  case ST_char:
1561  case ST_uint8:
1562  if (p + 1 > length) {
1563  pack_error = true;
1564  return;
1565  }
1566  value = do_unpack_uint8(data + p);
1567  _uint_range.validate(value, range_error);
1568  p++;
1569  break;
1570 
1571  case ST_uint16:
1572  if (p + 2 > length) {
1573  pack_error = true;
1574  return;
1575  }
1576  value = do_unpack_uint16(data + p);
1577  _uint_range.validate(value, range_error);
1578  p += 2;
1579  break;
1580 
1581  case ST_uint32:
1582  if (p + 4 > length) {
1583  pack_error = true;
1584  return;
1585  }
1586  value = do_unpack_uint32(data + p);
1587  _uint_range.validate(value, range_error);
1588  p += 4;
1589  break;
1590 
1591  case ST_uint64:
1592  {
1593  if (p + 8 > length) {
1594  pack_error = true;
1595  return;
1596  }
1597  uint64_t uint_value = do_unpack_uint64(data + p);
1598  _uint64_range.validate(uint_value, range_error);
1599  value = (unsigned int)uint_value;
1600  if (value != uint_value) {
1601  pack_error = true;
1602  }
1603  p += 8;
1604  }
1605  break;
1606 
1607  case ST_float64:
1608  {
1609  if (p + 8 > length) {
1610  pack_error = true;
1611  return;
1612  }
1613  double real_value = do_unpack_float64(data + p);
1614  _double_range.validate(real_value, range_error);
1615  value = (unsigned int)real_value;
1616  p += 8;
1617  }
1618  break;
1619 
1620  default:
1621  pack_error = true;
1622  return;
1623  }
1624 
1625  if (_divisor != 1) {
1626  value = value / _divisor;
1627  }
1628 
1629  return;
1630 }
1631 
1632 /**
1633  * Unpacks the current numeric or string value from the stream.
1634  */
1636 unpack_int64(const char *data, size_t length, size_t &p, int64_t &value,
1637  bool &pack_error, bool &range_error) const {
1638  switch (_type) {
1639  case ST_int8:
1640  {
1641  if (p + 1 > length) {
1642  pack_error = true;
1643  return;
1644  }
1645  int int_value = do_unpack_int8(data + p);
1646  _int_range.validate(int_value, range_error);
1647  value = (int64_t)int_value;
1648  p++;
1649  }
1650  break;
1651 
1652  case ST_int16:
1653  {
1654  if (p + 2 > length) {
1655  pack_error = true;
1656  return;
1657  }
1658  int int_value = do_unpack_int16(data + p);
1659  _int_range.validate(int_value, range_error);
1660  value = (int64_t)int_value;
1661  p += 2;
1662  }
1663  break;
1664 
1665  case ST_int32:
1666  {
1667  if (p + 4 > length) {
1668  pack_error = true;
1669  return;
1670  }
1671  int int_value = do_unpack_int32(data + p);
1672  _int_range.validate(int_value, range_error);
1673  value = (int64_t)int_value;
1674  p += 4;
1675  }
1676  break;
1677 
1678  case ST_int64:
1679  if (p + 8 > length) {
1680  pack_error = true;
1681  return;
1682  }
1683  value = do_unpack_int64(data + p);
1684  _int64_range.validate(value, range_error);
1685  p += 8;
1686  break;
1687 
1688  case ST_char:
1689  case ST_uint8:
1690  {
1691  if (p + 1 > length) {
1692  pack_error = true;
1693  return;
1694  }
1695  unsigned int uint_value = do_unpack_uint8(data + p);
1696  _uint_range.validate(uint_value, range_error);
1697  value = (int64_t)(int)uint_value;
1698  p++;
1699  }
1700  break;
1701 
1702  case ST_uint16:
1703  {
1704  if (p + 2 > length) {
1705  pack_error = true;
1706  return;
1707  }
1708  unsigned int uint_value = do_unpack_uint16(data + p);
1709  _uint_range.validate(uint_value, range_error);
1710  value = (int64_t)(int)uint_value;
1711  p += 2;
1712  }
1713  break;
1714 
1715  case ST_uint32:
1716  {
1717  if (p + 4 > length) {
1718  pack_error = true;
1719  return;
1720  }
1721  unsigned int uint_value = do_unpack_uint32(data + p);
1722  _uint_range.validate(uint_value, range_error);
1723  value = (int64_t)(int)uint_value;
1724  p += 4;
1725  }
1726  break;
1727 
1728  case ST_uint64:
1729  {
1730  if (p + 8 > length) {
1731  pack_error = true;
1732  return;
1733  }
1734  uint64_t uint_value = do_unpack_uint64(data + p);
1735  _uint64_range.validate(uint_value, range_error);
1736  value = (int64_t)uint_value;
1737  if (value < 0) {
1738  pack_error = true;
1739  }
1740  p += 8;
1741  }
1742  break;
1743 
1744  case ST_float64:
1745  {
1746  if (p + 8 > length) {
1747  pack_error = true;
1748  return;
1749  }
1750  double real_value = do_unpack_float64(data + p);
1751  _double_range.validate(real_value, range_error);
1752  value = (int64_t)real_value;
1753  p += 8;
1754  }
1755  break;
1756 
1757  default:
1758  pack_error = true;
1759  return;
1760  }
1761 
1762  if (_divisor != 1) {
1763  value = value / _divisor;
1764  }
1765 
1766  return;
1767 }
1768 
1769 /**
1770  * Unpacks the current numeric or string value from the stream.
1771  */
1773 unpack_uint64(const char *data, size_t length, size_t &p, uint64_t &value,
1774  bool &pack_error, bool &range_error) const {
1775  switch (_type) {
1776  case ST_int8:
1777  {
1778  if (p + 1 > length) {
1779  pack_error = true;
1780  return;
1781  }
1782  int int_value = do_unpack_int8(data + p);
1783  _int_range.validate(int_value, range_error);
1784  if (int_value < 0) {
1785  pack_error = true;
1786  }
1787  value = (uint64_t)(unsigned int)int_value;
1788  p++;
1789  }
1790  break;
1791 
1792  case ST_int16:
1793  {
1794  if (p + 2 > length) {
1795  pack_error = true;
1796  return;
1797  }
1798  int int_value = do_unpack_int16(data + p);
1799  _int_range.validate(int_value, range_error);
1800  if (int_value < 0) {
1801  pack_error = true;
1802  }
1803  value = (uint64_t)(unsigned int)int_value;
1804  p += 2;
1805  }
1806  break;
1807 
1808  case ST_int32:
1809  {
1810  if (p + 4 > length) {
1811  pack_error = true;
1812  return;
1813  }
1814  int int_value = do_unpack_int32(data + p);
1815  _int_range.validate(int_value, range_error);
1816  if (int_value < 0) {
1817  pack_error = true;
1818  }
1819  value = (uint64_t)(unsigned int)int_value;
1820  p += 4;
1821  }
1822  break;
1823 
1824  case ST_int64:
1825  {
1826  if (p + 8 > length) {
1827  pack_error = true;
1828  return;
1829  }
1830  int64_t int_value = do_unpack_int64(data + p);
1831  _int64_range.validate(int_value, range_error);
1832  if (int_value < 0) {
1833  pack_error = true;
1834  }
1835  value = (uint64_t)int_value;
1836  p += 8;
1837  }
1838  break;
1839 
1840  case ST_char:
1841  case ST_uint8:
1842  {
1843  if (p + 1 > length) {
1844  pack_error = true;
1845  return;
1846  }
1847  unsigned int uint_value = do_unpack_uint8(data + p);
1848  _uint_range.validate(uint_value, range_error);
1849  value = (uint64_t)uint_value;
1850  p++;
1851  }
1852  break;
1853 
1854  case ST_uint16:
1855  {
1856  if (p + 2 > length) {
1857  pack_error = true;
1858  return;
1859  }
1860  unsigned int uint_value = do_unpack_uint16(data + p);
1861  _uint_range.validate(uint_value, range_error);
1862  value = (uint64_t)uint_value;
1863  p += 2;
1864  }
1865  break;
1866 
1867  case ST_uint32:
1868  {
1869  if (p + 4 > length) {
1870  pack_error = true;
1871  return;
1872  }
1873  unsigned int uint_value = do_unpack_uint32(data + p);
1874  _uint_range.validate(uint_value, range_error);
1875  value = (uint64_t)uint_value;
1876  p += 4;
1877  }
1878  break;
1879 
1880  case ST_uint64:
1881  if (p + 8 > length) {
1882  pack_error = true;
1883  return;
1884  }
1885  value = do_unpack_uint64(data + p);
1886  _uint64_range.validate(value, range_error);
1887  p += 8;
1888  break;
1889 
1890  case ST_float64:
1891  {
1892  if (p + 8 > length) {
1893  pack_error = true;
1894  return;
1895  }
1896  double real_value = do_unpack_float64(data + p);
1897  _double_range.validate(real_value, range_error);
1898  value = (uint64_t)real_value;
1899  p += 8;
1900  }
1901  break;
1902 
1903  default:
1904  pack_error = true;
1905  return;
1906  }
1907 
1908  if (_divisor != 1) {
1909  value = value / _divisor;
1910  }
1911 
1912  return;
1913 }
1914 
1915 /**
1916  * Unpacks the current numeric or string value from the stream.
1917  */
1919 unpack_string(const char *data, size_t length, size_t &p, string &value,
1920  bool &pack_error, bool &range_error) const {
1921  // If the type is a single byte, unpack it into a string of length 1.
1922  switch (_type) {
1923  case ST_char:
1924  case ST_int8:
1925  case ST_uint8:
1926  {
1927  if (p + 1 > length) {
1928  pack_error = true;
1929  return;
1930  }
1931  unsigned int int_value = do_unpack_uint8(data + p);
1932  _uint_range.validate(int_value, range_error);
1933  value.assign(1, int_value);
1934  p++;
1935  }
1936  return;
1937 
1938  default:
1939  break;
1940  }
1941 
1942  size_t string_length;
1943 
1944  if (_num_length_bytes == 0) {
1945  string_length = _fixed_byte_size;
1946 
1947  } else {
1948  switch (_type) {
1949  case ST_string:
1950  case ST_blob:
1951  if (p + 2 > length) {
1952  pack_error = true;
1953  return;
1954  }
1955  string_length = do_unpack_uint16(data + p);
1956  p += 2;
1957  break;
1958 
1959  case ST_blob32:
1960  if (p + 4 > length) {
1961  pack_error = true;
1962  return;
1963  }
1964  string_length = do_unpack_uint32(data + p);
1965  p += 4;
1966  break;
1967 
1968  default:
1969  pack_error = true;
1970  return;
1971  }
1972  }
1973 
1974  _uint_range.validate(string_length, range_error);
1975 
1976  if (p + string_length > length) {
1977  pack_error = true;
1978  return;
1979  }
1980  value.assign(data + p, string_length);
1981  p += string_length;
1982 
1983  return;
1984 }
1985 
1986 /**
1987  * Unpacks the current numeric or string value from the stream.
1988  */
1990 unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value,
1991  bool &pack_error, bool &range_error) const {
1992  // If the type is a single byte, unpack it into a string of length 1.
1993  switch (_type) {
1994  case ST_char:
1995  case ST_int8:
1996  case ST_uint8:
1997  {
1998  if (p + 1 > length) {
1999  pack_error = true;
2000  return;
2001  }
2002  unsigned int int_value = do_unpack_uint8(data + p);
2003  _uint_range.validate(int_value, range_error);
2004  value.resize(1);
2005  value[0] = int_value;
2006  p++;
2007  }
2008  return;
2009 
2010  default:
2011  break;
2012  }
2013 
2014  size_t blob_size;
2015 
2016  if (_num_length_bytes == 0) {
2017  blob_size = _fixed_byte_size;
2018 
2019  } else {
2020  switch (_type) {
2021  case ST_string:
2022  case ST_blob:
2023  if (p + 2 > length) {
2024  pack_error = true;
2025  return;
2026  }
2027  blob_size = do_unpack_uint16(data + p);
2028  p += 2;
2029  break;
2030 
2031  case ST_blob32:
2032  if (p + 4 > length) {
2033  pack_error = true;
2034  return;
2035  }
2036  blob_size = do_unpack_uint32(data + p);
2037  p += 4;
2038  break;
2039 
2040  default:
2041  pack_error = true;
2042  return;
2043  }
2044  }
2045 
2046  _uint_range.validate(blob_size, range_error);
2047 
2048  if (p + blob_size > length) {
2049  pack_error = true;
2050  return;
2051  }
2052  value = vector_uchar((const unsigned char *)data + p,
2053  (const unsigned char *)data + p + blob_size);
2054  p += blob_size;
2055 
2056  return;
2057 }
2058 
2059 /**
2060  * Internally unpacks the current numeric or string value and validates it
2061  * against the type range limits, but does not return the value. Returns true
2062  * on success, false on failure (e.g. we don't know how to validate this
2063  * field).
2064  */
2066 unpack_validate(const char *data, size_t length, size_t &p,
2067  bool &pack_error, bool &range_error) const {
2068  if (!_has_range_limits) {
2069  return unpack_skip(data, length, p, pack_error);
2070  }
2071  switch (_type) {
2072  case ST_int8:
2073  {
2074  if (p + 1 > length) {
2075  pack_error = true;
2076  return true;
2077  }
2078  int int_value = do_unpack_int8(data + p);
2079  _int_range.validate(int_value, range_error);
2080  p++;
2081  }
2082  break;
2083 
2084  case ST_int16:
2085  {
2086  if (p + 2 > length) {
2087  pack_error = true;
2088  return true;
2089  }
2090  int int_value = do_unpack_int16(data + p);
2091  _int_range.validate(int_value, range_error);
2092  p += 2;
2093  }
2094  break;
2095 
2096  case ST_int32:
2097  {
2098  if (p + 4 > length) {
2099  pack_error = true;
2100  return true;
2101  }
2102  int int_value = do_unpack_int32(data + p);
2103  _int_range.validate(int_value, range_error);
2104  p += 4;
2105  }
2106  break;
2107 
2108  case ST_int64:
2109  {
2110  if (p + 8 > length) {
2111  pack_error = true;
2112  return true;
2113  }
2114  int64_t int_value = do_unpack_int64(data + p);
2115  _int64_range.validate(int_value, range_error);
2116  p += 8;
2117  }
2118  break;
2119 
2120  case ST_char:
2121  case ST_uint8:
2122  {
2123  if (p + 1 > length) {
2124  pack_error = true;
2125  return true;
2126  }
2127  unsigned int uint_value = do_unpack_uint8(data + p);
2128  _uint_range.validate(uint_value, range_error);
2129  p++;
2130  }
2131  break;
2132 
2133  case ST_uint16:
2134  {
2135  if (p + 2 > length) {
2136  pack_error = true;
2137  return true;
2138  }
2139  unsigned int uint_value = do_unpack_uint16(data + p);
2140  _uint_range.validate(uint_value, range_error);
2141  p += 2;
2142  }
2143  break;
2144 
2145  case ST_uint32:
2146  {
2147  if (p + 4 > length) {
2148  pack_error = true;
2149  return true;
2150  }
2151  unsigned int uint_value = do_unpack_uint32(data + p);
2152  _uint_range.validate(uint_value, range_error);
2153  p += 4;
2154  }
2155  break;
2156 
2157  case ST_uint64:
2158  {
2159  if (p + 8 > length) {
2160  pack_error = true;
2161  return true;
2162  }
2163  uint64_t uint_value = do_unpack_uint64(data + p);
2164  _uint64_range.validate(uint_value, range_error);
2165  p += 8;
2166  }
2167  break;
2168 
2169  case ST_float64:
2170  {
2171  if (p + 8 > length) {
2172  pack_error = true;
2173  return true;
2174  }
2175  double real_value = do_unpack_float64(data + p);
2176  _double_range.validate(real_value, range_error);
2177  p += 8;
2178  }
2179  break;
2180 
2181  case ST_string:
2182  case ST_blob:
2183  if (_num_length_bytes == 0) {
2184  p += _fixed_byte_size;
2185 
2186  } else {
2187  if (p + 2 > length) {
2188  pack_error = true;
2189  return true;
2190  }
2191  size_t string_length = do_unpack_uint16(data + p);
2192  _uint_range.validate(string_length, range_error);
2193  p += 2 + string_length;
2194  }
2195  break;
2196 
2197  case ST_blob32:
2198  if (_num_length_bytes == 0) {
2199  p += _fixed_byte_size;
2200 
2201  } else {
2202  if (p + 4 > length) {
2203  pack_error = true;
2204  return true;
2205  }
2206  size_t string_length = do_unpack_uint32(data + p);
2207  _uint_range.validate(string_length, range_error);
2208  p += 4 + string_length;
2209  }
2210  break;
2211 
2212  default:
2213  return false;
2214  }
2215 
2216  return true;
2217 }
2218 
2219 /**
2220  * Increments p to the end of the current field without actually unpacking any
2221  * data or performing any range validation. Returns true on success, false on
2222  * failure (e.g. we don't know how to skip this field).
2223  */
2225 unpack_skip(const char *data, size_t length, size_t &p,
2226  bool &pack_error) const {
2227  size_t string_length;
2228 
2229  switch (_type) {
2230  case ST_char:
2231  case ST_int8:
2232  case ST_uint8:
2233  p++;
2234  break;
2235 
2236  case ST_int16:
2237  case ST_uint16:
2238  p += 2;
2239  break;
2240 
2241  case ST_int32:
2242  case ST_uint32:
2243  p += 4;
2244  break;
2245 
2246  case ST_int64:
2247  case ST_uint64:
2248  case ST_float64:
2249  p += 8;
2250  break;
2251 
2252  case ST_string:
2253  case ST_blob:
2254  if (_num_length_bytes == 0) {
2255  p += _fixed_byte_size;
2256 
2257  } else {
2258  if (p + 2 > length) {
2259  return false;
2260  }
2261  string_length = do_unpack_uint16(data + p);
2262  p += 2 + string_length;
2263  }
2264  break;
2265 
2266  case ST_blob32:
2267  if (_num_length_bytes == 0) {
2268  p += _fixed_byte_size;
2269 
2270  } else {
2271  if (p + 4 > length) {
2272  return false;
2273  }
2274  string_length = do_unpack_uint32(data + p);
2275  p += 4 + string_length;
2276  }
2277  break;
2278 
2279  default:
2280  return false;
2281  }
2282 
2283  if (p > length) {
2284  pack_error = true;
2285  }
2286 
2287  return true;
2288 }
2289 
2290 /**
2291  * Formats the parameter in the C++-like dc syntax as a typename and
2292  * identifier.
2293  */
2295 output_instance(std::ostream &out, bool brief, const string &prename,
2296  const string &name, const string &postname) const {
2297  if (get_typedef() != nullptr) {
2298  output_typedef_name(out, brief, prename, name, postname);
2299 
2300  } else {
2301  out << _type;
2302  if (_has_modulus) {
2303  out << "%" << _orig_modulus;
2304  }
2305  if (_divisor != 1) {
2306  out << "/" << _divisor;
2307  }
2308 
2309  switch (_type) {
2310  case ST_int8:
2311  case ST_int16:
2312  case ST_int32:
2313  if (!_int_range.is_empty()) {
2314  out << "(";
2315  _int_range.output(out, _divisor);
2316  out << ")";
2317  }
2318  break;
2319 
2320  case ST_int64:
2321  if (!_int64_range.is_empty()) {
2322  out << "(";
2323  _int64_range.output(out, _divisor);
2324  out << ")";
2325  }
2326  break;
2327 
2328  case ST_uint8:
2329  case ST_uint16:
2330  case ST_uint32:
2331  if (!_uint_range.is_empty()) {
2332  out << "(";
2333  _uint_range.output(out, _divisor);
2334  out << ")";
2335  }
2336  break;
2337 
2338  case ST_char:
2339  if (!_uint_range.is_empty()) {
2340  out << "(";
2341  _uint_range.output_char(out, _divisor);
2342  out << ")";
2343  }
2344  break;
2345 
2346  case ST_uint64:
2347  if (!_uint64_range.is_empty()) {
2348  out << "(";
2349  _uint64_range.output(out, _divisor);
2350  out << ")";
2351  }
2352  break;
2353 
2354  case ST_float64:
2355  if (!_double_range.is_empty()) {
2356  out << "(";
2357  _double_range.output(out, _divisor);
2358  out << ")";
2359  }
2360  break;
2361 
2362  case ST_blob:
2363  case ST_blob32:
2364  case ST_string:
2365  if (!_uint_range.is_empty()) {
2366  out << "(";
2367  _uint_range.output(out, _divisor);
2368  out << ")";
2369  }
2370  break;
2371  default:
2372  break;
2373  }
2374 
2375  if (!prename.empty() || !name.empty() || !postname.empty()) {
2376  out << " " << prename << name << postname;
2377  }
2378  }
2379 }
2380 
2381 /**
2382  * Accumulates the properties of this type into the hash.
2383  */
2385 generate_hash(HashGenerator &hashgen) const {
2386  DCParameter::generate_hash(hashgen);
2387 
2388  hashgen.add_int(_type);
2389  hashgen.add_int(_divisor);
2390  if (_has_modulus) {
2391  hashgen.add_int((int)_double_modulus);
2392  }
2393 
2394  _int_range.generate_hash(hashgen);
2395  _int64_range.generate_hash(hashgen);
2396  _uint_range.generate_hash(hashgen);
2397  _uint64_range.generate_hash(hashgen);
2398  _double_range.generate_hash(hashgen);
2399 }
2400 
2401 /**
2402  * Returns true if the other interface is bitwise the same as this one--that
2403  * is, a uint32 only matches a uint32, etc. Names of components, and range
2404  * limits, are not compared.
2405  */
2406 bool DCSimpleParameter::
2407 do_check_match(const DCPackerInterface *other) const {
2408  return other->do_check_match_simple_parameter(this);
2409 }
2410 
2411 /**
2412  * Returns true if this field matches the indicated simple parameter, false
2413  * otherwise.
2414  */
2415 bool DCSimpleParameter::
2416 do_check_match_simple_parameter(const DCSimpleParameter *other) const {
2417  if (_divisor != other->_divisor) {
2418  return false;
2419  }
2420 
2421  if (_type == other->_type) {
2422  return true;
2423  }
2424 
2425  // Check for certain types that are considered equivalent to each other.
2426  switch (_type) {
2427  case ST_uint8:
2428  case ST_char:
2429  switch (other->_type) {
2430  case ST_uint8:
2431  case ST_char:
2432  return true;
2433 
2434  default:
2435  return false;
2436  }
2437 
2438  case ST_string:
2439  case ST_blob:
2440  case ST_uint8array:
2441  switch (other->_type) {
2442  case ST_string:
2443  case ST_blob:
2444  case ST_uint8array:
2445  return true;
2446 
2447  default:
2448  return false;
2449  }
2450 
2451  default:
2452  return false;
2453  }
2454 }
2455 
2456 /**
2457  * Returns true if this field matches the indicated array parameter, false
2458  * otherwise.
2459  */
2460 bool DCSimpleParameter::
2461 do_check_match_array_parameter(const DCArrayParameter *other) const {
2462  if (other->get_array_size() != -1) {
2463  // We cannot match a fixed-size array.
2464  return false;
2465  }
2466  if (_nested_field == nullptr) {
2467  // Only an array-style simple parameter can match a DCArrayParameter.
2468  return false;
2469  }
2470 
2471  return _nested_field->check_match(other->get_element_type());
2472 }
2473 
2474 /**
2475  * Creates the one instance of the DCSimpleParameter corresponding to this
2476  * combination of type and divisor if it is not already created.
2477  */
2478 DCSimpleParameter *DCSimpleParameter::
2479 create_nested_field(DCSubatomicType type, unsigned int divisor) {
2480  DivisorMap &divisor_map = _nested_field_map[type];
2481  DivisorMap::iterator di;
2482  di = divisor_map.find(divisor);
2483  if (di != divisor_map.end()) {
2484  return (*di).second;
2485  }
2486 
2487  DCSimpleParameter *nested_field = new DCSimpleParameter(type, divisor);
2488  divisor_map[divisor] = nested_field;
2489  return nested_field;
2490 }
2491 
2492 /**
2493  * Creates the one instance of the Uint32Uint8Type object if it is not already
2494  * created.
2495  */
2496 DCPackerInterface *DCSimpleParameter::
2497 create_uint32uint8_type() {
2498  if (_uint32uint8_type == nullptr) {
2499  DCClass *dclass = new DCClass(nullptr, "", true, false);
2500  dclass->add_field(new DCSimpleParameter(ST_uint32));
2501  dclass->add_field(new DCSimpleParameter(ST_uint8));
2502  _uint32uint8_type = new DCClassParameter(dclass);
2503  }
2504  return _uint32uint8_type;
2505 }
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.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this type into the hash.
This is a block of data that receives the results of DCPacker.
Definition: dcPackData.h:22
DCSubatomicType
This defines the numeric type of each element of a DCAtomicField; that is, the particular values that...
void append_data(const char *buffer, size_t size)
Adds the indicated bytes to the end of the data.
Definition: dcPackData.I:47
bool set_divisor(unsigned int divisor)
Assigns the indicated divisor to the simple type.
int get_array_size() const
Returns the fixed number of elements in this array, or -1 if the array may contain a variable number ...
double get_modulus() const
Returns the modulus associated with this type, if any.
void add_int(int num)
Adds another integer to the hash so far.
This represents a class (or struct) object used as a parameter itself.
This is the most fundamental kind of parameter type: a single number or string, one of the DCSubatomi...
virtual bool unpack_validate(const char *data, size_t length, size_t &p, bool &pack_error, bool &range_error) const
Internally unpacks the current numeric or string value and validates it against the type range limits...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const
Packs the field's specified default value (or a sensible default if no value is specified) into the s...
Definition: dcField.cxx:487
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
Defines a particular DistributedClass as read from an input .dc file.
Definition: dcClass.h:44
virtual bool do_check_match_simple_parameter(const DCSimpleParameter *other) const
Returns true if this field matches the indicated simple parameter, false otherwise.
DCSubatomicType get_type() const
Returns the particular subatomic type represented by this instance.
size_t get_length() const
Returns the current length of the buffer.
Definition: dcPacker.I:583
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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_ranges() const
Returns the number of minmax components in the range description.
Represents the type specification for a single parameter within a field specification.
Definition: dcParameter.h:35
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.
void pack_default_value()
Adds the default value for the current element into the stream.
Definition: dcPacker.cxx:552
This represents an array of some other kind of object, meaning this parameter type accepts an arbitra...
bool set_range(const DCDoubleRange &range)
Sets the parameter with the indicated range.
Number get_max(int n) const
Returns the maximum value defined by the nth component.
bool has_modulus() const
Returns true if there is a modulus associated, false otherwise.,.
void push()
Marks the beginning of a nested series of fields.
Definition: dcPacker.cxx:411
Number get_min(int n) const
Returns the minimum value defined by the nth component.
const char * get_data() const
Returns the beginning of the data buffer.
Definition: dcPacker.I:641
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.
This class generates an arbitrary hash number from a sequence of ints.
Definition: hashGenerator.h:24
virtual bool unpack_skip(const char *data, size_t length, size_t &p, bool &pack_error) const
Increments p to the end of the current field without actually unpacking any data or performing any ra...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void output_instance(std::ostream &out, bool brief, const std::string &prename, const std::string &name, const std::string &postname) const
Formats the parameter in the C++-like dc syntax as a typename and identifier.
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 begin_pack(const DCPackerInterface *root)
Begins a packing session.
Definition: dcPacker.cxx:73
virtual void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this type into the hash.
virtual bool is_valid() const
Returns false if the type is an invalid type (e.g.
bool is_numeric_type() const
Returns true if the type is a numeric type (and therefore can accept a divisor and/or a modulus),...
This class can be used for packing a series of numeric and string data into a binary stream,...
Definition: dcPacker.h:34
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.
DCParameter * get_element_type() const
Returns the type of the individual elements of this array.
bool add_field(DCField *field)
Adds the newly-allocated field to the class.
Definition: dcClass.cxx:1260
int get_divisor() const
Returns the divisor associated with this type.
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.
bool end_pack()
Finishes a packing session.
Definition: dcPacker.cxx:98
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 pop()
Marks the end of a nested series of fields.
Definition: dcPacker.cxx:495
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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_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 bool pack_default_value(DCPackData &pack_data, bool &pack_error) const
Packs the simpleParameter's specified default value (or a sensible default if no value is specified) ...
This defines the internal interface for packing values into a DCField.
bool set_modulus(double modulus)
Assigns the indicated modulus to the simple type.
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 int calc_num_nested_fields(size_t length_bytes) const
This flavor of get_num_nested_fields is used during unpacking.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.