Panda3D
|
00001 // Filename: dcPacker.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 "dcPacker.h" 00016 #include "dcSwitch.h" 00017 #include "dcParserDefs.h" 00018 #include "dcLexerDefs.h" 00019 #include "dcClassParameter.h" 00020 #include "dcSwitchParameter.h" 00021 #include "dcClass.h" 00022 00023 DCPacker::StackElement *DCPacker::StackElement::_deleted_chain = NULL; 00024 int DCPacker::StackElement::_num_ever_allocated = 0; 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: DCPacker::Constructor 00028 // Access: Published 00029 // Description: 00030 //////////////////////////////////////////////////////////////////// 00031 DCPacker:: 00032 DCPacker() { 00033 _mode = M_idle; 00034 _unpack_data = NULL; 00035 _unpack_length = 0; 00036 _owns_unpack_data = false; 00037 _unpack_p = 0; 00038 _live_catalog = NULL; 00039 _parse_error = false; 00040 _pack_error = false; 00041 _range_error = false; 00042 _stack = NULL; 00043 00044 clear(); 00045 } 00046 00047 //////////////////////////////////////////////////////////////////// 00048 // Function: DCPacker::Destructor 00049 // Access: Published 00050 // Description: 00051 //////////////////////////////////////////////////////////////////// 00052 DCPacker:: 00053 ~DCPacker() { 00054 clear_data(); 00055 clear(); 00056 } 00057 00058 //////////////////////////////////////////////////////////////////// 00059 // Function: DCPacker::begin_pack 00060 // Access: Published 00061 // Description: Begins a packing session. The parameter is the DC 00062 // object that describes the packing format; it may be a 00063 // DCParameter or DCField. 00064 // 00065 // Unless you call clear_data() between sessions, 00066 // multiple packing sessions will be concatenated 00067 // together into the same buffer. If you wish to add 00068 // bytes to the buffer between packing sessions, use 00069 // append_data() or get_write_pointer(). 00070 //////////////////////////////////////////////////////////////////// 00071 void DCPacker:: 00072 begin_pack(const DCPackerInterface *root) { 00073 nassertv(_mode == M_idle); 00074 00075 _mode = M_pack; 00076 _parse_error = false; 00077 _pack_error = false; 00078 _range_error = false; 00079 00080 _root = root; 00081 _catalog = NULL; 00082 _live_catalog = NULL; 00083 00084 _current_field = root; 00085 _current_parent = NULL; 00086 _current_field_index = 0; 00087 _num_nested_fields = 0; 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 // Function: DCPacker::end_pack 00092 // Access: Published, Virtual 00093 // Description: Finishes a packing session. 00094 // 00095 // The return value is true on success, or false if 00096 // there has been some error during packing. 00097 //////////////////////////////////////////////////////////////////// 00098 bool DCPacker:: 00099 end_pack() { 00100 nassertr(_mode == M_pack, false); 00101 00102 _mode = M_idle; 00103 00104 if (_stack != NULL || _current_field != NULL || _current_parent != NULL) { 00105 _pack_error = true; 00106 } 00107 00108 clear(); 00109 00110 return !had_error(); 00111 } 00112 00113 //////////////////////////////////////////////////////////////////// 00114 // Function: DCPacker::set_unpack_data 00115 // Access: Public 00116 // Description: Sets up the unpack_data pointer. You may call this 00117 // before calling the version of begin_unpack() that 00118 // takes only one parameter. 00119 //////////////////////////////////////////////////////////////////// 00120 void DCPacker:: 00121 set_unpack_data(const string &data) { 00122 nassertv(_mode == M_idle); 00123 00124 char *buffer = new char[data.length()]; 00125 memcpy(buffer, data.data(), data.length()); 00126 set_unpack_data(buffer, data.length(), true); 00127 } 00128 00129 //////////////////////////////////////////////////////////////////// 00130 // Function: DCPacker::set_unpack_data 00131 // Access: Public 00132 // Description: Sets up the unpack_data pointer. You may call this 00133 // before calling the version of begin_unpack() that 00134 // takes only one parameter. 00135 //////////////////////////////////////////////////////////////////// 00136 void DCPacker:: 00137 set_unpack_data(const char *unpack_data, size_t unpack_length, 00138 bool owns_unpack_data) { 00139 nassertv(_mode == M_idle); 00140 00141 if (_owns_unpack_data) { 00142 delete[] _unpack_data; 00143 } 00144 _unpack_data = unpack_data; 00145 _unpack_length = unpack_length; 00146 _owns_unpack_data = owns_unpack_data; 00147 _unpack_p = 0; 00148 } 00149 00150 //////////////////////////////////////////////////////////////////// 00151 // Function: DCPacker::begin_unpack 00152 // Access: Public 00153 // Description: Begins an unpacking session. You must have 00154 // previously called set_unpack_data() to specify a 00155 // buffer to unpack. 00156 // 00157 // If there was data left in the buffer after a previous 00158 // begin_unpack() .. end_unpack() session, the new 00159 // session will resume from the current point. This 00160 // method may be used, therefore, to unpack a sequence 00161 // of objects from the same buffer. 00162 //////////////////////////////////////////////////////////////////// 00163 void DCPacker:: 00164 begin_unpack(const DCPackerInterface *root) { 00165 nassertv(_mode == M_idle); 00166 nassertv(_unpack_data != NULL); 00167 00168 _mode = M_unpack; 00169 _parse_error = false; 00170 _pack_error = false; 00171 _range_error = false; 00172 00173 _root = root; 00174 _catalog = NULL; 00175 _live_catalog = NULL; 00176 00177 _current_field = root; 00178 _current_parent = NULL; 00179 _current_field_index = 0; 00180 _num_nested_fields = 0; 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: DCPacker::end_unpack 00185 // Access: Published 00186 // Description: Finishes the unpacking session. 00187 // 00188 // The return value is true on success, or false if 00189 // there has been some error during unpacking (or if all 00190 // fields have not been unpacked). 00191 //////////////////////////////////////////////////////////////////// 00192 bool DCPacker:: 00193 end_unpack() { 00194 nassertr(_mode == M_unpack, false); 00195 00196 _mode = M_idle; 00197 00198 if (_stack != NULL || _current_field != NULL || _current_parent != NULL) { 00199 // This happens if we have not unpacked all of the fields. 00200 // However, this is not an error if we have called seek() during 00201 // the unpack session (in which case the _catalog will be 00202 // non-NULL). On the other hand, if the catalog is still NULL, 00203 // then we have never called seek() and it is an error not to 00204 // unpack all values. 00205 if (_catalog == (DCPackerCatalog *)NULL) { 00206 _pack_error = true; 00207 } 00208 } 00209 00210 clear(); 00211 00212 return !had_error(); 00213 } 00214 00215 //////////////////////////////////////////////////////////////////// 00216 // Function: DCPacker::begin_repack 00217 // Access: Public 00218 // Description: Begins a repacking session. You must have previously 00219 // called set_unpack_data() to specify a buffer to 00220 // unpack. 00221 // 00222 // Unlike begin_pack() or begin_unpack() you may not 00223 // concatenate the results of multiple begin_repack() 00224 // sessions in one buffer. 00225 // 00226 // Also, unlike in packing or unpacking modes, you may 00227 // not walk through the fields from beginning to end, or 00228 // even pack two consecutive fields at once. Instead, 00229 // you must call seek() for each field you wish to 00230 // modify and pack only that one field; then call seek() 00231 // again to modify another field. 00232 //////////////////////////////////////////////////////////////////// 00233 void DCPacker:: 00234 begin_repack(const DCPackerInterface *root) { 00235 nassertv(_mode == M_idle); 00236 nassertv(_unpack_data != NULL); 00237 nassertv(_unpack_p == 0); 00238 00239 _mode = M_repack; 00240 _parse_error = false; 00241 _pack_error = false; 00242 _range_error = false; 00243 _pack_data.clear(); 00244 00245 // In repack mode, we immediately get the catalog, since we know 00246 // we'll need it. 00247 _root = root; 00248 _catalog = _root->get_catalog(); 00249 _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length); 00250 if (_live_catalog == NULL) { 00251 _pack_error = true; 00252 } 00253 00254 // We don't begin at the first field in repack mode. Instead, you 00255 // must explicitly call seek(). 00256 _current_field = NULL; 00257 _current_parent = NULL; 00258 _current_field_index = 0; 00259 _num_nested_fields = 0; 00260 } 00261 00262 //////////////////////////////////////////////////////////////////// 00263 // Function: DCPacker::end_repack 00264 // Access: Published 00265 // Description: Finishes the repacking session. 00266 // 00267 // The return value is true on success, or false if 00268 // there has been some error during repacking (or if all 00269 // fields have not been repacked). 00270 //////////////////////////////////////////////////////////////////// 00271 bool DCPacker:: 00272 end_repack() { 00273 nassertr(_mode == M_repack, false); 00274 00275 // Put the rest of the data onto the pack stream. 00276 _pack_data.append_data(_unpack_data + _unpack_p, _unpack_length - _unpack_p); 00277 00278 _mode = M_idle; 00279 clear(); 00280 00281 return !had_error(); 00282 } 00283 00284 //////////////////////////////////////////////////////////////////// 00285 // Function: DCPacker::seek 00286 // Access: Published 00287 // Description: Sets the current unpack (or repack) position to the 00288 // named field. In unpack mode, the next call to 00289 // unpack_*() or push() will begin to read the named 00290 // field. In repack mode, the next call to pack_*() or 00291 // push() will modify the named field. 00292 // 00293 // Returns true if successful, false if the field is not 00294 // known (or if the packer is in an invalid mode). 00295 //////////////////////////////////////////////////////////////////// 00296 bool DCPacker:: 00297 seek(const string &field_name) { 00298 if (_catalog == (DCPackerCatalog *)NULL) { 00299 _catalog = _root->get_catalog(); 00300 _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length); 00301 } 00302 nassertr(_catalog != (DCPackerCatalog *)NULL, false); 00303 if (_live_catalog == NULL) { 00304 _pack_error = true; 00305 return false; 00306 } 00307 00308 int seek_index = _live_catalog->find_entry_by_name(field_name); 00309 if (seek_index < 0) { 00310 // The field was not known. 00311 _pack_error = true; 00312 return false; 00313 } 00314 00315 return seek(seek_index); 00316 } 00317 00318 //////////////////////////////////////////////////////////////////// 00319 // Function: DCPacker::seek 00320 // Access: Published 00321 // Description: Seeks to the field indentified by seek_index, which 00322 // was returned by an earlier call to 00323 // DCField::find_seek_index() to get the index of some 00324 // nested field. Also see the version of seek() that 00325 // accepts a field name. 00326 // 00327 // Returns true if successful, false if the field is not 00328 // known (or if the packer is in an invalid mode). 00329 //////////////////////////////////////////////////////////////////// 00330 bool DCPacker:: 00331 seek(int seek_index) { 00332 if (_catalog == (DCPackerCatalog *)NULL) { 00333 _catalog = _root->get_catalog(); 00334 _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length); 00335 } 00336 nassertr(_catalog != (DCPackerCatalog *)NULL, false); 00337 if (_live_catalog == NULL) { 00338 _pack_error = true; 00339 return false; 00340 } 00341 00342 if (_mode == M_unpack) { 00343 const DCPackerCatalog::Entry &entry = _live_catalog->get_entry(seek_index); 00344 00345 // If we are seeking, we don't need to remember our current stack 00346 // position. 00347 clear_stack(); 00348 _current_field = entry._field; 00349 _current_parent = entry._parent; 00350 _current_field_index = entry._field_index; 00351 _num_nested_fields = _current_parent->get_num_nested_fields(); 00352 _unpack_p = _live_catalog->get_begin(seek_index); 00353 00354 // We don't really need _push_marker and _pop_marker now, except 00355 // that we should set _push_marker in case we have just seeked to 00356 // a switch parameter, and we should set _pop_marker to 0 just so 00357 // it won't get in the way. 00358 _push_marker = _unpack_p; 00359 _pop_marker = 0; 00360 00361 return true; 00362 00363 } else if (_mode == M_repack) { 00364 nassertr(_catalog != (DCPackerCatalog *)NULL, false); 00365 00366 if (_stack != NULL || _current_field != NULL) { 00367 // It is an error to reseek while the stack is nonempty--that 00368 // means we haven't finished packing the current field. 00369 _pack_error = true; 00370 return false; 00371 } 00372 const DCPackerCatalog::Entry &entry = _live_catalog->get_entry(seek_index); 00373 00374 if (entry._parent->as_switch_parameter() != (DCSwitchParameter *)NULL) { 00375 // If the parent is a DCSwitch, that can only mean that the 00376 // seeked field is a switch parameter. We can't support seeking 00377 // to a switch parameter and modifying it directly--what would 00378 // happen to all of the related fields? Instead, you'll have to 00379 // seek to the switch itself and repack the whole entity. 00380 _pack_error = true; 00381 return false; 00382 } 00383 00384 size_t begin = _live_catalog->get_begin(seek_index); 00385 if (begin < _unpack_p) { 00386 // Whoops, we are seeking fields out-of-order. That means we 00387 // need to write the entire record and start again. 00388 _pack_data.append_data(_unpack_data + _unpack_p, _unpack_length - _unpack_p); 00389 size_t length = _pack_data.get_length(); 00390 char *buffer = _pack_data.take_data(); 00391 set_unpack_data(buffer, length, true); 00392 _unpack_p = 0; 00393 00394 _catalog->release_live_catalog(_live_catalog); 00395 _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length); 00396 00397 if (_live_catalog == NULL) { 00398 _pack_error = true; 00399 return false; 00400 } 00401 00402 begin = _live_catalog->get_begin(seek_index); 00403 } 00404 00405 // Now copy the bytes from _unpack_p to begin from the 00406 // _unpack_data to the _pack_data. These are the bytes we just 00407 // skipped over with the call to seek(). 00408 _pack_data.append_data(_unpack_data + _unpack_p, begin - _unpack_p); 00409 00410 // And set the packer up to pack the indicated field (but no 00411 // subsequent fields). 00412 _current_field = entry._field; 00413 _current_parent = entry._parent; 00414 _current_field_index = entry._field_index; 00415 _num_nested_fields = 1; 00416 _unpack_p = _live_catalog->get_end(seek_index); 00417 00418 // Set up push_marker and pop_marker so we won't try to advance 00419 // beyond this field. 00420 _push_marker = begin; 00421 _pop_marker = _live_catalog->get_end(seek_index); 00422 00423 return true; 00424 } 00425 00426 // Invalid mode. 00427 _pack_error = true; 00428 return false; 00429 } 00430 00431 //////////////////////////////////////////////////////////////////// 00432 // Function: DCPacker::push 00433 // Access: Published 00434 // Description: Marks the beginning of a nested series of fields. 00435 // 00436 // This must be called before filling the elements of an 00437 // array or the individual fields in a structure field. 00438 // It must also be balanced by a matching pop(). 00439 // 00440 // It is necessary to use push() / pop() only if 00441 // has_nested_fields() returns true. 00442 //////////////////////////////////////////////////////////////////// 00443 void DCPacker:: 00444 push() { 00445 if (!has_nested_fields()) { 00446 _pack_error = true; 00447 00448 } else { 00449 StackElement *element = new StackElement; 00450 element->_current_parent = _current_parent; 00451 element->_current_field_index = _current_field_index; 00452 element->_push_marker = _push_marker; 00453 element->_pop_marker = _pop_marker; 00454 element->_next = _stack; 00455 _stack = element; 00456 _current_parent = _current_field; 00457 00458 00459 // Now deal with the length prefix that might or might not be 00460 // before a sequence of nested fields. 00461 int num_nested_fields = _current_parent->get_num_nested_fields(); 00462 size_t length_bytes = _current_parent->get_num_length_bytes(); 00463 00464 if (_mode == M_pack || _mode == M_repack) { 00465 // Reserve length_bytes for when we figure out what the length 00466 // is. 00467 _push_marker = _pack_data.get_length(); 00468 _pop_marker = 0; 00469 _pack_data.append_junk(length_bytes); 00470 00471 } else if (_mode == M_unpack) { 00472 // Read length_bytes to determine the end of this nested 00473 // sequence. 00474 _push_marker = _unpack_p; 00475 _pop_marker = 0; 00476 00477 if (length_bytes != 0) { 00478 if (_unpack_p + length_bytes > _unpack_length) { 00479 _pack_error = true; 00480 00481 } else { 00482 size_t length; 00483 if (length_bytes == 4) { 00484 length = DCPackerInterface::do_unpack_uint32 00485 (_unpack_data + _unpack_p); 00486 _unpack_p += 4; 00487 } else { 00488 length = DCPackerInterface::do_unpack_uint16 00489 (_unpack_data + _unpack_p); 00490 _unpack_p += 2; 00491 } 00492 _pop_marker = _unpack_p + length; 00493 00494 // The explicit length trumps the number of nested fields 00495 // reported by get_num_nested_fields(). 00496 if (length == 0) { 00497 num_nested_fields = 0; 00498 } else { 00499 num_nested_fields = _current_parent->calc_num_nested_fields(length); 00500 } 00501 } 00502 } 00503 } else { 00504 _pack_error = true; 00505 } 00506 00507 00508 // Now point to the first field in the nested range. 00509 _num_nested_fields = num_nested_fields; 00510 _current_field_index = 0; 00511 00512 if (_num_nested_fields >= 0 && 00513 _current_field_index >= _num_nested_fields) { 00514 _current_field = NULL; 00515 00516 } else { 00517 _current_field = _current_parent->get_nested_field(_current_field_index); 00518 } 00519 } 00520 } 00521 00522 //////////////////////////////////////////////////////////////////// 00523 // Function: DCPacker::pop 00524 // Access: Published 00525 // Description: Marks the end of a nested series of fields. 00526 // 00527 // This must be called to match a previous push() only 00528 // after all the expected number of nested fields have 00529 // been packed. It is an error to call it too early, or 00530 // too late. 00531 //////////////////////////////////////////////////////////////////// 00532 void DCPacker:: 00533 pop() { 00534 if (_current_field != NULL && _num_nested_fields >= 0) { 00535 // Oops, didn't pack or unpack enough values. 00536 _pack_error = true; 00537 00538 } else if (_mode == M_unpack && _pop_marker != 0 && 00539 _unpack_p != _pop_marker) { 00540 // Didn't unpack the right number of values. 00541 _pack_error = true; 00542 } 00543 00544 if (_stack == NULL) { 00545 // Unbalanced pop(). 00546 _pack_error = true; 00547 00548 } else { 00549 if (!_current_parent->validate_num_nested_fields(_current_field_index)) { 00550 // Incorrect number of nested elements. 00551 _pack_error = true; 00552 } 00553 00554 if (_mode == M_pack || _mode == M_repack) { 00555 size_t length_bytes = _current_parent->get_num_length_bytes(); 00556 if (length_bytes != 0) { 00557 // Now go back and fill in the length of the array. 00558 size_t length = _pack_data.get_length() - _push_marker - length_bytes; 00559 if (length_bytes == 4) { 00560 DCPackerInterface::do_pack_uint32 00561 (_pack_data.get_rewrite_pointer(_push_marker, 4), length); 00562 } else { 00563 DCPackerInterface::validate_uint_limits(length, 16, _range_error); 00564 DCPackerInterface::do_pack_uint16 00565 (_pack_data.get_rewrite_pointer(_push_marker, 2), length); 00566 } 00567 } 00568 } 00569 00570 _current_field = _current_parent; 00571 _current_parent = _stack->_current_parent; 00572 _current_field_index = _stack->_current_field_index; 00573 _push_marker = _stack->_push_marker; 00574 _pop_marker = _stack->_pop_marker; 00575 _num_nested_fields = (_current_parent == NULL) ? 0 : _current_parent->get_num_nested_fields(); 00576 00577 StackElement *next = _stack->_next; 00578 delete _stack; 00579 _stack = next; 00580 } 00581 00582 advance(); 00583 } 00584 00585 //////////////////////////////////////////////////////////////////// 00586 // Function: DCPacker::pack_default_value 00587 // Access: Published 00588 // Description: Adds the default value for the current element into 00589 // the stream. If no default has been set for the 00590 // current element, creates a sensible default. 00591 //////////////////////////////////////////////////////////////////// 00592 void DCPacker:: 00593 pack_default_value() { 00594 nassertv(_mode == M_pack || _mode == M_repack); 00595 if (_current_field == NULL) { 00596 _pack_error = true; 00597 } else { 00598 if (_current_field->pack_default_value(_pack_data, _pack_error)) { 00599 advance(); 00600 00601 } else { 00602 // If the single field didn't know how to pack a default value, 00603 // try packing nested fields. 00604 push(); 00605 while (more_nested_fields()) { 00606 pack_default_value(); 00607 } 00608 pop(); 00609 } 00610 } 00611 } 00612 00613 //////////////////////////////////////////////////////////////////// 00614 // Function: DCPacker::unpack_validate 00615 // Access: Published 00616 // Description: Internally unpacks the current numeric or string 00617 // value and validates it against the type range limits, 00618 // but does not return the value. If the current field 00619 // contains nested fields, validates all of them. 00620 //////////////////////////////////////////////////////////////////// 00621 void DCPacker:: 00622 unpack_validate() { 00623 nassertv(_mode == M_unpack); 00624 if (_current_field == NULL) { 00625 _pack_error = true; 00626 00627 } else { 00628 if (_current_field->unpack_validate(_unpack_data, _unpack_length, _unpack_p, 00629 _pack_error, _range_error)) { 00630 advance(); 00631 } else { 00632 // If the single field couldn't be validated, try validating 00633 // nested fields. 00634 push(); 00635 while (more_nested_fields()) { 00636 unpack_validate(); 00637 } 00638 pop(); 00639 } 00640 } 00641 } 00642 00643 //////////////////////////////////////////////////////////////////// 00644 // Function: DCPacker::unpack_skip 00645 // Access: Published 00646 // Description: Skips the current field without unpacking it and 00647 // advances to the next field. If the current field 00648 // contains nested fields, skips all of them. 00649 //////////////////////////////////////////////////////////////////// 00650 void DCPacker:: 00651 unpack_skip() { 00652 nassertv(_mode == M_unpack); 00653 if (_current_field == NULL) { 00654 _pack_error = true; 00655 00656 } else { 00657 if (_current_field->unpack_skip(_unpack_data, _unpack_length, _unpack_p, 00658 _pack_error)) { 00659 advance(); 00660 00661 } else { 00662 // If the single field couldn't be skipped, try skipping nested fields. 00663 push(); 00664 while (more_nested_fields()) { 00665 unpack_skip(); 00666 } 00667 pop(); 00668 } 00669 } 00670 } 00671 00672 #ifdef HAVE_PYTHON 00673 //////////////////////////////////////////////////////////////////// 00674 // Function: DCPacker::pack_object 00675 // Access: Published 00676 // Description: Packs the Python object of whatever type into the 00677 // packer. Each numeric object and string object maps 00678 // to the corresponding pack_value() call; a tuple or 00679 // sequence maps to a push() followed by all of the 00680 // tuple's contents followed by a pop(). 00681 //////////////////////////////////////////////////////////////////// 00682 void DCPacker:: 00683 pack_object(PyObject *object) { 00684 nassertv(_mode == M_pack || _mode == M_repack); 00685 DCPackType pack_type = get_pack_type(); 00686 00687 // had to add this for basic 64 and unsigned data to get packed right .. 00688 // Not sure if we can just do the rest this way.. 00689 00690 switch(pack_type) 00691 { 00692 case PT_int64: 00693 if(PyLong_Check(object)) 00694 { 00695 pack_int64(PyLong_AsLongLong(object)); 00696 return; 00697 } 00698 else if (PyInt_Check(object)) 00699 { 00700 pack_int64(PyInt_AsLong(object)); 00701 return; 00702 } 00703 break; 00704 case PT_uint64: 00705 if(PyLong_Check(object)) 00706 { 00707 pack_uint64(PyLong_AsUnsignedLongLong(object)); 00708 return; 00709 } 00710 else if(PyInt_Check(object)) 00711 { 00712 PyObject *obj1 = PyNumber_Long(object); 00713 pack_int(PyLong_AsUnsignedLongLong(obj1)); 00714 Py_DECREF(obj1); 00715 return; 00716 } 00717 break; 00718 case PT_int: 00719 if(PyLong_Check(object)) 00720 { 00721 pack_int(PyLong_AsLong(object)); 00722 return; 00723 } 00724 else if (PyInt_Check(object)) 00725 { 00726 pack_int(PyInt_AsLong(object)); 00727 return; 00728 } 00729 break; 00730 case PT_uint: 00731 if(PyLong_Check(object)) 00732 { 00733 pack_uint(PyLong_AsUnsignedLong(object)); 00734 return; 00735 } 00736 else if (PyInt_Check(object)) 00737 { 00738 PyObject *obj1 = PyNumber_Long(object); 00739 pack_uint(PyLong_AsUnsignedLong(obj1)); 00740 Py_DECREF(obj1); 00741 return; 00742 } 00743 break; 00744 default: 00745 break; 00746 } 00747 #ifdef USE_PYTHON_2_2_OR_EARLIER 00748 if (PyInt_Check(object)) { 00749 #else 00750 if (PyLong_Check(object)) { 00751 pack_int(PyLong_AsLong(object)); 00752 } else if (PyInt_Check(object)) { 00753 #endif 00754 pack_int(PyInt_AS_LONG(object)); 00755 } else if (PyFloat_Check(object)) { 00756 pack_double(PyFloat_AS_DOUBLE(object)); 00757 } else if (PyLong_Check(object)) { 00758 pack_int64(PyLong_AsLongLong(object)); 00759 } else if (PyString_Check(object) || PyUnicode_Check(object)) { 00760 char *buffer; 00761 Py_ssize_t length; 00762 PyString_AsStringAndSize(object, &buffer, &length); 00763 if (buffer) { 00764 pack_string(string(buffer, length)); 00765 } 00766 } else { 00767 // For some reason, PySequence_Check() is incorrectly reporting 00768 // that a class instance is a sequence, even if it doesn't provide 00769 // __len__, so we double-check by testing for __len__ explicitly. 00770 bool is_sequence = 00771 (PySequence_Check(object) != 0) && 00772 (PyObject_HasAttrString(object, "__len__") != 0); 00773 bool is_instance = false; 00774 00775 const DCClass *dclass = NULL; 00776 const DCPackerInterface *current_field = get_current_field(); 00777 if (current_field != (DCPackerInterface *)NULL) { 00778 const DCClassParameter *class_param = get_current_field()->as_class_parameter(); 00779 if (class_param != (DCClassParameter *)NULL) { 00780 dclass = class_param->get_class(); 00781 00782 if (dclass->has_class_def()) { 00783 PyObject *class_def = dclass->get_class_def(); 00784 is_instance = (PyObject_IsInstance(object, dclass->get_class_def()) != 0); 00785 Py_DECREF(class_def); 00786 } 00787 } 00788 } 00789 00790 // If dclass is not NULL, the packer is expecting a class object. 00791 // There are then two cases: (1) the user has supplied a matching 00792 // class object, or (2) the user has supplied a sequence object. 00793 // Unfortunately, it may be difficult to differentiate these two 00794 // cases, since a class object may also be a sequence object. 00795 00796 // The rule to differentiate them is: 00797 00798 // (1) If the supplied class object is an instance of the expected 00799 // class object, it is considered to be a class object. 00800 00801 // (2) Otherwise, if the supplied class object has a __len__() 00802 // method (i.e. PySequence_Check() returns true), then it is 00803 // considered to be a sequence. 00804 00805 // (3) Otherwise, it is considered to be a class object. 00806 00807 if (dclass != (DCClass *)NULL && (is_instance || !is_sequence)) { 00808 // The supplied object is either an instance of the expected 00809 // class object, or it is not a sequence--this is case (1) or 00810 // (3). 00811 pack_class_object(dclass, object); 00812 } else if (is_sequence) { 00813 // The supplied object is not an instance of the expected class 00814 // object, but it is a sequence. This is case (2). 00815 push(); 00816 int size = PySequence_Size(object); 00817 for (int i = 0; i < size; ++i) { 00818 PyObject *element = PySequence_GetItem(object, i); 00819 if (element != (PyObject *)NULL) { 00820 pack_object(element); 00821 Py_DECREF(element); 00822 } else { 00823 cerr << "Unable to extract item " << i << " from sequence.\n"; 00824 } 00825 } 00826 pop(); 00827 } else { 00828 // The supplied object is not a sequence, and we weren't 00829 // expecting a class parameter. This is none of the above, an 00830 // error. 00831 ostringstream strm; 00832 strm << "Don't know how to pack object: " 00833 << DCField::get_pystr(object); 00834 nassert_raise(strm.str()); 00835 _pack_error = true; 00836 } 00837 } 00838 } 00839 #endif // HAVE_PYTHON 00840 00841 #ifdef HAVE_PYTHON 00842 //////////////////////////////////////////////////////////////////// 00843 // Function: DCPacker::unpack_object 00844 // Access: Published 00845 // Description: Unpacks a Python object of the appropriate type from 00846 // the stream for the current field. This may be an 00847 // integer or a string for a simple field object; if the 00848 // current field represents a list of fields it will be 00849 // a tuple. 00850 //////////////////////////////////////////////////////////////////// 00851 PyObject *DCPacker:: 00852 unpack_object() { 00853 PyObject *object = NULL; 00854 00855 DCPackType pack_type = get_pack_type(); 00856 00857 switch (pack_type) { 00858 case PT_invalid: 00859 object = Py_None; 00860 Py_INCREF(object); 00861 unpack_skip(); 00862 break; 00863 00864 case PT_double: 00865 { 00866 double value = unpack_double(); 00867 object = PyFloat_FromDouble(value); 00868 } 00869 break; 00870 00871 case PT_int: 00872 { 00873 int value = unpack_int(); 00874 object = PyInt_FromLong(value); 00875 } 00876 break; 00877 00878 case PT_uint: 00879 { 00880 unsigned int value = unpack_uint(); 00881 if (value & 0x80000000) { 00882 object = PyLong_FromUnsignedLong(value); 00883 } else { 00884 object = PyInt_FromLong(value); 00885 } 00886 } 00887 break; 00888 00889 case PT_int64: 00890 { 00891 PN_int64 value = unpack_int64(); 00892 object = PyLong_FromLongLong(value); 00893 } 00894 break; 00895 00896 case PT_uint64: 00897 { 00898 PN_uint64 value = unpack_uint64(); 00899 object = PyLong_FromUnsignedLongLong(value); 00900 } 00901 break; 00902 00903 case PT_string: 00904 case PT_blob: 00905 { 00906 string str; 00907 unpack_string(str); 00908 object = PyString_FromStringAndSize(str.data(), str.size()); 00909 } 00910 break; 00911 00912 case PT_class: 00913 { 00914 const DCClassParameter *class_param = get_current_field()->as_class_parameter(); 00915 if (class_param != (DCClassParameter *)NULL) { 00916 const DCClass *dclass = class_param->get_class(); 00917 if (dclass->has_class_def()) { 00918 // If we know what kind of class object this is and it has a 00919 // valid constructor, create the class object instead of 00920 // just a tuple. 00921 object = unpack_class_object(dclass); 00922 if (object == (PyObject *)NULL) { 00923 cerr << "Unable to construct object of class " 00924 << dclass->get_name() << "\n"; 00925 } else { 00926 break; 00927 } 00928 } 00929 } 00930 } 00931 // Fall through (if no constructor) 00932 00933 // If we don't know what kind of class object it is, or it doesn't 00934 // have a constructor, fall through and make a tuple. 00935 default: 00936 { 00937 // First, build up a list from the nested objects. 00938 object = PyList_New(0); 00939 00940 push(); 00941 while (more_nested_fields()) { 00942 PyObject *element = unpack_object(); 00943 PyList_Append(object, element); 00944 Py_DECREF(element); 00945 } 00946 pop(); 00947 00948 if (pack_type != PT_array) { 00949 // For these other kinds of objects, we'll convert the list 00950 // into a tuple. 00951 PyObject *tuple = PyList_AsTuple(object); 00952 Py_DECREF(object); 00953 object = tuple; 00954 } 00955 } 00956 break; 00957 } 00958 00959 nassertr(object != (PyObject *)NULL, NULL); 00960 return object; 00961 } 00962 #endif // HAVE_PYTHON 00963 00964 00965 //////////////////////////////////////////////////////////////////// 00966 // Function: DCPacker::parse_and_pack 00967 // Access: Published 00968 // Description: Parses an object's value according to the DC file 00969 // syntax (e.g. as a default value string) and packs it. 00970 // Returns true on success, false on a parse error. 00971 //////////////////////////////////////////////////////////////////// 00972 bool DCPacker:: 00973 parse_and_pack(const string &formatted_object) { 00974 istringstream strm(formatted_object); 00975 return parse_and_pack(strm); 00976 } 00977 00978 //////////////////////////////////////////////////////////////////// 00979 // Function: DCPacker::parse_and_pack 00980 // Access: Published 00981 // Description: Parses an object's value according to the DC file 00982 // syntax (e.g. as a default value string) and packs it. 00983 // Returns true on success, false on a parse error. 00984 //////////////////////////////////////////////////////////////////// 00985 bool DCPacker:: 00986 parse_and_pack(istream &in) { 00987 dc_init_parser_parameter_value(in, "parse_and_pack", *this); 00988 dcyyparse(); 00989 dc_cleanup_parser(); 00990 00991 bool parse_error = (dc_error_count() != 0); 00992 if (parse_error) { 00993 _parse_error = true; 00994 } 00995 00996 return !parse_error; 00997 } 00998 00999 //////////////////////////////////////////////////////////////////// 01000 // Function: DCPacker::unpack_and_format 01001 // Access: Published 01002 // Description: Unpacks an object and formats its value into a syntax 01003 // suitable for parsing in the dc file (e.g. as a 01004 // default value), or as an input to parse_object. 01005 //////////////////////////////////////////////////////////////////// 01006 string DCPacker:: 01007 unpack_and_format(bool show_field_names) { 01008 ostringstream strm; 01009 unpack_and_format(strm, show_field_names); 01010 return strm.str(); 01011 } 01012 01013 //////////////////////////////////////////////////////////////////// 01014 // Function: DCPacker::unpack_and_format 01015 // Access: Published 01016 // Description: Unpacks an object and formats its value into a syntax 01017 // suitable for parsing in the dc file (e.g. as a 01018 // default value), or as an input to parse_object. 01019 //////////////////////////////////////////////////////////////////// 01020 void DCPacker:: 01021 unpack_and_format(ostream &out, bool show_field_names) { 01022 DCPackType pack_type = get_pack_type(); 01023 01024 if (show_field_names && !get_current_field_name().empty()) { 01025 nassertv(_current_field != (DCPackerInterface *)NULL); 01026 const DCField *field = _current_field->as_field(); 01027 if (field != (DCField *)NULL && 01028 field->as_parameter() != (DCParameter *)NULL) { 01029 out << field->get_name() << " = "; 01030 } 01031 } 01032 01033 switch (pack_type) { 01034 case PT_invalid: 01035 out << "<invalid>"; 01036 break; 01037 01038 case PT_double: 01039 out << unpack_double(); 01040 break; 01041 01042 case PT_int: 01043 out << unpack_int(); 01044 break; 01045 01046 case PT_uint: 01047 out << unpack_uint(); 01048 break; 01049 01050 case PT_int64: 01051 out << unpack_int64(); 01052 break; 01053 01054 case PT_uint64: 01055 out << unpack_uint64(); 01056 break; 01057 01058 case PT_string: 01059 enquote_string(out, '"', unpack_string()); 01060 break; 01061 01062 case PT_blob: 01063 output_hex_string(out, unpack_literal_value()); 01064 break; 01065 01066 default: 01067 { 01068 switch (pack_type) { 01069 case PT_array: 01070 out << '['; 01071 break; 01072 01073 case PT_field: 01074 case PT_switch: 01075 out << '('; 01076 break; 01077 01078 case PT_class: 01079 default: 01080 out << '{'; 01081 break; 01082 } 01083 01084 push(); 01085 while (more_nested_fields() && !had_pack_error()) { 01086 unpack_and_format(out, show_field_names); 01087 01088 if (more_nested_fields()) { 01089 out << ", "; 01090 } 01091 } 01092 pop(); 01093 01094 switch (pack_type) { 01095 case PT_array: 01096 out << ']'; 01097 break; 01098 01099 case PT_field: 01100 case PT_switch: 01101 out << ')'; 01102 break; 01103 01104 case PT_class: 01105 default: 01106 out << '}'; 01107 break; 01108 } 01109 } 01110 break; 01111 } 01112 } 01113 01114 //////////////////////////////////////////////////////////////////// 01115 // Function: DCPacker::enquote_string 01116 // Access: Public, Static 01117 // Description: Outputs the indicated string within quotation marks. 01118 //////////////////////////////////////////////////////////////////// 01119 void DCPacker:: 01120 enquote_string(ostream &out, char quote_mark, const string &str) { 01121 out << quote_mark; 01122 for (string::const_iterator pi = str.begin(); 01123 pi != str.end(); 01124 ++pi) { 01125 if ((*pi) == quote_mark || (*pi) == '\\') { 01126 out << '\\' << (*pi); 01127 01128 } else if (!isprint(*pi)) { 01129 char buffer[10]; 01130 sprintf(buffer, "%02x", (unsigned char)(*pi)); 01131 out << "\\x" << buffer; 01132 01133 } else { 01134 out << (*pi); 01135 } 01136 } 01137 out << quote_mark; 01138 } 01139 01140 //////////////////////////////////////////////////////////////////// 01141 // Function: DCPacker::output_hex_string 01142 // Access: Public, Static 01143 // Description: Outputs the indicated string as a hex constant. 01144 //////////////////////////////////////////////////////////////////// 01145 void DCPacker:: 01146 output_hex_string(ostream &out, const string &str) { 01147 out << '<'; 01148 for (string::const_iterator pi = str.begin(); 01149 pi != str.end(); 01150 ++pi) { 01151 char buffer[10]; 01152 sprintf(buffer, "%02x", (unsigned char)(*pi)); 01153 out << buffer; 01154 } 01155 out << '>'; 01156 } 01157 01158 //////////////////////////////////////////////////////////////////// 01159 // Function: DCPacker::handle_switch 01160 // Access: Private 01161 // Description: When we advance past the key field on a switch 01162 // record, we suddenly have more fields available--all 01163 // the appropriate alternate fields in the switch. 01164 // 01165 // This function is called when we detect this 01166 // condition; it switches the _current_parent to the 01167 // appropriate case of the switch record. 01168 //////////////////////////////////////////////////////////////////// 01169 void DCPacker:: 01170 handle_switch(const DCSwitchParameter *switch_parameter) { 01171 // First, get the value from the key. This is either found in the 01172 // unpack or the pack data, depending on what mode we're in. 01173 const DCPackerInterface *new_parent = NULL; 01174 01175 if (_mode == M_pack || _mode == M_repack) { 01176 const char *data = _pack_data.get_data(); 01177 new_parent = switch_parameter->apply_switch 01178 (data + _push_marker, _pack_data.get_length() - _push_marker); 01179 01180 } else if (_mode == M_unpack) { 01181 new_parent = switch_parameter->apply_switch 01182 (_unpack_data + _push_marker, _unpack_p - _push_marker); 01183 } 01184 01185 if (new_parent == (DCPackerInterface *)NULL) { 01186 // This means an invalid value was packed for the key. 01187 _range_error = true; 01188 return; 01189 } 01190 01191 _last_switch = switch_parameter; 01192 01193 // Now substitute in the switch case for the previous parent (which 01194 // replaces the switch node itself). This will suddenly make a slew 01195 // of new fields appear. 01196 _current_parent = new_parent; 01197 _num_nested_fields = _current_parent->get_num_nested_fields(); 01198 01199 if (_num_nested_fields < 0 || 01200 _current_field_index < _num_nested_fields) { 01201 _current_field = _current_parent->get_nested_field(_current_field_index); 01202 } 01203 } 01204 01205 //////////////////////////////////////////////////////////////////// 01206 // Function: DCPacker::clear 01207 // Access: Private 01208 // Description: Resets the data structures after a pack or unpack 01209 // sequence. 01210 //////////////////////////////////////////////////////////////////// 01211 void DCPacker:: 01212 clear() { 01213 clear_stack(); 01214 _current_field = NULL; 01215 _current_parent = NULL; 01216 _current_field_index = 0; 01217 _num_nested_fields = 0; 01218 _push_marker = 0; 01219 _pop_marker = 0; 01220 _last_switch = NULL; 01221 01222 if (_live_catalog != (DCPackerCatalog::LiveCatalog *)NULL) { 01223 _catalog->release_live_catalog(_live_catalog); 01224 _live_catalog = NULL; 01225 } 01226 _catalog = NULL; 01227 _root = NULL; 01228 } 01229 01230 //////////////////////////////////////////////////////////////////// 01231 // Function: DCPacker::clear_stack 01232 // Access: Private 01233 // Description: Empties the stack. 01234 //////////////////////////////////////////////////////////////////// 01235 void DCPacker:: 01236 clear_stack() { 01237 while (_stack != (StackElement *)NULL) { 01238 StackElement *next = _stack->_next; 01239 delete _stack; 01240 _stack = next; 01241 } 01242 } 01243 01244 #ifdef HAVE_PYTHON 01245 //////////////////////////////////////////////////////////////////// 01246 // Function: DCPacker::pack_class_object 01247 // Access: Private 01248 // Description: Given that the current element is a ClassParameter 01249 // for a Python class object, try to extract the 01250 // appropriate values from the class object and pack in. 01251 //////////////////////////////////////////////////////////////////// 01252 void DCPacker:: 01253 pack_class_object(const DCClass *dclass, PyObject *object) { 01254 push(); 01255 while (more_nested_fields() && !_pack_error) { 01256 const DCField *field = get_current_field()->as_field(); 01257 nassertv(field != (DCField *)NULL); 01258 get_class_element(dclass, object, field); 01259 } 01260 pop(); 01261 } 01262 #endif // HAVE_PYTHON 01263 01264 #ifdef HAVE_PYTHON 01265 //////////////////////////////////////////////////////////////////// 01266 // Function: DCPacker::unpack_class_object 01267 // Access: Private 01268 // Description: Given that the current element is a ClassParameter 01269 // for a Python class for which we have a valid 01270 // constructor, unpack it and fill in its values. 01271 //////////////////////////////////////////////////////////////////// 01272 PyObject *DCPacker:: 01273 unpack_class_object(const DCClass *dclass) { 01274 PyObject *class_def = dclass->get_class_def(); 01275 nassertr(class_def != (PyObject *)NULL, NULL); 01276 01277 PyObject *object = NULL; 01278 01279 if (!dclass->has_constructor()) { 01280 // If the class uses a default constructor, go ahead and create 01281 // the Python object for it now. 01282 object = PyObject_CallObject(class_def, NULL); 01283 if (object == (PyObject *)NULL) { 01284 return NULL; 01285 } 01286 } 01287 01288 push(); 01289 if (object == (PyObject *)NULL && more_nested_fields()) { 01290 // The first nested field will be the constructor. 01291 const DCField *field = get_current_field()->as_field(); 01292 nassertr(field != (DCField *)NULL, object); 01293 nassertr(field == dclass->get_constructor(), object); 01294 01295 set_class_element(class_def, object, field); 01296 01297 // By now, the object should have been constructed. 01298 if (object == (PyObject *)NULL) { 01299 return NULL; 01300 } 01301 } 01302 while (more_nested_fields()) { 01303 const DCField *field = get_current_field()->as_field(); 01304 nassertr(field != (DCField *)NULL, object); 01305 01306 set_class_element(class_def, object, field); 01307 } 01308 pop(); 01309 01310 return object; 01311 } 01312 #endif // HAVE_PYTHON 01313 01314 01315 #ifdef HAVE_PYTHON 01316 //////////////////////////////////////////////////////////////////// 01317 // Function: DCPacker::set_class_element 01318 // Access: Private 01319 // Description: Unpacks the current element and stuffs it on the 01320 // Python class object in whatever way is appropriate. 01321 //////////////////////////////////////////////////////////////////// 01322 void DCPacker:: 01323 set_class_element(PyObject *class_def, PyObject *&object, 01324 const DCField *field) { 01325 string field_name = field->get_name(); 01326 DCPackType pack_type = get_pack_type(); 01327 01328 if (field_name.empty()) { 01329 switch (pack_type) { 01330 case PT_class: 01331 case PT_switch: 01332 // If the field has no name, but it is one of these container 01333 // objects, we want to unpack its nested objects directly into 01334 // the class. 01335 push(); 01336 while (more_nested_fields()) { 01337 const DCField *field = get_current_field()->as_field(); 01338 nassertv(field != (DCField *)NULL); 01339 nassertv(object != (PyObject *)NULL); 01340 set_class_element(class_def, object, field); 01341 } 01342 pop(); 01343 break; 01344 01345 default: 01346 // Otherwise, we just skip over the field. 01347 unpack_skip(); 01348 } 01349 01350 } else { 01351 // If the field does have a name, we will want to store it on the 01352 // class, either by calling a method (for a PT_field pack_type) or 01353 // by setting a value (for any other kind of pack_type). 01354 01355 PyObject *element = unpack_object(); 01356 01357 if (pack_type == PT_field) { 01358 if (object == (PyObject *)NULL) { 01359 // If the object hasn't been constructed yet, assume this is 01360 // the constructor. 01361 object = PyObject_CallObject(class_def, element); 01362 01363 } else { 01364 if (PyObject_HasAttrString(object, (char *)field_name.c_str())) { 01365 PyObject *func = PyObject_GetAttrString(object, (char *)field_name.c_str()); 01366 if (func != (PyObject *)NULL) { 01367 PyObject *result = PyObject_CallObject(func, element); 01368 Py_XDECREF(result); 01369 Py_DECREF(func); 01370 } 01371 } 01372 } 01373 01374 } else { 01375 nassertv(object != (PyObject *)NULL); 01376 PyObject_SetAttrString(object, (char *)field_name.c_str(), element); 01377 } 01378 01379 Py_DECREF(element); 01380 } 01381 } 01382 #endif // HAVE_PYTHON 01383 01384 01385 #ifdef HAVE_PYTHON 01386 //////////////////////////////////////////////////////////////////// 01387 // Function: DCPacker::get_class_element 01388 // Access: Private 01389 // Description: Gets the current element from the Python object and 01390 // packs it. 01391 //////////////////////////////////////////////////////////////////// 01392 void DCPacker:: 01393 get_class_element(const DCClass *dclass, PyObject *object, 01394 const DCField *field) { 01395 string field_name = field->get_name(); 01396 DCPackType pack_type = get_pack_type(); 01397 01398 if (field_name.empty()) { 01399 switch (pack_type) { 01400 case PT_class: 01401 case PT_switch: 01402 // If the field has no name, but it is one of these container 01403 // objects, we want to get its nested objects directly from 01404 // the class. 01405 push(); 01406 while (more_nested_fields() && !_pack_error) { 01407 const DCField *field = get_current_field()->as_field(); 01408 nassertv(field != (DCField *)NULL); 01409 get_class_element(dclass, object, field); 01410 } 01411 pop(); 01412 break; 01413 01414 default: 01415 // Otherwise, we just pack the default value. 01416 pack_default_value(); 01417 } 01418 01419 } else { 01420 // If the field does have a name, we will want to get it from the 01421 // class and pack it. It just so happens that there's already a 01422 // method that does this on DCClass. 01423 01424 if (!dclass->pack_required_field(*this, object, field)) { 01425 _pack_error = true; 01426 } 01427 } 01428 } 01429 #endif // HAVE_PYTHON