Panda3D
 All Classes Functions Variables Enumerations
dcSimpleParameter.cxx
00001 // Filename: dcSimpleParameter.cxx
00002 // Created by:  drose (15Jun04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "dcSimpleParameter.h"
00016 #include "dcPackData.h"
00017 #include "dcTypedef.h"
00018 #include "dcArrayParameter.h"
00019 #include "dcClassParameter.h"
00020 #include "dcClass.h"
00021 #include "hashGenerator.h"
00022 #include <math.h>
00023 
00024 DCSimpleParameter::NestedFieldMap DCSimpleParameter::_nested_field_map;
00025 DCClassParameter *DCSimpleParameter::_uint32uint8_type = NULL;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: DCSimpleParameter::Constructor
00029 //       Access: Public
00030 //  Description: 
00031 ////////////////////////////////////////////////////////////////////
00032 DCSimpleParameter::
00033 DCSimpleParameter(DCSubatomicType type, unsigned int divisor) :
00034   _type(type),
00035   _divisor(1),
00036   _has_modulus(false)
00037 {
00038   _pack_type = PT_invalid;
00039   _nested_type = ST_invalid;
00040   _has_nested_fields = false;
00041   _bytes_per_element = 0;
00042   _num_length_bytes = 2;
00043 
00044   // Check for one of the built-in array types.  For these types, we
00045   // must present a packing interface that has a variable number of
00046   // nested fields of the appropriate type.
00047   switch (_type) {
00048   case ST_int8array:
00049     _pack_type = PT_array;
00050     _nested_type = ST_int8;
00051     _has_nested_fields = true;
00052     _bytes_per_element = 1;
00053     break;
00054 
00055   case ST_int16array:
00056     _pack_type = PT_array;
00057     _nested_type = ST_int16;
00058     _has_nested_fields = true;
00059     _bytes_per_element = 2;
00060     break;
00061 
00062   case ST_int32array:
00063     _pack_type = PT_array;
00064     _nested_type = ST_int32;
00065     _has_nested_fields = true;
00066     _bytes_per_element = 4;
00067     break;
00068 
00069   case ST_uint8array:
00070     _pack_type = PT_array;
00071     _nested_type = ST_uint8;
00072     _has_nested_fields = true;
00073     _bytes_per_element = 1;
00074     break;
00075 
00076   case ST_uint16array:
00077     _pack_type = PT_array;
00078     _nested_type = ST_uint16;
00079     _has_nested_fields = true;
00080     _bytes_per_element = 2;
00081     break;
00082 
00083   case ST_uint32array:
00084     _pack_type = PT_array;
00085     _nested_type = ST_uint32;
00086     _has_nested_fields = true;
00087     _bytes_per_element = 4;
00088     break;
00089 
00090   case ST_uint32uint8array:
00091     _pack_type = PT_array;
00092     _has_nested_fields = true;
00093     _bytes_per_element = 5;
00094     break;
00095 
00096   case ST_blob32:
00097     _num_length_bytes = 4;
00098     // fall through
00099   case ST_blob:
00100     // For blob and string, we will present an array interface
00101     // as an array of uint8, but we will also accept a set_value()
00102     // with a string parameter.
00103     _pack_type = PT_blob;
00104     _nested_type = ST_uint8;
00105     _has_nested_fields = true;
00106     _bytes_per_element = 1;
00107     break;
00108 
00109   case ST_string: 
00110     _pack_type = PT_string;
00111     _nested_type = ST_char;
00112     _has_nested_fields = true;
00113     _bytes_per_element = 1;
00114     break;
00115 
00116     // The simple types can be packed directly.
00117   case ST_int8:
00118     _pack_type = PT_int;
00119     _has_fixed_byte_size = true;
00120     _fixed_byte_size = 1;
00121     break;
00122 
00123   case ST_int16:
00124     _pack_type = PT_int;
00125     _has_fixed_byte_size = true;
00126     _fixed_byte_size = 2;
00127     break;
00128 
00129   case ST_int32:
00130     _pack_type = PT_int;
00131     _has_fixed_byte_size = true;
00132     _fixed_byte_size = 4;
00133     break;
00134 
00135   case ST_int64:
00136     _pack_type = PT_int64;
00137     _has_fixed_byte_size = true;
00138     _fixed_byte_size = 8;
00139     break;
00140 
00141   case ST_char:
00142     _pack_type = PT_string;
00143     _has_fixed_byte_size = true;
00144     _fixed_byte_size = 1;
00145     break;
00146 
00147   case ST_uint8:
00148     _pack_type = PT_uint;
00149     _has_fixed_byte_size = true;
00150     _fixed_byte_size = 1;
00151     break;
00152 
00153   case ST_uint16:
00154     _pack_type = PT_uint;
00155     _has_fixed_byte_size = true;
00156     _fixed_byte_size = 2;
00157     break;
00158 
00159   case ST_uint32:
00160     _pack_type = PT_uint;
00161     _has_fixed_byte_size = true;
00162     _fixed_byte_size = 4;
00163     break;
00164 
00165   case ST_uint64:
00166     _pack_type = PT_uint64;
00167     _has_fixed_byte_size = true;
00168     _fixed_byte_size = 8;
00169     break;
00170 
00171   case ST_float64:
00172     _pack_type = PT_double;
00173     _has_fixed_byte_size = true;
00174     _fixed_byte_size = 8;
00175     break;
00176 
00177   case ST_invalid:
00178     break;
00179   }
00180   _has_fixed_structure = _has_fixed_byte_size;
00181 
00182   set_divisor(divisor);
00183 
00184   if (_nested_type != ST_invalid) {
00185     _nested_field = create_nested_field(_nested_type, _divisor);
00186 
00187   } else if (_type == ST_uint32uint8array) {
00188     // This one is a special case.  We must create a special nested
00189     // type that accepts a uint32 followed by a uint8 for each
00190     // element.
00191     _nested_field = create_uint32uint8_type();
00192 
00193   } else {
00194     _nested_field = NULL;
00195   }
00196 }
00197 
00198 ////////////////////////////////////////////////////////////////////
00199 //     Function: DCSimpleParameter::Copy Constructor
00200 //       Access: Public
00201 //  Description: 
00202 ////////////////////////////////////////////////////////////////////
00203 DCSimpleParameter::
00204 DCSimpleParameter(const DCSimpleParameter &copy) :
00205   DCParameter(copy),
00206   _type(copy._type),
00207   _divisor(copy._divisor),
00208   _nested_field(copy._nested_field),
00209   _bytes_per_element(copy._bytes_per_element),
00210   _orig_range(copy._orig_range),
00211   _has_modulus(copy._has_modulus),
00212   _orig_modulus(copy._orig_modulus),
00213   _int_range(copy._int_range),
00214   _uint_range(copy._uint_range),
00215   _int64_range(copy._int64_range),
00216   _uint64_range(copy._uint64_range),
00217   _double_range(copy._double_range),
00218   _uint_modulus(copy._uint_modulus),
00219   _uint64_modulus(copy._uint64_modulus),
00220   _double_modulus(copy._double_modulus)
00221 {
00222 }
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: DCSimpleParameter::as_simple_parameter
00226 //       Access: Published, Virtual
00227 //  Description: 
00228 ////////////////////////////////////////////////////////////////////
00229 DCSimpleParameter *DCSimpleParameter::
00230 as_simple_parameter() {
00231   return this;
00232 }
00233 
00234 ////////////////////////////////////////////////////////////////////
00235 //     Function: DCSimpleParameter::as_simple_parameter
00236 //       Access: Published, Virtual
00237 //  Description: 
00238 ////////////////////////////////////////////////////////////////////
00239 const DCSimpleParameter *DCSimpleParameter::
00240 as_simple_parameter() const {
00241   return this;
00242 }
00243 
00244 ////////////////////////////////////////////////////////////////////
00245 //     Function: DCSimpleParameter::make_copy
00246 //       Access: Published, Virtual
00247 //  Description: 
00248 ////////////////////////////////////////////////////////////////////
00249 DCParameter *DCSimpleParameter::
00250 make_copy() const {
00251   return new DCSimpleParameter(*this);
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: DCSimpleParameter::is_valid
00256 //       Access: Published, Virtual
00257 //  Description: Returns false if the type is an invalid type
00258 //               (e.g. declared from an undefined typedef), true if
00259 //               it is valid.
00260 ////////////////////////////////////////////////////////////////////
00261 bool DCSimpleParameter::
00262 is_valid() const {
00263   return _type != ST_invalid;
00264 }
00265 
00266 ////////////////////////////////////////////////////////////////////
00267 //     Function: DCSimpleParameter::get_type
00268 //       Access: Published
00269 //  Description: Returns the particular subatomic type represented by
00270 //               this instance.
00271 ////////////////////////////////////////////////////////////////////
00272 DCSubatomicType DCSimpleParameter::
00273 get_type() const {
00274   return _type;
00275 }
00276 
00277 ////////////////////////////////////////////////////////////////////
00278 //     Function: DCSimpleParameter::has_modulus
00279 //       Access: Published
00280 //  Description: Returns true if there is a modulus associated, false
00281 //               otherwise.,
00282 ////////////////////////////////////////////////////////////////////
00283 bool DCSimpleParameter::
00284 has_modulus() const {
00285   return _has_modulus;
00286 }
00287 
00288 ////////////////////////////////////////////////////////////////////
00289 //     Function: DCSimpleParameter::get_modulus
00290 //       Access: Published
00291 //  Description: Returns the modulus associated with this type, if
00292 //               any.  It is an error to call this if has_modulus()
00293 //               returned false.
00294 //
00295 //               If present, this is the modulus that is used to
00296 //               constrain the numeric value of the field before it is
00297 //               packed (and range-checked).
00298 ////////////////////////////////////////////////////////////////////
00299 double DCSimpleParameter::
00300 get_modulus() const {
00301   return _orig_modulus;
00302 }
00303 
00304 ////////////////////////////////////////////////////////////////////
00305 //     Function: DCSimpleParameter::get_divisor
00306 //       Access: Published
00307 //  Description: Returns the divisor associated with this type.  This
00308 //               is 1 by default, but if this is other than one it
00309 //               represents the scale to apply when packing and
00310 //               unpacking numeric values (to store fixed-point values
00311 //               in an integer field).  It is only meaningful for
00312 //               numeric-type fields.
00313 ////////////////////////////////////////////////////////////////////
00314 int DCSimpleParameter::
00315 get_divisor() const {
00316   return _divisor;
00317 }
00318 
00319 ////////////////////////////////////////////////////////////////////
00320 //     Function: DCSimpleParameter::is_numeric_type
00321 //       Access: Public
00322 //  Description: Returns true if the type is a numeric type (and
00323 //               therefore can accept a divisor and/or a modulus), or
00324 //               false if it is some string-based type.
00325 ////////////////////////////////////////////////////////////////////
00326 bool DCSimpleParameter::
00327 is_numeric_type() const {
00328   return !(_pack_type == PT_string || _pack_type == PT_blob);
00329 }
00330 
00331 ////////////////////////////////////////////////////////////////////
00332 //     Function: DCSimpleParameter::set_modulus
00333 //       Access: Public
00334 //  Description: Assigns the indicated modulus to the simple type.
00335 //               Any packed value will be constrained to be within [0,
00336 //               modulus).
00337 //
00338 //               Returns true if assigned, false if this type cannot
00339 //               accept a modulus or if the modulus is invalid.
00340 ////////////////////////////////////////////////////////////////////
00341 bool DCSimpleParameter::
00342 set_modulus(double modulus) {
00343   if (_pack_type == PT_string || _pack_type == PT_blob || modulus <= 0.0) {
00344     return false;
00345   }
00346 
00347   _has_modulus = true;
00348   _orig_modulus = modulus;
00349 
00350   bool range_error = false;
00351   _double_modulus = modulus * _divisor;
00352   _uint64_modulus = (PN_uint64)floor(_double_modulus + 0.5);
00353   _uint_modulus = (unsigned int)_uint64_modulus;
00354 
00355   // Check the range.  The legitimate range for a modulus value is 1
00356   // through (maximum_value + 1).
00357   switch (_type) {
00358   case ST_int8:
00359   case ST_int8array:
00360     validate_uint64_limits(_uint64_modulus - 1, 7, range_error);
00361     break;
00362 
00363   case ST_int16:
00364   case ST_int16array:
00365     validate_uint64_limits(_uint64_modulus - 1, 15, range_error);
00366     break;
00367 
00368   case ST_int32:
00369   case ST_int32array:
00370     validate_uint64_limits(_uint64_modulus - 1, 31, range_error);
00371     break;
00372     
00373   case ST_int64:
00374     validate_uint64_limits(_uint64_modulus - 1, 63, range_error);
00375     break;
00376 
00377   case ST_char:
00378   case ST_uint8:
00379   case ST_uint8array:
00380     validate_uint64_limits(_uint64_modulus - 1, 8, range_error);
00381     break;
00382 
00383   case ST_uint16:
00384   case ST_uint16array:
00385     validate_uint64_limits(_uint64_modulus - 1, 16, range_error);
00386     break;
00387 
00388   case ST_uint32:
00389   case ST_uint32array:
00390     validate_uint64_limits(_uint64_modulus - 1, 32, range_error);
00391     break;
00392     
00393   case ST_uint64:
00394   case ST_float64:
00395     break;
00396 
00397   default:
00398     return false;
00399   }
00400 
00401   return !range_error;
00402 }
00403 
00404 ////////////////////////////////////////////////////////////////////
00405 //     Function: DCSimpleParameter::set_divisor
00406 //       Access: Public
00407 //  Description: Assigns the indicated divisor to the simple type.
00408 //               Returns true if assigned, false if this type cannot
00409 //               accept a divisor or if the divisor is invalid.
00410 ////////////////////////////////////////////////////////////////////
00411 bool DCSimpleParameter::
00412 set_divisor(unsigned int divisor) {
00413   if (_pack_type == PT_string || _pack_type == PT_blob || divisor == 0) {
00414     return false;
00415   }
00416 
00417   _divisor = divisor;
00418   if ((_divisor != 1) &&
00419       (_pack_type == PT_int || _pack_type == PT_int64 ||
00420        _pack_type == PT_uint || _pack_type == PT_uint64)) {
00421     _pack_type = PT_double;
00422   }
00423 
00424   if (_has_range_limits) {
00425     set_range(_orig_range);
00426   }
00427   if (_has_modulus) {
00428     set_modulus(_orig_modulus);
00429   }
00430 
00431   return true;
00432 }
00433 
00434 ////////////////////////////////////////////////////////////////////
00435 //     Function: DCSimpleParameter::set_range
00436 //       Access: Public
00437 //  Description: Sets the parameter with the indicated range.  A
00438 //               DCDoubleRange is used for specification, since this
00439 //               is the most generic type; but it is converted to the
00440 //               appropriate type internally.  The return value is
00441 //               true if successful, or false if the range is
00442 //               inappropriate for the type.
00443 ////////////////////////////////////////////////////////////////////
00444 bool DCSimpleParameter::
00445 set_range(const DCDoubleRange &range) {
00446   bool range_error = false;
00447   int num_ranges = range.get_num_ranges();
00448   int i;
00449 
00450   _has_range_limits = (num_ranges != 0);
00451   _orig_range = range;
00452 
00453   switch (_type) {
00454   case ST_int8:
00455   case ST_int8array:
00456     _int_range.clear();
00457     for (i = 0; i < num_ranges; i++) {
00458       PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5);
00459       PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5);
00460       validate_int64_limits(min, 8, range_error);
00461       validate_int64_limits(max, 8, range_error);
00462       _int_range.add_range((int)min, (int)max);
00463     }
00464     break;
00465     
00466   case ST_int16:
00467   case ST_int16array:
00468     _int_range.clear();
00469     for (i = 0; i < num_ranges; i++) {
00470       PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5);
00471       PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5);
00472       validate_int64_limits(min, 16, range_error);
00473       validate_int64_limits(max, 16, range_error);
00474       _int_range.add_range((int)min, (int)max);
00475     }
00476     break;
00477     
00478   case ST_int32:
00479   case ST_int32array:
00480     _int_range.clear();
00481     for (i = 0; i < num_ranges; i++) {
00482       PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5);
00483       PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5);
00484       validate_int64_limits(min, 32, range_error);
00485       validate_int64_limits(max, 32, range_error);
00486       _int_range.add_range((int)min, (int)max);
00487     }
00488     break;
00489     
00490   case ST_int64:
00491     _int64_range.clear();
00492     for (i = 0; i < num_ranges; i++) {
00493       PN_int64 min = (PN_int64)floor(range.get_min(i) * _divisor + 0.5);
00494       PN_int64 max = (PN_int64)floor(range.get_max(i) * _divisor + 0.5);
00495       _int64_range.add_range(min, max);
00496     }
00497     break;
00498     
00499   case ST_char:
00500   case ST_uint8:
00501   case ST_uint8array:
00502     _uint_range.clear();
00503     for (i = 0; i < num_ranges; i++) {
00504       PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5);
00505       PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5);
00506       validate_uint64_limits(min, 8, range_error);
00507       validate_uint64_limits(max, 8, range_error);
00508       _uint_range.add_range((unsigned int)min, (unsigned int)max);
00509     }
00510     break;
00511     
00512   case ST_uint16:
00513   case ST_uint16array:
00514     _uint_range.clear();
00515     for (i = 0; i < num_ranges; i++) {
00516       PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5);
00517       PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5);
00518       validate_uint64_limits(min, 16, range_error);
00519       validate_uint64_limits(max, 16, range_error);
00520       _uint_range.add_range((unsigned int)min, (unsigned int)max);
00521     }
00522     break;
00523     
00524   case ST_uint32:
00525   case ST_uint32array:
00526     _uint_range.clear();
00527     for (i = 0; i < num_ranges; i++) {
00528       PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5);
00529       PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5);
00530       validate_uint64_limits(min, 32, range_error);
00531       validate_uint64_limits(max, 32, range_error);
00532       _uint_range.add_range((unsigned int)min, (unsigned int)max);
00533     }
00534     break;
00535     
00536   case ST_uint64:
00537     _uint64_range.clear();
00538     for (i = 0; i < num_ranges; i++) {
00539       PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5);
00540       PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5);
00541       _uint64_range.add_range(min, max);
00542     }
00543     break;
00544 
00545   case ST_float64:
00546     _double_range.clear();
00547     for (i = 0; i < num_ranges; i++) {
00548       double min = range.get_min(i) * _divisor;
00549       double max = range.get_max(i) * _divisor;
00550       _double_range.add_range(min, max);
00551     }
00552     break;
00553 
00554   case ST_string:
00555   case ST_blob:
00556     _uint_range.clear();
00557     for (i = 0; i < num_ranges; i++) {
00558       PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5);
00559       PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5);
00560       validate_uint64_limits(min, 16, range_error);
00561       validate_uint64_limits(max, 16, range_error);
00562       _uint_range.add_range((unsigned int)min, (unsigned int)max);
00563     }
00564     if (_uint_range.has_one_value()) {
00565       // If we now have a fixed-length string requirement, we don't
00566       // need a leading number of bytes.
00567       _num_length_bytes = 0;
00568       _has_fixed_byte_size = true;
00569       _fixed_byte_size = _uint_range.get_one_value();
00570       _has_fixed_structure = true;
00571     } else {
00572       _num_length_bytes = 2;
00573       _has_fixed_byte_size = false;
00574       _has_fixed_structure = false;
00575     }
00576     break;
00577 
00578   case ST_blob32:
00579     _uint_range.clear();
00580     for (i = 0; i < num_ranges; i++) {
00581       PN_uint64 min = (PN_uint64)floor(range.get_min(i) * _divisor + 0.5);
00582       PN_uint64 max = (PN_uint64)floor(range.get_max(i) * _divisor + 0.5);
00583       validate_uint64_limits(min, 32, range_error);
00584       validate_uint64_limits(max, 32, range_error);
00585       _uint_range.add_range((unsigned int)min, (unsigned int)max);
00586     }
00587     if (_uint_range.has_one_value()) {
00588       // If we now have a fixed-length string requirement, we don't
00589       // need a leading number of bytes.
00590       _num_length_bytes = 0;
00591       _has_fixed_byte_size = true;
00592       _fixed_byte_size = _uint_range.get_one_value();
00593       _has_fixed_structure = true;
00594     } else {
00595       _num_length_bytes = 4;
00596       _has_fixed_byte_size = false;
00597       _has_fixed_structure = false;
00598     }
00599     break;
00600 
00601   default:
00602     return false;
00603   }
00604 
00605   return !range_error;
00606 }
00607 
00608 ////////////////////////////////////////////////////////////////////
00609 //     Function: DCSimpleParameter::calc_num_nested_fields
00610 //       Access: Public, Virtual
00611 //  Description: This flavor of get_num_nested_fields is used during
00612 //               unpacking.  It returns the number of nested fields to
00613 //               expect, given a certain length in bytes (as read from
00614 //               the _num_length_bytes stored in the stream on the
00615 //               push).  This will only be called if _num_length_bytes
00616 //               is nonzero.
00617 ////////////////////////////////////////////////////////////////////
00618 int DCSimpleParameter::
00619 calc_num_nested_fields(size_t length_bytes) const {
00620   if (_bytes_per_element != 0) {
00621     return length_bytes / _bytes_per_element;
00622   }
00623   return 0;
00624 }
00625 
00626 ////////////////////////////////////////////////////////////////////
00627 //     Function: DCSimpleParameter::get_nested_field
00628 //       Access: Public, Virtual
00629 //  Description: Returns the DCPackerInterface object that represents
00630 //               the nth nested field.  This may return NULL if there
00631 //               is no such field (but it shouldn't do this if n is in
00632 //               the range 0 <= n < get_num_nested_fields()).
00633 ////////////////////////////////////////////////////////////////////
00634 DCPackerInterface *DCSimpleParameter::
00635 get_nested_field(int) const {
00636   return _nested_field;
00637 }
00638 
00639 ////////////////////////////////////////////////////////////////////
00640 //     Function: DCSimpleParameter::pack_double
00641 //       Access: Published, Virtual
00642 //  Description: Packs the indicated numeric or string value into the
00643 //               stream.
00644 ////////////////////////////////////////////////////////////////////
00645 void DCSimpleParameter::
00646 pack_double(DCPackData &pack_data, double value,
00647             bool &pack_error, bool &range_error) const {
00648   double real_value = value * _divisor;
00649   if (_has_modulus) {
00650     if (real_value < 0.0) {
00651       real_value = _double_modulus - fmod(-real_value, _double_modulus);
00652       if (real_value == _double_modulus) {
00653         real_value = 0.0;
00654       }
00655     } else {
00656       real_value = fmod(real_value, _double_modulus);
00657     }
00658   }
00659 
00660   switch (_type) {
00661   case ST_int8:
00662     {
00663       int int_value = (int)floor(real_value + 0.5);
00664       _int_range.validate(int_value, range_error);
00665       validate_int_limits(int_value, 8, range_error);
00666       do_pack_int8(pack_data.get_write_pointer(1), int_value);
00667     }
00668     break;
00669 
00670   case ST_int16:
00671     {
00672       int int_value = (int)floor(real_value + 0.5);
00673       _int_range.validate(int_value, range_error);
00674       validate_int_limits(int_value, 16, range_error);
00675       do_pack_int16(pack_data.get_write_pointer(2), int_value);
00676     }
00677     break;
00678     
00679   case ST_int32:
00680     {
00681       int int_value = (int)floor(real_value + 0.5);
00682       _int_range.validate(int_value, range_error);
00683       do_pack_int32(pack_data.get_write_pointer(4), int_value);
00684     }
00685     break;
00686     
00687   case ST_int64:
00688     {
00689       PN_int64 int64_value = (PN_int64)floor(real_value + 0.5);
00690       _int64_range.validate(int64_value, range_error);
00691       do_pack_int64(pack_data.get_write_pointer(8), int64_value);
00692     }
00693     break;
00694     
00695   case ST_char:
00696   case ST_uint8:
00697     {
00698       unsigned int int_value = (unsigned int)floor(real_value + 0.5);
00699       _uint_range.validate(int_value, range_error);
00700       validate_uint_limits(int_value, 8, range_error);
00701       do_pack_uint8(pack_data.get_write_pointer(1), int_value);
00702     }
00703     break;
00704     
00705   case ST_uint16:
00706     {
00707       unsigned int int_value = (unsigned int)floor(real_value + 0.5);
00708       _uint_range.validate(int_value, range_error);
00709       validate_uint_limits(int_value, 16, range_error);
00710       do_pack_uint16(pack_data.get_write_pointer(2), int_value);
00711     }
00712     break;
00713     
00714   case ST_uint32:
00715     {
00716       unsigned int int_value = (unsigned int)floor(real_value + 0.5);
00717       _uint_range.validate(int_value, range_error);
00718       do_pack_uint32(pack_data.get_write_pointer(4), int_value);
00719     }
00720     break;
00721     
00722   case ST_uint64:
00723     {
00724       PN_uint64 int64_value = (PN_uint64)floor(real_value + 0.5);
00725       _uint64_range.validate(int64_value, range_error);
00726       do_pack_uint64(pack_data.get_write_pointer(8), int64_value);
00727     }
00728     break;
00729 
00730   case ST_float64:
00731     _double_range.validate(real_value, range_error);
00732     do_pack_float64(pack_data.get_write_pointer(8), real_value);
00733     break;
00734 
00735   default:
00736     pack_error = true;
00737   }
00738 }
00739 
00740 ////////////////////////////////////////////////////////////////////
00741 //     Function: DCSimpleParameter::pack_int
00742 //       Access: Published, Virtual
00743 //  Description: Packs the indicated numeric or string value into the
00744 //               stream.
00745 ////////////////////////////////////////////////////////////////////
00746 void DCSimpleParameter::
00747 pack_int(DCPackData &pack_data, int value,
00748          bool &pack_error, bool &range_error) const {
00749   int int_value = value * _divisor;
00750 
00751   if (value != 0 && (int_value / value) != (int)_divisor) {
00752     // If we've experienced overflow after applying the divisor, pack
00753     // it as an int64 instead.
00754     pack_int64(pack_data, (PN_int64)value, pack_error, range_error);
00755     return;
00756   }
00757 
00758   if (_has_modulus && _uint_modulus != 0) {
00759     if (int_value < 0) {
00760       int_value = _uint_modulus - 1 - (-int_value - 1) % _uint_modulus;
00761     } else {
00762       int_value = int_value % _uint_modulus;
00763     }
00764   }
00765 
00766   switch (_type) {
00767   case ST_int8:
00768     _int_range.validate(int_value, range_error);
00769     validate_int_limits(int_value, 8, range_error);
00770     do_pack_int8(pack_data.get_write_pointer(1), int_value);
00771     break;
00772 
00773   case ST_int16:
00774     _int_range.validate(int_value, range_error);
00775     validate_int_limits(int_value, 16, range_error);
00776     do_pack_int16(pack_data.get_write_pointer(2), int_value);
00777     break;
00778 
00779   case ST_int32:
00780     _int_range.validate(int_value, range_error);
00781     do_pack_int32(pack_data.get_write_pointer(4), int_value);
00782     break;
00783 
00784   case ST_int64:
00785     _int64_range.validate(int_value, range_error);
00786     do_pack_int64(pack_data.get_write_pointer(8), int_value);
00787     break;
00788 
00789   case ST_char:
00790   case ST_uint8:
00791     if (int_value < 0) {
00792       range_error = true;
00793     }
00794     _uint_range.validate((unsigned int)int_value, range_error);
00795     validate_uint_limits((unsigned int)int_value, 8, range_error);
00796     do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
00797     break;
00798 
00799   case ST_uint16:
00800     if (int_value < 0) {
00801       range_error = true;
00802     }
00803     _uint_range.validate((unsigned int)int_value, range_error);
00804     validate_uint_limits((unsigned int)int_value, 16, range_error);
00805     do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
00806     break;
00807 
00808   case ST_uint32:
00809     if (int_value < 0) {
00810       range_error = true;
00811     }
00812     _uint_range.validate((unsigned int)int_value, range_error);
00813     do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
00814     break;
00815 
00816   case ST_uint64:
00817     if (int_value < 0) {
00818       range_error = true;
00819     }
00820     _uint64_range.validate((unsigned int)int_value, range_error);
00821     do_pack_uint64(pack_data.get_write_pointer(8), (unsigned int)int_value);
00822     break;
00823 
00824   case ST_float64:
00825     _double_range.validate(int_value, range_error);
00826     do_pack_float64(pack_data.get_write_pointer(8), int_value);
00827     break;
00828 
00829   default:
00830     pack_error = true;
00831   }
00832 }
00833 
00834 ////////////////////////////////////////////////////////////////////
00835 //     Function: DCSimpleParameter::pack_uint
00836 //       Access: Published, Virtual
00837 //  Description: Packs the indicated numeric or string value into the
00838 //               stream.
00839 ////////////////////////////////////////////////////////////////////
00840 void DCSimpleParameter::
00841 pack_uint(DCPackData &pack_data, unsigned int value,
00842           bool &pack_error, bool &range_error) const {
00843   unsigned int int_value = value * _divisor;
00844   if (_has_modulus && _uint_modulus != 0) {
00845     int_value = int_value % _uint_modulus;
00846   }
00847 
00848   switch (_type) {
00849   case ST_int8:
00850     if ((int)int_value < 0) {
00851       range_error = true;
00852     }
00853     _int_range.validate((int)int_value, range_error);
00854     validate_int_limits((int)int_value, 8, range_error);
00855     do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
00856     break;
00857 
00858   case ST_int16:
00859     if ((int)int_value < 0) {
00860       range_error = true;
00861     }
00862     _int_range.validate((int)int_value, range_error);
00863     validate_int_limits((int)int_value, 16, range_error);
00864     do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
00865     break;
00866 
00867   case ST_int32:
00868     if ((int)int_value < 0) {
00869       range_error = true;
00870     }
00871     _int_range.validate((int)int_value, range_error);
00872     do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
00873     break;
00874 
00875   case ST_int64:
00876     if ((int)int_value < 0) {
00877       range_error = true;
00878     }
00879     _int64_range.validate((int)int_value, range_error);
00880     do_pack_int64(pack_data.get_write_pointer(8), (int)int_value);
00881     break;
00882 
00883   case ST_char:
00884   case ST_uint8:
00885     _uint_range.validate(int_value, range_error);
00886     validate_uint_limits(int_value, 8, range_error);
00887     do_pack_uint8(pack_data.get_write_pointer(1), int_value);
00888     break;
00889 
00890   case ST_uint16:
00891     _uint_range.validate(int_value, range_error);
00892     validate_uint_limits(int_value, 16, range_error);
00893     do_pack_uint16(pack_data.get_write_pointer(2), int_value);
00894     break;
00895 
00896   case ST_uint32:
00897     _uint_range.validate(int_value, range_error);
00898     do_pack_uint32(pack_data.get_write_pointer(4), int_value);
00899     break;
00900 
00901   case ST_uint64:
00902     _uint64_range.validate(int_value, range_error);
00903     do_pack_uint64(pack_data.get_write_pointer(8), int_value);
00904     break;
00905 
00906   case ST_float64:
00907     _double_range.validate(int_value, range_error);
00908     do_pack_float64(pack_data.get_write_pointer(8), int_value);
00909     break;
00910 
00911   default:
00912     pack_error = true;
00913   }
00914 }
00915 
00916 ////////////////////////////////////////////////////////////////////
00917 //     Function: DCSimpleParameter::pack_int64
00918 //       Access: Published, Virtual
00919 //  Description: Packs the indicated numeric or string value into the
00920 //               stream.
00921 ////////////////////////////////////////////////////////////////////
00922 void DCSimpleParameter::
00923 pack_int64(DCPackData &pack_data, PN_int64 value,
00924             bool &pack_error, bool &range_error) const {
00925   PN_int64 int_value = value * _divisor;
00926   if (_has_modulus && _uint64_modulus != 0) {
00927     if (int_value < 0) {
00928       int_value = _uint64_modulus - 1 - (-int_value - 1) % _uint64_modulus;
00929     } else {
00930       int_value = int_value % _uint64_modulus;
00931     }
00932   }
00933 
00934   switch (_type) {
00935   case ST_int8:
00936     _int_range.validate((int)int_value, range_error);
00937     validate_int64_limits(int_value, 8, range_error);
00938     do_pack_int8(pack_data.get_write_pointer(1), (int)int_value);
00939     break;
00940 
00941   case ST_int16:
00942     _int_range.validate((int)int_value, range_error);
00943     validate_int64_limits(int_value, 16, range_error);
00944     do_pack_int16(pack_data.get_write_pointer(2), (int)int_value);
00945     break;
00946 
00947   case ST_int32:
00948     _int_range.validate((int)int_value, range_error);
00949     validate_int64_limits(int_value, 32, range_error);
00950     do_pack_int32(pack_data.get_write_pointer(4), (int)int_value);
00951     break;
00952 
00953   case ST_int64:
00954     _int64_range.validate(int_value, range_error);
00955     do_pack_int64(pack_data.get_write_pointer(8), int_value);
00956     break;
00957 
00958   case ST_char:
00959   case ST_uint8:
00960     if (int_value < 0) {
00961       range_error = true;
00962     }
00963     _uint_range.validate((unsigned int)(PN_uint64)int_value, range_error);
00964     validate_uint64_limits((PN_uint64)int_value, 8, range_error);
00965     do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)(PN_uint64)int_value);
00966     break;
00967 
00968   case ST_uint16:
00969     if (int_value < 0) {
00970       range_error = true;
00971     }
00972     _uint_range.validate((unsigned int)(PN_uint64)int_value, range_error);
00973     validate_uint64_limits((PN_uint64)int_value, 16, range_error);
00974     do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)(PN_uint64)int_value);
00975     break;
00976 
00977   case ST_uint32:
00978     if (int_value < 0) {
00979       range_error = true;
00980     }
00981     _uint_range.validate((unsigned int)(PN_uint64)int_value, range_error);
00982     validate_uint64_limits((PN_uint64)int_value, 32, range_error);
00983     do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)(PN_uint64)int_value);
00984     break;
00985 
00986   case ST_uint64:
00987     if (int_value < 0) {
00988       range_error = true;
00989     }
00990     _uint64_range.validate((PN_uint64)int_value, range_error);
00991     do_pack_uint64(pack_data.get_write_pointer(8), (PN_uint64)int_value);
00992     break;
00993 
00994   case ST_float64:
00995     _double_range.validate((double)int_value, range_error);
00996     do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
00997     break;
00998 
00999   default:
01000     pack_error = true;
01001   }
01002 }
01003 
01004 ////////////////////////////////////////////////////////////////////
01005 //     Function: DCSimpleParameter::pack_uint64
01006 //       Access: Published, Virtual
01007 //  Description: Packs the indicated numeric or string value into the
01008 //               stream.
01009 ////////////////////////////////////////////////////////////////////
01010 void DCSimpleParameter::
01011 pack_uint64(DCPackData &pack_data, PN_uint64 value,
01012             bool &pack_error, bool &range_error) const {
01013   PN_uint64 int_value = value * _divisor;
01014   if (_has_modulus && _uint64_modulus != 0) {
01015     int_value = int_value % _uint64_modulus;
01016   }
01017 
01018   switch (_type) {
01019   case ST_int8:
01020     if ((PN_int64)int_value < 0) {
01021       range_error = true;
01022     }
01023     _int_range.validate((int)(PN_int64)int_value, range_error);
01024     validate_int64_limits((PN_int64)int_value, 8, range_error);
01025     do_pack_int8(pack_data.get_write_pointer(1), (int)(PN_int64)int_value);
01026     break;
01027 
01028   case ST_int16:
01029     if ((PN_int64)int_value < 0) {
01030       range_error = true;
01031     }
01032     _int_range.validate((int)(PN_int64)int_value, range_error);
01033     validate_int64_limits((PN_int64)int_value, 16, range_error);
01034     do_pack_int16(pack_data.get_write_pointer(2), (int)(PN_int64)int_value);
01035     break;
01036 
01037   case ST_int32:
01038     if ((PN_int64)int_value < 0) {
01039       range_error = true;
01040     }
01041     _int_range.validate((int)(PN_int64)int_value, range_error);
01042     validate_int64_limits((PN_int64)int_value, 32, range_error);
01043     do_pack_int32(pack_data.get_write_pointer(4), (int)(PN_int64)int_value);
01044     break;
01045 
01046   case ST_int64:
01047     if ((PN_int64)int_value < 0) {
01048       range_error = true;
01049     }
01050     _int64_range.validate((PN_int64)int_value, range_error);
01051     do_pack_int64(pack_data.get_write_pointer(8), (PN_int64)int_value);
01052     break;
01053 
01054   case ST_char:
01055   case ST_uint8:
01056     _uint_range.validate((unsigned int)int_value, range_error);
01057     validate_uint64_limits(int_value, 8, range_error);
01058     do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)int_value);
01059     break;
01060 
01061   case ST_uint16:
01062     _uint_range.validate((unsigned int)int_value, range_error);
01063     validate_uint64_limits(int_value, 16, range_error);
01064     do_pack_uint16(pack_data.get_write_pointer(2), (unsigned int)int_value);
01065     break;
01066 
01067   case ST_uint32:
01068     _uint_range.validate((unsigned int)int_value, range_error);
01069     validate_uint64_limits(int_value, 32, range_error);
01070     do_pack_uint32(pack_data.get_write_pointer(4), (unsigned int)int_value);
01071     break;
01072 
01073   case ST_uint64:
01074     _uint64_range.validate(int_value, range_error);
01075     do_pack_uint64(pack_data.get_write_pointer(8), int_value);
01076     break;
01077 
01078   case ST_float64:
01079     _double_range.validate((double)int_value, range_error);
01080     do_pack_float64(pack_data.get_write_pointer(8), (double)int_value);
01081     break;
01082 
01083   default:
01084     pack_error = true;
01085   }
01086 }
01087 
01088 ////////////////////////////////////////////////////////////////////
01089 //     Function: DCSimpleParameter::pack_string
01090 //       Access: Published, Virtual
01091 //  Description: Packs the indicated numeric or string value into the
01092 //               stream.
01093 ////////////////////////////////////////////////////////////////////
01094 void DCSimpleParameter::
01095 pack_string(DCPackData &pack_data, const string &value,
01096             bool &pack_error, bool &range_error) const {
01097   size_t string_length = value.length();
01098 
01099   switch (_type) {
01100   case ST_char:
01101   case ST_uint8:
01102   case ST_int8:
01103     if (string_length == 0) {
01104       pack_error = true;
01105     } else {
01106       if (string_length != 1) {
01107         range_error = true;
01108       }
01109       _uint_range.validate((unsigned int)value[0], range_error);
01110       do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)value[0]);
01111     }
01112     break;
01113 
01114   case ST_string:
01115   case ST_blob:
01116     _uint_range.validate(string_length, range_error);
01117     validate_uint_limits(string_length, 16, range_error);
01118     if (_num_length_bytes != 0) {
01119       do_pack_uint16(pack_data.get_write_pointer(2), string_length);
01120     }
01121     pack_data.append_data(value.data(), string_length);
01122     break;
01123 
01124   case ST_blob32:
01125     _uint_range.validate(string_length, range_error);
01126     if (_num_length_bytes != 0) {
01127       do_pack_uint32(pack_data.get_write_pointer(4), string_length);
01128     }
01129     pack_data.append_data(value.data(), string_length);
01130     break;
01131 
01132   default:
01133     pack_error = true;
01134   }
01135 }
01136 
01137 ////////////////////////////////////////////////////////////////////
01138 //     Function: DCSimpleParameter::pack_default_value
01139 //       Access: Public, Virtual
01140 //  Description: Packs the simpleParameter's specified default value (or a
01141 //               sensible default if no value is specified) into the
01142 //               stream.  Returns true if the default value is packed,
01143 //               false if the simpleParameter doesn't know how to pack its
01144 //               default value.
01145 ////////////////////////////////////////////////////////////////////
01146 bool DCSimpleParameter::
01147 pack_default_value(DCPackData &pack_data, bool &pack_error) const {
01148   if (has_default_value()) {
01149     return DCField::pack_default_value(pack_data, pack_error);
01150   }
01151 
01152   if (_has_nested_fields) {
01153     // If the simple type is an array (or string) type, pack the
01154     // appropriate length array, with code similar to
01155     // DCArrayParameter::pack_default_value().
01156 
01157     unsigned int minimum_length = 0;
01158     if (!_uint_range.is_empty()) {
01159       minimum_length = _uint_range.get_min(0);
01160     }
01161     
01162     DCPacker packer;
01163     packer.begin_pack(this);
01164     packer.push();
01165     for (unsigned int i = 0; i < minimum_length; i++) {
01166       packer.pack_default_value();
01167     }
01168     packer.pop();
01169     if (!packer.end_pack()) {
01170       pack_error = true;
01171       
01172     } else {
01173       pack_data.append_data(packer.get_data(), packer.get_length());
01174     }
01175 
01176   } else {
01177     // Otherwise, if it's just a simple numeric type, pack a zero or
01178     // the minimum value.
01179     switch (_type) {
01180     case ST_int8:
01181     case ST_int16:
01182     case ST_int32:
01183       if (_int_range.is_in_range(0)) {
01184         pack_int(pack_data, 0, pack_error, pack_error);
01185       } else {
01186         pack_int(pack_data, _int_range.get_min(0), pack_error, pack_error);
01187       }
01188       break;
01189 
01190     case ST_int64:
01191       if (_int64_range.is_in_range(0)) {
01192         pack_int64(pack_data, 0, pack_error, pack_error);
01193       } else {
01194         pack_int64(pack_data, _int64_range.get_min(0), pack_error, pack_error);
01195       }
01196       break;
01197 
01198     case ST_char:
01199     case ST_uint8:
01200     case ST_uint16:
01201     case ST_uint32:
01202       if (_uint_range.is_in_range(0)) {
01203         pack_uint(pack_data, 0, pack_error, pack_error);
01204       } else {
01205         pack_uint(pack_data, _uint_range.get_min(0), pack_error, pack_error);
01206       }
01207       break;
01208 
01209     case ST_uint64:
01210       if (_uint64_range.is_in_range(0)) {
01211         pack_uint64(pack_data, 0, pack_error, pack_error);
01212       } else {
01213         pack_uint64(pack_data, _uint64_range.get_min(0), pack_error, pack_error);
01214       }
01215       break;
01216       
01217     case ST_float64:
01218       if (_double_range.is_in_range(0.0)) {
01219         pack_double(pack_data, 0.0, pack_error, pack_error);
01220       } else {
01221         pack_double(pack_data, _double_range.get_min(0), pack_error, pack_error);
01222       }
01223       break;
01224       
01225     default:
01226       pack_error = true;
01227     }
01228   }
01229   return true;
01230 }
01231 
01232 
01233 
01234 ////////////////////////////////////////////////////////////////////
01235 //     Function: DCSimpleParameter::unpack_double
01236 //       Access: Public, Virtual
01237 //  Description: Unpacks the current numeric or string value from the
01238 //               stream.
01239 ////////////////////////////////////////////////////////////////////
01240 void DCSimpleParameter::
01241 unpack_double(const char *data, size_t length, size_t &p, double &value,
01242               bool &pack_error, bool &range_error) const {
01243   switch (_type) {
01244   case ST_int8:
01245     {
01246       if (p + 1 > length) {
01247         pack_error = true;
01248         return;
01249       }
01250       int int_value = do_unpack_int8(data + p);
01251       _int_range.validate(int_value, range_error);
01252       value = int_value;
01253       p++;
01254     }
01255     break;
01256 
01257   case ST_int16:
01258     {
01259       if (p + 2 > length) {
01260         pack_error = true;
01261         return;
01262       }
01263       int int_value = do_unpack_int16(data + p);
01264       _int_range.validate(int_value, range_error);
01265       value = int_value;
01266       p += 2;
01267     }
01268     break;
01269 
01270   case ST_int32:
01271     {
01272       if (p + 4 > length) {
01273         pack_error = true;
01274         return;
01275       }
01276       int int_value = do_unpack_int32(data + p);
01277       _int_range.validate(int_value, range_error);
01278       value = int_value;
01279       p += 4;
01280     }
01281     break;
01282 
01283   case ST_int64:
01284     {
01285       if (p + 8 > length) {
01286         pack_error = true;
01287         return;
01288       }
01289       PN_int64 int_value = do_unpack_int64(data + p);
01290       _int64_range.validate(int_value, range_error);
01291       value = (double)int_value;
01292       p += 8;
01293     }
01294     break;
01295 
01296   case ST_char:
01297   case ST_uint8:
01298     {
01299       if (p + 1 > length) {
01300         pack_error = true;
01301         return;
01302       }
01303       unsigned int uint_value = do_unpack_uint8(data + p);
01304       _uint_range.validate(uint_value, range_error);
01305       value = uint_value;
01306       p++;
01307     }
01308     break;
01309 
01310   case ST_uint16:
01311     {
01312       if (p + 2 > length) {
01313         pack_error = true;
01314         return;
01315       }
01316       unsigned int uint_value = do_unpack_uint16(data + p);
01317       _uint_range.validate(uint_value, range_error);
01318       value = uint_value;
01319       p += 2;
01320     }
01321     break;
01322 
01323   case ST_uint32:
01324     {
01325       if (p + 4 > length) {
01326         pack_error = true;
01327         return;
01328       }
01329       unsigned int uint_value = do_unpack_uint32(data + p);
01330       _uint_range.validate(uint_value, range_error);
01331       value = uint_value;
01332       p += 4;
01333     }
01334     break;
01335 
01336   case ST_uint64:
01337     {
01338       if (p + 8 > length) {
01339         pack_error = true;
01340         return;
01341       }
01342       PN_uint64 uint_value = do_unpack_uint64(data + p);
01343       _uint64_range.validate(uint_value, range_error);
01344       value = (double)uint_value;
01345       p += 8;
01346     }
01347     break;
01348 
01349   case ST_float64:
01350     {
01351       if (p + 8 > length) {
01352         pack_error = true;
01353         return;
01354       }
01355       value = do_unpack_float64(data + p);
01356       _double_range.validate(value, range_error);
01357       p += 8;
01358     }
01359     break;
01360 
01361   default:
01362     pack_error = true;
01363     return;
01364   }
01365 
01366   if (_divisor != 1) {
01367     value = value / _divisor;
01368   }
01369 
01370   return;
01371 }
01372 
01373 ////////////////////////////////////////////////////////////////////
01374 //     Function: DCSimpleParameter::unpack_int
01375 //       Access: Public, Virtual
01376 //  Description: Unpacks the current numeric or string value from the
01377 //               stream.
01378 ////////////////////////////////////////////////////////////////////
01379 void DCSimpleParameter::
01380 unpack_int(const char *data, size_t length, size_t &p, int &value,
01381            bool &pack_error, bool &range_error) const {
01382   switch (_type) {
01383   case ST_int8:
01384     if (p + 1 > length) {
01385       pack_error = true;
01386       return;
01387     }
01388     value = do_unpack_int8(data + p);
01389     _int_range.validate(value, range_error);
01390     p++;
01391     break;
01392 
01393   case ST_int16:
01394     if (p + 2 > length) {
01395       pack_error = true;
01396       return;
01397     }
01398     value = do_unpack_int16(data + p);
01399     _int_range.validate(value, range_error);
01400     p += 2;
01401     break;
01402 
01403   case ST_int32:
01404     if (p + 4 > length) {
01405       pack_error = true;
01406       return;
01407     }
01408     value = do_unpack_int32(data + p);
01409     _int_range.validate(value, range_error);
01410     p += 4;
01411     break;
01412 
01413   case ST_int64:
01414     {
01415       if (p + 8 > length) {
01416         pack_error = true;
01417         return;
01418       }
01419       PN_int64 int_value = do_unpack_uint64(data + p);
01420       _int64_range.validate(int_value, range_error);
01421       value = (int)int_value;
01422       if (value != int_value) {
01423         // uint exceeded the storage capacity of a signed int.
01424         pack_error = true;
01425       }
01426       p += 8;
01427     }
01428     break;
01429 
01430   case ST_char:
01431   case ST_uint8:
01432     {
01433       if (p + 1 > length) {
01434         pack_error = true;
01435         return;
01436       }
01437       unsigned int uint_value = do_unpack_uint8(data + p);
01438       _uint_range.validate(uint_value, range_error);
01439       value = uint_value;
01440       p++;
01441     }
01442     break;
01443 
01444   case ST_uint16:
01445     {
01446       if (p + 2 > length) {
01447         pack_error = true;
01448         return;
01449       }
01450       unsigned int uint_value = do_unpack_uint16(data + p);
01451       _uint_range.validate(uint_value, range_error);
01452       value = (int)uint_value;
01453       p += 2;
01454     }
01455     break;
01456 
01457   case ST_uint32:
01458     {
01459       if (p + 4 > length) {
01460         pack_error = true;
01461         return;
01462       }
01463       unsigned int uint_value = do_unpack_uint32(data + p);
01464       _uint_range.validate(uint_value, range_error);
01465       value = (int)uint_value;
01466       if (value < 0) {
01467         pack_error = true;
01468       }
01469       p += 4;
01470     }
01471     break;
01472 
01473   case ST_uint64:
01474     {
01475       if (p + 8 > length) {
01476         pack_error = true;
01477         return;
01478       }
01479       PN_uint64 uint_value = do_unpack_uint64(data + p);
01480       _uint64_range.validate(uint_value, range_error);
01481       value = (int)(unsigned int)uint_value;
01482       if ((unsigned int)value != uint_value || value < 0) {
01483         pack_error = true;
01484       }
01485       p += 8;
01486     }
01487     break;
01488 
01489   case ST_float64:
01490     {
01491       if (p + 8 > length) {
01492         pack_error = true;
01493         return;
01494       }
01495       double real_value = do_unpack_float64(data + p);
01496       _double_range.validate(real_value, range_error);
01497       value = (int)real_value;
01498       p += 8;
01499     }
01500     break;
01501 
01502   default:
01503     pack_error = true;
01504     return;
01505   }
01506 
01507   if (_divisor != 1) {
01508     value = value / _divisor;
01509   }
01510 
01511   return;
01512 }
01513 
01514 ////////////////////////////////////////////////////////////////////
01515 //     Function: DCSimpleParameter::unpack_uint
01516 //       Access: Public, Virtual
01517 //  Description: Unpacks the current numeric or string value from the
01518 //               stream.
01519 ////////////////////////////////////////////////////////////////////
01520 void DCSimpleParameter::
01521 unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value,
01522               bool &pack_error, bool &range_error) const {
01523   switch (_type) {
01524   case ST_int8:
01525     {
01526       if (p + 1 > length) {
01527         pack_error = true;
01528       return;
01529       }
01530       int int_value = do_unpack_int8(data + p);
01531       _int_range.validate(int_value, range_error);
01532       if (int_value < 0) {
01533         pack_error = true;
01534       }
01535       value = (unsigned int)int_value;
01536       p++;
01537     }
01538     break;
01539 
01540   case ST_int16:
01541     {
01542       if (p + 2 > length) {
01543         pack_error = true;
01544         return;
01545       }
01546       int int_value = do_unpack_int16(data + p);
01547       _int_range.validate(int_value, range_error);
01548       if (int_value < 0) {
01549         pack_error = true;
01550       }
01551       value = (unsigned int)int_value;
01552       p += 2;
01553     }
01554     break;
01555 
01556   case ST_int32:
01557     {
01558       if (p + 4 > length) {
01559         pack_error = true;
01560         return;
01561       }
01562       int int_value = do_unpack_int32(data + p);
01563       _int_range.validate(int_value, range_error);
01564       if (int_value < 0) {
01565         pack_error = true;
01566       }
01567       value = (unsigned int)int_value;
01568       p += 4;
01569     }
01570     break;
01571 
01572   case ST_int64:
01573     {
01574       if (p + 8 > length) {
01575         pack_error = true;
01576         return;
01577       }
01578       PN_int64 int_value = do_unpack_int64(data + p);
01579       _int64_range.validate(int_value, range_error);
01580       if (int_value < 0) {
01581         pack_error = true;
01582       }
01583       value = (unsigned int)(int)int_value;
01584       if (value != int_value) {
01585         pack_error = true;
01586       }
01587       p += 8;
01588     }
01589     break;
01590 
01591   case ST_char:
01592   case ST_uint8:
01593     if (p + 1 > length) {
01594       pack_error = true;
01595       return;
01596     }
01597     value = do_unpack_uint8(data + p);
01598     _uint_range.validate(value, range_error);
01599     p++;
01600     break;
01601 
01602   case ST_uint16:
01603     if (p + 2 > length) {
01604       pack_error = true;
01605       return;
01606     }
01607     value = do_unpack_uint16(data + p);
01608     _uint_range.validate(value, range_error);
01609     p += 2;
01610     break;
01611 
01612   case ST_uint32:
01613     if (p + 4 > length) {
01614       pack_error = true;
01615       return;
01616     }
01617     value = do_unpack_uint32(data + p);
01618     _uint_range.validate(value, range_error);
01619     p += 4;
01620     break;
01621 
01622   case ST_uint64:
01623     {
01624       if (p + 8 > length) {
01625         pack_error = true;
01626         return;
01627       }
01628       PN_uint64 uint_value = do_unpack_uint64(data + p);
01629       _uint64_range.validate(uint_value, range_error);
01630       value = (unsigned int)uint_value;
01631       if (value != uint_value) {
01632         pack_error = true;
01633       }
01634       p += 8;
01635     }
01636     break;
01637 
01638   case ST_float64:
01639     {
01640       if (p + 8 > length) {
01641         pack_error = true;
01642         return;
01643       }
01644       double real_value = do_unpack_float64(data + p);
01645       _double_range.validate(real_value, range_error);
01646       value = (unsigned int)real_value;
01647       p += 8;
01648     }
01649     break;
01650 
01651   default:
01652     pack_error = true;
01653     return;
01654   }
01655 
01656   if (_divisor != 1) {
01657     value = value / _divisor;
01658   }
01659 
01660   return;
01661 }
01662 
01663 ////////////////////////////////////////////////////////////////////
01664 //     Function: DCSimpleParameter::unpack_int64
01665 //       Access: Public, Virtual
01666 //  Description: Unpacks the current numeric or string value from the
01667 //               stream.
01668 ////////////////////////////////////////////////////////////////////
01669 void DCSimpleParameter::
01670 unpack_int64(const char *data, size_t length, size_t &p, PN_int64 &value,
01671               bool &pack_error, bool &range_error) const {
01672   switch (_type) {
01673   case ST_int8:
01674     {
01675       if (p + 1 > length) {
01676         pack_error = true;
01677         return;
01678       }
01679       int int_value = do_unpack_int8(data + p);
01680       _int_range.validate(int_value, range_error);
01681       value = (PN_int64)int_value;
01682       p++;
01683     }
01684     break;
01685 
01686   case ST_int16:
01687     {
01688       if (p + 2 > length) {
01689         pack_error = true;
01690         return;
01691       }
01692       int int_value = do_unpack_int16(data + p);
01693       _int_range.validate(int_value, range_error);
01694       value = (PN_int64)int_value;
01695       p += 2;
01696     }
01697     break;
01698 
01699   case ST_int32:
01700     {
01701       if (p + 4 > length) {
01702         pack_error = true;
01703         return;
01704       }
01705       int int_value = do_unpack_int32(data + p);
01706       _int_range.validate(int_value, range_error);
01707       value = (PN_int64)int_value;
01708       p += 4;
01709     }
01710     break;
01711 
01712   case ST_int64:
01713     if (p + 8 > length) {
01714       pack_error = true;
01715       return;
01716     }
01717     value = do_unpack_int64(data + p);
01718     _int64_range.validate(value, range_error);
01719     p += 8;
01720     break;
01721 
01722   case ST_char:
01723   case ST_uint8:
01724     {
01725       if (p + 1 > length) {
01726         pack_error = true;
01727         return;
01728       }
01729       unsigned int uint_value = do_unpack_uint8(data + p);
01730       _uint_range.validate(uint_value, range_error);
01731       value = (PN_int64)(int)uint_value;
01732       p++;
01733     }
01734     break;
01735 
01736   case ST_uint16:
01737     {
01738       if (p + 2 > length) {
01739         pack_error = true;
01740         return;
01741       }
01742       unsigned int uint_value = do_unpack_uint16(data + p);
01743       _uint_range.validate(uint_value, range_error);
01744       value = (PN_int64)(int)uint_value;
01745       p += 2;
01746     }
01747     break;
01748 
01749   case ST_uint32:
01750     {
01751       if (p + 4 > length) {
01752         pack_error = true;
01753         return;
01754       }
01755       unsigned int uint_value = do_unpack_uint32(data + p);
01756       _uint_range.validate(uint_value, range_error);
01757       value = (PN_int64)(int)uint_value;
01758       p += 4;
01759     }
01760     break;
01761 
01762   case ST_uint64:
01763     {
01764       if (p + 8 > length) {
01765         pack_error = true;
01766         return;
01767       }
01768       PN_uint64 uint_value = do_unpack_uint64(data + p);
01769       _uint64_range.validate(uint_value, range_error);
01770       value = (PN_int64)uint_value;
01771       if (value < 0) {
01772         pack_error = true;
01773       }
01774       p += 8;
01775     }
01776     break;
01777 
01778   case ST_float64:
01779     {
01780       if (p + 8 > length) {
01781         pack_error = true;
01782         return;
01783       }
01784       double real_value = do_unpack_float64(data + p);
01785       _double_range.validate(real_value, range_error);
01786       value = (PN_int64)real_value;
01787       p += 8;
01788     }
01789     break;
01790 
01791   default:
01792     pack_error = true;
01793     return;
01794   }
01795 
01796   if (_divisor != 1) {
01797     value = value / _divisor;
01798   }
01799 
01800   return;
01801 }
01802 
01803 ////////////////////////////////////////////////////////////////////
01804 //     Function: DCSimpleParameter::unpack_uint64
01805 //       Access: Public, Virtual
01806 //  Description: Unpacks the current numeric or string value from the
01807 //               stream.
01808 ////////////////////////////////////////////////////////////////////
01809 void DCSimpleParameter::
01810 unpack_uint64(const char *data, size_t length, size_t &p, PN_uint64 &value,
01811               bool &pack_error, bool &range_error) const {
01812   switch (_type) {
01813   case ST_int8:
01814     {
01815       if (p + 1 > length) {
01816         pack_error = true;
01817         return;
01818       }
01819       int int_value = do_unpack_int8(data + p);
01820       _int_range.validate(int_value, range_error);
01821       if (int_value < 0) {
01822         pack_error = true;
01823       }
01824       value = (PN_uint64)(unsigned int)int_value;
01825       p++;
01826     }
01827     break;
01828 
01829   case ST_int16:
01830     {
01831       if (p + 2 > length) {
01832         pack_error = true;
01833         return;
01834       }
01835       int int_value = do_unpack_int16(data + p);
01836       _int_range.validate(int_value, range_error);
01837       if (int_value < 0) {
01838         pack_error = true;
01839       }
01840       value = (PN_uint64)(unsigned int)int_value;
01841       p += 2;
01842     }
01843     break;
01844 
01845   case ST_int32:
01846     {
01847       if (p + 4 > length) {
01848         pack_error = true;
01849         return;
01850       }
01851       int int_value = do_unpack_int32(data + p);
01852       _int_range.validate(int_value, range_error);
01853       if (int_value < 0) {
01854         pack_error = true;
01855       }
01856       value = (PN_uint64)(unsigned int)int_value;
01857       p += 4;
01858     }
01859     break;
01860 
01861   case ST_int64:
01862     {
01863       if (p + 8 > length) {
01864         pack_error = true;
01865         return;
01866       }
01867       PN_int64 int_value = do_unpack_int64(data + p);
01868       _int64_range.validate(int_value, range_error);
01869       if (int_value < 0) {
01870         pack_error = true;
01871       }
01872       value = (PN_uint64)int_value;
01873       p += 8;
01874     }
01875     break;
01876 
01877   case ST_char:
01878   case ST_uint8:
01879     {
01880       if (p + 1 > length) {
01881         pack_error = true;
01882         return;
01883       }
01884       unsigned int uint_value = do_unpack_uint8(data + p);
01885       _uint_range.validate(uint_value, range_error);
01886       value = (PN_uint64)uint_value;
01887       p++;
01888     }
01889     break;
01890 
01891   case ST_uint16:
01892     {
01893       if (p + 2 > length) {
01894         pack_error = true;
01895         return;
01896       }
01897       unsigned int uint_value = do_unpack_uint16(data + p);
01898       _uint_range.validate(uint_value, range_error);
01899       value = (PN_uint64)uint_value;
01900       p += 2;
01901     }
01902     break;
01903 
01904   case ST_uint32:
01905     {
01906       if (p + 4 > length) {
01907         pack_error = true;
01908         return;
01909       }
01910       unsigned int uint_value = do_unpack_uint32(data + p);
01911       _uint_range.validate(uint_value, range_error);
01912       value = (PN_uint64)uint_value;
01913       p += 4;
01914     }
01915     break;
01916 
01917   case ST_uint64:
01918     if (p + 8 > length) {
01919       pack_error = true;
01920       return;
01921     }
01922     value = do_unpack_uint64(data + p);
01923     _uint64_range.validate(value, range_error);
01924     p += 8;
01925     break;
01926 
01927   case ST_float64:
01928     {
01929       if (p + 8 > length) {
01930         pack_error = true;
01931         return;
01932       }
01933       double real_value = do_unpack_float64(data + p);
01934       _double_range.validate(real_value, range_error);
01935       value = (PN_uint64)real_value;
01936       p += 8;
01937     }
01938     break;
01939 
01940   default:
01941     pack_error = true;
01942     return;
01943   }
01944 
01945   if (_divisor != 1) {
01946     value = value / _divisor;
01947   }
01948 
01949   return;
01950 }
01951 
01952 ////////////////////////////////////////////////////////////////////
01953 //     Function: DCSimpleParameter::unpack_string
01954 //       Access: Public, Virtual
01955 //  Description: Unpacks the current numeric or string value from the
01956 //               stream.
01957 ////////////////////////////////////////////////////////////////////
01958 void DCSimpleParameter::
01959 unpack_string(const char *data, size_t length, size_t &p, string &value,
01960               bool &pack_error, bool &range_error) const {
01961   // If the type is a single byte, unpack it into a string of length 1.
01962   switch (_type) {
01963   case ST_char:
01964   case ST_int8:
01965   case ST_uint8:
01966     {
01967       if (p + 1 > length) {
01968         pack_error = true;
01969         return;
01970       }
01971       unsigned int int_value = do_unpack_uint8(data + p);
01972       _uint_range.validate(int_value, range_error);
01973       value.assign(1, int_value);
01974       p++;
01975     }
01976     return;
01977 
01978   default:
01979     break;
01980   }
01981 
01982   size_t string_length;
01983 
01984   if (_num_length_bytes == 0) {
01985     string_length = _fixed_byte_size;
01986 
01987   } else {
01988     switch (_type) {
01989     case ST_string:
01990     case ST_blob:
01991       if (p + 2 > length) {
01992         pack_error = true;
01993         return;
01994       }
01995       string_length = do_unpack_uint16(data + p);
01996       p += 2;
01997       break;
01998       
01999     case ST_blob32:
02000       if (p + 4 > length) {
02001         pack_error = true;
02002         return;
02003       }
02004       string_length = do_unpack_uint32(data + p);
02005       p += 4;
02006       break;
02007       
02008     default:
02009       pack_error = true;
02010       return;
02011     }
02012   }
02013 
02014   _uint_range.validate(string_length, range_error);
02015 
02016   if (p + string_length > length) {
02017     pack_error = true;
02018     return;
02019   }
02020   value.assign(data + p, string_length);
02021   p += string_length;
02022 
02023   return;
02024 }
02025 
02026 ////////////////////////////////////////////////////////////////////
02027 //     Function: DCSimpleParameter::unpack_validate
02028 //       Access: Public, Virtual
02029 //  Description: Internally unpacks the current numeric or string
02030 //               value and validates it against the type range limits,
02031 //               but does not return the value.  Returns true on
02032 //               success, false on failure (e.g. we don't know how to
02033 //               validate this field).
02034 ////////////////////////////////////////////////////////////////////
02035 bool DCSimpleParameter::
02036 unpack_validate(const char *data, size_t length, size_t &p,
02037                 bool &pack_error, bool &range_error) const { 
02038   if (!_has_range_limits) {
02039     return unpack_skip(data, length, p, pack_error);
02040   }
02041   switch (_type) {
02042   case ST_int8:
02043     {
02044       if (p + 1 > length) {
02045         pack_error = true;
02046         return true;
02047       }
02048       int int_value = do_unpack_int8(data + p);
02049       _int_range.validate(int_value, range_error);
02050       p++;
02051     }
02052     break;
02053 
02054   case ST_int16:
02055     {
02056       if (p + 2 > length) {
02057         pack_error = true;
02058         return true;
02059       }
02060       int int_value = do_unpack_int16(data + p);
02061       _int_range.validate(int_value, range_error);
02062       p += 2;
02063     }
02064     break;
02065 
02066   case ST_int32:
02067     {
02068       if (p + 4 > length) {
02069         pack_error = true;
02070         return true;
02071       }
02072       int int_value = do_unpack_int32(data + p);
02073       _int_range.validate(int_value, range_error);
02074       p += 4;
02075     }
02076     break;
02077 
02078   case ST_int64:
02079     {
02080       if (p + 8 > length) {
02081         pack_error = true;
02082         return true;
02083       }
02084       PN_int64 int_value = do_unpack_int64(data + p);
02085       _int64_range.validate(int_value, range_error);
02086       p += 8;
02087     }
02088     break;
02089 
02090   case ST_char:
02091   case ST_uint8:
02092     {
02093       if (p + 1 > length) {
02094         pack_error = true;
02095         return true;
02096       }
02097       unsigned int uint_value = do_unpack_uint8(data + p);
02098       _uint_range.validate(uint_value, range_error);
02099       p++;
02100     }
02101     break;
02102 
02103   case ST_uint16:
02104     {
02105       if (p + 2 > length) {
02106         pack_error = true;
02107         return true;
02108       }
02109       unsigned int uint_value = do_unpack_uint16(data + p);
02110       _uint_range.validate(uint_value, range_error);
02111       p += 2;
02112     }
02113     break;
02114 
02115   case ST_uint32:
02116     {
02117       if (p + 4 > length) {
02118         pack_error = true;
02119         return true;
02120       }
02121       unsigned int uint_value = do_unpack_uint32(data + p);
02122       _uint_range.validate(uint_value, range_error);
02123       p += 4;
02124     }
02125     break;
02126 
02127   case ST_uint64:
02128     {
02129       if (p + 8 > length) {
02130         pack_error = true;
02131         return true;
02132       }
02133       PN_uint64 uint_value = do_unpack_uint64(data + p);
02134       _uint64_range.validate(uint_value, range_error);
02135       p += 8;
02136     }
02137     break;
02138 
02139   case ST_float64:
02140     {
02141       if (p + 8 > length) {
02142         pack_error = true;
02143         return true;
02144       }
02145       double real_value = do_unpack_float64(data + p);
02146       _double_range.validate(real_value, range_error);
02147       p += 8;
02148     }
02149     break;
02150 
02151   case ST_string:
02152   case ST_blob:
02153     if (_num_length_bytes == 0) {
02154       p += _fixed_byte_size;
02155 
02156     } else {
02157       if (p + 2 > length) {
02158         pack_error = true;
02159         return true;
02160       }
02161       size_t string_length = do_unpack_uint16(data + p);
02162       _uint_range.validate(string_length, range_error);
02163       p += 2 + string_length;
02164     }
02165     break;
02166 
02167   case ST_blob32:
02168     if (_num_length_bytes == 0) {
02169       p += _fixed_byte_size;
02170 
02171     } else {
02172       if (p + 4 > length) {
02173         pack_error = true;
02174         return true;
02175       }
02176       size_t string_length = do_unpack_uint32(data + p);
02177       _uint_range.validate(string_length, range_error);
02178       p += 4 + string_length;
02179     }
02180     break;
02181 
02182   default:
02183     return false;
02184   }
02185 
02186   return true;
02187 }
02188 
02189 ////////////////////////////////////////////////////////////////////
02190 //     Function: DCSimpleParameter::unpack_skip
02191 //       Access: Public, Virtual
02192 //  Description: Increments p to the end of the current field without
02193 //               actually unpacking any data or performing any range
02194 //               validation.  Returns true on success, false on
02195 //               failure (e.g. we don't know how to skip this field).
02196 ////////////////////////////////////////////////////////////////////
02197 bool DCSimpleParameter::
02198 unpack_skip(const char *data, size_t length, size_t &p, 
02199             bool &pack_error) const {
02200   size_t string_length;
02201 
02202   switch (_type) {
02203   case ST_char:
02204   case ST_int8:
02205   case ST_uint8:
02206     p++;
02207     break;
02208 
02209   case ST_int16:
02210   case ST_uint16:
02211     p += 2;
02212     break;
02213 
02214   case ST_int32:
02215   case ST_uint32:
02216     p += 4;
02217     break;
02218 
02219   case ST_int64:
02220   case ST_uint64:
02221   case ST_float64:
02222     p += 8;
02223     break;
02224 
02225   case ST_string:
02226   case ST_blob:
02227     if (_num_length_bytes == 0) {
02228       p += _fixed_byte_size;
02229 
02230     } else {
02231       if (p + 2 > length) {
02232         return false;
02233       }
02234       string_length = do_unpack_uint16(data + p);
02235       p += 2 + string_length;
02236     }
02237     break;
02238 
02239   case ST_blob32:
02240     if (_num_length_bytes == 0) {
02241       p += _fixed_byte_size;
02242 
02243     } else {
02244       if (p + 4 > length) {
02245         return false;
02246       }
02247       string_length = do_unpack_uint32(data + p);
02248       p += 4 + string_length;
02249     }
02250     break;
02251 
02252   default:
02253     return false;
02254   }
02255 
02256   if (p > length) {
02257     pack_error = true;
02258   }
02259 
02260   return true;
02261 }
02262 
02263 ////////////////////////////////////////////////////////////////////
02264 //     Function: DCSimpleParameter::output_instance
02265 //       Access: Public, Virtual
02266 //  Description: Formats the parameter in the C++-like dc syntax as a
02267 //               typename and identifier.
02268 ////////////////////////////////////////////////////////////////////
02269 void DCSimpleParameter::
02270 output_instance(ostream &out, bool brief, const string &prename,
02271                 const string &name, const string &postname) const {
02272   if (get_typedef() != (DCTypedef *)NULL) {
02273     output_typedef_name(out, brief, prename, name, postname);
02274 
02275   } else {
02276     out << _type;
02277     if (_has_modulus) {
02278       out << "%" << _orig_modulus;
02279     }
02280     if (_divisor != 1) {
02281       out << "/" << _divisor;
02282     }
02283 
02284     switch (_type) {
02285     case ST_int8:
02286     case ST_int16:
02287     case ST_int32:
02288       if (!_int_range.is_empty()) {
02289         out << "(";
02290         _int_range.output(out, _divisor);
02291         out << ")";
02292       }
02293       break;
02294     
02295     case ST_int64:
02296       if (!_int64_range.is_empty()) {
02297         out << "(";
02298         _int64_range.output(out, _divisor);
02299         out << ")";
02300       }
02301       break;
02302     
02303     case ST_uint8:
02304     case ST_uint16:
02305     case ST_uint32:
02306       if (!_uint_range.is_empty()) {
02307         out << "(";
02308         _uint_range.output(out, _divisor);
02309         out << ")";
02310       }
02311       break;
02312 
02313     case ST_char:
02314       if (!_uint_range.is_empty()) {
02315         out << "(";
02316         _uint_range.output_char(out, _divisor);
02317         out << ")";
02318       }
02319       break;
02320     
02321     case ST_uint64:
02322       if (!_uint64_range.is_empty()) {
02323         out << "(";
02324         _uint64_range.output(out, _divisor);
02325         out << ")";
02326       }
02327       break;
02328 
02329     case ST_float64:
02330       if (!_double_range.is_empty()) {
02331         out << "(";
02332         _double_range.output(out, _divisor);
02333         out << ")";
02334       }
02335       break;
02336 
02337     case ST_string:
02338       if (!_uint_range.is_empty()) {
02339         out << "(";
02340         _uint_range.output(out, _divisor);
02341         out << ")";
02342       }
02343       break;
02344     default:
02345       break;
02346     }
02347 
02348     if (!prename.empty() || !name.empty() || !postname.empty()) {
02349       out << " " << prename << name << postname;
02350     }
02351   }
02352 }
02353 
02354 ////////////////////////////////////////////////////////////////////
02355 //     Function: DCSimpleParameter::generate_hash
02356 //       Access: Public, Virtual
02357 //  Description: Accumulates the properties of this type into the
02358 //               hash.
02359 ////////////////////////////////////////////////////////////////////
02360 void DCSimpleParameter::
02361 generate_hash(HashGenerator &hashgen) const {
02362   DCParameter::generate_hash(hashgen);
02363 
02364   hashgen.add_int(_type);
02365   hashgen.add_int(_divisor);
02366   if (_has_modulus) {
02367     hashgen.add_int((int)_double_modulus);
02368   }
02369 
02370   _int_range.generate_hash(hashgen);
02371   _int64_range.generate_hash(hashgen);
02372   _uint_range.generate_hash(hashgen);
02373   _uint64_range.generate_hash(hashgen);
02374   _double_range.generate_hash(hashgen);
02375 }
02376 
02377 ////////////////////////////////////////////////////////////////////
02378 //     Function: DCSimpleParameter::do_check_match
02379 //       Access: Protected, Virtual
02380 //  Description: Returns true if the other interface is bitwise the
02381 //               same as this one--that is, a uint32 only matches a
02382 //               uint32, etc. Names of components, and range limits,
02383 //               are not compared.
02384 ////////////////////////////////////////////////////////////////////
02385 bool DCSimpleParameter::
02386 do_check_match(const DCPackerInterface *other) const {
02387   return other->do_check_match_simple_parameter(this);
02388 }
02389 
02390 ////////////////////////////////////////////////////////////////////
02391 //     Function: DCSimpleParameter::do_check_match_simple_parameter
02392 //       Access: Protected, Virtual
02393 //  Description: Returns true if this field matches the indicated
02394 //               simple parameter, false otherwise.
02395 ////////////////////////////////////////////////////////////////////
02396 bool DCSimpleParameter::
02397 do_check_match_simple_parameter(const DCSimpleParameter *other) const {
02398   if (_divisor != other->_divisor) {
02399     return false;
02400   }
02401 
02402   if (_type == other->_type) {
02403     return true;
02404   }
02405 
02406   // Check for certain types that are considered equivalent to each
02407   // other.
02408   switch (_type) {
02409   case ST_uint8:
02410   case ST_char:
02411     switch (other->_type) {
02412     case ST_uint8:
02413     case ST_char:
02414       return true;
02415 
02416     default:
02417       return false;
02418     }
02419 
02420   case ST_string:
02421   case ST_blob:
02422   case ST_uint8array:
02423     switch (other->_type) {
02424     case ST_string:
02425     case ST_blob:
02426     case ST_uint8array:
02427       return true;
02428 
02429     default:
02430       return false;
02431     }
02432 
02433   default:
02434     return false;
02435   }
02436 }
02437 
02438 ////////////////////////////////////////////////////////////////////
02439 //     Function: DCSimpleParameter::do_check_match_array_parameter
02440 //       Access: Protected, Virtual
02441 //  Description: Returns true if this field matches the indicated
02442 //               array parameter, false otherwise.
02443 ////////////////////////////////////////////////////////////////////
02444 bool DCSimpleParameter::
02445 do_check_match_array_parameter(const DCArrayParameter *other) const {
02446   if (other->get_array_size() != -1) {
02447     // We cannot match a fixed-size array.
02448     return false;
02449   }
02450   if (_nested_field == NULL) {
02451     // Only an array-style simple parameter can match a DCArrayParameter.
02452     return false;
02453   }
02454 
02455   return _nested_field->check_match(other->get_element_type());
02456 }
02457 
02458 ////////////////////////////////////////////////////////////////////
02459 //     Function: DCSimpleParameter::create_nested_field
02460 //       Access: Private, Static
02461 //  Description: Creates the one instance of the DCSimpleParameter
02462 //               corresponding to this combination of type and divisor
02463 //               if it is not already created.
02464 ////////////////////////////////////////////////////////////////////
02465 DCSimpleParameter *DCSimpleParameter::
02466 create_nested_field(DCSubatomicType type, unsigned int divisor) {
02467   DivisorMap &divisor_map = _nested_field_map[type];
02468   DivisorMap::iterator di;
02469   di = divisor_map.find(divisor);
02470   if (di != divisor_map.end()) {
02471     return (*di).second;
02472   }
02473 
02474   DCSimpleParameter *nested_field = new DCSimpleParameter(type, divisor);
02475   divisor_map[divisor] = nested_field;
02476   return nested_field;
02477 }
02478 
02479 ////////////////////////////////////////////////////////////////////
02480 //     Function: DCSimpleParameter::create_uint32uint8_type
02481 //       Access: Private, Static
02482 //  Description: Creates the one instance of the Uint32Uint8Type
02483 //               object if it is not already created.
02484 ////////////////////////////////////////////////////////////////////
02485 DCPackerInterface *DCSimpleParameter::
02486 create_uint32uint8_type() {
02487   if (_uint32uint8_type == NULL) {
02488     DCClass *dclass = new DCClass(NULL, "", true, false);
02489     dclass->add_field(new DCSimpleParameter(ST_uint32));
02490     dclass->add_field(new DCSimpleParameter(ST_uint8));
02491     _uint32uint8_type = new DCClassParameter(dclass);
02492   }
02493   return _uint32uint8_type;
02494 }
 All Classes Functions Variables Enumerations