Panda3D
dcPacker.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file dcPacker.cxx
10  * @author drose
11  * @date 2004-06-15
12  */
13 
14 #include "dcPacker.h"
15 #include "dcSwitch.h"
16 #include "dcParserDefs.h"
17 #include "dcLexerDefs.h"
18 #include "dcClassParameter.h"
19 #include "dcSwitchParameter.h"
20 #include "dcClass.h"
21 
22 #ifdef HAVE_PYTHON
23 #include "py_panda.h"
24 #endif
25 
26 using std::istream;
27 using std::istringstream;
28 using std::ostream;
29 using std::ostringstream;
30 using std::string;
31 
32 DCPacker::StackElement *DCPacker::StackElement::_deleted_chain = nullptr;
33 int DCPacker::StackElement::_num_ever_allocated = 0;
34 
35 /**
36  *
37  */
38 DCPacker::
39 DCPacker() {
40  _mode = M_idle;
41  _unpack_data = nullptr;
42  _unpack_length = 0;
43  _owns_unpack_data = false;
44  _unpack_p = 0;
45  _live_catalog = nullptr;
46  _parse_error = false;
47  _pack_error = false;
48  _range_error = false;
49  _stack = nullptr;
50 
51  clear();
52 }
53 
54 /**
55  *
56  */
57 DCPacker::
58 ~DCPacker() {
59  clear_data();
60  clear();
61 }
62 
63 /**
64  * Begins a packing session. The parameter is the DC object that describes
65  * the packing format; it may be a DCParameter or DCField.
66  *
67  * Unless you call clear_data() between sessions, multiple packing sessions
68  * will be concatenated together into the same buffer. If you wish to add
69  * bytes to the buffer between packing sessions, use append_data() or
70  * get_write_pointer().
71  */
73 begin_pack(const DCPackerInterface *root) {
74  nassertv(_mode == M_idle);
75 
76  _mode = M_pack;
77  _parse_error = false;
78  _pack_error = false;
79  _range_error = false;
80 
81  _root = root;
82  _catalog = nullptr;
83  _live_catalog = nullptr;
84 
85  _current_field = root;
86  _current_parent = nullptr;
87  _current_field_index = 0;
88  _num_nested_fields = 0;
89 }
90 
91 /**
92  * Finishes a packing session.
93  *
94  * The return value is true on success, or false if there has been some error
95  * during packing.
96  */
98 end_pack() {
99  nassertr(_mode == M_pack, false);
100 
101  _mode = M_idle;
102 
103  if (_stack != nullptr || _current_field != nullptr || _current_parent != nullptr) {
104  _pack_error = true;
105  }
106 
107  clear();
108 
109  return !had_error();
110 }
111 
112 /**
113  * Sets up the unpack_data pointer. You may call this before calling the
114  * version of begin_unpack() that takes only one parameter.
115  */
117 set_unpack_data(const vector_uchar &data) {
118  nassertv(_mode == M_idle);
119 
120  char *buffer = new char[data.size()];
121  memcpy(buffer, data.data(), data.size());
122  set_unpack_data(buffer, data.size(), true);
123 }
124 
125 /**
126  * Sets up the unpack_data pointer. You may call this before calling the
127  * version of begin_unpack() that takes only one parameter.
128  */
130 set_unpack_data(const char *unpack_data, size_t unpack_length,
131  bool owns_unpack_data) {
132  nassertv(_mode == M_idle);
133 
134  if (_owns_unpack_data) {
135  delete[] _unpack_data;
136  }
137  _unpack_data = unpack_data;
138  _unpack_length = unpack_length;
139  _owns_unpack_data = owns_unpack_data;
140  _unpack_p = 0;
141 }
142 
143 /**
144  * Begins an unpacking session. You must have previously called
145  * set_unpack_data() to specify a buffer to unpack.
146  *
147  * If there was data left in the buffer after a previous begin_unpack() ..
148  * end_unpack() session, the new session will resume from the current point.
149  * This method may be used, therefore, to unpack a sequence of objects from
150  * the same buffer.
151  */
153 begin_unpack(const DCPackerInterface *root) {
154  nassertv(_mode == M_idle);
155  nassertv(_unpack_data != nullptr);
156 
157  _mode = M_unpack;
158  _parse_error = false;
159  _pack_error = false;
160  _range_error = false;
161 
162  _root = root;
163  _catalog = nullptr;
164  _live_catalog = nullptr;
165 
166  _current_field = root;
167  _current_parent = nullptr;
168  _current_field_index = 0;
169  _num_nested_fields = 0;
170 }
171 
172 /**
173  * Finishes the unpacking session.
174  *
175  * The return value is true on success, or false if there has been some error
176  * during unpacking (or if all fields have not been unpacked).
177  */
179 end_unpack() {
180  nassertr(_mode == M_unpack, false);
181 
182  _mode = M_idle;
183 
184  if (_stack != nullptr || _current_field != nullptr || _current_parent != nullptr) {
185  // This happens if we have not unpacked all of the fields. However, this
186  // is not an error if we have called seek() during the unpack session (in
187  // which case the _catalog will be non-NULL). On the other hand, if the
188  // catalog is still NULL, then we have never called seek() and it is an
189  // error not to unpack all values.
190  if (_catalog == nullptr) {
191  _pack_error = true;
192  }
193  }
194 
195  clear();
196 
197  return !had_error();
198 }
199 
200 /**
201  * Begins a repacking session. You must have previously called
202  * set_unpack_data() to specify a buffer to unpack.
203  *
204  * Unlike begin_pack() or begin_unpack() you may not concatenate the results
205  * of multiple begin_repack() sessions in one buffer.
206  *
207  * Also, unlike in packing or unpacking modes, you may not walk through the
208  * fields from beginning to end, or even pack two consecutive fields at once.
209  * Instead, you must call seek() for each field you wish to modify and pack
210  * only that one field; then call seek() again to modify another field.
211  */
213 begin_repack(const DCPackerInterface *root) {
214  nassertv(_mode == M_idle);
215  nassertv(_unpack_data != nullptr);
216  nassertv(_unpack_p == 0);
217 
218  _mode = M_repack;
219  _parse_error = false;
220  _pack_error = false;
221  _range_error = false;
222  _pack_data.clear();
223 
224  // In repack mode, we immediately get the catalog, since we know we'll need
225  // it.
226  _root = root;
227  _catalog = _root->get_catalog();
228  _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
229  if (_live_catalog == nullptr) {
230  _pack_error = true;
231  }
232 
233  // We don't begin at the first field in repack mode. Instead, you must
234  // explicitly call seek().
235  _current_field = nullptr;
236  _current_parent = nullptr;
237  _current_field_index = 0;
238  _num_nested_fields = 0;
239 }
240 
241 /**
242  * Finishes the repacking session.
243  *
244  * The return value is true on success, or false if there has been some error
245  * during repacking (or if all fields have not been repacked).
246  */
248 end_repack() {
249  nassertr(_mode == M_repack, false);
250 
251  // Put the rest of the data onto the pack stream.
252  _pack_data.append_data(_unpack_data + _unpack_p, _unpack_length - _unpack_p);
253 
254  _mode = M_idle;
255  clear();
256 
257  return !had_error();
258 }
259 
260 /**
261  * Sets the current unpack (or repack) position to the named field. In unpack
262  * mode, the next call to unpack_*() or push() will begin to read the named
263  * field. In repack mode, the next call to pack_*() or push() will modify the
264  * named field.
265  *
266  * Returns true if successful, false if the field is not known (or if the
267  * packer is in an invalid mode).
268  */
270 seek(const string &field_name) {
271  if (_catalog == nullptr) {
272  _catalog = _root->get_catalog();
273  _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
274  }
275  nassertr(_catalog != nullptr, false);
276  if (_live_catalog == nullptr) {
277  _pack_error = true;
278  return false;
279  }
280 
281  int seek_index = _live_catalog->find_entry_by_name(field_name);
282  if (seek_index < 0) {
283  // The field was not known.
284  _pack_error = true;
285  return false;
286  }
287 
288  return seek(seek_index);
289 }
290 
291 /**
292  * Seeks to the field indentified by seek_index, which was returned by an
293  * earlier call to DCField::find_seek_index() to get the index of some nested
294  * field. Also see the version of seek() that accepts a field name.
295  *
296  * Returns true if successful, false if the field is not known (or if the
297  * packer is in an invalid mode).
298  */
300 seek(int seek_index) {
301  if (_catalog == nullptr) {
302  _catalog = _root->get_catalog();
303  _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
304  }
305  nassertr(_catalog != nullptr, false);
306  if (_live_catalog == nullptr) {
307  _pack_error = true;
308  return false;
309  }
310 
311  if (_mode == M_unpack) {
312  const DCPackerCatalog::Entry &entry = _live_catalog->get_entry(seek_index);
313 
314  // If we are seeking, we don't need to remember our current stack
315  // position.
316  clear_stack();
317  _current_field = entry._field;
318  _current_parent = entry._parent;
319  _current_field_index = entry._field_index;
320  _num_nested_fields = _current_parent->get_num_nested_fields();
321  _unpack_p = _live_catalog->get_begin(seek_index);
322 
323  // We don't really need _push_marker and _pop_marker now, except that we
324  // should set _push_marker in case we have just seeked to a switch
325  // parameter, and we should set _pop_marker to 0 just so it won't get in
326  // the way.
327  _push_marker = _unpack_p;
328  _pop_marker = 0;
329 
330  return true;
331 
332  } else if (_mode == M_repack) {
333  nassertr(_catalog != nullptr, false);
334 
335  if (_stack != nullptr || _current_field != nullptr) {
336  // It is an error to reseek while the stack is nonempty--that means we
337  // haven't finished packing the current field.
338  _pack_error = true;
339  return false;
340  }
341  const DCPackerCatalog::Entry &entry = _live_catalog->get_entry(seek_index);
342 
343  if (entry._parent->as_switch_parameter() != nullptr) {
344  // If the parent is a DCSwitch, that can only mean that the seeked field
345  // is a switch parameter. We can't support seeking to a switch
346  // parameter and modifying it directly--what would happen to all of the
347  // related fields? Instead, you'll have to seek to the switch itself
348  // and repack the whole entity.
349  _pack_error = true;
350  return false;
351  }
352 
353  size_t begin = _live_catalog->get_begin(seek_index);
354  if (begin < _unpack_p) {
355  // Whoops, we are seeking fields out-of-order. That means we need to
356  // write the entire record and start again.
357  _pack_data.append_data(_unpack_data + _unpack_p, _unpack_length - _unpack_p);
358  size_t length = _pack_data.get_length();
359  char *buffer = _pack_data.take_data();
360  set_unpack_data(buffer, length, true);
361  _unpack_p = 0;
362 
363  _catalog->release_live_catalog(_live_catalog);
364  _live_catalog = _catalog->get_live_catalog(_unpack_data, _unpack_length);
365 
366  if (_live_catalog == nullptr) {
367  _pack_error = true;
368  return false;
369  }
370 
371  begin = _live_catalog->get_begin(seek_index);
372  }
373 
374  // Now copy the bytes from _unpack_p to begin from the _unpack_data to the
375  // _pack_data. These are the bytes we just skipped over with the call to
376  // seek().
377  _pack_data.append_data(_unpack_data + _unpack_p, begin - _unpack_p);
378 
379  // And set the packer up to pack the indicated field (but no subsequent
380  // fields).
381  _current_field = entry._field;
382  _current_parent = entry._parent;
383  _current_field_index = entry._field_index;
384  _num_nested_fields = 1;
385  _unpack_p = _live_catalog->get_end(seek_index);
386 
387  // Set up push_marker and pop_marker so we won't try to advance beyond
388  // this field.
389  _push_marker = begin;
390  _pop_marker = _live_catalog->get_end(seek_index);
391 
392  return true;
393  }
394 
395  // Invalid mode.
396  _pack_error = true;
397  return false;
398 }
399 
400 /**
401  * Marks the beginning of a nested series of fields.
402  *
403  * This must be called before filling the elements of an array or the
404  * individual fields in a structure field. It must also be balanced by a
405  * matching pop().
406  *
407  * It is necessary to use push() / pop() only if has_nested_fields() returns
408  * true.
409  */
411 push() {
412  if (!has_nested_fields()) {
413  _pack_error = true;
414 
415  } else {
416  StackElement *element = new StackElement;
417  element->_current_parent = _current_parent;
418  element->_current_field_index = _current_field_index;
419  element->_push_marker = _push_marker;
420  element->_pop_marker = _pop_marker;
421  element->_next = _stack;
422  _stack = element;
423  _current_parent = _current_field;
424 
425 
426  // Now deal with the length prefix that might or might not be before a
427  // sequence of nested fields.
428  int num_nested_fields = _current_parent->get_num_nested_fields();
429  size_t length_bytes = _current_parent->get_num_length_bytes();
430 
431  if (_mode == M_pack || _mode == M_repack) {
432  // Reserve length_bytes for when we figure out what the length is.
433  _push_marker = _pack_data.get_length();
434  _pop_marker = 0;
435  _pack_data.append_junk(length_bytes);
436 
437  } else if (_mode == M_unpack) {
438  // Read length_bytes to determine the end of this nested sequence.
439  _push_marker = _unpack_p;
440  _pop_marker = 0;
441 
442  if (length_bytes != 0) {
443  if (_unpack_p + length_bytes > _unpack_length) {
444  _pack_error = true;
445 
446  } else {
447  size_t length;
448  if (length_bytes == 4) {
449  length = DCPackerInterface::do_unpack_uint32
450  (_unpack_data + _unpack_p);
451  _unpack_p += 4;
452  } else {
453  length = DCPackerInterface::do_unpack_uint16
454  (_unpack_data + _unpack_p);
455  _unpack_p += 2;
456  }
457  _pop_marker = _unpack_p + length;
458 
459  // The explicit length trumps the number of nested fields reported
460  // by get_num_nested_fields().
461  if (length == 0) {
462  num_nested_fields = 0;
463  } else {
464  num_nested_fields = _current_parent->calc_num_nested_fields(length);
465  }
466  }
467  }
468  } else {
469  _pack_error = true;
470  }
471 
472 
473  // Now point to the first field in the nested range.
474  _num_nested_fields = num_nested_fields;
475  _current_field_index = 0;
476 
477  if (_num_nested_fields >= 0 &&
478  _current_field_index >= _num_nested_fields) {
479  _current_field = nullptr;
480 
481  } else {
482  _current_field = _current_parent->get_nested_field(_current_field_index);
483  }
484  }
485 }
486 
487 /**
488  * Marks the end of a nested series of fields.
489  *
490  * This must be called to match a previous push() only after all the expected
491  * number of nested fields have been packed. It is an error to call it too
492  * early, or too late.
493  */
495 pop() {
496  if (_current_field != nullptr && _num_nested_fields >= 0) {
497  // Oops, didn't pack or unpack enough values.
498  _pack_error = true;
499 
500  } else if (_mode == M_unpack && _pop_marker != 0 &&
501  _unpack_p != _pop_marker) {
502  // Didn't unpack the right number of values.
503  _pack_error = true;
504  }
505 
506  if (_stack == nullptr) {
507  // Unbalanced pop().
508  _pack_error = true;
509 
510  } else {
511  if (!_current_parent->validate_num_nested_fields(_current_field_index)) {
512  // Incorrect number of nested elements.
513  _pack_error = true;
514  }
515 
516  if (_mode == M_pack || _mode == M_repack) {
517  size_t length_bytes = _current_parent->get_num_length_bytes();
518  if (length_bytes != 0) {
519  // Now go back and fill in the length of the array.
520  size_t length = _pack_data.get_length() - _push_marker - length_bytes;
521  if (length_bytes == 4) {
522  DCPackerInterface::do_pack_uint32
523  (_pack_data.get_rewrite_pointer(_push_marker, 4), length);
524  } else {
525  DCPackerInterface::validate_uint_limits(length, 16, _range_error);
526  DCPackerInterface::do_pack_uint16
527  (_pack_data.get_rewrite_pointer(_push_marker, 2), length);
528  }
529  }
530  }
531 
532  _current_field = _current_parent;
533  _current_parent = _stack->_current_parent;
534  _current_field_index = _stack->_current_field_index;
535  _push_marker = _stack->_push_marker;
536  _pop_marker = _stack->_pop_marker;
537  _num_nested_fields = (_current_parent == nullptr) ? 0 : _current_parent->get_num_nested_fields();
538 
539  StackElement *next = _stack->_next;
540  delete _stack;
541  _stack = next;
542  }
543 
544  advance();
545 }
546 
547 /**
548  * Adds the default value for the current element into the stream. If no
549  * default has been set for the current element, creates a sensible default.
550  */
553  nassertv(_mode == M_pack || _mode == M_repack);
554  if (_current_field == nullptr) {
555  _pack_error = true;
556  } else {
557  if (_current_field->pack_default_value(_pack_data, _pack_error)) {
558  advance();
559 
560  } else {
561  // If the single field didn't know how to pack a default value, try
562  // packing nested fields.
563  push();
564  while (more_nested_fields()) {
566  }
567  pop();
568  }
569  }
570 }
571 
572 /**
573  * Internally unpacks the current numeric or string value and validates it
574  * against the type range limits, but does not return the value. If the
575  * current field contains nested fields, validates all of them.
576  */
578 unpack_validate() {
579  nassertv(_mode == M_unpack);
580  if (_current_field == nullptr) {
581  _pack_error = true;
582 
583  } else {
584  if (_current_field->unpack_validate(_unpack_data, _unpack_length, _unpack_p,
585  _pack_error, _range_error)) {
586  advance();
587  } else {
588  // If the single field couldn't be validated, try validating nested
589  // fields.
590  push();
591  while (more_nested_fields()) {
592  unpack_validate();
593  }
594  pop();
595  }
596  }
597 }
598 
599 /**
600  * Skips the current field without unpacking it and advances to the next
601  * field. If the current field contains nested fields, skips all of them.
602  */
604 unpack_skip() {
605  nassertv(_mode == M_unpack);
606  if (_current_field == nullptr) {
607  _pack_error = true;
608 
609  } else {
610  if (_current_field->unpack_skip(_unpack_data, _unpack_length, _unpack_p,
611  _pack_error)) {
612  advance();
613 
614  } else {
615  // If the single field couldn't be skipped, try skipping nested fields.
616  push();
617  while (more_nested_fields()) {
618  unpack_skip();
619  }
620  pop();
621  }
622  }
623 }
624 
625 #ifdef HAVE_PYTHON
626 /**
627  * Packs the Python object of whatever type into the packer. Each numeric
628  * object and string object maps to the corresponding pack_value() call; a
629  * tuple or sequence maps to a push() followed by all of the tuple's contents
630  * followed by a pop().
631  */
632 void DCPacker::
633 pack_object(PyObject *object) {
634  nassertv(_mode == M_pack || _mode == M_repack);
635  DCPackType pack_type = get_pack_type();
636 
637  // had to add this for basic 64 and unsigned data to get packed right .. Not
638  // sure if we can just do the rest this way..
639 
640  switch(pack_type)
641  {
642  case PT_int64:
643  if(PyLong_Check(object))
644  {
645  pack_int64(PyLong_AsLongLong(object));
646  return;
647  }
648 #if PY_MAJOR_VERSION < 3
649  else if (PyInt_Check(object))
650  {
651  pack_int64(PyInt_AsLong(object));
652  return;
653  }
654 #endif
655  break;
656  case PT_uint64:
657  if(PyLong_Check(object))
658  {
659  pack_uint64(PyLong_AsUnsignedLongLong(object));
660  return;
661  }
662 #if PY_MAJOR_VERSION < 3
663  else if(PyInt_Check(object))
664  {
665  PyObject *obj1 = PyNumber_Long(object);
666  pack_int(PyLong_AsUnsignedLongLong(obj1));
667  Py_DECREF(obj1);
668  return;
669  }
670 #endif
671  break;
672  case PT_int:
673  if(PyLong_Check(object))
674  {
675  pack_int(PyLong_AsLong(object));
676  return;
677  }
678 #if PY_MAJOR_VERSION < 3
679  else if (PyInt_Check(object))
680  {
681  pack_int(PyInt_AsLong(object));
682  return;
683  }
684 #endif
685  break;
686  case PT_uint:
687  if(PyLong_Check(object))
688  {
689  pack_uint(PyLong_AsUnsignedLong(object));
690  return;
691  }
692 #if PY_MAJOR_VERSION < 3
693  else if (PyInt_Check(object))
694  {
695  PyObject *obj1 = PyNumber_Long(object);
696  pack_uint(PyLong_AsUnsignedLong(obj1));
697  Py_DECREF(obj1);
698  return;
699  }
700 #endif
701  break;
702  default:
703  break;
704  }
705  if (PyLong_Check(object)) {
706  pack_int(PyLong_AsLong(object));
707 #if PY_MAJOR_VERSION < 3
708  } else if (PyInt_Check(object)) {
709  pack_int(PyInt_AS_LONG(object));
710 #endif
711  } else if (PyFloat_Check(object)) {
712  pack_double(PyFloat_AS_DOUBLE(object));
713  } else if (PyLong_Check(object)) {
714  pack_int64(PyLong_AsLongLong(object));
715 #if PY_MAJOR_VERSION >= 3
716  } else if (PyUnicode_Check(object)) {
717  const char *buffer;
718  Py_ssize_t length;
719  buffer = PyUnicode_AsUTF8AndSize(object, &length);
720  if (buffer) {
721  pack_string(string(buffer, length));
722  }
723  } else if (PyBytes_Check(object)) {
724  const unsigned char *buffer;
725  Py_ssize_t length;
726  PyBytes_AsStringAndSize(object, (char **)&buffer, &length);
727  if (buffer) {
728  pack_blob(vector_uchar(buffer, buffer + length));
729  }
730 #else
731  } else if (PyString_Check(object) || PyUnicode_Check(object)) {
732  char *buffer;
733  Py_ssize_t length;
734  PyString_AsStringAndSize(object, &buffer, &length);
735  if (buffer) {
736  pack_string(string(buffer, length));
737  }
738 #endif
739  } else {
740  // For some reason, PySequence_Check() is incorrectly reporting that a
741  // class instance is a sequence, even if it doesn't provide __len__, so we
742  // double-check by testing for __len__ explicitly.
743  bool is_sequence =
744  (PySequence_Check(object) != 0) &&
745  (PyObject_HasAttrString(object, "__len__") != 0);
746  bool is_instance = false;
747 
748  const DCClass *dclass = nullptr;
749  const DCPackerInterface *current_field = get_current_field();
750  if (current_field != nullptr) {
751  const DCClassParameter *class_param = get_current_field()->as_class_parameter();
752  if (class_param != nullptr) {
753  dclass = class_param->get_class();
754 
755  if (dclass->has_class_def()) {
756  PyObject *class_def = dclass->get_class_def();
757  is_instance = (PyObject_IsInstance(object, dclass->get_class_def()) != 0);
758  Py_DECREF(class_def);
759  }
760  }
761  }
762 
763  // If dclass is not NULL, the packer is expecting a class object. There
764  // are then two cases: (1) the user has supplied a matching class object,
765  // or (2) the user has supplied a sequence object. Unfortunately, it may
766  // be difficult to differentiate these two cases, since a class object may
767  // also be a sequence object.
768 
769  // The rule to differentiate them is:
770 
771  // (1) If the supplied class object is an instance of the expected class
772  // object, it is considered to be a class object.
773 
774  // (2) Otherwise, if the supplied class object has a __len__() method
775  // (i.e. PySequence_Check() returns true), then it is considered to be a
776  // sequence.
777 
778  // (3) Otherwise, it is considered to be a class object.
779 
780  if (dclass != nullptr && (is_instance || !is_sequence)) {
781  // The supplied object is either an instance of the expected class
782  // object, or it is not a sequence--this is case (1) or (3).
783  pack_class_object(dclass, object);
784  } else if (is_sequence) {
785  // The supplied object is not an instance of the expected class object,
786  // but it is a sequence. This is case (2).
787  push();
788  int size = PySequence_Size(object);
789  for (int i = 0; i < size; ++i) {
790  PyObject *element = PySequence_GetItem(object, i);
791  if (element != nullptr) {
792  pack_object(element);
793  Py_DECREF(element);
794  } else {
795  std::cerr << "Unable to extract item " << i << " from sequence.\n";
796  }
797  }
798  pop();
799  } else {
800  // The supplied object is not a sequence, and we weren't expecting a
801  // class parameter. This is none of the above, an error.
802  ostringstream strm;
803  strm << "Don't know how to pack object: "
804  << DCField::get_pystr(object);
805  nassert_raise(strm.str());
806  _pack_error = true;
807  }
808  }
809 }
810 #endif // HAVE_PYTHON
811 
812 #ifdef HAVE_PYTHON
813 /**
814  * Unpacks a Python object of the appropriate type from the stream for the
815  * current field. This may be an integer or a string for a simple field
816  * object; if the current field represents a list of fields it will be a
817  * tuple.
818  */
819 PyObject *DCPacker::
820 unpack_object() {
821  PyObject *object = nullptr;
822 
823  DCPackType pack_type = get_pack_type();
824 
825  switch (pack_type) {
826  case PT_invalid:
827  object = Py_None;
828  Py_INCREF(object);
829  unpack_skip();
830  break;
831 
832  case PT_double:
833  {
834  double value = unpack_double();
835  object = PyFloat_FromDouble(value);
836  }
837  break;
838 
839  case PT_int:
840  {
841  int value = unpack_int();
842 #if PY_MAJOR_VERSION >= 3
843  object = PyLong_FromLong(value);
844 #else
845  object = PyInt_FromLong(value);
846 #endif
847  }
848  break;
849 
850  case PT_uint:
851  {
852  unsigned int value = unpack_uint();
853 #if PY_MAJOR_VERSION >= 3
854  object = PyLong_FromLong(value);
855 #else
856  if (value & 0x80000000) {
857  object = PyLong_FromUnsignedLong(value);
858  } else {
859  object = PyInt_FromLong(value);
860  }
861 #endif
862  }
863  break;
864 
865  case PT_int64:
866  {
867  int64_t value = unpack_int64();
868  object = PyLong_FromLongLong(value);
869  }
870  break;
871 
872  case PT_uint64:
873  {
874  uint64_t value = unpack_uint64();
875  object = PyLong_FromUnsignedLongLong(value);
876  }
877  break;
878 
879  case PT_blob:
880 #if PY_MAJOR_VERSION >= 3
881  {
882  string str;
883  unpack_string(str);
884  object = PyBytes_FromStringAndSize(str.data(), str.size());
885  }
886  break;
887 #endif
888  // On Python 2, fall through to below.
889 
890  case PT_string:
891  {
892  string str;
893  unpack_string(str);
894 #if PY_MAJOR_VERSION >= 3
895  object = PyUnicode_FromStringAndSize(str.data(), str.size());
896 #else
897  object = PyString_FromStringAndSize(str.data(), str.size());
898 #endif
899  }
900  break;
901 
902  case PT_class:
903  {
904  const DCClassParameter *class_param = get_current_field()->as_class_parameter();
905  if (class_param != nullptr) {
906  const DCClass *dclass = class_param->get_class();
907  if (dclass->has_class_def()) {
908  // If we know what kind of class object this is and it has a valid
909  // constructor, create the class object instead of just a tuple.
910  object = unpack_class_object(dclass);
911  if (object == nullptr) {
912  std::cerr << "Unable to construct object of class "
913  << dclass->get_name() << "\n";
914  } else {
915  break;
916  }
917  }
918  }
919  }
920  // Fall through (if no constructor)
921 
922  // If we don't know what kind of class object it is, or it doesn't have a
923  // constructor, fall through and make a tuple.
924  default:
925  {
926  // First, build up a list from the nested objects.
927  object = PyList_New(0);
928 
929  push();
930  while (more_nested_fields()) {
931  PyObject *element = unpack_object();
932  PyList_Append(object, element);
933  Py_DECREF(element);
934  }
935  pop();
936 
937  if (pack_type != PT_array) {
938  // For these other kinds of objects, we'll convert the list into a
939  // tuple.
940  PyObject *tuple = PyList_AsTuple(object);
941  Py_DECREF(object);
942  object = tuple;
943  }
944  }
945  break;
946  }
947 
948  nassertr(object != nullptr, nullptr);
949  return object;
950 }
951 #endif // HAVE_PYTHON
952 
953 
954 /**
955  * Parses an object's value according to the DC file syntax (e.g. as a
956  * default value string) and packs it. Returns true on success, false on a
957  * parse error.
958  */
960 parse_and_pack(const string &formatted_object) {
961  istringstream strm(formatted_object);
962  return parse_and_pack(strm);
963 }
964 
965 /**
966  * Parses an object's value according to the DC file syntax (e.g. as a
967  * default value string) and packs it. Returns true on success, false on a
968  * parse error.
969  */
971 parse_and_pack(istream &in) {
972  dc_init_parser_parameter_value(in, "parse_and_pack", *this);
973  dcyyparse();
974  dc_cleanup_parser();
975 
976  bool parse_error = (dc_error_count() != 0);
977  if (parse_error) {
978  _parse_error = true;
979  }
980 
981  return !parse_error;
982 }
983 
984 /**
985  * Unpacks an object and formats its value into a syntax suitable for parsing
986  * in the dc file (e.g. as a default value), or as an input to parse_object.
987  */
989 unpack_and_format(bool show_field_names) {
990  ostringstream strm;
991  unpack_and_format(strm, show_field_names);
992  return strm.str();
993 }
994 
995 /**
996  * Unpacks an object and formats its value into a syntax suitable for parsing
997  * in the dc file (e.g. as a default value), or as an input to parse_object.
998  */
1000 unpack_and_format(ostream &out, bool show_field_names) {
1001  DCPackType pack_type = get_pack_type();
1002 
1003  if (show_field_names && !get_current_field_name().empty()) {
1004  nassertv(_current_field != nullptr);
1005  const DCField *field = _current_field->as_field();
1006  if (field != nullptr &&
1007  field->as_parameter() != nullptr) {
1008  out << field->get_name() << " = ";
1009  }
1010  }
1011 
1012  switch (pack_type) {
1013  case PT_invalid:
1014  out << "<invalid>";
1015  break;
1016 
1017  case PT_double:
1018  out << unpack_double();
1019  break;
1020 
1021  case PT_int:
1022  out << unpack_int();
1023  break;
1024 
1025  case PT_uint:
1026  out << unpack_uint();
1027  break;
1028 
1029  case PT_int64:
1030  out << unpack_int64();
1031  break;
1032 
1033  case PT_uint64:
1034  out << unpack_uint64();
1035  break;
1036 
1037  case PT_string:
1038  enquote_string(out, '"', unpack_string());
1039  break;
1040 
1041  case PT_blob:
1043  break;
1044 
1045  default:
1046  {
1047  switch (pack_type) {
1048  case PT_array:
1049  out << '[';
1050  break;
1051 
1052  case PT_field:
1053  case PT_switch:
1054  out << '(';
1055  break;
1056 
1057  case PT_class:
1058  default:
1059  out << '{';
1060  break;
1061  }
1062 
1063  push();
1064  while (more_nested_fields() && !had_pack_error()) {
1065  unpack_and_format(out, show_field_names);
1066 
1067  if (more_nested_fields()) {
1068  out << ", ";
1069  }
1070  }
1071  pop();
1072 
1073  switch (pack_type) {
1074  case PT_array:
1075  out << ']';
1076  break;
1077 
1078  case PT_field:
1079  case PT_switch:
1080  out << ')';
1081  break;
1082 
1083  case PT_class:
1084  default:
1085  out << '}';
1086  break;
1087  }
1088  }
1089  break;
1090  }
1091 }
1092 
1093 /**
1094  * Outputs the indicated string within quotation marks.
1095  */
1097 enquote_string(ostream &out, char quote_mark, const string &str) {
1098  out << quote_mark;
1099  for (string::const_iterator pi = str.begin();
1100  pi != str.end();
1101  ++pi) {
1102  if ((*pi) == quote_mark || (*pi) == '\\') {
1103  out << '\\' << (*pi);
1104 
1105  } else if (!isprint(*pi) || (*pi) == '\t') {
1106  char buffer[10];
1107  sprintf(buffer, "%02x", (unsigned char)(*pi));
1108  out << "\\x" << buffer;
1109 
1110  } else {
1111  out << (*pi);
1112  }
1113  }
1114  out << quote_mark;
1115 }
1116 
1117 /**
1118  * Outputs the indicated string as a hex constant.
1119  */
1121 output_hex_string(ostream &out, const vector_uchar &str) {
1122  out << '<';
1123  for (vector_uchar::const_iterator pi = str.begin();
1124  pi != str.end();
1125  ++pi) {
1126  char buffer[10];
1127  sprintf(buffer, "%02x", (unsigned char)(*pi));
1128  out << buffer;
1129  }
1130  out << '>';
1131 }
1132 
1133 /**
1134  * When we advance past the key field on a switch record, we suddenly have
1135  * more fields available--all the appropriate alternate fields in the switch.
1136  *
1137  * This function is called when we detect this condition; it switches the
1138  * _current_parent to the appropriate case of the switch record.
1139  */
1140 void DCPacker::
1141 handle_switch(const DCSwitchParameter *switch_parameter) {
1142  // First, get the value from the key. This is either found in the unpack or
1143  // the pack data, depending on what mode we're in.
1144  const DCPackerInterface *new_parent = nullptr;
1145 
1146  if (_mode == M_pack || _mode == M_repack) {
1147  const char *data = _pack_data.get_data();
1148  new_parent = switch_parameter->apply_switch
1149  (data + _push_marker, _pack_data.get_length() - _push_marker);
1150 
1151  } else if (_mode == M_unpack) {
1152  new_parent = switch_parameter->apply_switch
1153  (_unpack_data + _push_marker, _unpack_p - _push_marker);
1154  }
1155 
1156  if (new_parent == nullptr) {
1157  // This means an invalid value was packed for the key.
1158  _range_error = true;
1159  return;
1160  }
1161 
1162  _last_switch = switch_parameter;
1163 
1164  // Now substitute in the switch case for the previous parent (which replaces
1165  // the switch node itself). This will suddenly make a slew of new fields
1166  // appear.
1167  _current_parent = new_parent;
1168  _num_nested_fields = _current_parent->get_num_nested_fields();
1169 
1170  if (_num_nested_fields < 0 ||
1171  _current_field_index < _num_nested_fields) {
1172  _current_field = _current_parent->get_nested_field(_current_field_index);
1173  }
1174 }
1175 
1176 /**
1177  * Resets the data structures after a pack or unpack sequence.
1178  */
1179 void DCPacker::
1180 clear() {
1181  clear_stack();
1182  _current_field = nullptr;
1183  _current_parent = nullptr;
1184  _current_field_index = 0;
1185  _num_nested_fields = 0;
1186  _push_marker = 0;
1187  _pop_marker = 0;
1188  _last_switch = nullptr;
1189 
1190  if (_live_catalog != nullptr) {
1191  _catalog->release_live_catalog(_live_catalog);
1192  _live_catalog = nullptr;
1193  }
1194  _catalog = nullptr;
1195  _root = nullptr;
1196 }
1197 
1198 /**
1199  * Empties the stack.
1200  */
1201 void DCPacker::
1202 clear_stack() {
1203  while (_stack != nullptr) {
1204  StackElement *next = _stack->_next;
1205  delete _stack;
1206  _stack = next;
1207  }
1208 }
1209 
1210 #ifdef HAVE_PYTHON
1211 /**
1212  * Given that the current element is a ClassParameter for a Python class
1213  * object, try to extract the appropriate values from the class object and
1214  * pack in.
1215  */
1216 void DCPacker::
1217 pack_class_object(const DCClass *dclass, PyObject *object) {
1218  push();
1219  while (more_nested_fields() && !_pack_error) {
1220  const DCField *field = get_current_field()->as_field();
1221  nassertv(field != nullptr);
1222  get_class_element(dclass, object, field);
1223  }
1224  pop();
1225 }
1226 #endif // HAVE_PYTHON
1227 
1228 #ifdef HAVE_PYTHON
1229 /**
1230  * Given that the current element is a ClassParameter for a Python class for
1231  * which we have a valid constructor, unpack it and fill in its values.
1232  */
1233 PyObject *DCPacker::
1234 unpack_class_object(const DCClass *dclass) {
1235  PyObject *class_def = dclass->get_class_def();
1236  nassertr(class_def != nullptr, nullptr);
1237 
1238  PyObject *object = nullptr;
1239 
1240  if (!dclass->has_constructor()) {
1241  // If the class uses a default constructor, go ahead and create the Python
1242  // object for it now.
1243  object = PyObject_CallObject(class_def, nullptr);
1244  if (object == nullptr) {
1245  return nullptr;
1246  }
1247  }
1248 
1249  push();
1250  if (object == nullptr && more_nested_fields()) {
1251  // The first nested field will be the constructor.
1252  const DCField *field = get_current_field()->as_field();
1253  nassertr(field != nullptr, object);
1254  nassertr(field == dclass->get_constructor(), object);
1255 
1256  set_class_element(class_def, object, field);
1257 
1258  // By now, the object should have been constructed.
1259  if (object == nullptr) {
1260  return nullptr;
1261  }
1262  }
1263  while (more_nested_fields()) {
1264  const DCField *field = get_current_field()->as_field();
1265  nassertr(field != nullptr, object);
1266 
1267  set_class_element(class_def, object, field);
1268  }
1269  pop();
1270 
1271  return object;
1272 }
1273 #endif // HAVE_PYTHON
1274 
1275 
1276 #ifdef HAVE_PYTHON
1277 /**
1278  * Unpacks the current element and stuffs it on the Python class object in
1279  * whatever way is appropriate.
1280  */
1281 void DCPacker::
1282 set_class_element(PyObject *class_def, PyObject *&object,
1283  const DCField *field) {
1284  string field_name = field->get_name();
1285  DCPackType pack_type = get_pack_type();
1286 
1287  if (field_name.empty()) {
1288  switch (pack_type) {
1289  case PT_class:
1290  case PT_switch:
1291  // If the field has no name, but it is one of these container objects,
1292  // we want to unpack its nested objects directly into the class.
1293  push();
1294  while (more_nested_fields()) {
1295  const DCField *field = get_current_field()->as_field();
1296  nassertv(field != nullptr);
1297  nassertv(object != nullptr);
1298  set_class_element(class_def, object, field);
1299  }
1300  pop();
1301  break;
1302 
1303  default:
1304  // Otherwise, we just skip over the field.
1305  unpack_skip();
1306  }
1307 
1308  } else {
1309  // If the field does have a name, we will want to store it on the class,
1310  // either by calling a method (for a PT_field pack_type) or by setting a
1311  // value (for any other kind of pack_type).
1312 
1313  PyObject *element = unpack_object();
1314 
1315  if (pack_type == PT_field) {
1316  if (object == nullptr) {
1317  // If the object hasn't been constructed yet, assume this is the
1318  // constructor.
1319  object = PyObject_CallObject(class_def, element);
1320 
1321  } else {
1322  if (PyObject_HasAttrString(object, (char *)field_name.c_str())) {
1323  PyObject *func = PyObject_GetAttrString(object, (char *)field_name.c_str());
1324  if (func != nullptr) {
1325  PyObject *result = PyObject_CallObject(func, element);
1326  Py_XDECREF(result);
1327  Py_DECREF(func);
1328  }
1329  }
1330  }
1331 
1332  } else {
1333  nassertv(object != nullptr);
1334  PyObject_SetAttrString(object, (char *)field_name.c_str(), element);
1335  }
1336 
1337  Py_DECREF(element);
1338  }
1339 }
1340 #endif // HAVE_PYTHON
1341 
1342 
1343 #ifdef HAVE_PYTHON
1344 /**
1345  * Gets the current element from the Python object and packs it.
1346  */
1347 void DCPacker::
1348 get_class_element(const DCClass *dclass, PyObject *object,
1349  const DCField *field) {
1350  string field_name = field->get_name();
1351  DCPackType pack_type = get_pack_type();
1352 
1353  if (field_name.empty()) {
1354  switch (pack_type) {
1355  case PT_class:
1356  case PT_switch:
1357  // If the field has no name, but it is one of these container objects,
1358  // we want to get its nested objects directly from the class.
1359  push();
1360  while (more_nested_fields() && !_pack_error) {
1361  const DCField *field = get_current_field()->as_field();
1362  nassertv(field != nullptr);
1363  get_class_element(dclass, object, field);
1364  }
1365  pop();
1366  break;
1367 
1368  default:
1369  // Otherwise, we just pack the default value.
1371  }
1372 
1373  } else {
1374  // If the field does have a name, we will want to get it from the class
1375  // and pack it. It just so happens that there's already a method that
1376  // does this on DCClass.
1377 
1378  if (!dclass->pack_required_field(*this, object, field)) {
1379  _pack_error = true;
1380  }
1381  }
1382 }
1383 #endif // HAVE_PYTHON
This represents a class (or struct) object used as a parameter itself.
const DCClass * get_class() const
Returns the class object this parameter represents.
Defines a particular DistributedClass as read from an input .dc file.
Definition: dcClass.h:44
DCField * get_constructor() const
Returns the constructor method for this class if it is defined, or NULL if the class uses the default...
Definition: dcClass.cxx:162
bool has_constructor() const
Returns true if this class has a constructor method, false if it just uses the default constructor.
Definition: dcClass.cxx:153
const std::string & get_name() const
Returns the name of this class.
Definition: dcClass.I:26
A single field of a Distributed Class, either atomic or molecular.
Definition: dcField.h:37
const char * get_data() const
Returns the beginning of the data buffer.
Definition: dcPackData.I:115
char * take_data()
Returns the pointer to the beginning of the data buffer, and transfers ownership of the buffer to the...
Definition: dcPackData.I:129
char * get_rewrite_pointer(size_t position, size_t size)
Returns a pointer into the middle of the data at the indicated point.
Definition: dcPackData.I:84
void append_junk(size_t size)
Adds some uninitialized bytes to the end of the data.
Definition: dcPackData.I:66
void append_data(const char *buffer, size_t size)
Adds the indicated bytes to the end of the data.
Definition: dcPackData.I:47
size_t get_length() const
Returns the current length of the buffer.
Definition: dcPackData.I:102
void clear()
Empties the contents of the data (without necessarily freeing its allocated memory).
Definition: dcPackData.I:39
size_t get_begin(int n) const
Returns the beginning of the indicated field within the live data.
int find_entry_by_name(const std::string &name) const
Returns the index number of the entry with the indicated name, or -1 if no entry has the indicated na...
const Entry & get_entry(int n) const
Returns the nth entry in the catalog.
size_t get_end(int n) const
Returns the end of the indicated field (the byte position of the first following field) within the li...
void release_live_catalog(const LiveCatalog *live_catalog) const
Releases the LiveCatalog object that was returned by an earlier call to get_live_catalog().
const LiveCatalog * get_live_catalog(const char *data, size_t length) const
Returns a LiveCatalog object indicating the positions within the indicated data record of each field ...
This defines the internal interface for packing values into a DCField.
static void validate_uint_limits(unsigned int value, int num_bits, bool &range_error)
Confirms that the unsigned value fits within num_bits bits.
const DCPackerCatalog * get_catalog() const
Returns the DCPackerCatalog associated with this field, listing all of the nested fields by name.
const std::string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
int get_num_nested_fields() const
Returns the number of nested fields required by this field type.
virtual bool unpack_validate(const char *data, size_t length, size_t &p, bool &pack_error, bool &range_error) const
Internally unpacks the current numeric or string value and validates it against the type range limits...
virtual int calc_num_nested_fields(size_t length_bytes) const
This flavor of get_num_nested_fields is used during unpacking.
size_t get_num_length_bytes() const
Returns the number of bytes that should be written into the stream on a push() to record the number o...
virtual bool validate_num_nested_fields(int num_nested_fields) const
After a number of fields have been packed via push() .
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.
virtual bool unpack_skip(const char *data, size_t length, size_t &p, bool &pack_error) const
Increments p to the end of the current field without actually unpacking any data or performing any ra...
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const
Packs the field's specified default value (or a sensible default if no value is specified) into the s...
const DCPackerInterface * get_current_field() const
Returns the field that will be referenced by the next call to pack_*() or unpack_*().
Definition: dcPacker.I:87
void unpack_validate()
Internally unpacks the current numeric or string value and validates it against the type range limits...
Definition: dcPacker.cxx:578
void push()
Marks the beginning of a nested series of fields.
Definition: dcPacker.cxx:411
bool more_nested_fields() const
Returns true if there are more nested fields to pack or unpack in the current push sequence,...
Definition: dcPacker.I:67
std::string unpack_string()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:347
void clear_data()
Empties the data in the pack buffer and unpack buffer.
Definition: dcPacker.I:20
void pack_blob(const std::vector< unsigned char > &value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:223
int unpack_int()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:271
void pack_uint(unsigned int value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:167
std::vector< unsigned char > unpack_literal_value()
Returns the literal string that represents the packed value of the current field, and advances the fi...
Definition: dcPacker.I:386
void begin_pack(const DCPackerInterface *root)
Begins a packing session.
Definition: dcPacker.cxx:73
void pack_int(int value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:153
void begin_unpack(const DCPackerInterface *root)
Begins an unpacking session.
Definition: dcPacker.cxx:153
void begin_repack(const DCPackerInterface *root)
Begins a repacking session.
Definition: dcPacker.cxx:213
bool end_repack()
Finishes the repacking session.
Definition: dcPacker.cxx:248
DCPackType get_pack_type() const
Returns the type of value expected by the current field.
Definition: dcPacker.I:114
bool end_unpack()
Finishes the unpacking session.
Definition: dcPacker.cxx:179
bool has_nested_fields() const
Returns true if the current field has any nested fields (and thus expects a push() .
Definition: dcPacker.I:37
void pack_uint64(uint64_t value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:195
bool had_error() const
Returns true if there has been any error (either a pack error or a range error) since the most recent...
Definition: dcPacker.I:563
double unpack_double()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:252
void pop()
Marks the end of a nested series of fields.
Definition: dcPacker.cxx:495
bool had_pack_error() const
Returns true if there has been an packing error since the most recent call to begin(); in particular,...
Definition: dcPacker.I:539
bool end_pack()
Finishes a packing session.
Definition: dcPacker.cxx:98
void pack_int64(int64_t value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:181
void unpack_skip()
Skips the current field without unpacking it and advances to the next field.
Definition: dcPacker.cxx:604
static void output_hex_string(std::ostream &out, const std::vector< unsigned char > &str)
Outputs the indicated string as a hex constant.
Definition: dcPacker.cxx:1121
bool seek(const std::string &field_name)
Sets the current unpack (or repack) position to the named field.
Definition: dcPacker.cxx:270
void set_unpack_data(const std::vector< unsigned char > &data)
Sets up the unpack_data pointer.
Definition: dcPacker.cxx:117
bool parse_and_pack(const std::string &formatted_object)
Parses an object's value according to the DC file syntax (e.g.
Definition: dcPacker.cxx:960
void pack_default_value()
Adds the default value for the current element into the stream.
Definition: dcPacker.cxx:552
static void enquote_string(std::ostream &out, char quote_mark, const std::string &str)
Outputs the indicated string within quotation marks.
Definition: dcPacker.cxx:1097
std::string unpack_and_format(bool show_field_names=true)
Unpacks an object and formats its value into a syntax suitable for parsing in the dc file (e....
Definition: dcPacker.cxx:989
void pack_double(double value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:139
int64_t unpack_int64()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:309
std::string get_current_field_name() const
Returns the name of the current field, if it has a name, or the empty string if the field does not ha...
Definition: dcPacker.I:127
unsigned int unpack_uint()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:290
uint64_t unpack_uint64()
Unpacks the current numeric or string value from the stream.
Definition: dcPacker.I:328
void pack_string(const std::string &value)
Packs the indicated numeric or string value into the stream.
Definition: dcPacker.I:209
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.