Panda3D
 All Classes Functions Variables Enumerations
bamReader.cxx
00001 // Filename: bamReader.cxx
00002 // Created by:  jason (12Jun00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pandabase.h"
00016 #include "pnotify.h"
00017 
00018 #include "bam.h"
00019 #include "bamReader.h"
00020 #include "datagramIterator.h"
00021 #include "config_util.h"
00022 #include "pipelineCyclerBase.h"
00023 
00024 TypeHandle BamReaderAuxData::_type_handle;
00025 
00026 WritableFactory *BamReader::_factory = (WritableFactory*)0L;
00027 BamReader *const BamReader::Null = (BamReader*)0L;
00028 WritableFactory *const BamReader::NullFactory = (WritableFactory*)0L;
00029 
00030 BamReader::NewTypes BamReader::_new_types;
00031 
00032 const int BamReader::_cur_major = _bam_major_ver;
00033 const int BamReader::_cur_minor = _bam_minor_ver;
00034 
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: BamReader::Constructor
00038 //       Access: Published
00039 //  Description:
00040 ////////////////////////////////////////////////////////////////////
00041 BamReader::
00042 BamReader(DatagramGenerator *source)
00043   : _source(source)
00044 {
00045   _needs_init = true;
00046   _num_extra_objects = 0;
00047   _nesting_level = 0;
00048   _now_creating = _created_objs.end();
00049   _reading_cycler = (PipelineCyclerBase *)NULL;
00050   _pta_id = -1;
00051   _long_object_id = false;
00052   _long_pta_id = false;
00053 }
00054 
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: BamReader::Destructor
00058 //       Access: Published
00059 //  Description:
00060 ////////////////////////////////////////////////////////////////////
00061 BamReader::
00062 ~BamReader() {
00063   nassertv(_num_extra_objects == 0);
00064   nassertv(_nesting_level == 0);
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: BamReader::set_source
00069 //       Access: Published
00070 //  Description: Changes the source of future datagrams for this
00071 //               BamReader.  This also implicitly calls init() if it
00072 //               has not already been called.
00073 ////////////////////////////////////////////////////////////////////
00074 void BamReader::
00075 set_source(DatagramGenerator *source) {
00076   _source = source;
00077   if (_needs_init && _source != NULL) {
00078     bool success = init();
00079     nassertv(success);
00080   }
00081 }
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: BamReader::init
00085 //       Access: Published
00086 //  Description: Initializes the BamReader prior to reading any
00087 //               objects from its source.  This includes reading the
00088 //               Bam header.
00089 //
00090 //               This returns true if the BamReader successfully
00091 //               initialized, false otherwise.
00092 ////////////////////////////////////////////////////////////////////
00093 bool BamReader::
00094 init() {
00095   nassertr(_source != NULL, false);
00096   nassertr(_needs_init, false);
00097   _needs_init = false;
00098   Datagram header;
00099 
00100   if (_source->is_error()) {
00101     return false;
00102   }
00103 
00104   if (!get_datagram(header)) {
00105     bam_cat.error()
00106       << "Unable to read Bam header.\n";
00107     return false;
00108   }
00109 
00110   DatagramIterator scan(header);
00111 
00112   _file_major = scan.get_uint16();
00113   _file_minor = scan.get_uint16();
00114 
00115   // If the major version is different, or the minor version is
00116   // *newer*, we can't safely load the file.
00117   if (_file_major != _bam_major_ver || 
00118       _file_minor < _bam_first_minor_ver ||
00119       _file_minor > _bam_minor_ver) {
00120     bam_cat.error()
00121       << "Bam file is version " << _file_major << "." << _file_minor
00122       << ".\n";
00123 
00124     if (_bam_minor_ver == _bam_first_minor_ver) {
00125       bam_cat.error()
00126         << "This program can only load version "
00127         << _bam_major_ver << "." << _bam_first_minor_ver << " bams.\n";
00128     } else {
00129       bam_cat.error()
00130         << "This program can only load version "
00131         << _bam_major_ver << "." << _bam_first_minor_ver << " through "
00132         << _bam_major_ver << "." << _bam_minor_ver << " bams.\n";
00133     }
00134 
00135     return false;
00136   }
00137 
00138   _file_endian = (BamEndian)scan.get_uint8();
00139 
00140   _file_stdfloat_double = false;
00141   if (_file_minor >= 27) {
00142     _file_stdfloat_double = scan.get_bool();
00143   }
00144 
00145   return true;
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: BamReader::set_aux_data
00150 //       Access: Published
00151 //  Description: Associates an arbitrary block of data with the
00152 //               indicated object (or NULL), and the indicated name.
00153 //
00154 //               This is intended to provide a place for temporary
00155 //               storage for objects reading themselves from the bam
00156 //               file.  To use it, inherit from BamReader::AuxData and
00157 //               store whatever data you like there.  Then associate
00158 //               your AuxData with the object as it is being read with
00159 //               set_aux_data().  You may later set the aux data to
00160 //               NULL to remove it; or it will automatically be
00161 //               removed (and deleted) after finalize() is called for
00162 //               the object in question.
00163 //
00164 //               If the TypedWritable pointer is NULL, the the aux
00165 //               data is stored globally for the BamReader in general.
00166 //               This pointer is available to any bam objects, and
00167 //               will not be automatically removed until the BamReader
00168 //               itself destructs.
00169 //
00170 //               In either case, the name is just an arbitrary
00171 //               user-defined key.  If there is already a data pointer
00172 //               stored for the obj/name pair, that data pointer will
00173 //               be replaced (and deleted).
00174 ////////////////////////////////////////////////////////////////////
00175 void BamReader::
00176 set_aux_data(TypedWritable *obj, const string &name, BamReader::AuxData *data) {
00177   if (data == (void *)NULL) {
00178     AuxDataTable::iterator ti = _aux_data.find(obj);
00179     if (ti != _aux_data.end()) {
00180       AuxDataNames &names = (*ti).second;
00181       names.erase(name);
00182       if (names.empty()) {
00183         _aux_data.erase(ti);
00184       }
00185     }
00186 
00187   } else {
00188     _aux_data[obj][name] = data;
00189   }
00190 }
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: BamReader::get_aux_data
00194 //       Access: Published
00195 //  Description: Returns the pointer previously associated with the
00196 //               bam reader by a previous call to set_aux_data(), or
00197 //               NULL if data with the indicated key has not been set.
00198 ////////////////////////////////////////////////////////////////////
00199 BamReader::AuxData *BamReader::
00200 get_aux_data(TypedWritable *obj, const string &name) const {
00201   AuxDataTable::const_iterator ti = _aux_data.find(obj);
00202   if (ti != _aux_data.end()) {
00203     const AuxDataNames &names = (*ti).second;
00204     AuxDataNames::const_iterator ni = names.find(name);
00205     if (ni != names.end()) {
00206       return (*ni).second;
00207     }
00208   }
00209 
00210   return NULL;
00211 }
00212 
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: BamReader::read_object
00216 //       Access: Published
00217 //  Description: Reads a single object from the Bam file.  If the
00218 //               object type is known, a new object of the appropriate
00219 //               type is created and returned; otherwise, NULL is
00220 //               returned.  NULL is also returned when the end of the
00221 //               file is reached.  is_eof() may be called to
00222 //               differentiate between these two cases.
00223 //
00224 //               This may be called repeatedly to extract out all the
00225 //               objects in the Bam file, but typically (especially
00226 //               for scene graph files, indicated with the .bam
00227 //               extension), only one object is retrieved directly
00228 //               from the Bam file: the root of the scene graph.  The
00229 //               remaining objects will all be retrieved recursively
00230 //               by the first object.
00231 //
00232 //               Note that the object returned may not yet be
00233 //               complete.  In particular, some of its pointers may
00234 //               not be filled in; you must call resolve() to fill in
00235 //               all the available pointers before you can safely use
00236 //               any objects returned by read_object().
00237 //
00238 //               This flavor of read_object() requires the caller to
00239 //               know what type of object it has received in order to
00240 //               properly manage the reference counts.
00241 ////////////////////////////////////////////////////////////////////
00242 TypedWritable *BamReader::
00243 read_object() {
00244   TypedWritable *ptr;
00245   ReferenceCount *ref_ptr;
00246 
00247   if (!read_object(ptr, ref_ptr)) {
00248     return NULL;
00249   }
00250 
00251   return ptr;
00252 }
00253 
00254 ////////////////////////////////////////////////////////////////////
00255 //     Function: BamReader::read_object
00256 //       Access: Published
00257 //  Description: Reads a single object from the Bam file.  
00258 //
00259 //               This flavor of read_object() returns both a
00260 //               TypedWritable and a ReferenceCount pointer to the
00261 //               same object, so the reference count may be tracked
00262 //               reliably, without having to know precisely what type
00263 //               of object we have.  It returns true on success, or
00264 //               false on failure.
00265 ////////////////////////////////////////////////////////////////////
00266 bool BamReader::
00267 read_object(TypedWritable *&ptr, ReferenceCount *&ref_ptr) {
00268   ptr = NULL;
00269   ref_ptr = NULL;
00270   nassertr(_num_extra_objects == 0, false);
00271 
00272   int start_level = _nesting_level;
00273 
00274   // First, read the base object.
00275   int object_id = p_read_object();
00276 
00277   // Now that object might have included some pointers to other
00278   // objects, which may still need to be read.  And those objects
00279   // might in turn require reading additional objects.  Read all the
00280   // remaining objects.
00281 
00282   // Prior to 6.21, we kept track of _num_extra_objects to know when
00283   // we're done.
00284   while (_num_extra_objects > 0) {
00285     p_read_object();
00286     _num_extra_objects--;
00287   }
00288 
00289   // Beginning with 6.21, we use explicit nesting commands to know
00290   // when we're done.
00291   while (_nesting_level > start_level) {
00292     p_read_object();
00293   }
00294 
00295   // Now look up the pointer of the object we read first.  It should
00296   // be available now.
00297   if (object_id == 0) {
00298     if (bam_cat.is_spam()) {
00299       bam_cat.spam()
00300         << "Returning false\n";
00301     }
00302     return false;
00303   }
00304 
00305   CreatedObjs::iterator oi = _created_objs.find(object_id);
00306 
00307   if (oi == _created_objs.end()) {
00308     bam_cat.error()
00309       << "Undefined object encountered!\n";
00310     return false;
00311 
00312   } else {
00313     CreatedObj &created_obj = (*oi).second;
00314     ptr = created_obj._ptr;
00315     ref_ptr = created_obj._ref_ptr;
00316 
00317     if (bam_cat.is_spam()) {
00318       if (ptr != (TypedWritable *)NULL) {
00319         bam_cat.spam()
00320           << "Returning object of type " << ptr->get_type() << "\n";
00321       }
00322     }
00323     if (created_obj._change_this != NULL ||
00324         created_obj._change_this_ref != NULL) {
00325       bam_cat.warning()
00326         << "Returning pointer to " << ptr->get_type()
00327         << " that might change.\n";
00328     }
00329 
00330     return true;
00331   }
00332 }
00333 
00334 ////////////////////////////////////////////////////////////////////
00335 //     Function: BamReader::resolve
00336 //       Access: Published
00337 //  Description: This may be called at any time during processing of
00338 //               the Bam file to resolve all the known pointers so
00339 //               far.  It is usually called at the end of the
00340 //               processing, after all objects have been read, which
00341 //               is generally the best time to call it.
00342 //
00343 //               This must be called at least once after reading a
00344 //               particular object via get_object() in order to
00345 //               validate that object.
00346 //
00347 //               The return value is true if all objects have been
00348 //               resolved, or false if some objects are still
00349 //               outstanding (in which case you will need to call
00350 //               resolve() again later).
00351 ////////////////////////////////////////////////////////////////////
00352 bool BamReader::
00353 resolve() {
00354   bool all_completed;
00355   bool any_completed_this_pass;
00356 
00357   do {
00358     if (bam_cat.is_spam()) {
00359       bam_cat.spam()
00360         << "resolve pass begin\n";
00361     }
00362     all_completed = true;
00363     any_completed_this_pass = false;
00364     
00365     ObjectPointers::iterator oi;
00366     oi = _object_pointers.begin();
00367     while (oi != _object_pointers.end()) {
00368       int object_id = (*oi).first;
00369       PointerReference &pref = (*oi).second;
00370 
00371       CreatedObjs::iterator ci = _created_objs.find(object_id);
00372       nassertr(ci != _created_objs.end(), false);
00373 
00374       CreatedObj &created_obj = (*ci).second;
00375       
00376       TypedWritable *object_ptr = created_obj._ptr;
00377 
00378       // Update _now_creating, so a call to get_int_tag() from within
00379       // complete_pointers() will come to the right place.
00380       CreatedObjs::iterator was_creating = _now_creating;
00381       _now_creating = ci;
00382       
00383       if (resolve_object_pointers(object_ptr, pref)) {
00384         // Now remove this object from the list of things that need
00385         // completion.  We have to be a bit careful when deleting things
00386         // from the STL container while we are traversing it.
00387         ObjectPointers::iterator old = oi;
00388         ++oi;
00389         _object_pointers.erase(old);
00390         any_completed_this_pass = true;
00391         
00392         // Does the pointer need to change?
00393         if (created_obj._change_this_ref != NULL) {
00394           // Reference-counting variant.
00395           TypedWritableReferenceCount *object_ref_ptr = (TypedWritableReferenceCount *)object_ptr;
00396           nassertr(created_obj._ref_ptr == NULL || created_obj._ref_ptr == object_ref_ptr, false);
00397           PT(TypedWritableReferenceCount) new_ptr = created_obj._change_this_ref(object_ref_ptr, this);
00398           if (new_ptr != object_ref_ptr) {
00399             // Also update the reverse
00400             vector_int &old_refs = _created_objs_by_pointer[object_ptr];
00401             vector_int &new_refs = _created_objs_by_pointer[new_ptr];
00402             for (vector_int::const_iterator oi = old_refs.begin();
00403                  oi != old_refs.end();
00404                  ++oi) {
00405               new_refs.push_back(*oi);
00406             }
00407             _created_objs_by_pointer.erase(object_ptr);
00408 
00409             // Remove the pointer from the finalize list (the new
00410             // pointer presumably doesn't require finalizing).
00411             _finalize_list.erase(object_ptr);
00412           }
00413           created_obj.set_ptr(new_ptr, new_ptr);
00414           created_obj._change_this = NULL;
00415           created_obj._change_this_ref = NULL;
00416 
00417         } else if (created_obj._change_this != NULL) {
00418           // Non-reference-counting variant.
00419           TypedWritable *new_ptr = created_obj._change_this(object_ptr, this);
00420           if (new_ptr != object_ptr) {
00421             // Also update the reverse
00422             vector_int &old_refs = _created_objs_by_pointer[object_ptr];
00423             vector_int &new_refs = _created_objs_by_pointer[new_ptr];
00424             for (vector_int::const_iterator oi = old_refs.begin();
00425                  oi != old_refs.end();
00426                  ++oi) {
00427               new_refs.push_back(*oi);
00428             }
00429             _created_objs_by_pointer.erase(object_ptr);
00430 
00431             // Remove the pointer from the finalize list (the new
00432             // pointer presumably doesn't require finalizing).
00433             _finalize_list.erase(object_ptr);
00434           }
00435           created_obj.set_ptr(new_ptr, new_ptr->as_reference_count());
00436           created_obj._change_this = NULL;
00437           created_obj._change_this_ref = NULL;
00438         }
00439         
00440       } else {
00441         // Couldn't complete this object yet; it'll wait for next time.
00442         ++oi;
00443         all_completed = false;
00444       }
00445 
00446       _now_creating = was_creating;
00447     }
00448 
00449     if (bam_cat.is_spam()) {
00450       bam_cat.spam()
00451         << "resolve pass end: all_completed = " << all_completed
00452         << " any_completed_this_pass = " << any_completed_this_pass
00453         << "\n";
00454     }
00455   } while (!all_completed && any_completed_this_pass);
00456 
00457   if (all_completed) {
00458     finalize();
00459   } else {
00460     // Report all the uncompleted objects for no good reason.  This
00461     // will probably have to come out later when we have cases in
00462     // which some objects might legitimately be uncompleted after
00463     // calling resolve(), but for now we expect resolve() to always
00464     // succeed.
00465     ObjectPointers::const_iterator oi;
00466     for (oi = _object_pointers.begin(); 
00467          oi != _object_pointers.end();
00468          ++oi) {
00469       int object_id = (*oi).first;
00470       CreatedObjs::iterator ci = _created_objs.find(object_id);
00471       nassertr(ci != _created_objs.end(), false);
00472       CreatedObj &created_obj = (*ci).second;
00473       TypedWritable *object_ptr = created_obj._ptr;
00474 
00475       bam_cat.warning()
00476         << "Unable to complete " << object_ptr->get_type() << "\n";
00477     }
00478   }
00479 
00480   return all_completed;
00481 }
00482 
00483 ////////////////////////////////////////////////////////////////////
00484 //     Function: BamReader::change_pointer
00485 //       Access: Published
00486 //  Description: Indicates that an object recently read from the bam
00487 //               stream should be replaced with a new object.  Any
00488 //               future occurrences of the original object in the
00489 //               stream will henceforth return the new object instead.
00490 //
00491 //               The return value is true if the replacement was
00492 //               successfully made, or false if the object was not
00493 //               read from the stream (or if change_pointer had
00494 //               already been called on it).
00495 ////////////////////////////////////////////////////////////////////
00496 bool BamReader::
00497 change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer) {
00498   if (orig_pointer == new_pointer) {
00499     return false;
00500   }
00501   CreatedObjsByPointer::iterator ci = _created_objs_by_pointer.find(orig_pointer);
00502   if (ci == _created_objs_by_pointer.end()) {
00503     // No record of this object.
00504     return false;
00505   }
00506 
00507   if (bam_cat.is_spam()) {
00508     bam_cat.spam()
00509       << "change_pointer(" << (void *)orig_pointer << ", " 
00510       << (void *)new_pointer << ") (" << new_pointer->get_type() << ")\n";
00511   }
00512 
00513   const vector_int &old_refs = (*ci).second;
00514   vector_int &new_refs = _created_objs_by_pointer[new_pointer];
00515 
00516   for (vector_int::const_iterator oi = old_refs.begin(); 
00517        oi != old_refs.end();
00518        ++oi) {
00519     int object_id = (*oi);
00520 
00521     CreatedObjs::iterator ci = _created_objs.find(object_id);
00522     nassertr(ci != _created_objs.end(), false);
00523     nassertr((*ci).second._ptr == orig_pointer, false);
00524 
00525     TypedWritable *ptr = (TypedWritable *)new_pointer;
00526     (*ci).second.set_ptr(ptr, ptr->as_reference_count());
00527     new_refs.push_back(object_id);
00528   }
00529 
00530   _created_objs_by_pointer.erase(ci);
00531 
00532   // Also change the pointer on the finalize_list.
00533   Finalize::iterator fi = _finalize_list.find((TypedWritable *)orig_pointer);
00534   if (fi != _finalize_list.end()) {
00535     _finalize_list.insert((TypedWritable *)new_pointer);
00536     _finalize_list.erase(fi);
00537   }
00538 
00539   return true;
00540 }
00541 
00542 
00543 ////////////////////////////////////////////////////////////////////
00544 //     Function: BamReader::read_handle
00545 //       Access: Published
00546 //  Description: Reads a TypeHandle out of the Datagram.
00547 ////////////////////////////////////////////////////////////////////
00548 TypeHandle BamReader::
00549 read_handle(DatagramIterator &scan) {
00550   // We encode TypeHandles within the Bam file by writing a unique
00551   // index number for each one to the file.  When we write a
00552   // particular TypeHandle for the first time, we assign it a new
00553   // index number and then immediately follow it by its definition;
00554   // when we write the same TypeHandle on subsequent times we only
00555   // write the index number.
00556 
00557   // Thus, to read a TypeHandle, we first read the index number.  If
00558   // it is a number we have not yet encountered, we must then read the
00559   // definition.
00560 
00561   // Here's the index number.
00562   int id = scan.get_uint16();
00563 
00564   if (id == 0) {
00565     // Index number 0 is always, by convention, TypeHandle::none().
00566     return TypeHandle::none();
00567   }
00568 
00569   IndexMap::const_iterator mi = _index_map.find(id);
00570   if (mi != _index_map.end()) {
00571     // We've encountered this index number before, so there should be
00572     // no type definition following the id.  Simply return the
00573     // TypeHandle we previously associated with the id.
00574     TypeHandle type = (*mi).second;
00575     return type;
00576   }
00577 
00578   // We haven't encountered this index number before.  This means it
00579   // will be immediately followed by the type definition.  This
00580   // consists of the string name, followed by the list of parent
00581   // TypeHandles for this type.
00582 
00583   string name = scan.get_string();
00584   bool new_type = false;
00585 
00586   TypeHandle type = TypeRegistry::ptr()->find_type(name);
00587   if (type == TypeHandle::none()) {
00588     // We've never heard of this type before!  This is really an error
00589     // condition, but we'll do the best we can and declare it
00590     // on-the-fly.
00591 
00592     type = TypeRegistry::ptr()->register_dynamic_type(name);
00593     bam_cat.warning()
00594       << "Bam file '" << get_filename() << "' contains objects of unknown type: " 
00595       << type << "\n";
00596     new_type = true;
00597     _new_types.insert(type);
00598   }
00599 
00600   // Now pick up the derivation information.
00601   int num_parent_classes = scan.get_uint8();
00602   for (int i = 0; i < num_parent_classes; i++) {
00603     TypeHandle parent_type = read_handle(scan);
00604     if (new_type) {
00605       TypeRegistry::ptr()->record_derivation(type, parent_type);
00606     } else {
00607       if (type.get_parent_towards(parent_type) != parent_type) {
00608         if (bam_cat.is_debug()) {
00609           bam_cat.debug()
00610             << "Bam file indicates a derivation of " << type
00611             << " from " << parent_type << " which is no longer true.\n";
00612         }
00613       }
00614     }
00615   }
00616 
00617   bool inserted = _index_map.insert(IndexMap::value_type(id, type)).second;
00618   nassertr(inserted, type);
00619 
00620   if (bam_cat.is_spam()) {
00621     bam_cat.spam()
00622       << "Read TypeHandle for " << type << ".\n";
00623   }
00624 
00625   return type;
00626 }
00627 
00628 ////////////////////////////////////////////////////////////////////
00629 //     Function: BamReader::read_pointer
00630 //       Access: Public
00631 //  Description: The interface for reading a pointer to another object
00632 //               from a Bam file.  Objects reading themselves from a
00633 //               Bam file should call this when they expect to read a
00634 //               pointer to some other object.  This function reads
00635 //               whatever is stored in the bam file to represent the
00636 //               pointer, and advances the datagram iterator
00637 //               accordingly.
00638 //
00639 //               Rather than returning a pointer immediately, this
00640 //               function reads the internal pointer information from
00641 //               the datagram and queues up the request.  The pointer
00642 //               itself may not be available until later (it may be a
00643 //               pointer to an object that appears later in the Bam
00644 //               file).  Later, when all pointers are available, the
00645 //               complete_pointers() callback function will be called
00646 //               with an array of actual pointers, one for each time
00647 //               read_pointer() was called.  It is then the calling
00648 //               object's responsibility to store these pointers in the
00649 //               object properly.
00650 ////////////////////////////////////////////////////////////////////
00651 void BamReader::
00652 read_pointer(DatagramIterator &scan) {
00653   Thread::consider_yield();
00654 
00655   nassertv(_now_creating != _created_objs.end());
00656   int requestor_id = (*_now_creating).first;
00657 
00658   // Read the object ID, and associate it with the requesting object.
00659   int object_id = read_object_id(scan);
00660 
00661   PointerReference &pref = _object_pointers[requestor_id];
00662   if (_reading_cycler == (PipelineCyclerBase *)NULL) {
00663     // This is not being read within a read_cdata() call.
00664     pref._objects.push_back(object_id);
00665   } else {
00666     // This *is* being read within a read_cdata() call.
00667     pref._cycler_pointers[_reading_cycler].push_back(object_id);
00668   }
00669 
00670   // If the object ID is zero (which indicates a NULL pointer), we
00671   // don't have to do anything else.
00672   if (object_id != 0) {
00673     /*
00674     CreatedObj new_created_obj;
00675     _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).second;
00676     */
00677 
00678     if (get_file_minor_ver() < 21) {
00679       // Prior to bam version 6.21, we expect to read an adjunct
00680       // object for each non-NULL pointer we read.
00681       _num_extra_objects++;
00682     }
00683   }
00684 }
00685 
00686 ////////////////////////////////////////////////////////////////////
00687 //     Function: BamReader::read_pointers
00688 //       Access: Public
00689 //  Description: A convenience function to read a contiguous list of
00690 //               pointers.  This is equivalent to calling
00691 //               read_pointer() count times.
00692 ////////////////////////////////////////////////////////////////////
00693 void BamReader::
00694 read_pointers(DatagramIterator &scan, int count) {
00695   for (int i = 0; i < count; i++) {
00696     read_pointer(scan);
00697   }
00698 }
00699 
00700 ////////////////////////////////////////////////////////////////////
00701 //     Function: BamReader::skip_pointer
00702 //       Access: Public
00703 //  Description: Reads and discards a pointer value from the Bam file.
00704 //               This pointer will not be counted among the pointers
00705 //               read for a given object, and will not be in the list
00706 //               of pointers passed to complete_pointers().
00707 ////////////////////////////////////////////////////////////////////
00708 void BamReader::
00709 skip_pointer(DatagramIterator &scan) {
00710   read_object_id(scan);
00711 }
00712 
00713 ////////////////////////////////////////////////////////////////////
00714 //     Function: BamReader::read_file_data
00715 //       Access: Public
00716 //  Description: Reads a block of auxiliary file data from the Bam
00717 //               file.  This can be a block of arbitrary size, and it
00718 //               is assumed it may be quite large.  Rather than
00719 //               reading the entire block into memory, a file
00720 //               reference is returned to locate the block on disk.
00721 //               The data must have been written by a matching call to
00722 //               write_file_data().
00723 ////////////////////////////////////////////////////////////////////
00724 void BamReader::
00725 read_file_data(SubfileInfo &info) {
00726   // write_file_data() actually writes the blocks in datagrams prior
00727   // to this particular datagram.  Assume we get the calls to
00728   // read_file_data() in the same order as the corresponding calls to
00729   // write_file_data(), and just pop the first one off the
00730   // queue. There's no actual data written to the stream at this
00731   // point.
00732   nassertv(!_file_data_records.empty());
00733   info = _file_data_records.front();
00734   _file_data_records.pop_front();
00735 }
00736 
00737 ////////////////////////////////////////////////////////////////////
00738 //     Function: BamReader::read_cdata
00739 //       Access: Public
00740 //  Description: Reads in the indicated CycleData object.  This should
00741 //               be used by classes that store some or all of their
00742 //               data within a CycleData subclass, in support of
00743 //               pipelining.  This will call the virtual
00744 //               CycleData::fillin() method to do the actual reading.
00745 ////////////////////////////////////////////////////////////////////
00746 void BamReader::
00747 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) {
00748   PipelineCyclerBase *old_cycler = _reading_cycler;
00749   _reading_cycler = &cycler;
00750   CycleData *cdata = cycler.write(Thread::get_current_thread());
00751   cdata->fillin(scan, this);
00752   cycler.release_write(cdata);
00753   _reading_cycler = old_cycler;
00754 }
00755 
00756 ////////////////////////////////////////////////////////////////////
00757 //     Function: BamReader::read_cdata
00758 //       Access: Public
00759 //  Description: This flavor of read_cdata allows passing an
00760 //               additional parameter to cdata->fillin().
00761 ////////////////////////////////////////////////////////////////////
00762 void BamReader::
00763 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler,
00764            void *extra_data) {
00765   PipelineCyclerBase *old_cycler = _reading_cycler;
00766   _reading_cycler = &cycler;
00767   CycleData *cdata = cycler.write(Thread::get_current_thread());
00768   cdata->fillin(scan, this, extra_data);
00769   cycler.release_write(cdata);
00770   _reading_cycler = old_cycler;
00771 }
00772 
00773 ////////////////////////////////////////////////////////////////////
00774 //     Function: BamReader::set_int_tag
00775 //       Access: Public
00776 //  Description: Allows the creating object to store a temporary data
00777 //               value on the BamReader.  This method may be called
00778 //               during an object's fillin() method; it will associate
00779 //               an integer value with an arbitrary string key (which
00780 //               is in turn associated with the calling object only).
00781 //               Later, in the complete_pointers() method, the same
00782 //               object may query this data again via get_int_tag().
00783 //
00784 //               The tag string need not be unique between different
00785 //               objects, but it should be unique between an object
00786 //               and its CData object(s).
00787 ////////////////////////////////////////////////////////////////////
00788 void BamReader::
00789 set_int_tag(const string &tag, int value) {
00790   nassertv(_now_creating != _created_objs.end());
00791   int requestor_id = (*_now_creating).first;
00792 
00793   PointerReference &pref = _object_pointers[requestor_id];
00794   pref._int_tags[tag] = value;
00795 }
00796 
00797 ////////////////////////////////////////////////////////////////////
00798 //     Function: BamReader::get_int_tag
00799 //       Access: Public
00800 //  Description: Returns the value previously set via set_int_tag().
00801 //               It is an error if no value has been set.
00802 ////////////////////////////////////////////////////////////////////
00803 int BamReader::
00804 get_int_tag(const string &tag) const {
00805   nassertr(_now_creating != _created_objs.end(), 0);
00806   int requestor_id = (*_now_creating).first;
00807 
00808   ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
00809   nassertr(opi != _object_pointers.end(), 0);
00810   const PointerReference &pref = (*opi).second;
00811 
00812   IntTags::const_iterator iti = pref._int_tags.find(tag);
00813   nassertr(iti != pref._int_tags.end(), 0);
00814   return (*iti).second;
00815 }
00816 
00817 ////////////////////////////////////////////////////////////////////
00818 //     Function: BamReader::set_aux_tag
00819 //       Access: Public
00820 //  Description: Allows the creating object to store a temporary data
00821 //               value on the BamReader.  This method may be called
00822 //               during an object's fillin() method; it will associate
00823 //               a newly-allocated BamReaderAuxData construct with an
00824 //               arbitrary string key (which is in turn associated
00825 //               with the calling object only).  Later, in the
00826 //               complete_pointers() method, the same object may query
00827 //               this data again via get_aux_tag().
00828 //
00829 //               The BamReader will maintain the reference count on
00830 //               the BamReaderAuxData, and destruct it when it is
00831 //               cleaned up.
00832 //
00833 //               The tag string need not be unique between different
00834 //               objects, but it should be unique between an object
00835 //               and its CData object(s).
00836 ////////////////////////////////////////////////////////////////////
00837 void BamReader::
00838 set_aux_tag(const string &tag, BamReaderAuxData *value) {
00839   nassertv(_now_creating != _created_objs.end());
00840   int requestor_id = (*_now_creating).first;
00841 
00842   PointerReference &pref = _object_pointers[requestor_id];
00843   pref._aux_tags[tag] = value;
00844 }
00845 
00846 ////////////////////////////////////////////////////////////////////
00847 //     Function: BamReader::get_aux_tag
00848 //       Access: Public
00849 //  Description: Returns the value previously set via set_aux_tag().
00850 //               It is an error if no value has been set.
00851 ////////////////////////////////////////////////////////////////////
00852 BamReaderAuxData *BamReader::
00853 get_aux_tag(const string &tag) const {
00854   nassertr(_now_creating != _created_objs.end(), NULL);
00855   int requestor_id = (*_now_creating).first;
00856 
00857   ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
00858   nassertr(opi != _object_pointers.end(), NULL);
00859   const PointerReference &pref = (*opi).second;
00860 
00861   AuxTags::const_iterator ati = pref._aux_tags.find(tag);
00862   nassertr(ati != pref._aux_tags.end(), NULL);
00863   return (*ati).second;
00864 }
00865 
00866 ////////////////////////////////////////////////////////////////////
00867 //     Function: BamReader::register_finalize
00868 //       Access: Public
00869 //  Description: Should be called by an object reading itself from the
00870 //               Bam file to indicate that this particular object
00871 //               would like to receive the finalize() callback when
00872 //               all the objects and pointers in the Bam file are
00873 //               completely read.
00874 //
00875 //               This provides a hook for objects that need to do any
00876 //               additional finalization work after all of their
00877 //               related pointers are guaranteed to be filled in.
00878 ////////////////////////////////////////////////////////////////////
00879 void BamReader::
00880 register_finalize(TypedWritable *whom) {
00881   nassertv(whom != (TypedWritable *)NULL);
00882 
00883   if (bam_cat.is_spam()) {
00884     bam_cat.spam()
00885       << "register_finalize(" << (void *)whom << ") (" << whom->get_type()
00886       << ")\n";
00887   }
00888 
00889   _finalize_list.insert(whom);
00890 }
00891 
00892 ////////////////////////////////////////////////////////////////////
00893 //     Function: BamReader::register_change_this
00894 //       Access: Public
00895 //  Description: Called by an object reading itself from the bam file
00896 //               to indicate that the object pointer that will be
00897 //               returned is temporary, and will eventually need to be
00898 //               replaced with another pointer.
00899 //
00900 //               The supplied function pointer will later be called on
00901 //               the object, immediately after complete_pointers() is
00902 //               called; it should return the new and final pointer.
00903 //
00904 //               We use a static function pointer instead of a virtual
00905 //               function (as in finalize()), to allow the function to
00906 //               destruct the old pointer if necessary.  (It is
00907 //               invalid to destruct the this pointer within a virtual
00908 //               function.)
00909 ////////////////////////////////////////////////////////////////////
00910 void BamReader::
00911 register_change_this(ChangeThisFunc func, TypedWritable *object) {
00912   nassertv(_now_creating != _created_objs.end());
00913   CreatedObj &created_obj = (*_now_creating).second;
00914 
00915 #ifndef NDEBUG
00916   // Sanity check the pointer--it should always be the same pointer
00917   // after we set it the first time.
00918   if (created_obj._ptr == (TypedWritable *)NULL) {
00919     created_obj.set_ptr(object, object->as_reference_count());
00920   } else {
00921     // We've previously assigned this pointer, and we should have
00922     // assigned it to the same this pointer we have now.
00923     nassertv(created_obj._ptr == object);
00924   }
00925 #endif  // NDEBUG
00926 
00927   created_obj._change_this = func;
00928   created_obj._change_this_ref = NULL;
00929 }
00930 
00931 ////////////////////////////////////////////////////////////////////
00932 //     Function: BamReader::register_change_this
00933 //       Access: Public
00934 //  Description: Called by an object reading itself from the bam file
00935 //               to indicate that the object pointer that will be
00936 //               returned is temporary, and will eventually need to be
00937 //               replaced with another pointer.
00938 //
00939 //               The supplied function pointer will later be called on
00940 //               the object, immediately after complete_pointers() is
00941 //               called; it should return the new and final pointer.
00942 //
00943 //               We use a static function pointer instead of a virtual
00944 //               function (as in finalize()), to allow the function to
00945 //               destruct the old pointer if necessary.  (It is
00946 //               invalid to destruct the this pointer within a virtual
00947 //               function.)
00948 ////////////////////////////////////////////////////////////////////
00949 void BamReader::
00950 register_change_this(ChangeThisRefFunc func, TypedWritableReferenceCount *object) {
00951   nassertv(_now_creating != _created_objs.end());
00952   CreatedObj &created_obj = (*_now_creating).second;
00953 
00954 #ifndef NDEBUG
00955   // Sanity check the pointer--it should always be the same pointer
00956   // after we set it the first time.
00957   if (created_obj._ptr == (TypedWritable *)NULL) {
00958     created_obj.set_ptr(object, object);
00959   } else {
00960     // We've previously assigned this pointer, and we should have
00961     // assigned it to the same this pointer we have now.
00962     nassertv(created_obj._ptr == object);
00963     nassertv(created_obj._ref_ptr == object);
00964   }
00965 #endif  // NDEBUG
00966 
00967   created_obj._change_this = NULL;
00968   created_obj._change_this_ref = func;
00969 }
00970 
00971 ////////////////////////////////////////////////////////////////////
00972 //     Function: BamReader::finalize_now
00973 //       Access: Public
00974 //  Description: Forces the finalization of a particular object.  This
00975 //               may be called by any of the objects during
00976 //               finalization, to guarantee finalization ordering
00977 //               where it is important.
00978 ////////////////////////////////////////////////////////////////////
00979 void BamReader::
00980 finalize_now(TypedWritable *whom) {
00981   if (whom == (TypedWritable *)NULL) {
00982     return;
00983   }
00984 
00985   Finalize::iterator fi = _finalize_list.find(whom);
00986   if (fi != _finalize_list.end()) {
00987     _finalize_list.erase(fi);
00988     if (bam_cat.is_spam()) {
00989       bam_cat.spam()
00990         << "finalizing " << (void *)whom << " (" << whom->get_type()
00991         << ")\n";
00992     }
00993     whom->finalize(this);
00994   }
00995 }
00996 
00997 ////////////////////////////////////////////////////////////////////
00998 //     Function: BamReader::get_pta
00999 //       Access: Public
01000 //  Description: This function works in conjection with
01001 //               register_pta(), below, to read a PointerToArray (PTA)
01002 //               from the Bam file, and unify references to the same
01003 //               PTA.
01004 //
01005 //               The first time get_pta() encounters a particular PTA,
01006 //               it will return NULL.  This is the indication that the
01007 //               caller should then read in the data associated with
01008 //               the PTA, and subsequently call register_pta() with
01009 //               the address of the filled-in array.
01010 //
01011 //               The next time (and all subsequent times) that
01012 //               get_pta() encounters this same PTA, it will return
01013 //               the pointer that was passed with register_pta().
01014 //
01015 //               Also see the READ_PTA() macro, which consolidates all
01016 //               the work that must be done to read a PTA.
01017 ////////////////////////////////////////////////////////////////////
01018 void *BamReader::
01019 get_pta(DatagramIterator &scan) {
01020   nassertr(_pta_id == -1, (void *)NULL);
01021   int id = read_pta_id(scan);
01022 
01023   if (id == 0) {
01024     // As always, a 0 ID indicates a NULL pointer.  The caller will
01025     // not be able to differentiate this case from that of a
01026     // previously-read pointer, but that's OK because the next data in
01027     // the Bam file is the length of the array, which will be
01028     // zero--indicating an empty or NULL array.
01029     return (void *)NULL;
01030   }
01031 
01032   PTAMap::iterator pi = _pta_map.find(id);
01033   if (pi == _pta_map.end()) {
01034     // This is the first time we've encountered this particular ID,
01035     // meaning we need to read the data now and register it.
01036     _pta_id = id;
01037     return (void *)NULL;
01038   }
01039 
01040   return (*pi).second;
01041 }
01042 
01043 ////////////////////////////////////////////////////////////////////
01044 //     Function: BamReader::register_pta
01045 //       Access: Public
01046 //  Description: The second part of read_pta(), this should be called
01047 //               with the pointer to the array that was read in after
01048 //               read_pta() returned NULL.  This associates the
01049 //               pointer with the ID that was previously read, so that
01050 //               future calls to read_pta() will return the same
01051 //               pointer.
01052 //
01053 //               Also see the READ_PTA() macro, which consolidates all
01054 //               the work that must be done to read a PTA.
01055 ////////////////////////////////////////////////////////////////////
01056 void BamReader::
01057 register_pta(void *ptr) {
01058   if (_pta_id != -1) {
01059     bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second;
01060     _pta_id = -1;
01061     nassertv(inserted);
01062   }
01063 }
01064 
01065 ////////////////////////////////////////////////////////////////////
01066 //     Function: BamReader::free_object_ids
01067 //       Access: Private
01068 //  Description: Handles a record that begins with the _remove_flag
01069 //               TypeHandle; this contains a list of object ID's that
01070 //               will no longer be used in this file and can safely be
01071 //               removed.
01072 ////////////////////////////////////////////////////////////////////
01073 void BamReader::
01074 free_object_ids(DatagramIterator &scan) {
01075   // We have to fully complete any objects before we remove them.
01076   // Might as well try to complete everything before we get started.
01077   resolve();
01078 
01079   while (scan.get_remaining_size() > 0) {
01080     int object_id = read_object_id(scan);
01081 
01082     CreatedObjs::iterator ci = _created_objs.find(object_id);
01083     if (ci == _created_objs.end()) {
01084       util_cat.warning()
01085         << "Bam file suggests eliminating object_id " << object_id
01086         << ", already gone.\n";
01087     } else {
01088 
01089       // Make sure the object was successfully completed.
01090       ObjectPointers::iterator oi = _object_pointers.find(object_id);
01091       if (oi != _object_pointers.end()) {
01092         util_cat.warning()
01093           << "Unable to resolve object " << object_id
01094           << " before removing from table.\n";
01095       }
01096 
01097       _created_objs_by_pointer.erase((*ci).second._ptr);
01098       _created_objs.erase(ci);
01099     }
01100   }
01101 }
01102 
01103 
01104 ////////////////////////////////////////////////////////////////////
01105 //     Function: BamReader::read_object_id
01106 //       Access: Private
01107 //  Description: Reads an object id from the datagram.
01108 ////////////////////////////////////////////////////////////////////
01109 int BamReader::
01110 read_object_id(DatagramIterator &scan) {
01111   int object_id;
01112 
01113   if (_long_object_id) {
01114     object_id = scan.get_uint32();
01115 
01116   } else {
01117     object_id = scan.get_uint16();
01118     if (object_id == 0xffff) {
01119       _long_object_id = true;
01120     }
01121   }
01122 
01123   return object_id;
01124 }
01125 
01126 ////////////////////////////////////////////////////////////////////
01127 //     Function: BamReader::read_pta_id
01128 //       Access: Private
01129 //  Description: Reads an pta id from the datagram.
01130 ////////////////////////////////////////////////////////////////////
01131 int BamReader::
01132 read_pta_id(DatagramIterator &scan) {
01133   int pta_id;
01134 
01135   if (_long_pta_id) {
01136     pta_id = scan.get_uint32();
01137 
01138   } else {
01139     pta_id = scan.get_uint16();
01140     if (pta_id == 0xffff) {
01141       _long_pta_id = true;
01142     }
01143   }
01144 
01145   return pta_id;
01146 }
01147 
01148 ////////////////////////////////////////////////////////////////////
01149 //     Function: BamReader::p_read_object
01150 //       Access: Private
01151 //  Description: The private implementation of read_object(); this
01152 //               reads an object from the file and returns its object
01153 //               ID.
01154 ////////////////////////////////////////////////////////////////////
01155 int BamReader::
01156 p_read_object() {
01157   Datagram dg;
01158 
01159   // First, read a datagram for the object.
01160   if (!get_datagram(dg)) {
01161     // When we run out of datagrams, we're at the end of the file.
01162     if (bam_cat.is_debug()) {
01163       bam_cat.debug()
01164         << "Reached end of bam source.\n";
01165     }
01166     return 0;
01167   }
01168 
01169   // Now extract the object definition from the datagram.
01170   DatagramIterator scan(dg);
01171 
01172   // First, read the BamObjectCode.  In bam versions prior to 6.21,
01173   // there was no BamObjectCode in the stream.
01174   BamObjectCode boc = BOC_adjunct;
01175   if (get_file_minor_ver() >= 21) {
01176     boc = (BamObjectCode)scan.get_uint8();
01177   }
01178   switch (boc) {
01179   case BOC_push:
01180     ++_nesting_level;
01181     break;
01182 
01183   case BOC_pop:
01184     --_nesting_level;
01185     return 0;
01186 
01187   case BOC_adjunct:
01188     break;
01189 
01190   case BOC_remove:
01191     // The BOC_remove code is a special case; it begins a
01192     // record that simply lists all of the object ID's that are no
01193     // longer important to the file and may be released.
01194     free_object_ids(scan);
01195 
01196     // Now that we've freed all of the object id's indicate, read the
01197     // next object id in the stream.  It's easiest to do this by
01198     // calling recursively.
01199     return p_read_object();
01200 
01201   case BOC_file_data:
01202     // Another special case.  This marks an auxiliary file data record
01203     // that we skip over for now, but we note its position within the
01204     // stream, so that we can hand it to a future object who may
01205     // request it.
01206     {
01207       SubfileInfo info;
01208       if (!_source->save_datagram(info)) {
01209         bam_cat.error()
01210           << "Failed to read file data.\n";
01211         return 0;
01212       }
01213       _file_data_records.push_back(info);
01214     }
01215 
01216     return p_read_object();
01217   }
01218 
01219   // An object definition in a Bam file consists of a TypeHandle
01220   // definition, defining the object's type, followed by an object ID
01221   // index, defining the particular instance (e.g. pointer) of this
01222   // object.
01223   
01224   TypeHandle type = read_handle(scan);
01225 
01226   int object_id = read_object_id(scan);
01227 
01228   // There are two cases (not counting the special _remove_flag case,
01229   // above).  Either this is a new object definition, or this is a
01230   // reference to an object that was previously defined.
01231 
01232   // We use the TypeHandle to differentiate these two cases.  By
01233   // convention, we write a TypeHandle::none() to the Bam file when we
01234   // are writing a reference to a previously-defined object, but we
01235   // write the object's actual type when we are writing its definition
01236   // right now.
01237 
01238   // Therefore, if the type is TypeHandle::none(), then we must have
01239   // already read in and created the object (although its pointers may
01240   // not be fully instantiated yet).  On the other hand, if the type
01241   // is anything else, then we must read the definition to follow.
01242 
01243   if (type != TypeHandle::none()) {
01244     // Now we are going to read and create a new object.
01245 
01246     // First, we must add an entry into the map for this object ID, so
01247     // that in case this function is called recursively during the
01248     // object's factory constructor, we will have some definition for
01249     // the object.  For now, we give it a NULL pointer.
01250     CreatedObj new_created_obj;
01251     CreatedObjs::iterator oi =
01252       _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first;
01253     CreatedObj &created_obj = (*oi).second;
01254 
01255     if (created_obj._ptr != NULL) {
01256       // This object had already existed; thus, we are just receiving
01257       // an update for it.
01258 
01259       // Update _now_creating during this call so if this function
01260       // calls read_pointer() or register_change_this() we'll match it
01261       // up properly.  This might recursively call back into this
01262       // p_read_object(), so be sure to save and restore the original
01263       // value of _now_creating.
01264       CreatedObjs::iterator was_creating = _now_creating;
01265       _now_creating = oi;
01266       created_obj._ptr->fillin(scan, this);
01267       _now_creating = was_creating;
01268 
01269     } else {
01270       // We are receiving a new object.  Now we can call the factory
01271       // to create the object.
01272 
01273       // Define the parameters for passing to the object factory.
01274       FactoryParams fparams;
01275       fparams.add_param(new BamReaderParam(scan, this));
01276       
01277       // As above, we update and preserve _now_creating during this
01278       // call.
01279       CreatedObjs::iterator was_creating = _now_creating;
01280       _now_creating = oi;
01281       TypedWritable *object =
01282         _factory->make_instance_more_general(type, fparams);
01283       _now_creating = was_creating;
01284       
01285       // And now we can store the new object pointer in the map.
01286       nassertr(created_obj._ptr == object || created_obj._ptr == NULL, object_id);
01287       if (object == NULL) {
01288         created_obj.set_ptr(NULL, NULL);
01289       } else {
01290         created_obj.set_ptr(object, object->as_reference_count());
01291       }
01292       created_obj._created = true;
01293 
01294       if (created_obj._change_this_ref != NULL) {
01295         // If the pointer is scheduled to change after
01296         // complete_pointers(), but we have no entry in
01297         // _object_pointers for this object (and hence no plan to call
01298         // complete_pointers()), then just change the pointer
01299         // immediately.
01300         ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
01301         if (ri == _object_pointers.end()) {
01302           PT(TypedWritableReferenceCount) object_ref = (*created_obj._change_this_ref)((TypedWritableReferenceCount *)object, this);
01303           TypedWritable *new_ptr = object_ref;
01304           created_obj.set_ptr(object_ref, object_ref);
01305           created_obj._change_this = NULL;
01306           created_obj._change_this_ref = NULL;
01307           
01308           // Remove the pointer from the finalize list (the new
01309           // pointer presumably doesn't require finalizing).
01310           if (new_ptr != object) {
01311             _finalize_list.erase(object);
01312           }
01313           object = new_ptr;
01314         }
01315         
01316       } else if (created_obj._change_this != NULL) {
01317         // Non-reference-counting variant.
01318         ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
01319         if (ri == _object_pointers.end()) {
01320           TypedWritable *new_ptr = (*created_obj._change_this)(object, this);
01321           created_obj.set_ptr(new_ptr, new_ptr->as_reference_count());
01322           created_obj._change_this = NULL;
01323           created_obj._change_this_ref = NULL;
01324 
01325           if (new_ptr != object) {
01326             _finalize_list.erase(object);
01327           }
01328           object = new_ptr;
01329         }
01330       }
01331       
01332       _created_objs_by_pointer[created_obj._ptr].push_back(object_id);
01333 
01334       // Just some sanity checks
01335       if (object == (TypedWritable *)NULL) {
01336         if (bam_cat.is_debug()) {
01337           bam_cat.debug()
01338             << "Unable to create an object of type " << type << endl;
01339         }
01340 
01341       } else if (object->get_type() != type) {
01342         if (_new_types.find(type) != _new_types.end()) {
01343           // This was a type we hadn't heard of before, so it's not
01344           // really surprising we didn't know how to create it.
01345           // Suppress the warning (make it a debug statement instead).
01346           if (bam_cat.is_debug()) {
01347             bam_cat.warning()
01348               << "Attempted to create a " << type.get_name()    \
01349               << " but a " << object->get_type()                \
01350               << " was created instead." << endl;
01351           }
01352           
01353         } else {
01354           // This was a normal type that we should have known how to
01355           // create.  Report the error.
01356           bam_cat.warning()
01357             << "Attempted to create a " << type.get_name()      \
01358             << " but a " << object->get_type()                  \
01359             << " was created instead." << endl;
01360         }
01361         
01362       } else {
01363         if (bam_cat.is_spam()) {
01364           bam_cat.spam()
01365             << "Read a " << object->get_type() << ": " << (void *)object << "\n";
01366         }
01367       }
01368     }
01369   }
01370 
01371   return object_id;
01372 }
01373 
01374 ////////////////////////////////////////////////////////////////////
01375 //     Function: BamReader::resolve_object_pointers
01376 //       Access: Private
01377 //  Description: Checks whether all of the pointers a particular
01378 //               object is waiting for have been filled in yet.  If
01379 //               they have, calls complete_pointers() on the object
01380 //               and returns true; otherwise, returns false.
01381 ////////////////////////////////////////////////////////////////////
01382 bool BamReader::
01383 resolve_object_pointers(TypedWritable *object, 
01384                         BamReader::PointerReference &pref) {
01385   // Some objects further require all of their nested objects to have
01386   // been completed (i.e. complete_pointers has been called on each
01387   // nested object) before they can themselves be completed.
01388   bool require_fully_complete = object->require_fully_complete();
01389 
01390   // First do the PipelineCycler objects.    
01391   CyclerPointers::iterator ci;
01392   ci = pref._cycler_pointers.begin();
01393   while (ci != pref._cycler_pointers.end()) {
01394     PipelineCyclerBase *cycler = (*ci).first;
01395     const vector_int &pointer_ids = (*ci).second;
01396       
01397     if (resolve_cycler_pointers(cycler, pointer_ids, require_fully_complete)) {
01398       // Now remove this cycler from the list of things that need
01399       // completion.  We have to be a bit careful when deleting things
01400       // from the STL container while we are traversing it.
01401       CyclerPointers::iterator old = ci;
01402       ++ci;
01403       pref._cycler_pointers.erase(old);
01404       
01405     } else {
01406       // Couldn't complete this cycler yet; it'll wait for next time.
01407       ++ci;
01408     }
01409   }
01410 
01411   if (!pref._cycler_pointers.empty()) {
01412     // If we didn't get all the cyclers, we have to wait.
01413     if (bam_cat.is_spam()) {
01414       bam_cat.spam()
01415         << "some cyclers pending: complete_pointers for " << (void *)object
01416         << " (" << object->get_type() << ")\n";
01417     }
01418     return false;
01419   }
01420   
01421   // Now make sure we have all of the pointers this object is
01422   // waiting for.  If any of the pointers has not yet been read
01423   // in, we can't resolve this object--we can't do anything for a
01424   // given object until we have *all* outstanding pointers for
01425   // that object.
01426   bool is_complete = true;
01427 
01428   vector_typedWritable references;
01429   references.reserve(pref._objects.size());
01430 
01431   vector_int::const_iterator pi;
01432   for (pi = pref._objects.begin(); 
01433        pi != pref._objects.end() && is_complete; 
01434        ++pi) {
01435     int child_id = (*pi);
01436     if (child_id == 0) {
01437       // A NULL pointer is a NULL pointer.
01438       references.push_back((TypedWritable *)NULL);
01439       
01440     } else {
01441       // See if we have the pointer available now.
01442       CreatedObjs::const_iterator oi = _created_objs.find(child_id);
01443       if (oi == _created_objs.end()) {
01444         // No, too bad.
01445         is_complete = false;
01446 
01447       } else {
01448         const CreatedObj &child_obj = (*oi).second;
01449         if (!child_obj._created) {
01450           // The child object hasn't yet been created.
01451           is_complete = false;
01452         } else if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) {
01453           // It's been created, but the pointer might still change.
01454           is_complete = false;
01455         } else {
01456           if (require_fully_complete && 
01457               _object_pointers.find(child_id) != _object_pointers.end()) {
01458             // It's not yet complete itself.
01459             is_complete = false;
01460             
01461           } else {
01462             // Yes, it's ready.
01463             references.push_back(child_obj._ptr);
01464           }
01465         }
01466       }
01467     }
01468   }
01469       
01470   if (is_complete) {
01471     // Okay, here's the complete list of pointers for you!
01472     nassertr(references.size() == pref._objects.size(), false);
01473 
01474     if (bam_cat.is_spam()) {
01475       bam_cat.spam()
01476         << "complete_pointers for " << (void *)object
01477         << " (" << object->get_type() << "), " << references.size()
01478         << " pointers.\n";
01479     }
01480     int num_completed = 0;
01481     if (!references.empty()) {
01482       num_completed = object->complete_pointers(&references[0], this);
01483     }
01484     if (num_completed != (int)references.size()) {
01485       bam_cat.warning()
01486         << object->get_type() << " completed " << num_completed
01487         << " of " << references.size() << " pointers.\n";
01488       nassertr(num_completed < (int)references.size(), true);
01489     }
01490     return true;
01491 
01492   } else {
01493     if (bam_cat.is_spam()) {
01494       bam_cat.spam()
01495         << "not ready: complete_pointers for " << (void *)object
01496         << " (" << object->get_type() << ")\n";
01497     }
01498   }
01499 
01500   return false;
01501 }
01502 
01503 ////////////////////////////////////////////////////////////////////
01504 //     Function: BamReader::resolve_cycler_pointers
01505 //       Access: Private
01506 //  Description: Checks whether all of the pointers a particular
01507 //               PipelineCycler is waiting for have been filled in
01508 //               yet.  If they have, calls complete_pointers() on the
01509 //               cycler and returns true; otherwise, returns false.
01510 ////////////////////////////////////////////////////////////////////
01511 bool BamReader::
01512 resolve_cycler_pointers(PipelineCyclerBase *cycler,
01513                         const vector_int &pointer_ids,
01514                         bool require_fully_complete) {
01515   // Now make sure we have all of the pointers this cycler is
01516   // waiting for.  If any of the pointers has not yet been read
01517   // in, we can't resolve this cycler--we can't do anything for a
01518   // given cycler until we have *all* outstanding pointers for
01519   // that cycler.
01520   
01521   bool is_complete = true;
01522   vector_typedWritable references;
01523   
01524   vector_int::const_iterator pi;
01525   for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
01526     int child_id = (*pi);
01527     
01528     if (child_id == 0) {
01529       // A NULL pointer is a NULL pointer.
01530       references.push_back((TypedWritable *)NULL);
01531       
01532     } else {
01533       // See if we have the pointer available now.
01534       CreatedObjs::const_iterator oi = _created_objs.find(child_id);
01535       if (oi == _created_objs.end()) {
01536         // No, too bad.
01537         is_complete = false;
01538 
01539       } else {
01540         const CreatedObj &child_obj = (*oi).second;
01541         if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) {
01542           // It's been created, but the pointer might still change.
01543           is_complete = false;
01544 
01545         } else {
01546           if (require_fully_complete && 
01547               _object_pointers.find(child_id) != _object_pointers.end()) {
01548             // It's not yet complete itself.
01549             is_complete = false;
01550             
01551           } else {
01552             // Yes, it's ready.
01553             references.push_back(child_obj._ptr);
01554           }
01555         }
01556       }
01557     }
01558   }
01559       
01560   if (is_complete) {
01561     // Okay, here's the complete list of pointers for you!
01562     CycleData *cdata = cycler->write(Thread::get_current_thread());
01563     if (bam_cat.is_spam()) {
01564       bam_cat.spam()
01565         << "complete_pointers for CycleData object " << (void *)cdata
01566         << "\n";
01567     }
01568     int num_completed = cdata->complete_pointers(&references[0], this);
01569     cycler->release_write(cdata);
01570     if (num_completed != (int)references.size()) {
01571       bam_cat.warning()
01572         << "CycleData object completed " << num_completed
01573         << " of " << references.size() << " pointers.\n";
01574       nassertr(num_completed < (int)references.size(), true);
01575     }
01576     return true;
01577   }
01578 
01579   return false;
01580 }
01581 
01582 ////////////////////////////////////////////////////////////////////
01583 //     Function: BamReader::finalize
01584 //       Access: Private
01585 //  Description: Should be called after all objects have been read,
01586 //               this will finalize all the objects that registered
01587 //               themselves for the finalize callback.
01588 ////////////////////////////////////////////////////////////////////
01589 void BamReader::
01590 finalize() {
01591   if (bam_cat.is_debug()) {
01592     bam_cat.debug()
01593       << "Finalizing bam source\n";
01594   }
01595 
01596   Finalize::iterator fi = _finalize_list.begin();
01597   while (fi != _finalize_list.end()) {
01598     TypedWritable *object = (*fi);
01599     nassertv(object != (TypedWritable *)NULL);
01600     _finalize_list.erase(fi);
01601     if (bam_cat.is_spam()) {
01602       bam_cat.spam()
01603         << "finalizing " << (void *)object << " (" << object->get_type()
01604         << ")\n";
01605     }
01606     object->finalize(this);
01607     _aux_data.erase(object);
01608     fi = _finalize_list.begin();
01609   }
01610 
01611   // Now clear the aux data of all objects, except the NULL object.
01612   if (!_aux_data.empty()) {
01613     AuxDataTable::iterator ti = _aux_data.find((TypedWritable *)NULL);
01614 
01615     if (ti != _aux_data.end()) {
01616       if (_aux_data.size() > 1) {
01617         // Move the NULL data to the new table; remove the rest.
01618         AuxDataTable new_aux_data;
01619         AuxDataTable::iterator nti = 
01620           new_aux_data.insert(AuxDataTable::value_type((TypedWritable *)NULL, AuxDataNames())).first;
01621         (*nti).second.swap((*ti).second);
01622         _aux_data.swap(new_aux_data);
01623       }
01624     } else {
01625       // There's no NULL data; clear the whole table.
01626       _aux_data.clear();
01627     }
01628   }
01629 }
01630 
01631 ////////////////////////////////////////////////////////////////////
01632 //     Function: BamReader::AuxData::Destructor
01633 //       Access: Public, Virtual
01634 //  Description: 
01635 ////////////////////////////////////////////////////////////////////
01636 BamReader::AuxData::
01637 ~AuxData() {
01638 }
01639 
 All Classes Functions Variables Enumerations