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