Panda3D
|
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 ©) : 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 }