Panda3D

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