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