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 }
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
void read_file_data(SubfileInfo &info)
Reads a block of auxiliary file data from the Bam file.
Definition: bamReader.cxx:677
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
bool get_bool()
Extracts a boolean value.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Stores auxiliary data that may be piggybacked on the BamReader during each object's read pass.
Definition: bamReader.h:61
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
A Factory can be used to create an instance of a particular subclass of some general base class.
Definition: factory.h:34
virtual ReferenceCount * as_reference_count()
Returns the pointer cast to a ReferenceCount pointer, if it is in fact of that type.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
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
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:695
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
TypedWritable * read_object()
Reads a single object from the Bam file.
Definition: bamReader.cxx:224
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
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void skip_pointer(DatagramIterator &scan)
Reads and discards a pointer value from the Bam file.
Definition: bamReader.cxx:665
This is the trivial, non-threaded implementation of PipelineCyclerBase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle register_dynamic_type(const std::string &name)
Registers a new type on-the-fly, presumably at runtime.
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
TypeHandle find_type(const std::string &name) const
Looks for a previously-registered type of the given name.
int get_int_tag(const std::string &tag) const
Returns the value previously set via set_int_tag().
Definition: bamReader.cxx:744
size_t get_remaining_size() const
Return the bytes left in the datagram.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CycleData * write(Thread *current_thread)
Returns a non-const CycleData pointer, filled with a unique copy of the data for the current stage of...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_string()
Extracts a variable-length string.
get_name
Returns the name of the type.
Definition: typeHandle.h:136
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool init()
Initializes the BamReader prior to reading any objects from its source.
Definition: bamReader.cxx:85
size_t get_current_index() const
Returns the current position within the datagram of the next piece of data to extract.
virtual bool save_datagram(SubfileInfo &info)
Skips over the next datagram without extracting it, but saves the relevant file information in the Su...
set_source
Changes the source of future datagrams for this BamReader.
Definition: bamReader.h:151
BamReaderAuxData * get_aux_tag(const std::string &tag) const
Returns the value previously set via set_aux_tag().
Definition: bamReader.cxx:785
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:653
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
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
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
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
Definition: bamReader.cxx:897
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
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
static TypeRegistry * ptr()
Returns the pointer to the global TypeRegistry object.
Definition: typeRegistry.I:30
A base class for all things that want to be reference-counted.
void release_write(CycleData *pointer)
Releases a pointer previously obtained via a call to write().
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
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
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
This class records a particular byte sub-range within an existing file on disk.
Definition: subfileInfo.h:26
A class to retrieve the individual data elements previously stored in a Datagram.
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
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
The parameters that are passed through the Factory to any object constructing itself from a Bam file.
get_filename
If a BAM is a file, then the BamReader should contain the name of the file.
Definition: bamReader.h:155
This class defines the abstract interace to any source of datagrams, whether it be from a file or fro...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void record_derivation(TypeHandle child, TypeHandle parent)
Records that the type referenced by child inherits directly from the type referenced by parent.
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
TypeHandle read_handle(DatagramIterator &scan)
Reads a TypeHandle out of the Datagram.
Definition: bamReader.cxx:514
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
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