28 BamReader *
const BamReader::Null =
nullptr;
31 BamReader::NewTypes BamReader::_new_types;
33 const int BamReader::_cur_major = _bam_major_ver;
34 const int BamReader::_cur_minor = _bam_minor_ver;
45 _num_extra_objects = 0;
47 _now_creating = _created_objs.end();
48 _reading_cycler =
nullptr;
50 _long_object_id =
false;
60 nassertv(_num_extra_objects == 0);
61 nassertv(_nesting_level == 0);
71 if (_needs_init && _source !=
nullptr) {
72 bool success =
init();
86 nassertr(_source !=
nullptr,
false);
87 nassertr(_needs_init,
false);
91 if (_source->is_error()) {
95 if (!get_datagram(header)) {
97 <<
"Unable to read Bam header.\n";
108 if (_file_major != _bam_major_ver ||
109 _file_minor < _bam_first_minor_ver ||
110 _file_minor > _bam_last_minor_ver) {
112 <<
"Bam file is version " << _file_major <<
"." << _file_minor
115 if (_bam_minor_ver == _bam_first_minor_ver) {
117 <<
"This program can only load version "
118 << _bam_major_ver <<
"." << _bam_first_minor_ver <<
" bams.\n";
121 <<
"This program can only load version "
122 << _bam_major_ver <<
"." << _bam_first_minor_ver <<
" through "
123 << _bam_major_ver <<
"." << _bam_last_minor_ver <<
" bams.\n";
131 _file_stdfloat_double =
false;
132 if (_file_minor >= 27) {
133 _file_stdfloat_double = scan.
get_bool();
138 <<
"Bam header is too short.\n";
168 if (data ==
nullptr) {
169 AuxDataTable::iterator ti = _aux_data.find(obj);
170 if (ti != _aux_data.end()) {
179 _aux_data[obj][name] = data;
190 AuxDataTable::const_iterator ti = _aux_data.find(obj);
191 if (ti != _aux_data.end()) {
193 AuxDataNames::const_iterator ni = names.find(name);
194 if (ni != names.end()) {
248 nassertr(_num_extra_objects == 0,
false);
250 int start_level = _nesting_level;
253 int object_id = p_read_object();
261 while (_num_extra_objects > 0) {
263 _num_extra_objects--;
268 while (_nesting_level > start_level) {
274 if (object_id == 0) {
275 if (bam_cat.is_spam()) {
277 <<
"Returning false\n";
282 CreatedObjs::iterator oi = _created_objs.find(object_id);
284 if (oi == _created_objs.end()) {
286 <<
"Undefined object encountered!\n";
290 CreatedObj &created_obj = (*oi).second;
291 ptr = created_obj._ptr;
292 ref_ptr = created_obj._ref_ptr;
294 if (bam_cat.is_spam()) {
295 if (ptr !=
nullptr) {
297 <<
"Returning object of type " << ptr->get_type() <<
"\n";
300 if (created_obj._change_this !=
nullptr ||
301 created_obj._change_this_ref !=
nullptr) {
303 <<
"Returning pointer to " << ptr->get_type()
304 <<
" that might change.\n";
327 bool any_completed_this_pass;
330 if (bam_cat.is_spam()) {
332 <<
"resolve pass begin\n";
334 all_completed =
true;
335 any_completed_this_pass =
false;
337 ObjectPointers::iterator oi;
338 oi = _object_pointers.begin();
339 while (oi != _object_pointers.end()) {
340 int object_id = (*oi).first;
341 PointerReference &pref = (*oi).second;
343 CreatedObjs::iterator ci = _created_objs.find(object_id);
344 nassertr(ci != _created_objs.end(),
false);
346 CreatedObj &created_obj = (*ci).second;
352 CreatedObjs::iterator was_creating = _now_creating;
355 if (resolve_object_pointers(object_ptr, pref)) {
359 ObjectPointers::iterator old = oi;
361 _object_pointers.erase(old);
362 any_completed_this_pass =
true;
365 if (created_obj._change_this_ref !=
nullptr) {
368 nassertr(created_obj._ref_ptr ==
nullptr || created_obj._ref_ptr == object_ref_ptr,
false);
370 if (new_ptr != object_ref_ptr) {
372 vector_int &old_refs = _created_objs_by_pointer[object_ptr];
373 vector_int &new_refs = _created_objs_by_pointer[new_ptr];
374 for (vector_int::const_iterator oi = old_refs.begin();
375 oi != old_refs.end();
377 new_refs.push_back(*oi);
379 _created_objs_by_pointer.erase(object_ptr);
383 _finalize_list.erase(object_ptr);
385 created_obj.set_ptr(new_ptr, new_ptr);
386 created_obj._change_this =
nullptr;
387 created_obj._change_this_ref =
nullptr;
389 }
else if (created_obj._change_this !=
nullptr) {
391 TypedWritable *new_ptr = created_obj._change_this(object_ptr,
this);
392 if (new_ptr != object_ptr) {
394 vector_int &old_refs = _created_objs_by_pointer[object_ptr];
395 vector_int &new_refs = _created_objs_by_pointer[new_ptr];
396 for (vector_int::const_iterator oi = old_refs.begin();
397 oi != old_refs.end();
399 new_refs.push_back(*oi);
401 _created_objs_by_pointer.erase(object_ptr);
405 _finalize_list.erase(object_ptr);
408 created_obj._change_this =
nullptr;
409 created_obj._change_this_ref =
nullptr;
415 all_completed =
false;
418 _now_creating = was_creating;
421 if (bam_cat.is_spam()) {
423 <<
"resolve pass end: all_completed = " << all_completed
424 <<
" any_completed_this_pass = " << any_completed_this_pass
427 }
while (!all_completed && any_completed_this_pass);
436 ObjectPointers::const_iterator oi;
437 for (oi = _object_pointers.begin();
438 oi != _object_pointers.end();
440 int object_id = (*oi).first;
441 CreatedObjs::iterator ci = _created_objs.find(object_id);
442 nassertr(ci != _created_objs.end(),
false);
443 CreatedObj &created_obj = (*ci).second;
447 <<
"Unable to complete " << object_ptr->get_type() <<
"\n";
451 return all_completed;
465 if (orig_pointer == new_pointer) {
468 CreatedObjsByPointer::iterator ci = _created_objs_by_pointer.find(orig_pointer);
469 if (ci == _created_objs_by_pointer.end()) {
474 if (bam_cat.is_spam()) {
476 <<
"change_pointer(" << (
void *)orig_pointer <<
", "
477 << (
void *)new_pointer <<
") (" << new_pointer->get_type() <<
")\n";
480 const vector_int &old_refs = (*ci).second;
481 vector_int &new_refs = _created_objs_by_pointer[new_pointer];
483 for (vector_int::const_iterator oi = old_refs.begin();
484 oi != old_refs.end();
486 int object_id = (*oi);
488 CreatedObjs::iterator ci = _created_objs.find(object_id);
489 nassertr(ci != _created_objs.end(),
false);
490 nassertr((*ci).second._ptr == orig_pointer,
false);
494 new_refs.push_back(object_id);
497 _created_objs_by_pointer.erase(ci);
500 Finalize::iterator fi = _finalize_list.find((
TypedWritable *)orig_pointer);
501 if (fi != _finalize_list.end()) {
503 _finalize_list.erase(fi);
529 return TypeHandle::none();
532 IndexMap::const_iterator mi = _index_map.find(
id);
533 if (mi != _index_map.end()) {
546 bool new_type =
false;
549 if (type == TypeHandle::none()) {
555 <<
"Bam file '" <<
get_filename() <<
"' contains objects of unknown type: "
558 _new_types.insert(type);
562 int num_parent_classes = scan.
get_uint8();
563 for (
int i = 0; i < num_parent_classes; i++) {
569 if (bam_cat.is_debug()) {
571 <<
"Bam file indicates a derivation of " << type
572 <<
" from " << parent_type <<
" which is no longer true.\n";
578 bool inserted = _index_map.insert(IndexMap::value_type(
id, type)).second;
579 nassertr(inserted, type);
581 if (bam_cat.is_spam()) {
583 <<
"Read TypeHandle for " << type <<
".\n";
613 nassertr(_now_creating != _created_objs.end(),
false);
614 int requestor_id = (*_now_creating).first;
617 int object_id = read_object_id(scan);
619 PointerReference &pref = _object_pointers[requestor_id];
620 if (_reading_cycler ==
nullptr) {
622 pref._objects.push_back(object_id);
625 pref._cycler_pointers[_reading_cycler].push_back(object_id);
630 if (object_id != 0) {
639 _num_extra_objects++;
654 for (
int i = 0; i < count; i++) {
666 read_object_id(scan);
683 nassertv(!_file_data_records.empty());
684 info = _file_data_records.front();
685 _file_data_records.pop_front();
697 _reading_cycler = &cycler;
699 cdata->
fillin(scan,
this);
701 _reading_cycler = old_cycler;
712 _reading_cycler = &cycler;
714 cdata->
fillin(scan,
this, extra_data);
716 _reading_cycler = old_cycler;
732 nassertv(_now_creating != _created_objs.end());
733 int requestor_id = (*_now_creating).first;
735 PointerReference &pref = _object_pointers[requestor_id];
736 pref._int_tags[tag] = value;
745 nassertr(_now_creating != _created_objs.end(), 0);
746 int requestor_id = (*_now_creating).first;
748 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
749 nassertr(opi != _object_pointers.end(), 0);
750 const PointerReference &pref = (*opi).second;
752 IntTags::const_iterator iti = pref._int_tags.find(tag);
753 nassertr(iti != pref._int_tags.end(), 0);
754 return (*iti).second;
773 nassertv(_now_creating != _created_objs.end());
774 int requestor_id = (*_now_creating).first;
776 PointerReference &pref = _object_pointers[requestor_id];
777 pref._aux_tags[tag] = value;
786 nassertr(_now_creating != _created_objs.end(),
nullptr);
787 int requestor_id = (*_now_creating).first;
789 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
790 nassertr(opi != _object_pointers.end(),
nullptr);
791 const PointerReference &pref = (*opi).second;
793 AuxTags::const_iterator ati = pref._aux_tags.find(tag);
794 nassertr(ati != pref._aux_tags.end(),
nullptr);
795 return (*ati).second;
809 nassertv(whom !=
nullptr);
811 if (bam_cat.is_spam()) {
813 <<
"register_finalize(" << (
void *)whom <<
") (" << whom->get_type()
817 _finalize_list.insert(whom);
836 nassertv(_now_creating != _created_objs.end());
837 CreatedObj &created_obj = (*_now_creating).second;
842 if (created_obj._ptr ==
nullptr) {
847 nassertv(created_obj._ptr ==
object);
851 created_obj._change_this = func;
852 created_obj._change_this_ref =
nullptr;
871 nassertv(_now_creating != _created_objs.end());
872 CreatedObj &created_obj = (*_now_creating).second;
877 if (created_obj._ptr ==
nullptr) {
878 created_obj.set_ptr(
object,
object);
882 nassertv(created_obj._ptr ==
object);
883 nassertv(created_obj._ref_ptr ==
object);
887 created_obj._change_this =
nullptr;
888 created_obj._change_this_ref = func;
898 if (whom ==
nullptr) {
902 Finalize::iterator fi = _finalize_list.find(whom);
903 if (fi != _finalize_list.end()) {
904 _finalize_list.erase(fi);
905 if (bam_cat.is_spam()) {
907 <<
"finalizing " << (
void *)whom <<
" (" << whom->get_type()
932 nassertr(_pta_id == -1,
nullptr);
933 int id = read_pta_id(scan);
943 PTAMap::iterator pi = _pta_map.find(
id);
944 if (pi == _pta_map.end()) {
966 bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second;
984 int object_id = read_object_id(scan);
986 CreatedObjs::iterator ci = _created_objs.find(object_id);
987 if (ci == _created_objs.end()) {
989 <<
"Bam file suggests eliminating object_id " << object_id
990 <<
", already gone.\n";
994 ObjectPointers::iterator oi = _object_pointers.find(object_id);
995 if (oi != _object_pointers.end()) {
997 <<
"Unable to resolve object " << object_id
998 <<
" before removing from table.\n";
1001 _created_objs_by_pointer.erase((*ci).second._ptr);
1002 _created_objs.erase(ci);
1015 if (_long_object_id) {
1020 if (object_id == 0xffff) {
1021 _long_object_id =
true;
1040 if (pta_id == 0xffff) {
1041 _long_pta_id =
true;
1057 if (!get_datagram(dg)) {
1059 if (bam_cat.is_debug()) {
1061 <<
"Reached end of bam source.\n";
1091 free_object_ids(scan);
1096 return p_read_object();
1106 <<
"Failed to read file data.\n";
1109 _file_data_records.push_back(info);
1112 return p_read_object();
1116 <<
"Encountered invalid BamObjectCode 0x" << std::hex << (int)boc << std::dec <<
".\n";
1126 int object_id = read_object_id(scan);
1130 <<
"Found truncated datagram in bam stream\n";
1148 if (type != TypeHandle::none()) {
1155 CreatedObj new_created_obj;
1156 CreatedObjs::iterator oi =
1157 _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first;
1158 CreatedObj &created_obj = (*oi).second;
1160 if (created_obj._ptr !=
nullptr) {
1164 if (_object_pointers.find(object_id) != _object_pointers.end()) {
1169 <<
"Found object " << object_id <<
" in bam stream again while "
1170 <<
"trying to resolve its own pointers.\n";
1178 CreatedObjs::iterator was_creating = _now_creating;
1180 created_obj._ptr->fillin(scan,
this);
1181 _now_creating = was_creating;
1186 <<
"in datagram containing type " << type <<
"\n";
1198 CreatedObjs::iterator was_creating = _now_creating;
1202 _now_creating = was_creating;
1205 nassertr(created_obj._ptr ==
object || created_obj._ptr ==
nullptr, object_id);
1206 if (
object ==
nullptr) {
1207 created_obj.set_ptr(
nullptr,
nullptr);
1211 created_obj._created =
true;
1213 if (created_obj._change_this_ref !=
nullptr) {
1218 ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
1219 if (ri == _object_pointers.end()) {
1222 created_obj.set_ptr(object_ref, object_ref);
1223 created_obj._change_this =
nullptr;
1224 created_obj._change_this_ref =
nullptr;
1228 if (new_ptr !=
object) {
1229 _finalize_list.erase(
object);
1234 }
else if (created_obj._change_this !=
nullptr) {
1236 ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
1237 if (ri == _object_pointers.end()) {
1238 TypedWritable *new_ptr = (*created_obj._change_this)(
object,
this);
1240 created_obj._change_this =
nullptr;
1241 created_obj._change_this_ref =
nullptr;
1243 if (new_ptr !=
object) {
1244 _finalize_list.erase(
object);
1250 _created_objs_by_pointer[created_obj._ptr].push_back(object_id);
1253 if (
object ==
nullptr) {
1254 if (bam_cat.is_debug()) {
1256 <<
"Unable to create an object of type " << type << std::endl;
1259 }
else if (object->get_type() != type) {
1260 if (_new_types.find(type) != _new_types.end()) {
1264 if (bam_cat.is_debug()) {
1266 <<
"Attempted to create a " << type.
get_name() \
1267 <<
" but a " <<
object->get_type() \
1268 <<
" was created instead." << std::endl;
1275 <<
"Attempted to create a " << type.
get_name() \
1276 <<
" but a " <<
object->get_type() \
1277 <<
" was created instead." << std::endl;
1281 if (bam_cat.is_spam()) {
1283 <<
"Read a " <<
object->get_type() <<
": " << (
void *)
object
1284 <<
" (id=" << object_id <<
")\n";
1292 <<
"End of datagram reached while reading bam object "
1293 << type <<
": " << (
void *)created_obj._ptr <<
"\n";
1307 BamReader::PointerReference &pref) {
1311 bool require_fully_complete =
object->require_fully_complete();
1314 CyclerPointers::iterator ci;
1315 ci = pref._cycler_pointers.begin();
1316 while (ci != pref._cycler_pointers.end()) {
1318 const vector_int &pointer_ids = (*ci).second;
1320 if (resolve_cycler_pointers(cycler, pointer_ids, require_fully_complete)) {
1324 CyclerPointers::iterator old = ci;
1326 pref._cycler_pointers.erase(old);
1334 if (!pref._cycler_pointers.empty()) {
1336 if (bam_cat.is_spam()) {
1338 <<
"some cyclers pending: complete_pointers for " << (
void *)
object
1339 <<
" (" << object->get_type() <<
")\n";
1348 bool is_complete =
true;
1350 vector_typedWritable references;
1351 references.reserve(pref._objects.size());
1353 vector_int::const_iterator pi;
1354 for (pi = pref._objects.begin();
1355 pi != pref._objects.end() && is_complete;
1357 int child_id = (*pi);
1358 if (child_id == 0) {
1360 references.push_back(
nullptr);
1365 CreatedObjs::const_iterator oi = _created_objs.find(child_id);
1366 if (oi == _created_objs.end()) {
1368 is_complete =
false;
1372 const CreatedObj &child_obj = (*oi).second;
1373 if (!child_obj._created) {
1375 is_complete =
false;
1379 if (child_obj._change_this !=
nullptr || child_obj._change_this_ref !=
nullptr) {
1381 is_complete =
false;
1385 if (require_fully_complete &&
1386 _object_pointers.find(child_id) != _object_pointers.end()) {
1388 is_complete =
false;
1393 references.push_back(child_obj._ptr);
1398 nassertr(references.size() == pref._objects.size(),
false);
1400 if (bam_cat.is_spam()) {
1402 <<
"complete_pointers for " << (
void *)
object
1403 <<
" (" << object->get_type() <<
"), " << references.size()
1406 int num_completed = 0;
1407 if (!references.empty()) {
1408 num_completed =
object->complete_pointers(&references[0],
this);
1410 if (num_completed != (
int)references.size()) {
1412 <<
object->get_type() <<
" completed " << num_completed
1413 <<
" of " << references.size() <<
" pointers.\n";
1414 nassertr(num_completed < (
int)references.size(),
true);
1419 if (bam_cat.is_spam()) {
1421 <<
"not ready: complete_pointers for " << (
void *)
object
1422 <<
" (" << object->get_type() <<
")\n";
1436 const vector_int &pointer_ids,
1437 bool require_fully_complete) {
1443 bool is_complete =
true;
1444 vector_typedWritable references;
1446 vector_int::const_iterator pi;
1447 for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
1448 int child_id = (*pi);
1450 if (child_id == 0) {
1452 references.push_back(
nullptr);
1457 CreatedObjs::const_iterator oi = _created_objs.find(child_id);
1458 if (oi == _created_objs.end()) {
1460 is_complete =
false;
1464 const CreatedObj &child_obj = (*oi).second;
1465 if (child_obj._change_this !=
nullptr || child_obj._change_this_ref !=
nullptr) {
1467 is_complete =
false;
1471 if (require_fully_complete &&
1472 _object_pointers.find(child_id) != _object_pointers.end()) {
1474 is_complete =
false;
1479 references.push_back(child_obj._ptr);
1485 if (bam_cat.is_spam()) {
1487 <<
"complete_pointers for CycleData object " << (
void *)cdata
1492 if (num_completed != (
int)references.size()) {
1494 <<
"CycleData object completed " << num_completed
1495 <<
" of " << references.size() <<
" pointers.\n";
1496 nassertr(num_completed < (
int)references.size(),
true);
1510 if (bam_cat.is_debug()) {
1512 <<
"Finalizing bam source\n";
1515 Finalize::iterator fi = _finalize_list.begin();
1516 while (fi != _finalize_list.end()) {
1518 nassertv(
object !=
nullptr);
1519 _finalize_list.erase(fi);
1520 if (bam_cat.is_spam()) {
1522 <<
"finalizing " << (
void *)
object <<
" (" << object->get_type()
1525 object->finalize(
this);
1526 _aux_data.erase(
object);
1527 fi = _finalize_list.begin();
1531 if (!_aux_data.empty()) {
1532 AuxDataTable::iterator ti = _aux_data.find(
nullptr);
1534 if (ti != _aux_data.end()) {
1535 if (_aux_data.size() > 1) {
1537 AuxDataTable new_aux_data;
1538 AuxDataTable::iterator nti =
1539 new_aux_data.insert(AuxDataTable::value_type(
nullptr, AuxDataNames())).first;
1540 (*nti).second.swap((*ti).second);
1541 _aux_data.swap(new_aux_data);