Panda3D
bamReader.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 bamReader.cxx
10  * @author jason
11  * @date 2000-06-12
12  */
13 
14 #include "pandabase.h"
15 #include "pnotify.h"
16 
17 #include "bam.h"
18 #include "bamReader.h"
19 #include "datagramIterator.h"
20 #include "config_putil.h"
21 #include "pipelineCyclerBase.h"
22 
23 using std::string;
24 
25 TypeHandle BamReaderAuxData::_type_handle;
26 
27 WritableFactory *BamReader::_factory = nullptr;
28 BamReader *const BamReader::Null = nullptr;
29 WritableFactory *const BamReader::NullFactory = nullptr;
30 
31 BamReader::NewTypes BamReader::_new_types;
32 
33 const int BamReader::_cur_major = _bam_major_ver;
34 const int BamReader::_cur_minor = _bam_minor_ver;
35 
36 
37 /**
38  *
39  */
40 BamReader::
41 BamReader(DatagramGenerator *source)
42  : _source(source)
43 {
44  _needs_init = true;
45  _num_extra_objects = 0;
46  _nesting_level = 0;
47  _now_creating = _created_objs.end();
48  _reading_cycler = nullptr;
49  _pta_id = -1;
50  _long_object_id = false;
51  _long_pta_id = false;
52 }
53 
54 
55 /**
56  *
57  */
58 BamReader::
59 ~BamReader() {
60  nassertv(_num_extra_objects == 0);
61  nassertv(_nesting_level == 0);
62 }
63 
64 /**
65  * Changes the source of future datagrams for this BamReader. This also
66  * implicitly calls init() if it has not already been called.
67  */
68 void BamReader::
70  _source = source;
71  if (_needs_init && _source != nullptr) {
72  bool success = init();
73  nassertv(success);
74  }
75 }
76 
77 /**
78  * Initializes the BamReader prior to reading any objects from its source.
79  * This includes reading the Bam header.
80  *
81  * This returns true if the BamReader successfully initialized, false
82  * otherwise.
83  */
84 bool BamReader::
85 init() {
86  nassertr(_source != nullptr, false);
87  nassertr(_needs_init, false);
88  _needs_init = false;
89  Datagram header;
90 
91  if (_source->is_error()) {
92  return false;
93  }
94 
95  if (!get_datagram(header)) {
96  bam_cat.error()
97  << "Unable to read Bam header.\n";
98  return false;
99  }
100 
101  DatagramIterator scan(header);
102 
103  _file_major = scan.get_uint16();
104  _file_minor = scan.get_uint16();
105 
106  // If the major version is different, or the minor version is *newer*, we
107  // can't safely load the file.
108  if (_file_major != _bam_major_ver ||
109  _file_minor < _bam_first_minor_ver ||
110  _file_minor > _bam_minor_ver) {
111  bam_cat.error()
112  << "Bam file is version " << _file_major << "." << _file_minor
113  << ".\n";
114 
115  if (_bam_minor_ver == _bam_first_minor_ver) {
116  bam_cat.error()
117  << "This program can only load version "
118  << _bam_major_ver << "." << _bam_first_minor_ver << " bams.\n";
119  } else {
120  bam_cat.error()
121  << "This program can only load version "
122  << _bam_major_ver << "." << _bam_first_minor_ver << " through "
123  << _bam_major_ver << "." << _bam_minor_ver << " bams.\n";
124  }
125 
126  return false;
127  }
128 
129  _file_endian = (BamEndian)scan.get_uint8();
130 
131  _file_stdfloat_double = false;
132  if (_file_minor >= 27) {
133  _file_stdfloat_double = scan.get_bool();
134  }
135 
136  if (scan.get_current_index() > header.get_length()) {
137  bam_cat.error()
138  << "Bam header is too short.\n";
139  return false;
140  }
141 
142  return true;
143 }
144 
145 /**
146  * Associates an arbitrary block of data with the indicated object (or NULL),
147  * and the indicated name.
148  *
149  * This is intended to provide a place for temporary storage for objects
150  * reading themselves from the bam file. To use it, inherit from
151  * BamReader::AuxData and store whatever data you like there. Then associate
152  * your AuxData with the object as it is being read with set_aux_data(). You
153  * may later set the aux data to NULL to remove it; or it will automatically
154  * be removed (and deleted) after finalize() is called for the object in
155  * question.
156  *
157  * If the TypedWritable pointer is NULL, the the aux data is stored globally
158  * for the BamReader in general. This pointer is available to any bam
159  * objects, and will not be automatically removed until the BamReader itself
160  * destructs.
161  *
162  * In either case, the name is just an arbitrary user-defined key. If there
163  * is already a data pointer stored for the obj/name pair, that data pointer
164  * will be replaced (and deleted).
165  */
166 void BamReader::
167 set_aux_data(TypedWritable *obj, const string &name, BamReader::AuxData *data) {
168  if (data == nullptr) {
169  AuxDataTable::iterator ti = _aux_data.find(obj);
170  if (ti != _aux_data.end()) {
171  AuxDataNames &names = (*ti).second;
172  names.erase(name);
173  if (names.empty()) {
174  _aux_data.erase(ti);
175  }
176  }
177 
178  } else {
179  _aux_data[obj][name] = data;
180  }
181 }
182 
183 /**
184  * Returns the pointer previously associated with the bam reader by a previous
185  * call to set_aux_data(), or NULL if data with the indicated key has not been
186  * set.
187  */
189 get_aux_data(TypedWritable *obj, const string &name) const {
190  AuxDataTable::const_iterator ti = _aux_data.find(obj);
191  if (ti != _aux_data.end()) {
192  const AuxDataNames &names = (*ti).second;
193  AuxDataNames::const_iterator ni = names.find(name);
194  if (ni != names.end()) {
195  return (*ni).second;
196  }
197  }
198 
199  return nullptr;
200 }
201 
202 
203 /**
204  * Reads a single object from the Bam file. If the object type is known, a
205  * new object of the appropriate type is created and returned; otherwise, NULL
206  * is returned. NULL is also returned when the end of the file is reached.
207  * is_eof() may be called to differentiate between these two cases.
208  *
209  * This may be called repeatedly to extract out all the objects in the Bam
210  * file, but typically (especially for scene graph files, indicated with the
211  * .bam extension), only one object is retrieved directly from the Bam file:
212  * the root of the scene graph. The remaining objects will all be retrieved
213  * recursively by the first object.
214  *
215  * Note that the object returned may not yet be complete. In particular, some
216  * of its pointers may not be filled in; you must call resolve() to fill in
217  * all the available pointers before you can safely use any objects returned
218  * by read_object().
219  *
220  * This flavor of read_object() requires the caller to know what type of
221  * object it has received in order to properly manage the reference counts.
222  */
225  TypedWritable *ptr;
226  ReferenceCount *ref_ptr;
227 
228  if (!read_object(ptr, ref_ptr)) {
229  return nullptr;
230  }
231 
232  return ptr;
233 }
234 
235 /**
236  * Reads a single object from the Bam file.
237  *
238  * This flavor of read_object() returns both a TypedWritable and a
239  * ReferenceCount pointer to the same object, so the reference count may be
240  * tracked reliably, without having to know precisely what type of object we
241  * have.
242  * @return true on success, or false on failure.
243  */
244 bool BamReader::
246  ptr = nullptr;
247  ref_ptr = nullptr;
248  nassertr(_num_extra_objects == 0, false);
249 
250  int start_level = _nesting_level;
251 
252  // First, read the base object.
253  int object_id = p_read_object();
254 
255  // Now that object might have included some pointers to other objects, which
256  // may still need to be read. And those objects might in turn require
257  // reading additional objects. Read all the remaining objects.
258 
259  // Prior to 6.21, we kept track of _num_extra_objects to know when we're
260  // done.
261  while (_num_extra_objects > 0) {
262  p_read_object();
263  _num_extra_objects--;
264  }
265 
266  // Beginning with 6.21, we use explicit nesting commands to know when we're
267  // done.
268  while (_nesting_level > start_level) {
269  p_read_object();
270  }
271 
272  // Now look up the pointer of the object we read first. It should be
273  // available now.
274  if (object_id == 0) {
275  if (bam_cat.is_spam()) {
276  bam_cat.spam()
277  << "Returning false\n";
278  }
279  return false;
280  }
281 
282  CreatedObjs::iterator oi = _created_objs.find(object_id);
283 
284  if (oi == _created_objs.end()) {
285  bam_cat.error()
286  << "Undefined object encountered!\n";
287  return false;
288 
289  } else {
290  CreatedObj &created_obj = (*oi).second;
291  ptr = created_obj._ptr;
292  ref_ptr = created_obj._ref_ptr;
293 
294  if (bam_cat.is_spam()) {
295  if (ptr != nullptr) {
296  bam_cat.spam()
297  << "Returning object of type " << ptr->get_type() << "\n";
298  }
299  }
300  if (created_obj._change_this != nullptr ||
301  created_obj._change_this_ref != nullptr) {
302  bam_cat.warning()
303  << "Returning pointer to " << ptr->get_type()
304  << " that might change.\n";
305  }
306 
307  return true;
308  }
309 }
310 
311 /**
312  * This may be called at any time during processing of the Bam file to resolve
313  * all the known pointers so far. It is usually called at the end of the
314  * processing, after all objects have been read, which is generally the best
315  * time to call it.
316  *
317  * This must be called at least once after reading a particular object via
318  * get_object() in order to validate that object.
319  *
320  * The return value is true if all objects have been resolved, or false if
321  * some objects are still outstanding (in which case you will need to call
322  * resolve() again later).
323  */
324 bool BamReader::
326  bool all_completed;
327  bool any_completed_this_pass;
328 
329  do {
330  if (bam_cat.is_spam()) {
331  bam_cat.spam()
332  << "resolve pass begin\n";
333  }
334  all_completed = true;
335  any_completed_this_pass = false;
336 
337  ObjectPointers::iterator oi;
338  oi = _object_pointers.begin();
339  while (oi != _object_pointers.end()) {
340  int object_id = (*oi).first;
341  PointerReference &pref = (*oi).second;
342 
343  CreatedObjs::iterator ci = _created_objs.find(object_id);
344  nassertr(ci != _created_objs.end(), false);
345 
346  CreatedObj &created_obj = (*ci).second;
347 
348  TypedWritable *object_ptr = created_obj._ptr;
349 
350  // Update _now_creating, so a call to get_int_tag() from within
351  // complete_pointers() will come to the right place.
352  CreatedObjs::iterator was_creating = _now_creating;
353  _now_creating = ci;
354 
355  if (resolve_object_pointers(object_ptr, pref)) {
356  // Now remove this object from the list of things that need
357  // completion. We have to be a bit careful when deleting things from
358  // the STL container while we are traversing it.
359  ObjectPointers::iterator old = oi;
360  ++oi;
361  _object_pointers.erase(old);
362  any_completed_this_pass = true;
363 
364  // Does the pointer need to change?
365  if (created_obj._change_this_ref != nullptr) {
366  // Reference-counting variant.
367  TypedWritableReferenceCount *object_ref_ptr = (TypedWritableReferenceCount *)object_ptr;
368  nassertr(created_obj._ref_ptr == nullptr || created_obj._ref_ptr == object_ref_ptr, false);
369  PT(TypedWritableReferenceCount) new_ptr = created_obj._change_this_ref(object_ref_ptr, this);
370  if (new_ptr != object_ref_ptr) {
371  // Also update the reverse
372  vector_int &old_refs = _created_objs_by_pointer[object_ptr];
373  vector_int &new_refs = _created_objs_by_pointer[new_ptr];
374  for (vector_int::const_iterator oi = old_refs.begin();
375  oi != old_refs.end();
376  ++oi) {
377  new_refs.push_back(*oi);
378  }
379  _created_objs_by_pointer.erase(object_ptr);
380 
381  // Remove the pointer from the finalize list (the new pointer
382  // presumably doesn't require finalizing).
383  _finalize_list.erase(object_ptr);
384  }
385  created_obj.set_ptr(new_ptr, new_ptr);
386  created_obj._change_this = nullptr;
387  created_obj._change_this_ref = nullptr;
388 
389  } else if (created_obj._change_this != nullptr) {
390  // Non-reference-counting variant.
391  TypedWritable *new_ptr = created_obj._change_this(object_ptr, this);
392  if (new_ptr != object_ptr) {
393  // Also update the reverse
394  vector_int &old_refs = _created_objs_by_pointer[object_ptr];
395  vector_int &new_refs = _created_objs_by_pointer[new_ptr];
396  for (vector_int::const_iterator oi = old_refs.begin();
397  oi != old_refs.end();
398  ++oi) {
399  new_refs.push_back(*oi);
400  }
401  _created_objs_by_pointer.erase(object_ptr);
402 
403  // Remove the pointer from the finalize list (the new pointer
404  // presumably doesn't require finalizing).
405  _finalize_list.erase(object_ptr);
406  }
407  created_obj.set_ptr(new_ptr, new_ptr->as_reference_count());
408  created_obj._change_this = nullptr;
409  created_obj._change_this_ref = nullptr;
410  }
411 
412  } else {
413  // Couldn't complete this object yet; it'll wait for next time.
414  ++oi;
415  all_completed = false;
416  }
417 
418  _now_creating = was_creating;
419  }
420 
421  if (bam_cat.is_spam()) {
422  bam_cat.spam()
423  << "resolve pass end: all_completed = " << all_completed
424  << " any_completed_this_pass = " << any_completed_this_pass
425  << "\n";
426  }
427  } while (!all_completed && any_completed_this_pass);
428 
429  if (all_completed) {
430  finalize();
431  } else {
432  // Report all the uncompleted objects for no good reason. This will
433  // probably have to come out later when we have cases in which some
434  // objects might legitimately be uncompleted after calling resolve(), but
435  // for now we expect resolve() to always succeed.
436  ObjectPointers::const_iterator oi;
437  for (oi = _object_pointers.begin();
438  oi != _object_pointers.end();
439  ++oi) {
440  int object_id = (*oi).first;
441  CreatedObjs::iterator ci = _created_objs.find(object_id);
442  nassertr(ci != _created_objs.end(), false);
443  CreatedObj &created_obj = (*ci).second;
444  TypedWritable *object_ptr = created_obj._ptr;
445 
446  bam_cat.warning()
447  << "Unable to complete " << object_ptr->get_type() << "\n";
448  }
449  }
450 
451  return all_completed;
452 }
453 
454 /**
455  * Indicates that an object recently read from the bam stream should be
456  * replaced with a new object. Any future occurrences of the original object
457  * in the stream will henceforth return the new object instead.
458  *
459  * The return value is true if the replacement was successfully made, or false
460  * if the object was not read from the stream (or if change_pointer had
461  * already been called on it).
462  */
463 bool BamReader::
464 change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer) {
465  if (orig_pointer == new_pointer) {
466  return false;
467  }
468  CreatedObjsByPointer::iterator ci = _created_objs_by_pointer.find(orig_pointer);
469  if (ci == _created_objs_by_pointer.end()) {
470  // No record of this object.
471  return false;
472  }
473 
474  if (bam_cat.is_spam()) {
475  bam_cat.spam()
476  << "change_pointer(" << (void *)orig_pointer << ", "
477  << (void *)new_pointer << ") (" << new_pointer->get_type() << ")\n";
478  }
479 
480  const vector_int &old_refs = (*ci).second;
481  vector_int &new_refs = _created_objs_by_pointer[new_pointer];
482 
483  for (vector_int::const_iterator oi = old_refs.begin();
484  oi != old_refs.end();
485  ++oi) {
486  int object_id = (*oi);
487 
488  CreatedObjs::iterator ci = _created_objs.find(object_id);
489  nassertr(ci != _created_objs.end(), false);
490  nassertr((*ci).second._ptr == orig_pointer, false);
491 
492  TypedWritable *ptr = (TypedWritable *)new_pointer;
493  (*ci).second.set_ptr(ptr, ptr->as_reference_count());
494  new_refs.push_back(object_id);
495  }
496 
497  _created_objs_by_pointer.erase(ci);
498 
499  // Also change the pointer on the finalize_list.
500  Finalize::iterator fi = _finalize_list.find((TypedWritable *)orig_pointer);
501  if (fi != _finalize_list.end()) {
502  _finalize_list.insert((TypedWritable *)new_pointer);
503  _finalize_list.erase(fi);
504  }
505 
506  return true;
507 }
508 
509 
510 /**
511  * Reads a TypeHandle out of the Datagram.
512  */
515  // We encode TypeHandles within the Bam file by writing a unique index
516  // number for each one to the file. When we write a particular TypeHandle
517  // for the first time, we assign it a new index number and then immediately
518  // follow it by its definition; when we write the same TypeHandle on
519  // subsequent times we only write the index number.
520 
521  // Thus, to read a TypeHandle, we first read the index number. If it is a
522  // number we have not yet encountered, we must then read the definition.
523 
524  // Here's the index number.
525  int id = scan.get_uint16();
526 
527  if (id == 0) {
528  // Index number 0 is always, by convention, TypeHandle::none().
529  return TypeHandle::none();
530  }
531 
532  IndexMap::const_iterator mi = _index_map.find(id);
533  if (mi != _index_map.end()) {
534  // We've encountered this index number before, so there should be no type
535  // definition following the id. Simply return the TypeHandle we
536  // previously associated with the id.
537  TypeHandle type = (*mi).second;
538  return type;
539  }
540 
541  // We haven't encountered this index number before. This means it will be
542  // immediately followed by the type definition. This consists of the string
543  // name, followed by the list of parent TypeHandles for this type.
544 
545  string name = scan.get_string();
546  bool new_type = false;
547 
548  TypeHandle type = TypeRegistry::ptr()->find_type(name);
549  if (type == TypeHandle::none()) {
550  // We've never heard of this type before! This is really an error
551  // condition, but we'll do the best we can and declare it on-the-fly.
552 
554  bam_cat.warning()
555  << "Bam file '" << get_filename() << "' contains objects of unknown type: "
556  << type << "\n";
557  new_type = true;
558  _new_types.insert(type);
559  }
560 
561  // Now pick up the derivation information.
562  int num_parent_classes = scan.get_uint8();
563  for (int i = 0; i < num_parent_classes; i++) {
564  TypeHandle parent_type = read_handle(scan);
565  if (new_type) {
566  TypeRegistry::ptr()->record_derivation(type, parent_type);
567  } else {
568  if (type.get_parent_towards(parent_type) != parent_type) {
569  if (bam_cat.is_debug()) {
570  bam_cat.debug()
571  << "Bam file indicates a derivation of " << type
572  << " from " << parent_type << " which is no longer true.\n";
573  }
574  }
575  }
576  }
577 
578  bool inserted = _index_map.insert(IndexMap::value_type(id, type)).second;
579  nassertr(inserted, type);
580 
581  if (bam_cat.is_spam()) {
582  bam_cat.spam()
583  << "Read TypeHandle for " << type << ".\n";
584  }
585 
586  return type;
587 }
588 
589 /**
590  * The interface for reading a pointer to another object from a Bam file.
591  * Objects reading themselves from a Bam file should call this when they
592  * expect to read a pointer to some other object. This function reads
593  * whatever is stored in the bam file to represent the pointer, and advances
594  * the datagram iterator accordingly.
595  *
596  * Rather than returning a pointer immediately, this function reads the
597  * internal pointer information from the datagram and queues up the request.
598  * The pointer itself may not be available until later (it may be a pointer to
599  * an object that appears later in the Bam file). Later, when all pointers
600  * are available, the complete_pointers() callback function will be called
601  * with an array of actual pointers, one for each time read_pointer() was
602  * called. It is then the calling object's responsibility to store these
603  * pointers in the object properly.
604  *
605  * We don't know what the final pointer will be yet, but we do know whether it
606  * was NULL, so this method returns true if the pointer is non-NULL, false if
607  * NULL.
608  */
609 bool BamReader::
612 
613  nassertr(_now_creating != _created_objs.end(), false);
614  int requestor_id = (*_now_creating).first;
615 
616  // Read the object ID, and associate it with the requesting object.
617  int object_id = read_object_id(scan);
618 
619  PointerReference &pref = _object_pointers[requestor_id];
620  if (_reading_cycler == nullptr) {
621  // This is not being read within a read_cdata() call.
622  pref._objects.push_back(object_id);
623  } else {
624  // This *is* being read within a read_cdata() call.
625  pref._cycler_pointers[_reading_cycler].push_back(object_id);
626  }
627 
628  // If the object ID is zero (which indicates a NULL pointer), we don't have
629  // to do anything else.
630  if (object_id != 0) {
631  /*
632  CreatedObj new_created_obj;
633  _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).second;
634  */
635 
636  if (get_file_minor_ver() < 21) {
637  // Prior to bam version 6.21, we expect to read an adjunct object for
638  // each non-NULL pointer we read.
639  _num_extra_objects++;
640  }
641 
642  return true;
643  } else {
644  return false;
645  }
646 }
647 
648 /**
649  * A convenience function to read a contiguous list of pointers. This is
650  * equivalent to calling read_pointer() count times.
651  */
652 void BamReader::
653 read_pointers(DatagramIterator &scan, int count) {
654  for (int i = 0; i < count; i++) {
655  read_pointer(scan);
656  }
657 }
658 
659 /**
660  * Reads and discards a pointer value from the Bam file. This pointer will
661  * not be counted among the pointers read for a given object, and will not be
662  * in the list of pointers passed to complete_pointers().
663  */
664 void BamReader::
666  read_object_id(scan);
667 }
668 
669 /**
670  * Reads a block of auxiliary file data from the Bam file. This can be a
671  * block of arbitrary size, and it is assumed it may be quite large. Rather
672  * than reading the entire block into memory, a file reference is returned to
673  * locate the block on disk. The data must have been written by a matching
674  * call to write_file_data().
675  */
676 void BamReader::
678  // write_file_data() actually writes the blocks in datagrams prior to this
679  // particular datagram. Assume we get the calls to read_file_data() in the
680  // same order as the corresponding calls to write_file_data(), and just pop
681  // the first one off the queue. There's no actual data written to the
682  // stream at this point.
683  nassertv(!_file_data_records.empty());
684  info = _file_data_records.front();
685  _file_data_records.pop_front();
686 }
687 
688 /**
689  * Reads in the indicated CycleData object. This should be used by classes
690  * that store some or all of their data within a CycleData subclass, in
691  * support of pipelining. This will call the virtual CycleData::fillin()
692  * method to do the actual reading.
693  */
694 void BamReader::
696  PipelineCyclerBase *old_cycler = _reading_cycler;
697  _reading_cycler = &cycler;
698  CycleData *cdata = cycler.write(Thread::get_current_thread());
699  cdata->fillin(scan, this);
700  cycler.release_write(cdata);
701  _reading_cycler = old_cycler;
702 }
703 
704 /**
705  * This flavor of read_cdata allows passing an additional parameter to
706  * cdata->fillin().
707  */
708 void BamReader::
710  void *extra_data) {
711  PipelineCyclerBase *old_cycler = _reading_cycler;
712  _reading_cycler = &cycler;
713  CycleData *cdata = cycler.write(Thread::get_current_thread());
714  cdata->fillin(scan, this, extra_data);
715  cycler.release_write(cdata);
716  _reading_cycler = old_cycler;
717 }
718 
719 /**
720  * Allows the creating object to store a temporary data value on the
721  * BamReader. This method may be called during an object's fillin() method;
722  * it will associate an integer value with an arbitrary string key (which is
723  * in turn associated with the calling object only). Later, in the
724  * complete_pointers() method, the same object may query this data again via
725  * get_int_tag().
726  *
727  * The tag string need not be unique between different objects, but it should
728  * be unique between an object and its CData object(s).
729  */
730 void BamReader::
731 set_int_tag(const string &tag, int value) {
732  nassertv(_now_creating != _created_objs.end());
733  int requestor_id = (*_now_creating).first;
734 
735  PointerReference &pref = _object_pointers[requestor_id];
736  pref._int_tags[tag] = value;
737 }
738 
739 /**
740  * Returns the value previously set via set_int_tag(). It is an error if no
741  * value has been set.
742  */
743 int BamReader::
744 get_int_tag(const string &tag) const {
745  nassertr(_now_creating != _created_objs.end(), 0);
746  int requestor_id = (*_now_creating).first;
747 
748  ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
749  nassertr(opi != _object_pointers.end(), 0);
750  const PointerReference &pref = (*opi).second;
751 
752  IntTags::const_iterator iti = pref._int_tags.find(tag);
753  nassertr(iti != pref._int_tags.end(), 0);
754  return (*iti).second;
755 }
756 
757 /**
758  * Allows the creating object to store a temporary data value on the
759  * BamReader. This method may be called during an object's fillin() method;
760  * it will associate a newly-allocated BamReaderAuxData construct with an
761  * arbitrary string key (which is in turn associated with the calling object
762  * only). Later, in the complete_pointers() method, the same object may query
763  * this data again via get_aux_tag().
764  *
765  * The BamReader will maintain the reference count on the BamReaderAuxData,
766  * and destruct it when it is cleaned up.
767  *
768  * The tag string need not be unique between different objects, but it should
769  * be unique between an object and its CData object(s).
770  */
771 void BamReader::
772 set_aux_tag(const string &tag, BamReaderAuxData *value) {
773  nassertv(_now_creating != _created_objs.end());
774  int requestor_id = (*_now_creating).first;
775 
776  PointerReference &pref = _object_pointers[requestor_id];
777  pref._aux_tags[tag] = value;
778 }
779 
780 /**
781  * Returns the value previously set via set_aux_tag(). It is an error if no
782  * value has been set.
783  */
785 get_aux_tag(const string &tag) const {
786  nassertr(_now_creating != _created_objs.end(), nullptr);
787  int requestor_id = (*_now_creating).first;
788 
789  ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
790  nassertr(opi != _object_pointers.end(), nullptr);
791  const PointerReference &pref = (*opi).second;
792 
793  AuxTags::const_iterator ati = pref._aux_tags.find(tag);
794  nassertr(ati != pref._aux_tags.end(), nullptr);
795  return (*ati).second;
796 }
797 
798 /**
799  * Should be called by an object reading itself from the Bam file to indicate
800  * that this particular object would like to receive the finalize() callback
801  * when all the objects and pointers in the Bam file are completely read.
802  *
803  * This provides a hook for objects that need to do any additional
804  * finalization work after all of their related pointers are guaranteed to be
805  * filled in.
806  */
807 void BamReader::
809  nassertv(whom != nullptr);
810 
811  if (bam_cat.is_spam()) {
812  bam_cat.spam()
813  << "register_finalize(" << (void *)whom << ") (" << whom->get_type()
814  << ")\n";
815  }
816 
817  _finalize_list.insert(whom);
818 }
819 
820 /**
821  * Called by an object reading itself from the bam file to indicate that the
822  * object pointer that will be returned is temporary, and will eventually need
823  * to be replaced with another pointer.
824  *
825  * The supplied function pointer will later be called on the object,
826  * immediately after complete_pointers() is called; it should return the new
827  * and final pointer.
828  *
829  * We use a static function pointer instead of a virtual function (as in
830  * finalize()), to allow the function to destruct the old pointer if
831  * necessary. (It is invalid to destruct the this pointer within a virtual
832  * function.)
833  */
834 void BamReader::
835 register_change_this(ChangeThisFunc func, TypedWritable *object) {
836  nassertv(_now_creating != _created_objs.end());
837  CreatedObj &created_obj = (*_now_creating).second;
838 
839 #ifndef NDEBUG
840  // Sanity check the pointer--it should always be the same pointer after we
841  // set it the first time.
842  if (created_obj._ptr == nullptr) {
843  created_obj.set_ptr(object, object->as_reference_count());
844  } else {
845  // We've previously assigned this pointer, and we should have assigned it
846  // to the same this pointer we have now.
847  nassertv(created_obj._ptr == object);
848  }
849 #endif // NDEBUG
850 
851  created_obj._change_this = func;
852  created_obj._change_this_ref = nullptr;
853 }
854 
855 /**
856  * Called by an object reading itself from the bam file to indicate that the
857  * object pointer that will be returned is temporary, and will eventually need
858  * to be replaced with another pointer.
859  *
860  * The supplied function pointer will later be called on the object,
861  * immediately after complete_pointers() is called; it should return the new
862  * and final pointer.
863  *
864  * We use a static function pointer instead of a virtual function (as in
865  * finalize()), to allow the function to destruct the old pointer if
866  * necessary. (It is invalid to destruct the this pointer within a virtual
867  * function.)
868  */
869 void BamReader::
870 register_change_this(ChangeThisRefFunc func, TypedWritableReferenceCount *object) {
871  nassertv(_now_creating != _created_objs.end());
872  CreatedObj &created_obj = (*_now_creating).second;
873 
874 #ifndef NDEBUG
875  // Sanity check the pointer--it should always be the same pointer after we
876  // set it the first time.
877  if (created_obj._ptr == nullptr) {
878  created_obj.set_ptr(object, object);
879  } else {
880  // We've previously assigned this pointer, and we should have assigned it
881  // to the same this pointer we have now.
882  nassertv(created_obj._ptr == object);
883  nassertv(created_obj._ref_ptr == object);
884  }
885 #endif // NDEBUG
886 
887  created_obj._change_this = nullptr;
888  created_obj._change_this_ref = func;
889 }
890 
891 /**
892  * Forces the finalization of a particular object. This may be called by any
893  * of the objects during finalization, to guarantee finalization ordering
894  * where it is important.
895  */
896 void BamReader::
898  if (whom == nullptr) {
899  return;
900  }
901 
902  Finalize::iterator fi = _finalize_list.find(whom);
903  if (fi != _finalize_list.end()) {
904  _finalize_list.erase(fi);
905  if (bam_cat.is_spam()) {
906  bam_cat.spam()
907  << "finalizing " << (void *)whom << " (" << whom->get_type()
908  << ")\n";
909  }
910  whom->finalize(this);
911  }
912 }
913 
914 /**
915  * This function works in conjection with register_pta(), below, to read a
916  * PointerToArray (PTA) from the Bam file, and unify references to the same
917  * PTA.
918  *
919  * The first time get_pta() encounters a particular PTA, it will return NULL.
920  * This is the indication that the caller should then read in the data
921  * associated with the PTA, and subsequently call register_pta() with the
922  * address of the filled-in array.
923  *
924  * The next time (and all subsequent times) that get_pta() encounters this
925  * same PTA, it will return the pointer that was passed with register_pta().
926  *
927  * Also see the READ_PTA() macro, which consolidates all the work that must be
928  * done to read a PTA.
929  */
930 void *BamReader::
932  nassertr(_pta_id == -1, nullptr);
933  int id = read_pta_id(scan);
934 
935  if (id == 0) {
936  // As always, a 0 ID indicates a NULL pointer. The caller will not be
937  // able to differentiate this case from that of a previously-read pointer,
938  // but that's OK because the next data in the Bam file is the length of
939  // the array, which will be zero--indicating an empty or NULL array.
940  return nullptr;
941  }
942 
943  PTAMap::iterator pi = _pta_map.find(id);
944  if (pi == _pta_map.end()) {
945  // This is the first time we've encountered this particular ID, meaning we
946  // need to read the data now and register it.
947  _pta_id = id;
948  return nullptr;
949  }
950 
951  return (*pi).second;
952 }
953 
954 /**
955  * The second part of read_pta(), this should be called with the pointer to
956  * the array that was read in after read_pta() returned NULL. This associates
957  * the pointer with the ID that was previously read, so that future calls to
958  * read_pta() will return the same pointer.
959  *
960  * Also see the READ_PTA() macro, which consolidates all the work that must be
961  * done to read a PTA.
962  */
963 void BamReader::
964 register_pta(void *ptr) {
965  if (_pta_id != -1) {
966  bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second;
967  _pta_id = -1;
968  nassertv(inserted);
969  }
970 }
971 
972 /**
973  * Handles a record that begins with the _remove_flag TypeHandle; this
974  * contains a list of object ID's that will no longer be used in this file and
975  * can safely be removed.
976  */
977 void BamReader::
978 free_object_ids(DatagramIterator &scan) {
979  // We have to fully complete any objects before we remove them. Might as
980  // well try to complete everything before we get started.
981  resolve();
982 
983  while (scan.get_remaining_size() > 0) {
984  int object_id = read_object_id(scan);
985 
986  CreatedObjs::iterator ci = _created_objs.find(object_id);
987  if (ci == _created_objs.end()) {
988  util_cat.warning()
989  << "Bam file suggests eliminating object_id " << object_id
990  << ", already gone.\n";
991  } else {
992 
993  // Make sure the object was successfully completed.
994  ObjectPointers::iterator oi = _object_pointers.find(object_id);
995  if (oi != _object_pointers.end()) {
996  util_cat.warning()
997  << "Unable to resolve object " << object_id
998  << " before removing from table.\n";
999  }
1000 
1001  _created_objs_by_pointer.erase((*ci).second._ptr);
1002  _created_objs.erase(ci);
1003  }
1004  }
1005 }
1006 
1007 
1008 /**
1009  * Reads an object id from the datagram.
1010  */
1011 int BamReader::
1012 read_object_id(DatagramIterator &scan) {
1013  int object_id;
1014 
1015  if (_long_object_id) {
1016  object_id = scan.get_uint32();
1017 
1018  } else {
1019  object_id = scan.get_uint16();
1020  if (object_id == 0xffff) {
1021  _long_object_id = true;
1022  }
1023  }
1024 
1025  return object_id;
1026 }
1027 
1028 /**
1029  * Reads an pta id from the datagram.
1030  */
1031 int BamReader::
1032 read_pta_id(DatagramIterator &scan) {
1033  int pta_id;
1034 
1035  if (_long_pta_id) {
1036  pta_id = scan.get_uint32();
1037 
1038  } else {
1039  pta_id = scan.get_uint16();
1040  if (pta_id == 0xffff) {
1041  _long_pta_id = true;
1042  }
1043  }
1044 
1045  return pta_id;
1046 }
1047 
1048 /**
1049  * The private implementation of read_object(); this reads an object from the
1050  * file and returns its object ID.
1051  */
1052 int BamReader::
1053 p_read_object() {
1054  Datagram dg;
1055 
1056  // First, read a datagram for the object.
1057  if (!get_datagram(dg)) {
1058  // When we run out of datagrams, we're at the end of the file.
1059  if (bam_cat.is_debug()) {
1060  bam_cat.debug()
1061  << "Reached end of bam source.\n";
1062  }
1063  return 0;
1064  }
1065 
1066  // Now extract the object definition from the datagram.
1067  DatagramIterator scan(dg);
1068 
1069  // First, read the BamObjectCode. In bam versions prior to 6.21, there was
1070  // no BamObjectCode in the stream.
1071  BamObjectCode boc = BOC_adjunct;
1072  if (get_file_minor_ver() >= 21) {
1073  boc = (BamObjectCode)scan.get_uint8();
1074  }
1075  switch (boc) {
1076  case BOC_push:
1077  ++_nesting_level;
1078  break;
1079 
1080  case BOC_pop:
1081  --_nesting_level;
1082  return 0;
1083 
1084  case BOC_adjunct:
1085  break;
1086 
1087  case BOC_remove:
1088  // The BOC_remove code is a special case; it begins a record that simply
1089  // lists all of the object ID's that are no longer important to the file
1090  // and may be released.
1091  free_object_ids(scan);
1092 
1093  // Now that we've freed all of the object id's indicate, read the next
1094  // object id in the stream. It's easiest to do this by calling
1095  // recursively.
1096  return p_read_object();
1097 
1098  case BOC_file_data:
1099  // Another special case. This marks an auxiliary file data record that we
1100  // skip over for now, but we note its position within the stream, so that
1101  // we can hand it to a future object who may request it.
1102  {
1103  SubfileInfo info;
1104  if (!_source->save_datagram(info)) {
1105  bam_cat.error()
1106  << "Failed to read file data.\n";
1107  return 0;
1108  }
1109  _file_data_records.push_back(info);
1110  }
1111 
1112  return p_read_object();
1113 
1114  default:
1115  bam_cat.error()
1116  << "Encountered invalid BamObjectCode 0x" << std::hex << (int)boc << std::dec << ".\n";
1117  return 0;
1118  }
1119 
1120  // An object definition in a Bam file consists of a TypeHandle definition,
1121  // defining the object's type, followed by an object ID index, defining the
1122  // particular instance (e.g. pointer) of this object.
1123 
1124  TypeHandle type = read_handle(scan);
1125 
1126  int object_id = read_object_id(scan);
1127 
1128  if (scan.get_current_index() > dg.get_length()) {
1129  bam_cat.error()
1130  << "Found truncated datagram in bam stream\n";
1131  return 0;
1132  }
1133 
1134  // There are two cases (not counting the special _remove_flag case, above).
1135  // Either this is a new object definition, or this is a reference to an
1136  // object that was previously defined.
1137 
1138  // We use the TypeHandle to differentiate these two cases. By convention,
1139  // we write a TypeHandle::none() to the Bam file when we are writing a
1140  // reference to a previously-defined object, but we write the object's
1141  // actual type when we are writing its definition right now.
1142 
1143  // Therefore, if the type is TypeHandle::none(), then we must have already
1144  // read in and created the object (although its pointers may not be fully
1145  // instantiated yet). On the other hand, if the type is anything else, then
1146  // we must read the definition to follow.
1147 
1148  if (type != TypeHandle::none()) {
1149  // Now we are going to read and create a new object.
1150 
1151  // First, we must add an entry into the map for this object ID, so that in
1152  // case this function is called recursively during the object's factory
1153  // constructor, we will have some definition for the object. For now, we
1154  // give it a NULL pointer.
1155  CreatedObj new_created_obj;
1156  CreatedObjs::iterator oi =
1157  _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first;
1158  CreatedObj &created_obj = (*oi).second;
1159 
1160  if (created_obj._ptr != nullptr) {
1161  // This object had already existed; thus, we are just receiving an
1162  // update for it.
1163 
1164  if (_object_pointers.find(object_id) != _object_pointers.end()) {
1165  // Aieee! This object isn't even complete from the last time we
1166  // encountered it in the stream! This should never happen. Something's
1167  // corrupt or the stream was maliciously crafted.
1168  bam_cat.error()
1169  << "Found object " << object_id << " in bam stream again while "
1170  << "trying to resolve its own pointers.\n";
1171  return 0;
1172  }
1173 
1174  // Update _now_creating during this call so if this function calls
1175  // read_pointer() or register_change_this() we'll match it up properly.
1176  // This might recursively call back into this p_read_object(), so be
1177  // sure to save and restore the original value of _now_creating.
1178  CreatedObjs::iterator was_creating = _now_creating;
1179  _now_creating = oi;
1180  created_obj._ptr->fillin(scan, this);
1181  _now_creating = was_creating;
1182 
1183  if (scan.get_remaining_size() > 0) {
1184  bam_cat.warning()
1185  << "Skipping " << scan.get_remaining_size() << " remaining bytes "
1186  << "in datagram containing type " << type << "\n";
1187  }
1188 
1189  } else {
1190  // We are receiving a new object. Now we can call the factory to create
1191  // the object.
1192 
1193  // Define the parameters for passing to the object factory.
1194  FactoryParams fparams;
1195  fparams.add_param(new BamReaderParam(scan, this));
1196 
1197  // As above, we update and preserve _now_creating during this call.
1198  CreatedObjs::iterator was_creating = _now_creating;
1199  _now_creating = oi;
1200  TypedWritable *object =
1201  _factory->make_instance_more_general(type, fparams);
1202  _now_creating = was_creating;
1203 
1204  // And now we can store the new object pointer in the map.
1205  nassertr(created_obj._ptr == object || created_obj._ptr == nullptr, object_id);
1206  if (object == nullptr) {
1207  created_obj.set_ptr(nullptr, nullptr);
1208  } else {
1209  created_obj.set_ptr(object, object->as_reference_count());
1210  }
1211  created_obj._created = true;
1212 
1213  if (created_obj._change_this_ref != nullptr) {
1214  // If the pointer is scheduled to change after complete_pointers(),
1215  // but we have no entry in _object_pointers for this object (and hence
1216  // no plan to call complete_pointers()), then just change the pointer
1217  // immediately.
1218  ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
1219  if (ri == _object_pointers.end()) {
1220  PT(TypedWritableReferenceCount) object_ref = (*created_obj._change_this_ref)((TypedWritableReferenceCount *)object, this);
1221  TypedWritable *new_ptr = object_ref;
1222  created_obj.set_ptr(object_ref, object_ref);
1223  created_obj._change_this = nullptr;
1224  created_obj._change_this_ref = nullptr;
1225 
1226  // Remove the pointer from the finalize list (the new pointer
1227  // presumably doesn't require finalizing).
1228  if (new_ptr != object) {
1229  _finalize_list.erase(object);
1230  }
1231  object = new_ptr;
1232  }
1233 
1234  } else if (created_obj._change_this != nullptr) {
1235  // Non-reference-counting variant.
1236  ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
1237  if (ri == _object_pointers.end()) {
1238  TypedWritable *new_ptr = (*created_obj._change_this)(object, this);
1239  created_obj.set_ptr(new_ptr, new_ptr->as_reference_count());
1240  created_obj._change_this = nullptr;
1241  created_obj._change_this_ref = nullptr;
1242 
1243  if (new_ptr != object) {
1244  _finalize_list.erase(object);
1245  }
1246  object = new_ptr;
1247  }
1248  }
1249 
1250  _created_objs_by_pointer[created_obj._ptr].push_back(object_id);
1251 
1252  // Just some sanity checks
1253  if (object == nullptr) {
1254  if (bam_cat.is_debug()) {
1255  bam_cat.debug()
1256  << "Unable to create an object of type " << type << std::endl;
1257  }
1258 
1259  } else if (object->get_type() != type) {
1260  if (_new_types.find(type) != _new_types.end()) {
1261  // This was a type we hadn't heard of before, so it's not really
1262  // surprising we didn't know how to create it. Suppress the warning
1263  // (make it a debug statement instead).
1264  if (bam_cat.is_debug()) {
1265  bam_cat.warning()
1266  << "Attempted to create a " << type.get_name() \
1267  << " but a " << object->get_type() \
1268  << " was created instead." << std::endl;
1269  }
1270 
1271  } else {
1272  // This was a normal type that we should have known how to create.
1273  // Report the error.
1274  bam_cat.warning()
1275  << "Attempted to create a " << type.get_name() \
1276  << " but a " << object->get_type() \
1277  << " was created instead." << std::endl;
1278  }
1279 
1280  } else {
1281  if (bam_cat.is_spam()) {
1282  bam_cat.spam()
1283  << "Read a " << object->get_type() << ": " << (void *)object
1284  << " (id=" << object_id << ")\n";
1285  }
1286  }
1287  }
1288 
1289  // Sanity check that we read the expected number of bytes.
1290  if (scan.get_current_index() > dg.get_length()) {
1291  bam_cat.error()
1292  << "End of datagram reached while reading bam object "
1293  << type << ": " << (void *)created_obj._ptr << "\n";
1294  }
1295  }
1296 
1297  return object_id;
1298 }
1299 
1300 /**
1301  * Checks whether all of the pointers a particular object is waiting for have
1302  * been filled in yet. If they have, calls complete_pointers() on the object
1303  * and returns true; otherwise, returns false.
1304  */
1305 bool BamReader::
1306 resolve_object_pointers(TypedWritable *object,
1307  BamReader::PointerReference &pref) {
1308  // Some objects further require all of their nested objects to have been
1309  // completed (i.e. complete_pointers has been called on each nested object)
1310  // before they can themselves be completed.
1311  bool require_fully_complete = object->require_fully_complete();
1312 
1313  // First do the PipelineCycler objects.
1314  CyclerPointers::iterator ci;
1315  ci = pref._cycler_pointers.begin();
1316  while (ci != pref._cycler_pointers.end()) {
1317  PipelineCyclerBase *cycler = (*ci).first;
1318  const vector_int &pointer_ids = (*ci).second;
1319 
1320  if (resolve_cycler_pointers(cycler, pointer_ids, require_fully_complete)) {
1321  // Now remove this cycler from the list of things that need completion.
1322  // We have to be a bit careful when deleting things from the STL
1323  // container while we are traversing it.
1324  CyclerPointers::iterator old = ci;
1325  ++ci;
1326  pref._cycler_pointers.erase(old);
1327 
1328  } else {
1329  // Couldn't complete this cycler yet; it'll wait for next time.
1330  ++ci;
1331  }
1332  }
1333 
1334  if (!pref._cycler_pointers.empty()) {
1335  // If we didn't get all the cyclers, we have to wait.
1336  if (bam_cat.is_spam()) {
1337  bam_cat.spam()
1338  << "some cyclers pending: complete_pointers for " << (void *)object
1339  << " (" << object->get_type() << ")\n";
1340  }
1341  return false;
1342  }
1343 
1344  // Now make sure we have all of the pointers this object is waiting for. If
1345  // any of the pointers has not yet been read in, we can't resolve this
1346  // object--we can't do anything for a given object until we have *all*
1347  // outstanding pointers for that object.
1348  bool is_complete = true;
1349 
1350  vector_typedWritable references;
1351  references.reserve(pref._objects.size());
1352 
1353  vector_int::const_iterator pi;
1354  for (pi = pref._objects.begin();
1355  pi != pref._objects.end() && is_complete;
1356  ++pi) {
1357  int child_id = (*pi);
1358  if (child_id == 0) {
1359  // A NULL pointer is a NULL pointer.
1360  references.push_back(nullptr);
1361  continue;
1362  }
1363 
1364  // See if we have the pointer available now.
1365  CreatedObjs::const_iterator oi = _created_objs.find(child_id);
1366  if (oi == _created_objs.end()) {
1367  // No, too bad.
1368  is_complete = false;
1369  break;
1370  }
1371 
1372  const CreatedObj &child_obj = (*oi).second;
1373  if (!child_obj._created) {
1374  // The child object hasn't yet been created.
1375  is_complete = false;
1376  break;
1377  }
1378 
1379  if (child_obj._change_this != nullptr || child_obj._change_this_ref != nullptr) {
1380  // It's been created, but the pointer might still change.
1381  is_complete = false;
1382  break;
1383  }
1384 
1385  if (require_fully_complete &&
1386  _object_pointers.find(child_id) != _object_pointers.end()) {
1387  // It's not yet complete itself.
1388  is_complete = false;
1389  break;
1390  }
1391 
1392  // Yes, it's ready.
1393  references.push_back(child_obj._ptr);
1394  }
1395 
1396  if (is_complete) {
1397  // Okay, here's the complete list of pointers for you!
1398  nassertr(references.size() == pref._objects.size(), false);
1399 
1400  if (bam_cat.is_spam()) {
1401  bam_cat.spam()
1402  << "complete_pointers for " << (void *)object
1403  << " (" << object->get_type() << "), " << references.size()
1404  << " pointers.\n";
1405  }
1406  int num_completed = 0;
1407  if (!references.empty()) {
1408  num_completed = object->complete_pointers(&references[0], this);
1409  }
1410  if (num_completed != (int)references.size()) {
1411  bam_cat.warning()
1412  << object->get_type() << " completed " << num_completed
1413  << " of " << references.size() << " pointers.\n";
1414  nassertr(num_completed < (int)references.size(), true);
1415  }
1416  return true;
1417 
1418  } else {
1419  if (bam_cat.is_spam()) {
1420  bam_cat.spam()
1421  << "not ready: complete_pointers for " << (void *)object
1422  << " (" << object->get_type() << ")\n";
1423  }
1424  }
1425 
1426  return false;
1427 }
1428 
1429 /**
1430  * Checks whether all of the pointers a particular PipelineCycler is waiting
1431  * for have been filled in yet. If they have, calls complete_pointers() on
1432  * the cycler and returns true; otherwise, returns false.
1433  */
1434 bool BamReader::
1435 resolve_cycler_pointers(PipelineCyclerBase *cycler,
1436  const vector_int &pointer_ids,
1437  bool require_fully_complete) {
1438  // Now make sure we have all of the pointers this cycler is waiting for. If
1439  // any of the pointers has not yet been read in, we can't resolve this
1440  // cycler--we can't do anything for a given cycler until we have *all*
1441  // outstanding pointers for that cycler.
1442 
1443  bool is_complete = true;
1444  vector_typedWritable references;
1445 
1446  vector_int::const_iterator pi;
1447  for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
1448  int child_id = (*pi);
1449 
1450  if (child_id == 0) {
1451  // A NULL pointer is a NULL pointer.
1452  references.push_back(nullptr);
1453  continue;
1454  }
1455 
1456  // See if we have the pointer available now.
1457  CreatedObjs::const_iterator oi = _created_objs.find(child_id);
1458  if (oi == _created_objs.end()) {
1459  // No, too bad.
1460  is_complete = false;
1461  break;
1462  }
1463 
1464  const CreatedObj &child_obj = (*oi).second;
1465  if (child_obj._change_this != nullptr || child_obj._change_this_ref != nullptr) {
1466  // It's been created, but the pointer might still change.
1467  is_complete = false;
1468  break;
1469  }
1470 
1471  if (require_fully_complete &&
1472  _object_pointers.find(child_id) != _object_pointers.end()) {
1473  // It's not yet complete itself.
1474  is_complete = false;
1475  break;
1476  }
1477 
1478  // Yes, it's ready.
1479  references.push_back(child_obj._ptr);
1480  }
1481 
1482  if (is_complete) {
1483  // Okay, here's the complete list of pointers for you!
1484  CycleData *cdata = cycler->write(Thread::get_current_thread());
1485  if (bam_cat.is_spam()) {
1486  bam_cat.spam()
1487  << "complete_pointers for CycleData object " << (void *)cdata
1488  << "\n";
1489  }
1490  int num_completed = cdata->complete_pointers(&references[0], this);
1491  cycler->release_write(cdata);
1492  if (num_completed != (int)references.size()) {
1493  bam_cat.warning()
1494  << "CycleData object completed " << num_completed
1495  << " of " << references.size() << " pointers.\n";
1496  nassertr(num_completed < (int)references.size(), true);
1497  }
1498  return true;
1499  }
1500 
1501  return false;
1502 }
1503 
1504 /**
1505  * Should be called after all objects have been read, this will finalize all
1506  * the objects that registered themselves for the finalize callback.
1507  */
1508 void BamReader::
1509 finalize() {
1510  if (bam_cat.is_debug()) {
1511  bam_cat.debug()
1512  << "Finalizing bam source\n";
1513  }
1514 
1515  Finalize::iterator fi = _finalize_list.begin();
1516  while (fi != _finalize_list.end()) {
1517  TypedWritable *object = (*fi);
1518  nassertv(object != nullptr);
1519  _finalize_list.erase(fi);
1520  if (bam_cat.is_spam()) {
1521  bam_cat.spam()
1522  << "finalizing " << (void *)object << " (" << object->get_type()
1523  << ")\n";
1524  }
1525  object->finalize(this);
1526  _aux_data.erase(object);
1527  fi = _finalize_list.begin();
1528  }
1529 
1530  // Now clear the aux data of all objects, except the NULL object.
1531  if (!_aux_data.empty()) {
1532  AuxDataTable::iterator ti = _aux_data.find(nullptr);
1533 
1534  if (ti != _aux_data.end()) {
1535  if (_aux_data.size() > 1) {
1536  // Move the NULL data to the new table; remove the rest.
1537  AuxDataTable new_aux_data;
1538  AuxDataTable::iterator nti =
1539  new_aux_data.insert(AuxDataTable::value_type(nullptr, AuxDataNames())).first;
1540  (*nti).second.swap((*ti).second);
1541  _aux_data.swap(new_aux_data);
1542  }
1543  } else {
1544  // There's no NULL data; clear the whole table.
1545  _aux_data.clear();
1546  }
1547  }
1548 }
BamReader::read_handle
TypeHandle read_handle(DatagramIterator &scan)
Reads a TypeHandle out of the Datagram.
Definition: bamReader.cxx:514
DatagramGenerator
This class defines the abstract interace to any source of datagrams, whether it be from a file or fro...
Definition: datagramGenerator.h:30
DatagramIterator::get_string
std::string get_string()
Extracts a variable-length string.
Definition: datagramIterator.cxx:26
TypeRegistry::register_dynamic_type
TypeHandle register_dynamic_type(const std::string &name)
Registers a new type on-the-fly, presumably at runtime.
Definition: typeRegistry.cxx:121
TypeHandle::get_name
get_name
Returns the name of the type.
Definition: typeHandle.h:136
CycleData
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader::set_source
set_source
Changes the source of future datagrams for this BamReader.
Definition: bamReader.h:154
TypeRegistry::find_type
TypeHandle find_type(const std::string &name) const
Looks for a previously-registered type of the given name.
Definition: typeRegistry.cxx:233
DatagramIterator::get_uint16
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
Definition: datagramIterator.I:145
DatagramIterator::get_current_index
size_t get_current_index() const
Returns the current position within the datagram of the next piece of data to extract.
Definition: datagramIterator.I:471
BamReader::get_int_tag
int get_int_tag(const std::string &tag) const
Returns the value previously set via set_int_tag().
Definition: bamReader.cxx:744
TypeHandle::get_parent_towards
TypeHandle get_parent_towards(TypeHandle ancestor, TypedObject *object=nullptr) const
Returns the parent class that is in a direct line of inheritance to the indicated ancestor class.
Definition: typeHandle.I:170
pandabase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ReferenceCount
A base class for all things that want to be reference-counted.
Definition: referenceCount.h:38
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
pmap
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
Thread::consider_yield
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
Definition: thread.I:212
BamReader::get_aux_tag
BamReaderAuxData * get_aux_tag(const std::string &tag) const
Returns the value previously set via set_aux_tag().
Definition: bamReader.cxx:785
bam.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader::register_change_this
void register_change_this(ChangeThisFunc func, TypedWritable *whom)
Called by an object reading itself from the bam file to indicate that the object pointer that will be...
Definition: bamReader.cxx:835
BamEnums::BamObjectCode
BamObjectCode
This is the code written along with each object.
Definition: bamEnums.h:46
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReaderParam
The parameters that are passed through the Factory to any object constructing itself from a Bam file.
Definition: bamReaderParam.h:28
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
DatagramGenerator::save_datagram
virtual bool save_datagram(SubfileInfo &info)
Skips over the next datagram without extracting it, but saves the relevant file information in the Su...
Definition: datagramGenerator.cxx:36
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
pnotify.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Thread::get_current_thread
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
BamEnums::BamEndian
BamEndian
This defines an enumerated type used to represent the endianness of certain numeric values stored in ...
Definition: bamEnums.h:32
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PipelineCyclerTrivialImpl::release_write
void release_write(CycleData *pointer)
Releases a pointer previously obtained via a call to write().
Definition: pipelineCyclerTrivialImpl.I:184
BamReader::register_finalize
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Definition: bamReader.cxx:808
BamReader::init
bool init()
Initializes the BamReader prior to reading any objects from its source.
Definition: bamReader.cxx:85
TypedWritable::finalize
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Definition: typedWritable.cxx:113
BamReader::read_pointers
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:653
DatagramIterator::get_bool
bool get_bool()
Extracts a boolean value.
Definition: datagramIterator.I:48
BamReader::read_cdata
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:695
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
BamReader::read_object
TypedWritable * read_object()
Reads a single object from the Bam file.
Definition: bamReader.cxx:224
BamReader::set_int_tag
void set_int_tag(const std::string &tag, int value)
Allows the creating object to store a temporary data value on the BamReader.
Definition: bamReader.cxx:731
BamReader::register_pta
void register_pta(void *ptr)
The second part of read_pta(), this should be called with the pointer to the array that was read in a...
Definition: bamReader.cxx:964
BamReader::get_filename
get_filename
If a BAM is a file, then the BamReader should contain the name of the file.
Definition: bamReader.h:155
CycleData::fillin
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
Definition: cycleData.cxx:58
TypeRegistry::record_derivation
void record_derivation(TypeHandle child, TypeHandle parent)
Records that the type referenced by child inherits directly from the type referenced by parent.
Definition: typeRegistry.cxx:159
BamReader::read_file_data
void read_file_data(SubfileInfo &info)
Reads a block of auxiliary file data from the Bam file.
Definition: bamReader.cxx:677
BamReader::change_pointer
bool change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer)
Indicates that an object recently read from the bam stream should be replaced with a new object.
Definition: bamReader.cxx:464
Datagram::get_length
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
PipelineCyclerTrivialImpl
This is the trivial, non-threaded implementation of PipelineCyclerBase.
Definition: pipelineCyclerTrivialImpl.h:41
Factory
A Factory can be used to create an instance of a particular subclass of some general base class.
Definition: factory.h:34
TypedWritable::as_reference_count
virtual ReferenceCount * as_reference_count()
Returns the pointer cast to a ReferenceCount pointer, if it is in fact of that type.
Definition: typedWritable.cxx:121
BamReader::resolve
bool resolve()
This may be called at any time during processing of the Bam file to resolve all the known pointers so...
Definition: bamReader.cxx:325
pipelineCyclerBase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PipelineCyclerTrivialImpl::write
CycleData * write(Thread *current_thread)
Returns a non-const CycleData pointer, filled with a unique copy of the data for the current stage of...
Definition: pipelineCyclerTrivialImpl.I:107
DatagramIterator::get_remaining_size
size_t get_remaining_size() const
Return the bytes left in the datagram.
Definition: datagramIterator.I:454
Factory::make_instance_more_general
Type * make_instance_more_general(TypeHandle handle, const FactoryParams &params=FactoryParams())
Attempts to create an instance of the type requested, or some base type of the type requested.
Definition: factory.I:48
BamReader::set_aux_data
void set_aux_data(TypedWritable *obj, const std::string &name, AuxData *data)
Associates an arbitrary block of data with the indicated object (or NULL), and the indicated name.
Definition: bamReader.cxx:167
BamReader::finalize_now
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
Definition: bamReader.cxx:897
BamReader::read_pointer
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
BamReader::skip_pointer
void skip_pointer(DatagramIterator &scan)
Reads and discards a pointer value from the Bam file.
Definition: bamReader.cxx:665
TypeRegistry::ptr
static TypeRegistry * ptr()
Returns the pointer to the global TypeRegistry object.
Definition: typeRegistry.I:30
BamReader::get_aux_data
AuxData * get_aux_data(TypedWritable *obj, const std::string &name) const
Returns the pointer previously associated with the bam reader by a previous call to set_aux_data(),...
Definition: bamReader.cxx:189
TypedWritableReferenceCount
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
Definition: typedWritableReferenceCount.h:31
BamReader::get_file_minor_ver
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DatagramIterator::get_uint32
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
Definition: datagramIterator.I:164
DatagramIterator::get_uint8
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
Definition: datagramIterator.I:72
BamReader::set_aux_tag
void set_aux_tag(const std::string &tag, BamReaderAuxData *value)
Allows the creating object to store a temporary data value on the BamReader.
Definition: bamReader.cxx:772
BamReader::AuxData
Definition: bamReader.h:228
BamReader::get_pta
void * get_pta(DatagramIterator &scan)
This function works in conjection with register_pta(), below, to read a PointerToArray (PTA) from the...
Definition: bamReader.cxx:931
SubfileInfo
This class records a particular byte sub-range within an existing file on disk.
Definition: subfileInfo.h:26
CycleData::complete_pointers
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: cycleData.cxx:48
BamReaderAuxData
Stores auxiliary data that may be piggybacked on the BamReader during each object's read pass.
Definition: bamReader.h:61