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