00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00028
00029
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
00049
00050
00051
00052 DCPacker::
00053 ~DCPacker() {
00054 clear_data();
00055 clear();
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
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
00092
00093
00094
00095
00096
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
00115
00116
00117
00118
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
00131
00132
00133
00134
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
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
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
00185
00186
00187
00188
00189
00190
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
00200
00201
00202
00203
00204
00205 if (_catalog == (DCPackerCatalog *)NULL) {
00206 _pack_error = true;
00207 }
00208 }
00209
00210 clear();
00211
00212 return !had_error();
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
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
00246
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
00255
00256 _current_field = NULL;
00257 _current_parent = NULL;
00258 _current_field_index = 0;
00259 _num_nested_fields = 0;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 bool DCPacker::
00272 end_repack() {
00273 nassertr(_mode == M_repack, false);
00274
00275
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
00286
00287
00288
00289
00290
00291
00292
00293
00294
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
00311 _pack_error = true;
00312 return false;
00313 }
00314
00315 return seek(seek_index);
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
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
00346
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
00355
00356
00357
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
00368
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
00376
00377
00378
00379
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
00387
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
00406
00407
00408 _pack_data.append_data(_unpack_data + _unpack_p, begin - _unpack_p);
00409
00410
00411
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
00419
00420 _push_marker = begin;
00421 _pop_marker = _live_catalog->get_end(seek_index);
00422
00423 return true;
00424 }
00425
00426
00427 _pack_error = true;
00428 return false;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
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
00460
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
00466
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
00473
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
00495
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
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
00524
00525
00526
00527
00528
00529
00530
00531
00532 void DCPacker::
00533 pop() {
00534 if (_current_field != NULL && _num_nested_fields >= 0) {
00535
00536 _pack_error = true;
00537
00538 } else if (_mode == M_unpack && _pop_marker != 0 &&
00539 _unpack_p != _pop_marker) {
00540
00541 _pack_error = true;
00542 }
00543
00544 if (_stack == NULL) {
00545
00546 _pack_error = true;
00547
00548 } else {
00549 if (!_current_parent->validate_num_nested_fields(_current_field_index)) {
00550
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
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
00587
00588
00589
00590
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
00603
00604 push();
00605 while (more_nested_fields()) {
00606 pack_default_value();
00607 }
00608 pop();
00609 }
00610 }
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
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
00633
00634 push();
00635 while (more_nested_fields()) {
00636 unpack_validate();
00637 }
00638 pop();
00639 }
00640 }
00641 }
00642
00643
00644
00645
00646
00647
00648
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
00663 push();
00664 while (more_nested_fields()) {
00665 unpack_skip();
00666 }
00667 pop();
00668 }
00669 }
00670 }
00671
00672 #ifdef HAVE_PYTHON
00673
00674
00675
00676
00677
00678
00679
00680
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
00688
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
00768
00769
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
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 if (dclass != (DCClass *)NULL && (is_instance || !is_sequence)) {
00808
00809
00810
00811 pack_class_object(dclass, object);
00812 } else if (is_sequence) {
00813
00814
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
00829
00830
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
00844
00845
00846
00847
00848
00849
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
00919
00920
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
00932
00933
00934
00935 default:
00936 {
00937
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
00950
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
00967
00968
00969
00970
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
00980
00981
00982
00983
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
01001
01002
01003
01004
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
01015
01016
01017
01018
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
01116
01117
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
01142
01143
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
01187 _range_error = true;
01188 return;
01189 }
01190
01191 _last_switch = switch_parameter;
01192
01193
01194
01195
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
01207
01208
01209
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
01232
01233
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
01247
01248
01249
01250
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
01267
01268
01269
01270
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
01281
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
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
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
01318
01319
01320
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
01333
01334
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
01347 unpack_skip();
01348 }
01349
01350 } else {
01351
01352
01353
01354
01355 PyObject *element = unpack_object();
01356
01357 if (pack_type == PT_field) {
01358 if (object == (PyObject *)NULL) {
01359
01360
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
01388
01389
01390
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
01403
01404
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
01416 pack_default_value();
01417 }
01418
01419 } else {
01420
01421
01422
01423
01424 if (!dclass->pack_required_field(*this, object, field)) {
01425 _pack_error = true;
01426 }
01427 }
01428 }
01429 #endif // HAVE_PYTHON