Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/putil/bamReader.cxx

Go to the documentation of this file.
00001 // Filename: bamReader.cxx
00002 // Created by:  jason (12Jun00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "pandabase.h"
00020 #include "notify.h"
00021 
00022 #include "bam.h"
00023 #include "bamReader.h"
00024 #include "datagramIterator.h"
00025 #include "config_util.h"
00026 #include "pipelineCyclerBase.h"
00027 
00028 WritableFactory *BamReader::_factory = (WritableFactory*)0L;
00029 BamReader *const BamReader::Null = (BamReader*)0L;
00030 WritableFactory *const BamReader::NullFactory = (WritableFactory*)0L;
00031 
00032 BamReader::NewTypes BamReader::_new_types;
00033 
00034 const int BamReader::_cur_major = _bam_major_ver;
00035 const int BamReader::_cur_minor = _bam_minor_ver;
00036 
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: BamReader::Constructor
00040 //       Access: Public
00041 //  Description:
00042 ////////////////////////////////////////////////////////////////////
00043 BamReader::
00044 BamReader(DatagramGenerator *generator)
00045   : _source(generator)
00046 {
00047   _num_extra_objects = 0;
00048   _now_creating = _created_objs.end();
00049   _reading_cycler = (PipelineCyclerBase *)NULL;
00050   _pta_id = -1;
00051 }
00052 
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: BamReader::Destructor
00056 //       Access: Public
00057 //  Description:
00058 ////////////////////////////////////////////////////////////////////
00059 BamReader::
00060 ~BamReader() {
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: BamReader::init
00065 //       Access: Public
00066 //  Description: Initializes the BamReader prior to reading any
00067 //               objects from its source.  This includes reading the
00068 //               Bam header.
00069 //
00070 //               This returns true if the BamReader successfully
00071 //               initialized, false otherwise.
00072 ////////////////////////////////////////////////////////////////////
00073 bool BamReader::
00074 init() {
00075   Datagram header;
00076 
00077   if (_source->is_error()) {
00078     return false;
00079   }
00080 
00081   if (!_source->get_datagram(header)) {
00082     bam_cat.error()
00083       << "Unable to read Bam header.\n";
00084     return false;
00085   }
00086 
00087   DatagramIterator scan(header);
00088 
00089   _file_major = scan.get_uint16();
00090   _file_minor = scan.get_uint16();
00091 
00092   // If the major version is different, or the minor version is
00093   // *newer*, we can't safely load the file.
00094   if (_file_major != _bam_major_ver || _file_minor > _bam_minor_ver) {
00095     bam_cat.error()
00096       << "Bam file is version " << _file_major << "." << _file_minor
00097       << ".\n";
00098 
00099     if (_bam_minor_ver == 0) {
00100       bam_cat.error()
00101         << "This program can only load version "
00102         << _bam_major_ver << ".0 bams.\n";
00103     } else {
00104       bam_cat.error()
00105         << "This program can only load version "
00106         << _bam_major_ver << ".0 through "
00107         << _bam_major_ver << "." << _bam_minor_ver << " bams.\n";
00108     }
00109 
00110     return false;
00111   }
00112 
00113   if (bam_cat.is_debug()) {
00114     bam_cat.debug()
00115       << "Bam file is version " << _file_major << "." << _file_minor
00116       << ".\n";
00117     if (_file_minor != _bam_minor_ver) {
00118       bam_cat.debug()
00119         << "(Current version is " << _bam_major_ver << "." << _bam_minor_ver
00120         << ".)\n";
00121     }
00122   }
00123 
00124   return true;
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: BamReader::read_object
00129 //       Access: Public
00130 //  Description: Reads a single object from the Bam file.  If the
00131 //               object type is known, a new object of the appropriate
00132 //               type is created and returned; otherwise, NULL is
00133 //               returned.  NULL is also returned when the end of the
00134 //               file is reached.  is_eof() may be called to
00135 //               differentiate between these two cases.
00136 //
00137 //               This may be called repeatedly to extract out all the
00138 //               objects in the Bam file, but typically (especially
00139 //               for scene graph files, indicated with the .bam
00140 //               extension), only one object is retrieved directly
00141 //               from the Bam file: the root of the scene graph.  The
00142 //               remaining objects will all be retrieved recursively
00143 //               by the first object.
00144 //
00145 //               Note that the object returned may not yet be
00146 //               complete.  In particular, some of its pointers may
00147 //               not be filled in; you must call resolve() to fill in
00148 //               all the available pointers before you can safely use
00149 //               any objects returned by read_object().
00150 ////////////////////////////////////////////////////////////////////
00151 TypedWritable *BamReader::
00152 read_object() {
00153   nassertr(_num_extra_objects == 0, (TypedWritable *)NULL);
00154 
00155   // First, read the base object.
00156   int object_id = p_read_object();
00157 
00158   // Now that object might have included some pointers to other
00159   // objects, which may still need to be read.  And those objects
00160   // might in turn require reading additional objects.  Read all the
00161   // remaining objects.
00162   while (_num_extra_objects > 0) {
00163     p_read_object();
00164     _num_extra_objects--;
00165   }
00166 
00167   // Now look up the pointer of the object we read first.  It should
00168   // be available now.
00169   if (object_id == 0) {
00170     if (bam_cat.is_spam()) {
00171       bam_cat.spam()
00172         << "Returning NULL\n";
00173     }
00174     return (TypedWritable *)NULL;
00175   }
00176 
00177   CreatedObjs::iterator oi = _created_objs.find(object_id);
00178 
00179   if (oi == _created_objs.end()) {
00180     bam_cat.error()
00181       << "Undefined object encountered!\n";
00182     return (TypedWritable *)NULL;
00183 
00184   } else {
00185     CreatedObj &created_obj = (*oi).second;
00186     TypedWritable *object = created_obj._ptr;
00187 
00188     if (bam_cat.is_spam()) {
00189       if (object != (TypedWritable *)NULL) {
00190         bam_cat.spam()
00191           << "Returning object of type " << object->get_type() << "\n";
00192       }
00193     }
00194     if (created_obj._change_this != NULL) {
00195       bam_cat.warning()
00196         << "Returning pointer to " << object->get_type()
00197         << " that might change.\n";
00198     }
00199 
00200     return object;
00201   }
00202 }
00203 
00204 ////////////////////////////////////////////////////////////////////
00205 //     Function: BamReader::resolve
00206 //       Access: Public
00207 //  Description: This may be called at any time during processing of
00208 //               the Bam file to resolve all the known pointers so
00209 //               far.  It is usually called at the end of the
00210 //               processing, after all objects have been read, which
00211 //               is generally the best time to call it.
00212 //
00213 //               This must be called at least once after reading a
00214 //               particular object via get_object() in order to
00215 //               validate that object.
00216 //
00217 //               The return value is true if all objects have been
00218 //               resolved, or false if some objects are still
00219 //               outstanding (in which case you will need to call
00220 //               resolve() again later).
00221 ////////////////////////////////////////////////////////////////////
00222 bool BamReader::
00223 resolve() {
00224   bool all_completed;
00225   bool any_completed_this_pass;
00226 
00227   do {
00228     all_completed = true;
00229     any_completed_this_pass = false;
00230 
00231     // Walk through all the objects that still have outstanding pointers.
00232     ObjectPointers::iterator oi;
00233     oi = _object_pointers.begin();
00234     while (oi != _object_pointers.end()) {
00235       int object_id = (*oi).first;
00236       const vector_int &pointer_ids = (*oi).second;
00237 
00238       CreatedObjs::iterator ci = _created_objs.find(object_id);
00239       nassertr(ci != _created_objs.end(), false);
00240       CreatedObj &created_obj = (*ci).second;
00241       
00242       TypedWritable *object_ptr = created_obj._ptr;
00243 
00244       if (resolve_object_pointers(object_ptr, pointer_ids)) {
00245         // Now remove this object from the list of things that need
00246         // completion.  We have to be a bit careful when deleting things
00247         // from the STL container while we are traversing it.
00248         ObjectPointers::iterator old = oi;
00249         ++oi;
00250         _object_pointers.erase(old);
00251         
00252         // Does the pointer need to change?
00253         if (created_obj._change_this != NULL) {
00254           created_obj._ptr = created_obj._change_this(object_ptr, this);
00255           created_obj._change_this = NULL;
00256         }
00257         any_completed_this_pass = true;
00258         
00259       } else {
00260         // Couldn't complete this object yet; it'll wait for next time.
00261         ++oi;
00262         all_completed = false;
00263       }
00264     }
00265   } while (!all_completed && any_completed_this_pass);
00266 
00267   // Also do the PipelineCycler objects.  We only need to try these
00268   // once, since they don't depend on each other.
00269 
00270   CyclerPointers::iterator ci;
00271   ci = _cycler_pointers.begin();
00272   while (ci != _cycler_pointers.end()) {
00273     PipelineCyclerBase *cycler = (*ci).first;
00274     const vector_int &pointer_ids = (*ci).second;
00275     
00276     if (resolve_cycler_pointers(cycler, pointer_ids)) {
00277       // Now remove this cycler from the list of things that need
00278       // completion.  We have to be a bit careful when deleting things
00279       // from the STL container while we are traversing it.
00280       CyclerPointers::iterator old = ci;
00281       ++ci;
00282       _cycler_pointers.erase(old);
00283       
00284     } else {
00285       // Couldn't complete this cycler yet; it'll wait for next time.
00286       ++ci;
00287       all_completed = false;
00288     }
00289   }
00290 
00291   if (all_completed) {
00292     finalize();
00293   } else {
00294     // Report all the uncompleted objects for no good reason.  This
00295     // will probably have to come out later when we have cases in
00296     // which some objects might legitimately be uncompleted after
00297     // calling resolve(), but for now we expect resolve() to always
00298     // succeed.
00299     ObjectPointers::const_iterator oi;
00300     for (oi = _object_pointers.begin(); 
00301          oi != _object_pointers.end();
00302          ++oi) {
00303       int object_id = (*oi).first;
00304       CreatedObjs::iterator ci = _created_objs.find(object_id);
00305       nassertr(ci != _created_objs.end(), false);
00306       CreatedObj &created_obj = (*ci).second;
00307       TypedWritable *object_ptr = created_obj._ptr;
00308 
00309       bam_cat.warning()
00310         << "Unable to complete " << object_ptr->get_type() << "\n";
00311     }
00312   }
00313 
00314   return all_completed;
00315 }
00316 
00317 ////////////////////////////////////////////////////////////////////
00318 //     Function: BamReader::read_handle
00319 //       Access: Public
00320 //  Description: Reads a TypeHandle out of the Datagram.
00321 ////////////////////////////////////////////////////////////////////
00322 TypeHandle BamReader::
00323 read_handle(DatagramIterator &scan) {
00324   // We encode TypeHandles within the Bam file by writing a unique
00325   // index number for each one to the file.  When we write a
00326   // particular TypeHandle for the first time, we assign it a new
00327   // index number and then immediately follow it by its definition;
00328   // when we write the same TypeHandle on subsequent times we only
00329   // write the index number.
00330 
00331   // Thus, to read a TypeHandle, we first read the index number.  If
00332   // it is a number we have not yet encountered, we must then read the
00333   // definition.
00334 
00335   // Here's the index number.
00336   int id = scan.get_uint16();
00337 
00338   if (id == 0) {
00339     // Index number 0 is always, by convention, TypeHandle::none().
00340     return TypeHandle::none();
00341   }
00342 
00343   IndexMap::const_iterator mi = _index_map.find(id);
00344   if (mi != _index_map.end()) {
00345     // We've encountered this index number before, so there should be
00346     // no type definition following the id.  Simply return the
00347     // TypeHandle we previously associated with the id.
00348     TypeHandle type = (*mi).second;
00349     return type;
00350   }
00351 
00352   // We haven't encountered this index number before.  This means it
00353   // will be immediately followed by the type definition.  This
00354   // consists of the string name, followed by the list of parent
00355   // TypeHandles for this type.
00356 
00357   string name = scan.get_string();
00358   bool new_type = false;
00359 
00360   TypeHandle type = TypeRegistry::ptr()->find_type(name);
00361   if (type == TypeHandle::none()) {
00362     // We've never heard of this type before!  This is really an error
00363     // condition, but we'll do the best we can and declare it
00364     // on-the-fly.
00365 
00366     type = TypeRegistry::ptr()->register_dynamic_type(name);
00367     bam_cat.warning()
00368       << "Bam file contains objects of unknown type: " << type << "\n";
00369     new_type = true;
00370     _new_types.insert(type);
00371   }
00372 
00373   // Now pick up the derivation information.
00374   int num_parent_classes = scan.get_uint8();
00375   for (int i = 0; i < num_parent_classes; i++) {
00376     TypeHandle parent_type = read_handle(scan);
00377     if (new_type) {
00378       TypeRegistry::ptr()->record_derivation(type, parent_type);
00379     } else {
00380       if (type.get_parent_towards(parent_type) != parent_type) {
00381         bam_cat.warning()
00382           << "Bam file indicates a derivation of " << type
00383           << " from " << parent_type << " which is no longer true.\n";
00384       }
00385     }
00386   }
00387 
00388   bool inserted = _index_map.insert(IndexMap::value_type(id, type)).second;
00389   nassertr(inserted, type);
00390 
00391   if (bam_cat.is_spam()) {
00392     bam_cat.spam()
00393       << "Read TypeHandle for " << type << ".\n";
00394   }
00395 
00396   return type;
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: BamReader::read_pointer
00401 //       Access: Public
00402 //  Description: The interface for reading a pointer to another object
00403 //               from a Bam file.  Objects reading themselves from a
00404 //               Bam file should call this when they expect to read a
00405 //               pointer to some other object.  This function reads
00406 //               whatever is stored in the bam file to represent the
00407 //               pointer, and advances the datagram iterator
00408 //               accordingly.
00409 //
00410 //               Rather than returning a pointer immediately, this
00411 //               function reads the internal pointer information from
00412 //               the datagram and queues up the request.  The pointer
00413 //               itself may not be available until later (it may be a
00414 //               pointer to an object that appears later in the Bam
00415 //               file).  Later, when all pointers are available, the
00416 //               complete_pointers() callback function will be called
00417 //               with an array of actual pointers, one for time
00418 //               read_pointer() was called.  It is then the calling
00419 //               object's responsibilty to store these pointers in the
00420 //               object properly.
00421 ////////////////////////////////////////////////////////////////////
00422 void BamReader::
00423 read_pointer(DatagramIterator &scan) {
00424   nassertv(_now_creating != _created_objs.end());
00425   int requestor_id = (*_now_creating).first;
00426 
00427   // Read the object ID, and associate it with the requesting object.
00428   int object_id = scan.get_uint16();
00429 
00430   if (_reading_cycler == (PipelineCyclerBase *)NULL) {
00431     // This is not being read within a read_cdata() call.
00432     _object_pointers[requestor_id].push_back(object_id);
00433   } else {
00434     // This *is* being read within a read_cdata() call.
00435     _cycler_pointers[_reading_cycler].push_back(object_id);
00436   }
00437 
00438   // If the object ID is zero (which indicates a NULL pointer), we
00439   // don't have to do anything else.
00440   if (object_id != 0) {
00441     if (_created_objs.count(object_id) == 0) {
00442       // If we don't already have an entry in the map for this object
00443       // ID (that is, we haven't encountered this object before), we
00444       // must remember to read the object definition later.
00445       _num_extra_objects++;
00446     }
00447   }
00448 }
00449 
00450 ////////////////////////////////////////////////////////////////////
00451 //     Function: BamReader::read_pointers
00452 //       Access: Public
00453 //  Description: A convenience function to read a contiguous list of
00454 //               pointers.  This is equivalent to calling
00455 //               read_pointer() count times.
00456 ////////////////////////////////////////////////////////////////////
00457 void BamReader::
00458 read_pointers(DatagramIterator &scan, int count) {
00459   for (int i = 0; i < count; i++) {
00460     read_pointer(scan);
00461   }
00462 }
00463 
00464 ////////////////////////////////////////////////////////////////////
00465 //     Function: BamReader::skip_pointer
00466 //       Access: Public
00467 //  Description: Reads and discards a pointer value from the Bam file.
00468 //               This pointer will not be counted among the pointers
00469 //               read for a given object, and will not be in the list
00470 //               of pointers passed to complete_pointers().
00471 ////////////////////////////////////////////////////////////////////
00472 void BamReader::
00473 skip_pointer(DatagramIterator &scan) {
00474   scan.get_uint16();
00475 }
00476 
00477 ////////////////////////////////////////////////////////////////////
00478 //     Function: BamReader::read_cdata
00479 //       Access: Public
00480 //  Description: Reads in the indicated CycleData object.  This should
00481 //               be used by classes that store some or all of their
00482 //               data within a CycleData subclass, in support of
00483 //               pipelining.  This will call the virtual
00484 //               CycleData::fillin() method to do the actual reading.
00485 ////////////////////////////////////////////////////////////////////
00486 void BamReader::
00487 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) {
00488   PipelineCyclerBase *old_cycler = _reading_cycler;
00489   _reading_cycler = &cycler;
00490   CycleData *cdata = cycler.write();
00491   cdata->fillin(scan, this);
00492   cycler.release_write(cdata);
00493   _reading_cycler = old_cycler;
00494 }
00495 
00496 ////////////////////////////////////////////////////////////////////
00497 //     Function: BamReader::register_finalize
00498 //       Access: Public
00499 //  Description: Should be called by an object reading itself from the
00500 //               Bam file to indicate that this particular object
00501 //               would like to receive the finalize() callback when
00502 //               all the objects and pointers in the Bam file are
00503 //               completely read.
00504 //
00505 //               This provides a hook for objects (like Characters)
00506 //               that need to do any additional finalization work
00507 //               after all of their related pointers are guaranteed to
00508 //               be filled in.
00509 ////////////////////////////////////////////////////////////////////
00510 void BamReader::
00511 register_finalize(TypedWritable *whom) {
00512   if (whom == TypedWritable::Null) {
00513     bam_cat.error() << "Can't register a null pointer to finalize!" << endl;
00514     return;
00515   }
00516   _finalize_list.insert(whom);
00517 }
00518 
00519 ////////////////////////////////////////////////////////////////////
00520 //     Function: BamReader::register_change_this
00521 //       Access: Public
00522 //  Description: Called by an object reading itself from the bam file
00523 //               to indicate that the object pointer that will be
00524 //               returned is temporary, and will eventually need to be
00525 //               replaced with another pointer.
00526 //
00527 //               The supplied function pointer will later be called on
00528 //               the object, immediately after complete_pointers() is
00529 //               called; it should return the new and final pointer.
00530 //
00531 //               We use a static function pointer instead of a virtual
00532 //               function (as in finalize()), to allow the function to
00533 //               destruct the old pointer if necessary.  (It is
00534 //               invalid to destruct the this pointer within a virtual
00535 //               function.)
00536 ////////////////////////////////////////////////////////////////////
00537 void BamReader::
00538 register_change_this(ChangeThisFunc func, TypedWritable *object) {
00539   nassertv(_now_creating != _created_objs.end());
00540   CreatedObj &created_obj = (*_now_creating).second;
00541 
00542 #ifndef NDEBUG
00543   // Sanity check the pointer--it should always be the same pointer
00544   // after we set it the first time.
00545   if (created_obj._ptr == (TypedWritable *)NULL) {
00546     created_obj._ptr = object;
00547   } else {
00548     // We've previously assigned this pointer, and we should have
00549     // assigned it to the same this pointer we have now.
00550     nassertv(created_obj._ptr == object);
00551   }
00552 #endif  // NDEBUG
00553 
00554   created_obj._change_this = func;
00555 }
00556 
00557 ////////////////////////////////////////////////////////////////////
00558 //     Function: BamReader::finalize_now
00559 //       Access: Public
00560 //  Description: Forces the finalization of a particular object.  This
00561 //               may be called by any of the objects during
00562 //               finalization, to guarantee finalization ordering
00563 //               where it is important.
00564 ////////////////////////////////////////////////////////////////////
00565 void BamReader::
00566 finalize_now(TypedWritable *whom) {
00567   nassertv(whom != (TypedWritable *)NULL);
00568 
00569   Finalize::iterator fi = _finalize_list.find(whom);
00570   if (fi != _finalize_list.end()) {
00571     _finalize_list.erase(fi);
00572     whom->finalize();
00573   }
00574 }
00575 
00576 ////////////////////////////////////////////////////////////////////
00577 //     Function: BamReader::get_pta
00578 //       Access: Public
00579 //  Description: This function works in conjection with
00580 //               register_pta(), below, to read a PointerToArray (PTA)
00581 //               from the Bam file, and unify references to the same
00582 //               PTA.
00583 //
00584 //               The first time get_pta() encounters a particular PTA,
00585 //               it will return NULL.  This is the indication that the
00586 //               caller should then read in the data associated with
00587 //               the PTA, and subsequently call register_pta() with
00588 //               the address of the filled-in array.
00589 //
00590 //               The next time (and all subsequent times) that
00591 //               get_pta() encounters this same PTA, it will return
00592 //               the pointer that was passed with register_pta().
00593 //
00594 //               Also see the READ_PTA() macro, which consolidates all
00595 //               the work that must be done to read a PTA.
00596 ////////////////////////////////////////////////////////////////////
00597 void *BamReader::
00598 get_pta(DatagramIterator &scan) {
00599   nassertr(_pta_id == -1, (void *)NULL);
00600   int id = scan.get_uint16();
00601 
00602   if (id == 0) {
00603     // As always, a 0 ID indicates a NULL pointer.  The caller will
00604     // not be able to differentiate this case from that of a
00605     // previously-read pointer, but that's OK because the next data in
00606     // the Bam file is the length of the array, which will be
00607     // zero--indicating an empty or NULL array.
00608     return (void *)NULL;
00609   }
00610 
00611   PTAMap::iterator pi = _pta_map.find(id);
00612   if (pi == _pta_map.end()) {
00613     // This is the first time we've encountered this particular ID,
00614     // meaning we need to read the data now and register it.
00615     _pta_id = id;
00616     return (void *)NULL;
00617   }
00618 
00619   return (*pi).second;
00620 }
00621 
00622 ////////////////////////////////////////////////////////////////////
00623 //     Function: BamReader::register_pta
00624 //       Access: Public
00625 //  Description: The second part of read_pta(), this should be called
00626 //               with the pointer to the array that was read in after
00627 //               read_pta() returned NULL.  This associates the
00628 //               pointer with the ID that was previously read, so that
00629 //               future calls to read_pta() will return the same
00630 //               pointer.
00631 //
00632 //               Also see the READ_PTA() macro, which consolidates all
00633 //               the work that must be done to read a PTA.
00634 ////////////////////////////////////////////////////////////////////
00635 void BamReader::
00636 register_pta(void *ptr) {
00637   if (_pta_id != -1) {
00638     bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second;
00639     _pta_id = -1;
00640     nassertv(inserted);
00641   }
00642 }
00643 
00644 
00645 
00646 ////////////////////////////////////////////////////////////////////
00647 //     Function: BamReader::p_read_object
00648 //       Access: Private
00649 //  Description: The private implementation of read_object(), this
00650 //               reads an object from the file and returns its object
00651 //               ID.
00652 ////////////////////////////////////////////////////////////////////
00653 int BamReader::
00654 p_read_object() {
00655   Datagram packet;
00656 
00657   if (_source->is_error()) {
00658     return 0;
00659   }
00660 
00661   // First, read a datagram for the object.
00662   if (!_source->get_datagram(packet)) {
00663     // When we run out of datagrams, we're at the end of the file.
00664 
00665     if (bam_cat.is_debug()) {
00666       bam_cat.debug()
00667         << "Reached end of bam source.\n";
00668     }
00669     return 0;
00670   }
00671 
00672   // Now extract the object definition from the datagram.
00673   DatagramIterator scan(packet);
00674 
00675   // An object definition in a Bam file consists of a TypeHandle
00676   // definition, defining the object's type, followed by an object ID
00677   // index, defining the particular instance (e.g. pointer) of this
00678   // object.
00679 
00680   TypeHandle type = read_handle(scan);
00681   int object_id = scan.get_uint16();
00682 
00683   // There are two cases.  Either this is a new object definition, or
00684   // this is a reference to an object that was previously defined.
00685 
00686   // We use the TypeHandle to differentiate these two cases.  By
00687   // convention, we write a TypeHandle::none() to the Bam file when we
00688   // are writing a reference to a previously-defined object, but we
00689   // write the object's actual type when we are writing its definition
00690   // right now.
00691 
00692   // Therefore, if the type is TypeHandle::none(), then we must have
00693   // already read in and created the object (although its pointers may
00694   // not be fully instantiated yet).  On the other hand, if the type
00695   // is anything else, then we must read the definition to follow.
00696 
00697   if (type != TypeHandle::none()) {
00698     // Now we are going to read and create a new object.
00699 
00700     // Defined the parameters for passing to the object factory.
00701     FactoryParams fparams;
00702     fparams.add_param(new BamReaderParam(scan, this));
00703 
00704     // First, we must add an entry into the map for this object ID, so
00705     // that in case this function is called recursively during the
00706     // object's factory constructor, we will have some definition for
00707     // the object.  For now, we give it a NULL pointer.
00708     CreatedObj new_created_obj;
00709     new_created_obj._ptr = NULL;
00710     new_created_obj._change_this = NULL;
00711     CreatedObjs::iterator oi =
00712       _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first;
00713     CreatedObj &created_obj = (*oi).second;
00714 
00715     // Now we can call the factory to create the object.  Update
00716     // _now_creating during this call so if this function calls
00717     // read_pointer() or register_change_this() we'll match it up
00718     // properly.  This might recursively call back into this
00719     // p_read_object(), so be sure to save and restore the original
00720     // value of _now_creating.
00721     CreatedObjs::iterator was_creating = _now_creating;
00722     _now_creating = oi;
00723     TypedWritable *object =
00724       _factory->make_instance_more_general(type, fparams);
00725     _now_creating = was_creating;
00726 
00727     // And now we can store the new object pointer in the map.
00728     nassertr(created_obj._ptr == object || created_obj._ptr == NULL, object_id);
00729     created_obj._ptr = object;
00730 
00731     if (created_obj._change_this != NULL) {
00732       // If the pointer is scheduled to change after
00733       // complete_pointers(), but we have no entry in
00734       // _object_pointers for this object (and hence no plan to call
00735       // complete_pointers()), then just change the pointer
00736       // immediately.
00737       ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
00738       if (ri == _object_pointers.end()) {
00739         object = created_obj._change_this(object, this);
00740         created_obj._ptr = object;
00741         created_obj._change_this = NULL;
00742       }
00743     }
00744 
00745     // Just some sanity checks
00746     if (object == (TypedWritable *)NULL) {
00747       bam_cat.info()
00748         << "Unable to create an object of type " << type << endl;
00749 
00750     } else if (object->get_type() != type) {
00751       if (_new_types.find(type) != _new_types.end()) {
00752         // This was a type we hadn't heard of before, so it's not
00753         // really surprising we didn't know how to create it.
00754         // Suppress the warning (make it a debug statement instead).
00755         if (bam_cat.is_debug()) {
00756           bam_cat.warning()
00757             << "Attempted to create a " << type.get_name() \
00758             << " but a " << object->get_type() \
00759             << " was created instead." << endl;
00760         }
00761 
00762       } else {
00763         // This was a normal type that we should have known how to
00764         // create.  Report the error.
00765         bam_cat.warning()
00766           << "Attempted to create a " << type.get_name() \
00767           << " but a " << object->get_type() \
00768           << " was created instead." << endl;
00769       }
00770 
00771     } else {
00772       if (bam_cat.is_spam()) {
00773         bam_cat.spam()
00774           << "Read a " << object->get_type() << "\n";
00775       }
00776     }
00777   }
00778 
00779   return object_id;
00780 }
00781 
00782 ////////////////////////////////////////////////////////////////////
00783 //     Function: BamReader::resolve_object_pointers
00784 //       Access: Private
00785 //  Description: Checks whether all of the pointers a particular
00786 //               object is waiting for have been filled in yet.  If
00787 //               they have, calls complete_pointers() on the object
00788 //               and returns true; otherwise, returns false.
00789 ////////////////////////////////////////////////////////////////////
00790 bool BamReader::
00791 resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
00792   // Now make sure we have all of the pointers this object is
00793   // waiting for.  If any of the pointers has not yet been read
00794   // in, we can't resolve this object--we can't do anything for a
00795   // given object until we have *all* outstanding pointers for
00796   // that object.
00797   
00798   bool is_complete = true;
00799   vector_typedWritable references;
00800   
00801   vector_int::const_iterator pi;
00802   for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
00803     int child_id = (*pi);
00804     
00805     if (child_id == 0) {
00806       // A NULL pointer is a NULL pointer.
00807       references.push_back((TypedWritable *)NULL);
00808       
00809     } else {
00810       // See if we have the pointer available now.
00811       CreatedObjs::const_iterator oi = _created_objs.find(child_id);
00812       if (oi == _created_objs.end()) {
00813     // No, too bad.
00814     is_complete = false;
00815     
00816       } else {
00817     const CreatedObj &child_obj = (*oi).second;
00818     if (child_obj._change_this != NULL) {
00819       // It's been created, but the pointer might still change.
00820       is_complete = false;
00821       
00822     } else {
00823       // Yes, it's ready.
00824       references.push_back(child_obj._ptr);
00825     }
00826       }
00827     }
00828   }
00829       
00830   if (is_complete) {
00831     // Okay, here's the complete list of pointers for you!
00832     int num_completed = object->complete_pointers(&references[0], this);
00833     if (num_completed != (int)references.size()) {
00834       bam_cat.warning()
00835     << object->get_type() << " completed " << num_completed
00836     << " of " << references.size() << " pointers.\n";
00837     }
00838     return true;
00839   }
00840 
00841   return false;
00842 }
00843 
00844 ////////////////////////////////////////////////////////////////////
00845 //     Function: BamReader::resolve_cycler_pointers
00846 //       Access: Private
00847 //  Description: Checks whether all of the pointers a particular
00848 //               PipelineCycler is waiting for have been filled in
00849 //               yet.  If they have, calls complete_pointers() on the
00850 //               cycler and returns true; otherwise, returns false.
00851 ////////////////////////////////////////////////////////////////////
00852 bool BamReader::
00853 resolve_cycler_pointers(PipelineCyclerBase *cycler,
00854             const vector_int &pointer_ids) {
00855   // Now make sure we have all of the pointers this cycler is
00856   // waiting for.  If any of the pointers has not yet been read
00857   // in, we can't resolve this cycler--we can't do anything for a
00858   // given cycler until we have *all* outstanding pointers for
00859   // that cycler.
00860   
00861   bool is_complete = true;
00862   vector_typedWritable references;
00863   
00864   vector_int::const_iterator pi;
00865   for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
00866     int child_id = (*pi);
00867     
00868     if (child_id == 0) {
00869       // A NULL pointer is a NULL pointer.
00870       references.push_back((TypedWritable *)NULL);
00871       
00872     } else {
00873       // See if we have the pointer available now.
00874       CreatedObjs::const_iterator oi = _created_objs.find(child_id);
00875       if (oi == _created_objs.end()) {
00876     // No, too bad.
00877     is_complete = false;
00878     
00879       } else {
00880     const CreatedObj &child_obj = (*oi).second;
00881     if (child_obj._change_this != NULL) {
00882       // It's been created, but the pointer might still change.
00883       is_complete = false;
00884       
00885     } else {
00886       // Yes, it's ready.
00887       references.push_back(child_obj._ptr);
00888     }
00889       }
00890     }
00891   }
00892       
00893   if (is_complete) {
00894     // Okay, here's the complete list of pointers for you!
00895     CycleData *cdata = cycler->write();
00896     int num_completed = cdata->complete_pointers(&references[0], this);
00897     cycler->release_write(cdata);
00898     if (num_completed != (int)references.size()) {
00899       bam_cat.warning()
00900     << "CycleData object completed " << num_completed
00901     << " of " << references.size() << " pointers.\n";
00902     }
00903     return true;
00904   }
00905 
00906   return false;
00907 }
00908 
00909 ////////////////////////////////////////////////////////////////////
00910 //     Function: BamReader::finalize
00911 //       Access: Private
00912 //  Description: Should be called after all objects have been read,
00913 //               this will finalize all the objects that registered
00914 //               themselves for the finalize callback.
00915 ////////////////////////////////////////////////////////////////////
00916 void BamReader::
00917 finalize() {
00918   if (bam_cat.is_debug()) {
00919     bam_cat.debug()
00920       << "Finalizing bam source\n";
00921   }
00922 
00923   Finalize::iterator fi = _finalize_list.begin();
00924   while (fi != _finalize_list.end()) {
00925     TypedWritable *object = (*fi);
00926     nassertv(object != (TypedWritable *)NULL);
00927     _finalize_list.erase(fi);
00928     object->finalize();
00929 
00930     fi = _finalize_list.begin();
00931   }
00932 }

Generated on Fri May 2 00:43:29 2003 for Panda by doxygen1.3