00001 // Filename: dcPacker.I 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 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: DCPacker::clear_data 00018 // Access: Published 00019 // Description: Empties the data in the pack buffer and unpack 00020 // buffer. This should be called between calls to 00021 // begin_pack(), unless you want to concatenate all of 00022 // the pack results together. 00023 //////////////////////////////////////////////////////////////////// 00024 INLINE void DCPacker:: 00025 clear_data() { 00026 _pack_data.clear(); 00027 00028 if (_owns_unpack_data) { 00029 delete[] _unpack_data; 00030 _owns_unpack_data = false; 00031 } 00032 _unpack_data = NULL; 00033 } 00034 00035 //////////////////////////////////////////////////////////////////// 00036 // Function: DCPacker::has_nested_fields 00037 // Access: Published 00038 // Description: Returns true if the current field has any nested 00039 // fields (and thus expects a push() .. pop() 00040 // interface), or false otherwise. If this returns 00041 // true, get_num_nested_fields() may be called to 00042 // determine how many nested fields are expected. 00043 //////////////////////////////////////////////////////////////////// 00044 INLINE bool DCPacker:: 00045 has_nested_fields() const { 00046 if (_current_field == NULL) { 00047 return false; 00048 } else { 00049 return _current_field->has_nested_fields(); 00050 } 00051 } 00052 00053 //////////////////////////////////////////////////////////////////// 00054 // Function: DCPacker::get_num_nested_fields 00055 // Access: Published 00056 // Description: Returns the number of nested fields associated with 00057 // the current field, if has_nested_fields() returned 00058 // true. 00059 // 00060 // The return value may be -1 to indicate that a 00061 // variable number of nested fields are accepted by this 00062 // field type (e.g. a variable-length array). 00063 // 00064 // Note that this method is unreliable to determine how 00065 // many fields you must traverse before you can call 00066 // pop(), since particularly in the presence of a 00067 // DCSwitch, it may change during traversal. Use 00068 // more_nested_fields() instead. 00069 //////////////////////////////////////////////////////////////////// 00070 INLINE int DCPacker:: 00071 get_num_nested_fields() const { 00072 return _num_nested_fields; 00073 } 00074 00075 //////////////////////////////////////////////////////////////////// 00076 // Function: DCPacker::more_nested_fields 00077 // Access: Published 00078 // Description: Returns true if there are more nested fields to pack 00079 // or unpack in the current push sequence, false if it 00080 // is time to call pop(). 00081 //////////////////////////////////////////////////////////////////// 00082 INLINE bool DCPacker:: 00083 more_nested_fields() const { 00084 return (_current_field != (DCPackerInterface *)NULL && !_pack_error); 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: DCPacker::get_current_parent 00089 // Access: Published 00090 // Description: Returns the field that we left in our last call to 00091 // push(): the owner of the current level of fields. 00092 // This may be NULL at the beginning of the pack 00093 // operation. 00094 //////////////////////////////////////////////////////////////////// 00095 INLINE const DCPackerInterface *DCPacker:: 00096 get_current_parent() const { 00097 return _current_parent; 00098 } 00099 00100 //////////////////////////////////////////////////////////////////// 00101 // Function: DCPacker::get_current_field 00102 // Access: Published 00103 // Description: Returns the field that will be referenced by the next 00104 // call to pack_*() or unpack_*(). This will be NULL if 00105 // we have unpacked (or packed) all fields, or if it is 00106 // time to call pop(). 00107 //////////////////////////////////////////////////////////////////// 00108 INLINE const DCPackerInterface *DCPacker:: 00109 get_current_field() const { 00110 return _current_field; 00111 } 00112 00113 //////////////////////////////////////////////////////////////////// 00114 // Function: DCPacker::get_last_switch 00115 // Access: Published 00116 // Description: Returns a pointer to the last DCSwitch instance that 00117 // we have passed by and selected one case of during the 00118 // pack/unpack process. Each time we encounter a new 00119 // DCSwitch and select a case, this will change state. 00120 // 00121 // This may be used to detect when a DCSwitch has been 00122 // selected. At the moment this changes state, 00123 // get_current_parent() will contain the particular 00124 // SwitchCase that was selected by the switch. 00125 //////////////////////////////////////////////////////////////////// 00126 INLINE const DCSwitchParameter *DCPacker:: 00127 get_last_switch() const { 00128 return _last_switch; 00129 } 00130 00131 //////////////////////////////////////////////////////////////////// 00132 // Function: DCPacker::get_pack_type 00133 // Access: Published 00134 // Description: Returns the type of value expected by the current 00135 // field. See the enumerated type definition at the top 00136 // of DCPackerInterface.h. If this returns one of 00137 // PT_double, PT_int, PT_int64, or PT_string, then you 00138 // should call the corresponding pack_double(), 00139 // pack_int() function (or unpack_double(), 00140 // unpack_int(), etc.) to transfer data. Otherwise, you 00141 // should call push() and begin packing or unpacking the 00142 // nested fields. 00143 //////////////////////////////////////////////////////////////////// 00144 INLINE DCPackType DCPacker:: 00145 get_pack_type() const { 00146 if (_current_field == NULL) { 00147 return PT_invalid; 00148 } else { 00149 return _current_field->get_pack_type(); 00150 } 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: DCPacker::get_current_field_name 00155 // Access: Published 00156 // Description: Returns the name of the current field, if it has a 00157 // name, or the empty string if the field does not have 00158 // a name or there is no current field. 00159 //////////////////////////////////////////////////////////////////// 00160 INLINE string DCPacker:: 00161 get_current_field_name() const { 00162 if (_current_field == NULL) { 00163 return string(); 00164 } else { 00165 return _current_field->get_name(); 00166 } 00167 } 00168 00169 //////////////////////////////////////////////////////////////////// 00170 // Function: DCPacker::pack_double 00171 // Access: Published 00172 // Description: Packs the indicated numeric or string value into the 00173 // stream. 00174 //////////////////////////////////////////////////////////////////// 00175 INLINE void DCPacker:: 00176 pack_double(double value) { 00177 nassertv(_mode == M_pack || _mode == M_repack); 00178 if (_current_field == NULL) { 00179 _pack_error = true; 00180 } else { 00181 _current_field->pack_double(_pack_data, value, _pack_error, _range_error); 00182 advance(); 00183 } 00184 } 00185 00186 //////////////////////////////////////////////////////////////////// 00187 // Function: DCPacker::pack_int 00188 // Access: Published 00189 // Description: Packs the indicated numeric or string value into the 00190 // stream. 00191 //////////////////////////////////////////////////////////////////// 00192 INLINE void DCPacker:: 00193 pack_int(int value) { 00194 nassertv(_mode == M_pack || _mode == M_repack); 00195 if (_current_field == NULL) { 00196 _pack_error = true; 00197 } else { 00198 _current_field->pack_int(_pack_data, value, _pack_error, _range_error); 00199 advance(); 00200 } 00201 } 00202 00203 //////////////////////////////////////////////////////////////////// 00204 // Function: DCPacker::pack_uint 00205 // Access: Published 00206 // Description: Packs the indicated numeric or string value into the 00207 // stream. 00208 //////////////////////////////////////////////////////////////////// 00209 INLINE void DCPacker:: 00210 pack_uint(unsigned int value) { 00211 nassertv(_mode == M_pack || _mode == M_repack); 00212 if (_current_field == NULL) { 00213 _pack_error = true; 00214 } else { 00215 _current_field->pack_uint(_pack_data, value, _pack_error, _range_error); 00216 advance(); 00217 } 00218 } 00219 00220 //////////////////////////////////////////////////////////////////// 00221 // Function: DCPacker::pack_int64 00222 // Access: Published 00223 // Description: Packs the indicated numeric or string value into the 00224 // stream. 00225 //////////////////////////////////////////////////////////////////// 00226 INLINE void DCPacker:: 00227 pack_int64(PN_int64 value) { 00228 nassertv(_mode == M_pack || _mode == M_repack); 00229 if (_current_field == NULL) { 00230 _pack_error = true; 00231 } else { 00232 _current_field->pack_int64(_pack_data, value, _pack_error, _range_error); 00233 advance(); 00234 } 00235 } 00236 00237 //////////////////////////////////////////////////////////////////// 00238 // Function: DCPacker::pack_uint64 00239 // Access: Published 00240 // Description: Packs the indicated numeric or string value into the 00241 // stream. 00242 //////////////////////////////////////////////////////////////////// 00243 INLINE void DCPacker:: 00244 pack_uint64(PN_uint64 value) { 00245 nassertv(_mode == M_pack || _mode == M_repack); 00246 if (_current_field == NULL) { 00247 _pack_error = true; 00248 } else { 00249 _current_field->pack_uint64(_pack_data, value, _pack_error, _range_error); 00250 advance(); 00251 } 00252 } 00253 00254 //////////////////////////////////////////////////////////////////// 00255 // Function: DCPacker::pack_string 00256 // Access: Published 00257 // Description: Packs the indicated numeric or string value into the 00258 // stream. 00259 //////////////////////////////////////////////////////////////////// 00260 INLINE void DCPacker:: 00261 pack_string(const string &value) { 00262 nassertv(_mode == M_pack || _mode == M_repack); 00263 if (_current_field == NULL) { 00264 _pack_error = true; 00265 } else { 00266 _current_field->pack_string(_pack_data, value, _pack_error, _range_error); 00267 advance(); 00268 } 00269 } 00270 00271 //////////////////////////////////////////////////////////////////// 00272 // Function: DCPacker::pack_literal_value 00273 // Access: Published 00274 // Description: Adds the indicated string value into the stream, 00275 // representing a single pre-packed field element, or a 00276 // whole group of field elements at once. 00277 //////////////////////////////////////////////////////////////////// 00278 INLINE void DCPacker:: 00279 pack_literal_value(const string &value) { 00280 nassertv(_mode == M_pack || _mode == M_repack); 00281 if (_current_field == NULL) { 00282 _pack_error = true; 00283 } else { 00284 _pack_data.append_data(value.data(), value.length()); 00285 advance(); 00286 } 00287 } 00288 00289 //////////////////////////////////////////////////////////////////// 00290 // Function: DCPacker::unpack_double 00291 // Access: Published 00292 // Description: Unpacks the current numeric or string value from the 00293 // stream. 00294 //////////////////////////////////////////////////////////////////// 00295 INLINE double DCPacker:: 00296 unpack_double() { 00297 double value = 0.0; 00298 nassertr(_mode == M_unpack, value); 00299 if (_current_field == NULL) { 00300 _pack_error = true; 00301 00302 } else { 00303 _current_field->unpack_double(_unpack_data, _unpack_length, _unpack_p, 00304 value, _pack_error, _range_error); 00305 advance(); 00306 } 00307 00308 return value; 00309 } 00310 00311 //////////////////////////////////////////////////////////////////// 00312 // Function: DCPacker::unpack_int 00313 // Access: Published 00314 // Description: Unpacks the current numeric or string value from the 00315 // stream. 00316 //////////////////////////////////////////////////////////////////// 00317 INLINE int DCPacker:: 00318 unpack_int() { 00319 int value = 0; 00320 nassertr(_mode == M_unpack, value); 00321 if (_current_field == NULL) { 00322 _pack_error = true; 00323 00324 } else { 00325 _current_field->unpack_int(_unpack_data, _unpack_length, _unpack_p, 00326 value, _pack_error, _range_error); 00327 advance(); 00328 } 00329 00330 return value; 00331 } 00332 00333 //////////////////////////////////////////////////////////////////// 00334 // Function: DCPacker::unpack_uint 00335 // Access: Published 00336 // Description: Unpacks the current numeric or string value from the 00337 // stream. 00338 //////////////////////////////////////////////////////////////////// 00339 INLINE unsigned int DCPacker:: 00340 unpack_uint() { 00341 unsigned int value = 0; 00342 nassertr(_mode == M_unpack, value); 00343 if (_current_field == NULL) { 00344 _pack_error = true; 00345 00346 } else { 00347 _current_field->unpack_uint(_unpack_data, _unpack_length, _unpack_p, 00348 value, _pack_error, _range_error); 00349 advance(); 00350 } 00351 00352 return value; 00353 } 00354 00355 //////////////////////////////////////////////////////////////////// 00356 // Function: DCPacker::unpack_int64 00357 // Access: Published 00358 // Description: Unpacks the current numeric or string value from the 00359 // stream. 00360 //////////////////////////////////////////////////////////////////// 00361 INLINE PN_int64 DCPacker:: 00362 unpack_int64() { 00363 PN_int64 value = 0; 00364 nassertr(_mode == M_unpack, value); 00365 if (_current_field == NULL) { 00366 _pack_error = true; 00367 00368 } else { 00369 _current_field->unpack_int64(_unpack_data, _unpack_length, _unpack_p, 00370 value, _pack_error, _range_error); 00371 advance(); 00372 } 00373 00374 return value; 00375 } 00376 00377 //////////////////////////////////////////////////////////////////// 00378 // Function: DCPacker::unpack_uint64 00379 // Access: Published 00380 // Description: Unpacks the current numeric or string value from the 00381 // stream. 00382 //////////////////////////////////////////////////////////////////// 00383 INLINE PN_uint64 DCPacker:: 00384 unpack_uint64() { 00385 PN_uint64 value = 0; 00386 nassertr(_mode == M_unpack, value); 00387 if (_current_field == NULL) { 00388 _pack_error = true; 00389 00390 } else { 00391 _current_field->unpack_uint64(_unpack_data, _unpack_length, _unpack_p, 00392 value, _pack_error, _range_error); 00393 advance(); 00394 } 00395 00396 return value; 00397 } 00398 00399 //////////////////////////////////////////////////////////////////// 00400 // Function: DCPacker::unpack_string 00401 // Access: Published 00402 // Description: Unpacks the current numeric or string value from the 00403 // stream. 00404 //////////////////////////////////////////////////////////////////// 00405 INLINE string DCPacker:: 00406 unpack_string() { 00407 string value; 00408 nassertr(_mode == M_unpack, value); 00409 if (_current_field == NULL) { 00410 _pack_error = true; 00411 00412 } else { 00413 _current_field->unpack_string(_unpack_data, _unpack_length, _unpack_p, 00414 value, _pack_error, _range_error); 00415 advance(); 00416 } 00417 00418 return value; 00419 } 00420 00421 //////////////////////////////////////////////////////////////////// 00422 // Function: DCPacker::unpack_literal_value 00423 // Access: Published 00424 // Description: Returns the literal string that represents the packed 00425 // value of the current field, and advances the field 00426 // pointer. 00427 //////////////////////////////////////////////////////////////////// 00428 INLINE string DCPacker:: 00429 unpack_literal_value() { 00430 size_t start = _unpack_p; 00431 unpack_skip(); 00432 nassertr(_unpack_p >= start, string()); 00433 return string(_unpack_data + start, _unpack_p - start); 00434 } 00435 00436 //////////////////////////////////////////////////////////////////// 00437 // Function: DCPacker::unpack_double 00438 // Access: Public 00439 // Description: Unpacks the current numeric or string value from the 00440 // stream. 00441 //////////////////////////////////////////////////////////////////// 00442 INLINE void DCPacker:: 00443 unpack_double(double &value) { 00444 nassertv(_mode == M_unpack); 00445 if (_current_field == NULL) { 00446 _pack_error = true; 00447 00448 } else { 00449 _current_field->unpack_double(_unpack_data, _unpack_length, _unpack_p, 00450 value, _pack_error, _range_error); 00451 advance(); 00452 } 00453 } 00454 00455 //////////////////////////////////////////////////////////////////// 00456 // Function: DCPacker::unpack_int 00457 // Access: Public 00458 // Description: Unpacks the current numeric or string value from the 00459 // stream. 00460 //////////////////////////////////////////////////////////////////// 00461 INLINE void DCPacker:: 00462 unpack_int(int &value) { 00463 nassertv(_mode == M_unpack); 00464 if (_current_field == NULL) { 00465 _pack_error = true; 00466 00467 } else { 00468 _current_field->unpack_int(_unpack_data, _unpack_length, _unpack_p, 00469 value, _pack_error, _range_error); 00470 advance(); 00471 } 00472 } 00473 00474 //////////////////////////////////////////////////////////////////// 00475 // Function: DCPacker::unpack_uint 00476 // Access: Public 00477 // Description: Unpacks the current numeric or string value from the 00478 // stream. 00479 //////////////////////////////////////////////////////////////////// 00480 INLINE void DCPacker:: 00481 unpack_uint(unsigned int &value) { 00482 nassertv(_mode == M_unpack); 00483 if (_current_field == NULL) { 00484 _pack_error = true; 00485 00486 } else { 00487 _current_field->unpack_uint(_unpack_data, _unpack_length, _unpack_p, 00488 value, _pack_error, _range_error); 00489 advance(); 00490 } 00491 } 00492 00493 //////////////////////////////////////////////////////////////////// 00494 // Function: DCPacker::unpack_int64 00495 // Access: Public 00496 // Description: Unpacks the current numeric or string value from the 00497 // stream. 00498 //////////////////////////////////////////////////////////////////// 00499 INLINE void DCPacker:: 00500 unpack_int64(PN_int64 &value) { 00501 nassertv(_mode == M_unpack); 00502 if (_current_field == NULL) { 00503 _pack_error = true; 00504 00505 } else { 00506 _current_field->unpack_int64(_unpack_data, _unpack_length, _unpack_p, 00507 value, _pack_error, _range_error); 00508 advance(); 00509 } 00510 } 00511 00512 //////////////////////////////////////////////////////////////////// 00513 // Function: DCPacker::unpack_uint64 00514 // Access: Public 00515 // Description: Unpacks the current numeric or string value from the 00516 // stream. 00517 //////////////////////////////////////////////////////////////////// 00518 INLINE void DCPacker:: 00519 unpack_uint64(PN_uint64 &value) { 00520 nassertv(_mode == M_unpack); 00521 if (_current_field == NULL) { 00522 _pack_error = true; 00523 00524 } else { 00525 _current_field->unpack_uint64(_unpack_data, _unpack_length, _unpack_p, 00526 value, _pack_error, _range_error); 00527 advance(); 00528 } 00529 } 00530 00531 //////////////////////////////////////////////////////////////////// 00532 // Function: DCPacker::unpack_string 00533 // Access: Public 00534 // Description: Unpacks the current numeric or string value from the 00535 // stream. 00536 //////////////////////////////////////////////////////////////////// 00537 INLINE void DCPacker:: 00538 unpack_string(string &value) { 00539 nassertv(_mode == M_unpack); 00540 if (_current_field == NULL) { 00541 _pack_error = true; 00542 00543 } else { 00544 _current_field->unpack_string(_unpack_data, _unpack_length, _unpack_p, 00545 value, _pack_error, _range_error); 00546 advance(); 00547 } 00548 } 00549 00550 //////////////////////////////////////////////////////////////////// 00551 // Function: DCPacker::unpack_literal_value 00552 // Access: Public 00553 // Description: Returns the literal string that represents the packed 00554 // value of the current field, and advances the field 00555 // pointer. 00556 //////////////////////////////////////////////////////////////////// 00557 INLINE void DCPacker:: 00558 unpack_literal_value(string &value) { 00559 size_t start = _unpack_p; 00560 unpack_skip(); 00561 nassertv(_unpack_p >= start); 00562 value.assign(_unpack_data + start, _unpack_p - start); 00563 } 00564 00565 //////////////////////////////////////////////////////////////////// 00566 // Function: DCPacker::had_parse_error 00567 // Access: Published 00568 // Description: Returns true if there has been an parse error 00569 // since the most recent call to begin(); this can only 00570 // happen if you call parse_and_pack(). 00571 //////////////////////////////////////////////////////////////////// 00572 INLINE bool DCPacker:: 00573 had_parse_error() const { 00574 return _parse_error; 00575 } 00576 00577 //////////////////////////////////////////////////////////////////// 00578 // Function: DCPacker::had_pack_error 00579 // Access: Published 00580 // Description: Returns true if there has been an packing error 00581 // since the most recent call to begin(); in particular, 00582 // this may be called after end() has returned false to 00583 // determine the nature of the failure. 00584 // 00585 // A return value of true indicates there was a push/pop 00586 // mismatch, or the push/pop structure did not match the 00587 // data structure, or there were the wrong number of 00588 // elements in a nested push/pop structure, or on unpack 00589 // that the data stream was truncated. 00590 //////////////////////////////////////////////////////////////////// 00591 INLINE bool DCPacker:: 00592 had_pack_error() const { 00593 return _pack_error; 00594 } 00595 00596 //////////////////////////////////////////////////////////////////// 00597 // Function: DCPacker::had_range_error 00598 // Access: Published 00599 // Description: Returns true if there has been an range validation 00600 // error since the most recent call to begin(); in 00601 // particular, this may be called after end() has 00602 // returned false to determine the nature of the 00603 // failure. 00604 // 00605 // A return value of true indicates a value that was 00606 // packed or unpacked did not fit within the specified 00607 // legal range for a parameter, or within the limits of 00608 // the field size. 00609 //////////////////////////////////////////////////////////////////// 00610 INLINE bool DCPacker:: 00611 had_range_error() const { 00612 return _range_error; 00613 } 00614 00615 //////////////////////////////////////////////////////////////////// 00616 // Function: DCPacker::had_error 00617 // Access: Published 00618 // Description: Returns true if there has been any error (either a 00619 // pack error or a range error) since the most recent 00620 // call to begin(). If this returns true, then the 00621 // matching call to end() will indicate an error 00622 // (false). 00623 //////////////////////////////////////////////////////////////////// 00624 INLINE bool DCPacker:: 00625 had_error() const { 00626 return _range_error || _pack_error || _parse_error; 00627 } 00628 00629 //////////////////////////////////////////////////////////////////// 00630 // Function: DCPacker::get_num_unpacked_bytes 00631 // Access: Published 00632 // Description: Returns the number of bytes that have been unpacked 00633 // so far, or after unpack_end(), the total number of 00634 // bytes that were unpacked at all. This can be used to 00635 // validate that all of the bytes in the buffer were 00636 // actually unpacked (which is not otherwise considered 00637 // an error). 00638 //////////////////////////////////////////////////////////////////// 00639 INLINE size_t DCPacker:: 00640 get_num_unpacked_bytes() const { 00641 return _unpack_p; 00642 } 00643 00644 //////////////////////////////////////////////////////////////////// 00645 // Function: DCPacker::get_length 00646 // Access: Published 00647 // Description: Returns the current length of the buffer. This is 00648 // the number of useful bytes stored in the buffer, not 00649 // the amount of memory it takes up. 00650 //////////////////////////////////////////////////////////////////// 00651 INLINE size_t DCPacker:: 00652 get_length() const { 00653 return _pack_data.get_length(); 00654 } 00655 00656 //////////////////////////////////////////////////////////////////// 00657 // Function: DCPacker::get_string 00658 // Access: Published 00659 // Description: Returns the packed data buffer as a string. Also see 00660 // get_data(). 00661 //////////////////////////////////////////////////////////////////// 00662 INLINE string DCPacker:: 00663 get_string() const { 00664 return _pack_data.get_string(); 00665 } 00666 00667 //////////////////////////////////////////////////////////////////// 00668 // Function: DCPacker::get_unpack_length 00669 // Access: Published 00670 // Description: Returns the total number of bytes in the unpack data 00671 // buffer. This is the buffer used when unpacking; it 00672 // is separate from the pack data returned by 00673 // get_length(), which is filled during packing. 00674 //////////////////////////////////////////////////////////////////// 00675 INLINE size_t DCPacker:: 00676 get_unpack_length() const { 00677 return _unpack_length; 00678 } 00679 00680 //////////////////////////////////////////////////////////////////// 00681 // Function: DCPacker::get_unpack_string 00682 // Access: Published 00683 // Description: Returns the unpack data buffer, as a string. 00684 // This is the buffer used when unpacking; it is 00685 // separate from the pack data returned by get_string(), 00686 // which is filled during packing. Also see 00687 // get_unpack_data(). 00688 //////////////////////////////////////////////////////////////////// 00689 INLINE string DCPacker:: 00690 get_unpack_string() const { 00691 return string(_unpack_data, _unpack_length); 00692 } 00693 00694 //////////////////////////////////////////////////////////////////// 00695 // Function: DCPacker::get_string 00696 // Access: Published 00697 // Description: Copies the packed data into the indicated string. 00698 // Also see get_data(). 00699 //////////////////////////////////////////////////////////////////// 00700 INLINE void DCPacker:: 00701 get_string(string &data) const { 00702 data.assign(_pack_data.get_data(), _pack_data.get_length()); 00703 } 00704 00705 //////////////////////////////////////////////////////////////////// 00706 // Function: DCPacker::get_data 00707 // Access: Public 00708 // Description: Returns the beginning of the data buffer. The buffer 00709 // is not null-terminated, but see also get_string(). 00710 // 00711 // This may be used in conjunction with get_length() to 00712 // copy all of the bytes out of the buffer. Also see 00713 // take_data() to get the packed data without a copy 00714 // operation. 00715 //////////////////////////////////////////////////////////////////// 00716 INLINE const char *DCPacker:: 00717 get_data() const { 00718 return _pack_data.get_data(); 00719 } 00720 00721 //////////////////////////////////////////////////////////////////// 00722 // Function: DCPacker::take_data 00723 // Access: Public 00724 // Description: Returns the pointer to the beginning of the data 00725 // buffer, and transfers ownership of the buffer to the 00726 // caller. The caller is now responsible for ultimately 00727 // freeing the returned pointer with delete[], if it is 00728 // non-NULL. This may (or may not) return NULL if the 00729 // buffer is empty. 00730 // 00731 // This also empties the DCPackData structure, and sets 00732 // its length to zero (so you should call get_length() 00733 // before calling this method). 00734 //////////////////////////////////////////////////////////////////// 00735 INLINE char *DCPacker:: 00736 take_data() { 00737 return _pack_data.take_data(); 00738 } 00739 00740 //////////////////////////////////////////////////////////////////// 00741 // Function: DCPacker::append_data 00742 // Access: Public 00743 // Description: Adds the indicated bytes to the end of the data. 00744 // This may only be called between packing sessions. 00745 //////////////////////////////////////////////////////////////////// 00746 INLINE void DCPacker:: 00747 append_data(const char *buffer, size_t size) { 00748 nassertv(_mode == M_idle); 00749 _pack_data.append_data(buffer, size); 00750 } 00751 00752 //////////////////////////////////////////////////////////////////// 00753 // Function: DCPacker::get_write_pointer 00754 // Access: Public 00755 // Description: Adds the indicated number of bytes to the end of the 00756 // data without initializing them, and returns a pointer 00757 // to the beginning of the new data. This may only be 00758 // called between packing sessions. 00759 //////////////////////////////////////////////////////////////////// 00760 INLINE char *DCPacker:: 00761 get_write_pointer(size_t size) { 00762 nassertr(_mode == M_idle, NULL); 00763 return _pack_data.get_write_pointer(size); 00764 } 00765 00766 //////////////////////////////////////////////////////////////////// 00767 // Function: DCPacker::get_unpack_data 00768 // Access: Public 00769 // Description: Returns a read pointer to the unpack data buffer. 00770 // This is the buffer used when unpacking; it is 00771 // separate from the pack data returned by get_data(), 00772 // which is filled during packing. 00773 //////////////////////////////////////////////////////////////////// 00774 INLINE const char *DCPacker:: 00775 get_unpack_data() const { 00776 return _unpack_data; 00777 } 00778 00779 //////////////////////////////////////////////////////////////////// 00780 // Function: DCPacker::StackElement::get_num_stack_elements_ever_allocated 00781 // Access: Published, Static 00782 // Description: Returns the number of DCPacker::StackElement pointers 00783 // ever simultaneously allocated; these are now either 00784 // in active use or have been recycled into the deleted 00785 // DCPacker::StackElement pool to be used again. 00786 //////////////////////////////////////////////////////////////////// 00787 INLINE int DCPacker:: 00788 get_num_stack_elements_ever_allocated() { 00789 return StackElement::_num_ever_allocated; 00790 } 00791 00792 //////////////////////////////////////////////////////////////////// 00793 // Function: DCPacker::raw_pack_int8 00794 // Access: Published 00795 // Description: Packs the data into the buffer between packing 00796 // sessions. 00797 //////////////////////////////////////////////////////////////////// 00798 INLINE void DCPacker:: 00799 raw_pack_int8(int value) { 00800 nassertv(_mode == M_idle); 00801 DCPackerInterface::do_pack_int8(_pack_data.get_write_pointer(1), value); 00802 } 00803 00804 //////////////////////////////////////////////////////////////////// 00805 // Function: DCPacker::raw_pack_int16 00806 // Access: Published 00807 // Description: Packs the data into the buffer between packing 00808 // sessions. 00809 //////////////////////////////////////////////////////////////////// 00810 INLINE void DCPacker:: 00811 raw_pack_int16(int value) { 00812 nassertv(_mode == M_idle); 00813 DCPackerInterface::do_pack_int16(_pack_data.get_write_pointer(2), value); 00814 } 00815 00816 //////////////////////////////////////////////////////////////////// 00817 // Function: DCPacker::raw_pack_int32 00818 // Access: Published 00819 // Description: Packs the data into the buffer between packing 00820 // sessions. 00821 //////////////////////////////////////////////////////////////////// 00822 INLINE void DCPacker:: 00823 raw_pack_int32(int value) { 00824 nassertv(_mode == M_idle); 00825 DCPackerInterface::do_pack_int32(_pack_data.get_write_pointer(4), value); 00826 } 00827 00828 //////////////////////////////////////////////////////////////////// 00829 // Function: DCPacker::raw_pack_int64 00830 // Access: Published 00831 // Description: Packs the data into the buffer between packing 00832 // sessions. 00833 //////////////////////////////////////////////////////////////////// 00834 INLINE void DCPacker:: 00835 raw_pack_int64(PN_int64 value) { 00836 nassertv(_mode == M_idle); 00837 DCPackerInterface::do_pack_int64(_pack_data.get_write_pointer(8), value); 00838 } 00839 00840 //////////////////////////////////////////////////////////////////// 00841 // Function: DCPacker::raw_pack_uint8 00842 // Access: Published 00843 // Description: Packs the data into the buffer between packing 00844 // sessions. 00845 //////////////////////////////////////////////////////////////////// 00846 INLINE void DCPacker:: 00847 raw_pack_uint8(unsigned int value) { 00848 nassertv(_mode == M_idle); 00849 DCPackerInterface::do_pack_uint8(_pack_data.get_write_pointer(1), value); 00850 } 00851 00852 //////////////////////////////////////////////////////////////////// 00853 // Function: DCPacker::raw_pack_uint16 00854 // Access: Published 00855 // Description: Packs the data into the buffer between packing 00856 // sessions. 00857 //////////////////////////////////////////////////////////////////// 00858 INLINE void DCPacker:: 00859 raw_pack_uint16(unsigned int value) { 00860 nassertv(_mode == M_idle); 00861 DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value); 00862 } 00863 00864 //////////////////////////////////////////////////////////////////// 00865 // Function: DCPacker::raw_pack_uint32 00866 // Access: Published 00867 // Description: Packs the data into the buffer between packing 00868 // sessions. 00869 //////////////////////////////////////////////////////////////////// 00870 INLINE void DCPacker:: 00871 raw_pack_uint32(unsigned int value) { 00872 nassertv(_mode == M_idle); 00873 DCPackerInterface::do_pack_uint32(_pack_data.get_write_pointer(4), value); 00874 } 00875 00876 //////////////////////////////////////////////////////////////////// 00877 // Function: DCPacker::raw_pack_uint64 00878 // Access: Published 00879 // Description: Packs the data into the buffer between packing 00880 // sessions. 00881 //////////////////////////////////////////////////////////////////// 00882 INLINE void DCPacker:: 00883 raw_pack_uint64(PN_uint64 value) { 00884 nassertv(_mode == M_idle); 00885 DCPackerInterface::do_pack_uint64(_pack_data.get_write_pointer(8), value); 00886 } 00887 00888 //////////////////////////////////////////////////////////////////// 00889 // Function: DCPacker::raw_pack_float64 00890 // Access: Published 00891 // Description: Packs the data into the buffer between packing 00892 // sessions. 00893 //////////////////////////////////////////////////////////////////// 00894 INLINE void DCPacker:: 00895 raw_pack_float64(double value) { 00896 nassertv(_mode == M_idle); 00897 DCPackerInterface::do_pack_float64(_pack_data.get_write_pointer(8), value); 00898 } 00899 00900 //////////////////////////////////////////////////////////////////// 00901 // Function: DCPacker::raw_pack_string 00902 // Access: Published 00903 // Description: Packs the data into the buffer between packing 00904 // sessions. 00905 //////////////////////////////////////////////////////////////////// 00906 INLINE void DCPacker:: 00907 raw_pack_string(const string &value) { 00908 nassertv(_mode == M_idle); 00909 DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value.length()); 00910 _pack_data.append_data(value.data(), value.length()); 00911 } 00912 00913 //////////////////////////////////////////////////////////////////// 00914 // Function: DCPacker::raw_unpack_int8 00915 // Access: Published 00916 // Description: Unpacks the data from the buffer between unpacking 00917 // sessions. 00918 //////////////////////////////////////////////////////////////////// 00919 INLINE int DCPacker:: 00920 raw_unpack_int8() { 00921 int value = 0; 00922 raw_unpack_int8(value); 00923 return value; 00924 } 00925 00926 //////////////////////////////////////////////////////////////////// 00927 // Function: DCPacker::raw_unpack_int16 00928 // Access: Published 00929 // Description: Unpacks the data from the buffer between unpacking 00930 // sessions. 00931 //////////////////////////////////////////////////////////////////// 00932 INLINE int DCPacker:: 00933 raw_unpack_int16() { 00934 int value = 0; 00935 raw_unpack_int16(value); 00936 return value; 00937 } 00938 00939 //////////////////////////////////////////////////////////////////// 00940 // Function: DCPacker::raw_unpack_int32 00941 // Access: Published 00942 // Description: Unpacks the data from the buffer between unpacking 00943 // sessions. 00944 //////////////////////////////////////////////////////////////////// 00945 INLINE int DCPacker:: 00946 raw_unpack_int32() { 00947 int value = 0; 00948 raw_unpack_int32(value); 00949 return value; 00950 } 00951 00952 //////////////////////////////////////////////////////////////////// 00953 // Function: DCPacker::raw_unpack_int64 00954 // Access: Published 00955 // Description: Unpacks the data from the buffer between unpacking 00956 // sessions. 00957 //////////////////////////////////////////////////////////////////// 00958 INLINE PN_int64 DCPacker:: 00959 raw_unpack_int64() { 00960 PN_int64 value = 0; 00961 raw_unpack_int64(value); 00962 return value; 00963 } 00964 00965 //////////////////////////////////////////////////////////////////// 00966 // Function: DCPacker::raw_unpack_int8 00967 // Access: Public 00968 // Description: Unpacks the data from the buffer between unpacking 00969 // sessions. 00970 //////////////////////////////////////////////////////////////////// 00971 INLINE void DCPacker:: 00972 raw_unpack_int8(int &value) { 00973 nassertv(_mode == M_idle && _unpack_data != NULL); 00974 if (_unpack_p + 1 > _unpack_length) { 00975 _pack_error = true; 00976 return; 00977 } 00978 value = DCPackerInterface::do_unpack_int8(_unpack_data + _unpack_p); 00979 _unpack_p++; 00980 } 00981 00982 //////////////////////////////////////////////////////////////////// 00983 // Function: DCPacker::raw_unpack_int16 00984 // Access: Public 00985 // Description: Unpacks the data from the buffer between unpacking 00986 // sessions. 00987 //////////////////////////////////////////////////////////////////// 00988 INLINE void DCPacker:: 00989 raw_unpack_int16(int &value) { 00990 nassertv(_mode == M_idle && _unpack_data != NULL); 00991 if (_unpack_p + 2 > _unpack_length) { 00992 _pack_error = true; 00993 return; 00994 } 00995 value = DCPackerInterface::do_unpack_int16(_unpack_data + _unpack_p); 00996 _unpack_p += 2; 00997 } 00998 00999 //////////////////////////////////////////////////////////////////// 01000 // Function: DCPacker::raw_unpack_int32 01001 // Access: Public 01002 // Description: Unpacks the data from the buffer between unpacking 01003 // sessions. 01004 //////////////////////////////////////////////////////////////////// 01005 INLINE void DCPacker:: 01006 raw_unpack_int32(int &value) { 01007 nassertv(_mode == M_idle && _unpack_data != NULL); 01008 if (_unpack_p + 4 > _unpack_length) { 01009 _pack_error = true; 01010 return; 01011 } 01012 value = DCPackerInterface::do_unpack_int32(_unpack_data + _unpack_p); 01013 _unpack_p += 4; 01014 } 01015 01016 //////////////////////////////////////////////////////////////////// 01017 // Function: DCPacker::raw_unpack_uint8 01018 // Access: Published 01019 // Description: Unpacks the data from the buffer between unpacking 01020 // sessions. 01021 //////////////////////////////////////////////////////////////////// 01022 INLINE unsigned int DCPacker:: 01023 raw_unpack_uint8() { 01024 unsigned int value = 0; 01025 raw_unpack_uint8(value); 01026 return value; 01027 } 01028 01029 //////////////////////////////////////////////////////////////////// 01030 // Function: DCPacker::raw_unpack_uint16 01031 // Access: Published 01032 // Description: Unpacks the data from the buffer between unpacking 01033 // sessions. 01034 //////////////////////////////////////////////////////////////////// 01035 INLINE unsigned int DCPacker:: 01036 raw_unpack_uint16() { 01037 unsigned int value = 0; 01038 raw_unpack_uint16(value); 01039 return value; 01040 } 01041 01042 //////////////////////////////////////////////////////////////////// 01043 // Function: DCPacker::raw_unpack_uint32 01044 // Access: Published 01045 // Description: Unpacks the data from the buffer between unpacking 01046 // sessions. 01047 //////////////////////////////////////////////////////////////////// 01048 INLINE unsigned int DCPacker:: 01049 raw_unpack_uint32() { 01050 unsigned int value = 0; 01051 raw_unpack_uint32(value); 01052 return value; 01053 } 01054 01055 //////////////////////////////////////////////////////////////////// 01056 // Function: DCPacker::raw_unpack_uint64 01057 // Access: Published 01058 // Description: Unpacks the data from the buffer between unpacking 01059 // sessions. 01060 //////////////////////////////////////////////////////////////////// 01061 INLINE PN_uint64 DCPacker:: 01062 raw_unpack_uint64() { 01063 PN_uint64 value = 0; 01064 raw_unpack_uint64(value); 01065 return value; 01066 } 01067 01068 //////////////////////////////////////////////////////////////////// 01069 // Function: DCPacker::raw_unpack_float64 01070 // Access: Published 01071 // Description: Unpacks the data from the buffer between unpacking 01072 // sessions. 01073 //////////////////////////////////////////////////////////////////// 01074 INLINE double DCPacker:: 01075 raw_unpack_float64() { 01076 double value = 0; 01077 raw_unpack_float64(value); 01078 return value; 01079 } 01080 01081 //////////////////////////////////////////////////////////////////// 01082 // Function: DCPacker::raw_unpack_string 01083 // Access: Published 01084 // Description: Unpacks the data from the buffer between unpacking 01085 // sessions. 01086 //////////////////////////////////////////////////////////////////// 01087 INLINE string DCPacker:: 01088 raw_unpack_string() { 01089 string value; 01090 raw_unpack_string(value); 01091 return value; 01092 } 01093 01094 //////////////////////////////////////////////////////////////////// 01095 // Function: DCPacker::raw_unpack_int64 01096 // Access: Public 01097 // Description: Unpacks the data from the buffer between unpacking 01098 // sessions. 01099 //////////////////////////////////////////////////////////////////// 01100 INLINE void DCPacker:: 01101 raw_unpack_int64(PN_int64 &value) { 01102 nassertv(_mode == M_idle && _unpack_data != NULL); 01103 if (_unpack_p + 8 > _unpack_length) { 01104 _pack_error = true; 01105 return; 01106 } 01107 value = DCPackerInterface::do_unpack_int64(_unpack_data + _unpack_p); 01108 _unpack_p += 8; 01109 } 01110 01111 //////////////////////////////////////////////////////////////////// 01112 // Function: DCPacker::raw_unpack_uint8 01113 // Access: Public 01114 // Description: Unpacks the data from the buffer between unpacking 01115 // sessions. 01116 //////////////////////////////////////////////////////////////////// 01117 INLINE void DCPacker:: 01118 raw_unpack_uint8(unsigned int &value) { 01119 nassertv(_mode == M_idle && _unpack_data != NULL); 01120 if (_unpack_p + 1 > _unpack_length) { 01121 _pack_error = true; 01122 return; 01123 } 01124 value = DCPackerInterface::do_unpack_uint8(_unpack_data + _unpack_p); 01125 _unpack_p++; 01126 } 01127 01128 //////////////////////////////////////////////////////////////////// 01129 // Function: DCPacker::raw_unpack_uint16 01130 // Access: Public 01131 // Description: Unpacks the data from the buffer between unpacking 01132 // sessions. 01133 //////////////////////////////////////////////////////////////////// 01134 INLINE void DCPacker:: 01135 raw_unpack_uint16(unsigned int &value) { 01136 nassertv(_mode == M_idle && _unpack_data != NULL); 01137 if (_unpack_p + 2 > _unpack_length) { 01138 _pack_error = true; 01139 return; 01140 } 01141 value = DCPackerInterface::do_unpack_uint16(_unpack_data + _unpack_p); 01142 _unpack_p += 2; 01143 } 01144 01145 //////////////////////////////////////////////////////////////////// 01146 // Function: DCPacker::raw_unpack_uint32 01147 // Access: Public 01148 // Description: Unpacks the data from the buffer between unpacking 01149 // sessions. 01150 //////////////////////////////////////////////////////////////////// 01151 INLINE void DCPacker:: 01152 raw_unpack_uint32(unsigned int &value) { 01153 nassertv(_mode == M_idle && _unpack_data != NULL); 01154 if (_unpack_p + 4 > _unpack_length) { 01155 _pack_error = true; 01156 return; 01157 } 01158 value = DCPackerInterface::do_unpack_uint32(_unpack_data + _unpack_p); 01159 _unpack_p += 4; 01160 } 01161 01162 //////////////////////////////////////////////////////////////////// 01163 // Function: DCPacker::raw_unpack_uint64 01164 // Access: Public 01165 // Description: Unpacks the data from the buffer between unpacking 01166 // sessions. 01167 //////////////////////////////////////////////////////////////////// 01168 INLINE void DCPacker:: 01169 raw_unpack_uint64(PN_uint64 &value) { 01170 nassertv(_mode == M_idle && _unpack_data != NULL); 01171 if (_unpack_p + 8 > _unpack_length) { 01172 _pack_error = true; 01173 return; 01174 } 01175 value = DCPackerInterface::do_unpack_uint64(_unpack_data + _unpack_p); 01176 _unpack_p += 8; 01177 } 01178 01179 //////////////////////////////////////////////////////////////////// 01180 // Function: DCPacker::raw_unpack_float64 01181 // Access: Public 01182 // Description: Unpacks the data from the buffer between unpacking 01183 // sessions. 01184 //////////////////////////////////////////////////////////////////// 01185 INLINE void DCPacker:: 01186 raw_unpack_float64(double &value) { 01187 nassertv(_mode == M_idle && _unpack_data != NULL); 01188 if (_unpack_p + 8 > _unpack_length) { 01189 _pack_error = true; 01190 return; 01191 } 01192 value = DCPackerInterface::do_unpack_float64(_unpack_data + _unpack_p); 01193 _unpack_p += 8; 01194 } 01195 01196 //////////////////////////////////////////////////////////////////// 01197 // Function: DCPacker::raw_unpack_string 01198 // Access: Public 01199 // Description: Unpacks the data from the buffer between unpacking 01200 // sessions. 01201 //////////////////////////////////////////////////////////////////// 01202 INLINE void DCPacker:: 01203 raw_unpack_string(string &value) { 01204 nassertv(_mode == M_idle && _unpack_data != NULL); 01205 unsigned int string_length = raw_unpack_uint16(); 01206 01207 if (_unpack_p + string_length > _unpack_length) { 01208 _pack_error = true; 01209 return; 01210 } 01211 01212 value.assign(_unpack_data + _unpack_p, string_length); 01213 _unpack_p += string_length; 01214 } 01215 01216 //////////////////////////////////////////////////////////////////// 01217 // Function: DCPacker::advance 01218 // Access: Private 01219 // Description: Advances to the next field after a call to 01220 // pack_value() or pop(). 01221 //////////////////////////////////////////////////////////////////// 01222 INLINE void DCPacker:: 01223 advance() { 01224 _current_field_index++; 01225 if (_num_nested_fields >= 0 && 01226 _current_field_index >= _num_nested_fields) { 01227 // Done with all the fields on this parent. The caller must now 01228 // call pop(). 01229 _current_field = NULL; 01230 01231 // But if the parent is a switch record, we make a special case so 01232 // we can get the alternate fields. 01233 if (_current_parent != (DCPackerInterface *)NULL) { 01234 const DCSwitchParameter *switch_parameter = ((DCPackerInterface *)_current_parent)->as_switch_parameter(); 01235 if (switch_parameter != (DCSwitchParameter *)NULL) { 01236 handle_switch(switch_parameter); 01237 } 01238 } 01239 01240 } else if (_pop_marker != 0 && _unpack_p >= _pop_marker) { 01241 // Done with all the fields on this parent. The caller must now 01242 // call pop(). 01243 _current_field = NULL; 01244 01245 } else { 01246 // We have another field to advance to. 01247 _current_field = _current_parent->get_nested_field(_current_field_index); 01248 } 01249 } 01250 01251 //////////////////////////////////////////////////////////////////// 01252 // Function: DCPacker::StackElement::operator new 01253 // Access: Public 01254 // Description: Allocates the memory for a new DCPacker::StackElement. 01255 // This is specialized here to provide for fast 01256 // allocation of these things. 01257 //////////////////////////////////////////////////////////////////// 01258 INLINE void *DCPacker::StackElement:: 01259 operator new(size_t size) { 01260 if (_deleted_chain != (DCPacker::StackElement *)NULL) { 01261 StackElement *obj = _deleted_chain; 01262 _deleted_chain = _deleted_chain->_next; 01263 return obj; 01264 } 01265 #ifndef NDEBUG 01266 _num_ever_allocated++; 01267 #endif // NDEBUG 01268 return ::operator new(size); 01269 } 01270 01271 //////////////////////////////////////////////////////////////////// 01272 // Function: DCPacker::StackElement::operator delete 01273 // Access: Public 01274 // Description: Frees the memory for a deleted DCPacker::StackElement. 01275 // This is specialized here to provide for fast 01276 // allocation of these things. 01277 //////////////////////////////////////////////////////////////////// 01278 INLINE void DCPacker::StackElement:: 01279 operator delete(void *ptr) { 01280 StackElement *obj = (StackElement *)ptr; 01281 obj->_next = _deleted_chain; 01282 _deleted_chain = obj; 01283 }