15 #include "pandabase.h"
19 #include "bamReader.h"
20 #include "datagramIterator.h"
21 #include "config_util.h"
22 #include "pipelineCyclerBase.h"
30 BamReader::NewTypes BamReader::_new_types;
32 const int BamReader::_cur_major = _bam_major_ver;
33 const int BamReader::_cur_minor = _bam_minor_ver;
46 _num_extra_objects = 0;
48 _now_creating = _created_objs.end();
51 _long_object_id =
false;
63 nassertv(_num_extra_objects == 0);
64 nassertv(_nesting_level == 0);
77 if (_needs_init && _source != NULL) {
78 bool success =
init();
95 nassertr(_source != NULL,
false);
96 nassertr(_needs_init,
false);
100 if (_source->is_error()) {
104 if (!get_datagram(header)) {
106 <<
"Unable to read Bam header.\n";
117 if (_file_major != _bam_major_ver ||
118 _file_minor < _bam_first_minor_ver ||
119 _file_minor > _bam_minor_ver) {
121 <<
"Bam file is version " << _file_major <<
"." << _file_minor
124 if (_bam_minor_ver == _bam_first_minor_ver) {
126 <<
"This program can only load version "
127 << _bam_major_ver <<
"." << _bam_first_minor_ver <<
" bams.\n";
130 <<
"This program can only load version "
131 << _bam_major_ver <<
"." << _bam_first_minor_ver <<
" through "
132 << _bam_major_ver <<
"." << _bam_minor_ver <<
" bams.\n";
138 _file_endian = (BamEndian)scan.
get_uint8();
140 _file_stdfloat_double =
false;
141 if (_file_minor >= 27) {
142 _file_stdfloat_double = scan.
get_bool();
177 if (data == (
void *)NULL) {
178 AuxDataTable::iterator ti = _aux_data.find(obj);
179 if (ti != _aux_data.end()) {
188 _aux_data[obj][name] = data;
201 AuxDataTable::const_iterator ti = _aux_data.find(obj);
202 if (ti != _aux_data.end()) {
204 AuxDataNames::const_iterator ni = names.find(name);
205 if (ni != names.end()) {
270 nassertr(_num_extra_objects == 0,
false);
272 int start_level = _nesting_level;
275 int object_id = p_read_object();
284 while (_num_extra_objects > 0) {
286 _num_extra_objects--;
291 while (_nesting_level > start_level) {
297 if (object_id == 0) {
298 if (bam_cat.is_spam()) {
300 <<
"Returning false\n";
305 CreatedObjs::iterator oi = _created_objs.find(object_id);
307 if (oi == _created_objs.end()) {
309 <<
"Undefined object encountered!\n";
313 CreatedObj &created_obj = (*oi).second;
314 ptr = created_obj._ptr;
315 ref_ptr = created_obj._ref_ptr;
317 if (bam_cat.is_spam()) {
320 <<
"Returning object of type " << ptr->get_type() <<
"\n";
323 if (created_obj._change_this != NULL ||
324 created_obj._change_this_ref != NULL) {
326 <<
"Returning pointer to " << ptr->get_type()
327 <<
" that might change.\n";
355 bool any_completed_this_pass;
358 if (bam_cat.is_spam()) {
360 <<
"resolve pass begin\n";
362 all_completed =
true;
363 any_completed_this_pass =
false;
365 ObjectPointers::iterator oi;
366 oi = _object_pointers.begin();
367 while (oi != _object_pointers.end()) {
368 int object_id = (*oi).first;
369 PointerReference &pref = (*oi).second;
371 CreatedObjs::iterator ci = _created_objs.find(object_id);
372 nassertr(ci != _created_objs.end(),
false);
374 CreatedObj &created_obj = (*ci).second;
380 CreatedObjs::iterator was_creating = _now_creating;
383 if (resolve_object_pointers(object_ptr, pref)) {
387 ObjectPointers::iterator old = oi;
389 _object_pointers.erase(old);
390 any_completed_this_pass =
true;
393 if (created_obj._change_this_ref != NULL) {
396 nassertr(created_obj._ref_ptr == NULL || created_obj._ref_ptr == object_ref_ptr,
false);
398 if (new_ptr != object_ref_ptr) {
400 vector_int &old_refs = _created_objs_by_pointer[object_ptr];
401 vector_int &new_refs = _created_objs_by_pointer[new_ptr];
402 for (vector_int::const_iterator oi = old_refs.begin();
403 oi != old_refs.end();
405 new_refs.push_back(*oi);
407 _created_objs_by_pointer.erase(object_ptr);
411 _finalize_list.erase(object_ptr);
413 created_obj.set_ptr(new_ptr, new_ptr);
414 created_obj._change_this = NULL;
415 created_obj._change_this_ref = NULL;
417 }
else if (created_obj._change_this != NULL) {
419 TypedWritable *new_ptr = created_obj._change_this(object_ptr,
this);
420 if (new_ptr != object_ptr) {
422 vector_int &old_refs = _created_objs_by_pointer[object_ptr];
423 vector_int &new_refs = _created_objs_by_pointer[new_ptr];
424 for (vector_int::const_iterator oi = old_refs.begin();
425 oi != old_refs.end();
427 new_refs.push_back(*oi);
429 _created_objs_by_pointer.erase(object_ptr);
433 _finalize_list.erase(object_ptr);
436 created_obj._change_this = NULL;
437 created_obj._change_this_ref = NULL;
443 all_completed =
false;
446 _now_creating = was_creating;
449 if (bam_cat.is_spam()) {
451 <<
"resolve pass end: all_completed = " << all_completed
452 <<
" any_completed_this_pass = " << any_completed_this_pass
455 }
while (!all_completed && any_completed_this_pass);
465 ObjectPointers::const_iterator oi;
466 for (oi = _object_pointers.begin();
467 oi != _object_pointers.end();
469 int object_id = (*oi).first;
470 CreatedObjs::iterator ci = _created_objs.find(object_id);
471 nassertr(ci != _created_objs.end(),
false);
472 CreatedObj &created_obj = (*ci).second;
476 <<
"Unable to complete " << object_ptr->get_type() <<
"\n";
480 return all_completed;
498 if (orig_pointer == new_pointer) {
501 CreatedObjsByPointer::iterator ci = _created_objs_by_pointer.find(orig_pointer);
502 if (ci == _created_objs_by_pointer.end()) {
507 if (bam_cat.is_spam()) {
509 <<
"change_pointer(" << (
void *)orig_pointer <<
", "
510 << (
void *)new_pointer <<
") (" << new_pointer->get_type() <<
")\n";
513 const vector_int &old_refs = (*ci).second;
514 vector_int &new_refs = _created_objs_by_pointer[new_pointer];
516 for (vector_int::const_iterator oi = old_refs.begin();
517 oi != old_refs.end();
519 int object_id = (*oi);
521 CreatedObjs::iterator ci = _created_objs.find(object_id);
522 nassertr(ci != _created_objs.end(),
false);
523 nassertr((*ci).second._ptr == orig_pointer,
false);
527 new_refs.push_back(object_id);
530 _created_objs_by_pointer.erase(ci);
533 Finalize::iterator fi = _finalize_list.find((
TypedWritable *)orig_pointer);
534 if (fi != _finalize_list.end()) {
536 _finalize_list.erase(fi);
569 IndexMap::const_iterator mi = _index_map.find(
id);
570 if (mi != _index_map.end()) {
584 bool new_type =
false;
594 <<
"Bam file '" <<
get_filename() <<
"' contains objects of unknown type: "
597 _new_types.insert(type);
601 int num_parent_classes = scan.
get_uint8();
602 for (
int i = 0; i < num_parent_classes; i++) {
608 if (bam_cat.is_debug()) {
610 <<
"Bam file indicates a derivation of " << type
611 <<
" from " << parent_type <<
" which is no longer true.\n";
617 bool inserted = _index_map.insert(IndexMap::value_type(
id, type)).second;
618 nassertr(inserted, type);
620 if (bam_cat.is_spam()) {
622 <<
"Read TypeHandle for " << type <<
".\n";
655 nassertv(_now_creating != _created_objs.end());
656 int requestor_id = (*_now_creating).first;
659 int object_id = read_object_id(scan);
661 PointerReference &pref = _object_pointers[requestor_id];
664 pref._objects.push_back(object_id);
667 pref._cycler_pointers[_reading_cycler].push_back(object_id);
672 if (object_id != 0) {
681 _num_extra_objects++;
695 for (
int i = 0; i < count; i++) {
710 read_object_id(scan);
732 nassertv(!_file_data_records.empty());
733 info = _file_data_records.front();
734 _file_data_records.pop_front();
749 _reading_cycler = &cycler;
751 cdata->
fillin(scan,
this);
753 _reading_cycler = old_cycler;
766 _reading_cycler = &cycler;
768 cdata->
fillin(scan,
this, extra_data);
770 _reading_cycler = old_cycler;
790 nassertv(_now_creating != _created_objs.end());
791 int requestor_id = (*_now_creating).first;
793 PointerReference &pref = _object_pointers[requestor_id];
794 pref._int_tags[tag] = value;
805 nassertr(_now_creating != _created_objs.end(), 0);
806 int requestor_id = (*_now_creating).first;
808 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
809 nassertr(opi != _object_pointers.end(), 0);
810 const PointerReference &pref = (*opi).second;
812 IntTags::const_iterator iti = pref._int_tags.find(tag);
813 nassertr(iti != pref._int_tags.end(), 0);
814 return (*iti).second;
839 nassertv(_now_creating != _created_objs.end());
840 int requestor_id = (*_now_creating).first;
842 PointerReference &pref = _object_pointers[requestor_id];
843 pref._aux_tags[tag] = value;
854 nassertr(_now_creating != _created_objs.end(), NULL);
855 int requestor_id = (*_now_creating).first;
857 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
858 nassertr(opi != _object_pointers.end(), NULL);
859 const PointerReference &pref = (*opi).second;
861 AuxTags::const_iterator ati = pref._aux_tags.find(tag);
862 nassertr(ati != pref._aux_tags.end(), NULL);
863 return (*ati).second;
883 if (bam_cat.is_spam()) {
885 <<
"register_finalize(" << (
void *)whom <<
") (" << whom->get_type()
889 _finalize_list.insert(whom);
912 nassertv(_now_creating != _created_objs.end());
913 CreatedObj &created_obj = (*_now_creating).second;
923 nassertv(created_obj._ptr ==
object);
927 created_obj._change_this = func;
928 created_obj._change_this_ref = NULL;
951 nassertv(_now_creating != _created_objs.end());
952 CreatedObj &created_obj = (*_now_creating).second;
958 created_obj.set_ptr(
object,
object);
962 nassertv(created_obj._ptr ==
object);
963 nassertv(created_obj._ref_ptr ==
object);
967 created_obj._change_this = NULL;
968 created_obj._change_this_ref = func;
985 Finalize::iterator fi = _finalize_list.find(whom);
986 if (fi != _finalize_list.end()) {
987 _finalize_list.erase(fi);
988 if (bam_cat.is_spam()) {
990 <<
"finalizing " << (
void *)whom <<
" (" << whom->get_type()
1020 nassertr(_pta_id == -1, (
void *)NULL);
1021 int id = read_pta_id(scan);
1029 return (
void *)NULL;
1032 PTAMap::iterator pi = _pta_map.find(
id);
1033 if (pi == _pta_map.end()) {
1037 return (
void *)NULL;
1040 return (*pi).second;
1058 if (_pta_id != -1) {
1059 bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second;
1080 int object_id = read_object_id(scan);
1082 CreatedObjs::iterator ci = _created_objs.find(object_id);
1083 if (ci == _created_objs.end()) {
1085 <<
"Bam file suggests eliminating object_id " << object_id
1086 <<
", already gone.\n";
1090 ObjectPointers::iterator oi = _object_pointers.find(object_id);
1091 if (oi != _object_pointers.end()) {
1093 <<
"Unable to resolve object " << object_id
1094 <<
" before removing from table.\n";
1097 _created_objs_by_pointer.erase((*ci).second._ptr);
1098 _created_objs.erase(ci);
1113 if (_long_object_id) {
1118 if (object_id == 0xffff) {
1119 _long_object_id =
true;
1140 if (pta_id == 0xffff) {
1141 _long_pta_id =
true;
1160 if (!get_datagram(dg)) {
1162 if (bam_cat.is_debug()) {
1164 <<
"Reached end of bam source.\n";
1174 BamObjectCode boc = BOC_adjunct;
1194 free_object_ids(scan);
1199 return p_read_object();
1210 <<
"Failed to read file data.\n";
1213 _file_data_records.push_back(info);
1216 return p_read_object();
1220 <<
"Encountered invalid BamObjectCode 0x" << hex << (int)boc << dec <<
".\n";
1231 int object_id = read_object_id(scan);
1255 CreatedObj new_created_obj;
1256 CreatedObjs::iterator oi =
1257 _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first;
1258 CreatedObj &created_obj = (*oi).second;
1260 if (created_obj._ptr != NULL) {
1269 CreatedObjs::iterator was_creating = _now_creating;
1271 created_obj._ptr->fillin(scan,
this);
1272 _now_creating = was_creating;
1284 CreatedObjs::iterator was_creating = _now_creating;
1288 _now_creating = was_creating;
1291 nassertr(created_obj._ptr ==
object || created_obj._ptr == NULL, object_id);
1292 if (
object == NULL) {
1293 created_obj.set_ptr(NULL, NULL);
1297 created_obj._created =
true;
1299 if (created_obj._change_this_ref != NULL) {
1305 ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
1306 if (ri == _object_pointers.end()) {
1309 created_obj.set_ptr(object_ref, object_ref);
1310 created_obj._change_this = NULL;
1311 created_obj._change_this_ref = NULL;
1315 if (new_ptr !=
object) {
1316 _finalize_list.erase(
object);
1321 }
else if (created_obj._change_this != NULL) {
1323 ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
1324 if (ri == _object_pointers.end()) {
1325 TypedWritable *new_ptr = (*created_obj._change_this)(
object,
this);
1327 created_obj._change_this = NULL;
1328 created_obj._change_this_ref = NULL;
1330 if (new_ptr !=
object) {
1331 _finalize_list.erase(
object);
1337 _created_objs_by_pointer[created_obj._ptr].push_back(object_id);
1341 if (bam_cat.is_debug()) {
1343 <<
"Unable to create an object of type " << type << endl;
1346 }
else if (object->get_type() != type) {
1347 if (_new_types.find(type) != _new_types.end()) {
1351 if (bam_cat.is_debug()) {
1353 <<
"Attempted to create a " << type.
get_name() \
1354 <<
" but a " <<
object->get_type() \
1355 <<
" was created instead." << endl;
1362 <<
"Attempted to create a " << type.
get_name() \
1363 <<
" but a " <<
object->get_type() \
1364 <<
" was created instead." << endl;
1368 if (bam_cat.is_spam()) {
1370 <<
"Read a " <<
object->get_type() <<
": " << (
void *)
object <<
"\n";
1389 BamReader::PointerReference &pref) {
1393 bool require_fully_complete =
object->require_fully_complete();
1396 CyclerPointers::iterator ci;
1397 ci = pref._cycler_pointers.begin();
1398 while (ci != pref._cycler_pointers.end()) {
1400 const vector_int &pointer_ids = (*ci).second;
1402 if (resolve_cycler_pointers(cycler, pointer_ids, require_fully_complete)) {
1406 CyclerPointers::iterator old = ci;
1408 pref._cycler_pointers.erase(old);
1416 if (!pref._cycler_pointers.empty()) {
1418 if (bam_cat.is_spam()) {
1420 <<
"some cyclers pending: complete_pointers for " << (
void *)
object
1421 <<
" (" << object->get_type() <<
")\n";
1431 bool is_complete =
true;
1433 vector_typedWritable references;
1434 references.reserve(pref._objects.size());
1436 vector_int::const_iterator pi;
1437 for (pi = pref._objects.begin();
1438 pi != pref._objects.end() && is_complete;
1440 int child_id = (*pi);
1441 if (child_id == 0) {
1447 CreatedObjs::const_iterator oi = _created_objs.find(child_id);
1448 if (oi == _created_objs.end()) {
1450 is_complete =
false;
1453 const CreatedObj &child_obj = (*oi).second;
1454 if (!child_obj._created) {
1456 is_complete =
false;
1457 }
else if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) {
1459 is_complete =
false;
1461 if (require_fully_complete &&
1462 _object_pointers.find(child_id) != _object_pointers.end()) {
1464 is_complete =
false;
1468 references.push_back(child_obj._ptr);
1477 nassertr(references.size() == pref._objects.size(),
false);
1479 if (bam_cat.is_spam()) {
1481 <<
"complete_pointers for " << (
void *)
object
1482 <<
" (" << object->get_type() <<
"), " << references.size()
1485 int num_completed = 0;
1486 if (!references.empty()) {
1487 num_completed =
object->complete_pointers(&references[0],
this);
1489 if (num_completed != (
int)references.size()) {
1491 <<
object->get_type() <<
" completed " << num_completed
1492 <<
" of " << references.size() <<
" pointers.\n";
1493 nassertr(num_completed < (
int)references.size(),
true);
1498 if (bam_cat.is_spam()) {
1500 <<
"not ready: complete_pointers for " << (
void *)
object
1501 <<
" (" << object->get_type() <<
")\n";
1518 const vector_int &pointer_ids,
1519 bool require_fully_complete) {
1526 bool is_complete =
true;
1527 vector_typedWritable references;
1529 vector_int::const_iterator pi;
1530 for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
1531 int child_id = (*pi);
1533 if (child_id == 0) {
1539 CreatedObjs::const_iterator oi = _created_objs.find(child_id);
1540 if (oi == _created_objs.end()) {
1542 is_complete =
false;
1545 const CreatedObj &child_obj = (*oi).second;
1546 if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) {
1548 is_complete =
false;
1551 if (require_fully_complete &&
1552 _object_pointers.find(child_id) != _object_pointers.end()) {
1554 is_complete =
false;
1558 references.push_back(child_obj._ptr);
1568 if (bam_cat.is_spam()) {
1570 <<
"complete_pointers for CycleData object " << (
void *)cdata
1575 if (num_completed != (
int)references.size()) {
1577 <<
"CycleData object completed " << num_completed
1578 <<
" of " << references.size() <<
" pointers.\n";
1579 nassertr(num_completed < (
int)references.size(),
true);
1596 if (bam_cat.is_debug()) {
1598 <<
"Finalizing bam source\n";
1601 Finalize::iterator fi = _finalize_list.begin();
1602 while (fi != _finalize_list.end()) {
1605 _finalize_list.erase(fi);
1606 if (bam_cat.is_spam()) {
1608 <<
"finalizing " << (
void *)
object <<
" (" << object->get_type()
1611 object->finalize(
this);
1612 _aux_data.erase(
object);
1613 fi = _finalize_list.begin();
1617 if (!_aux_data.empty()) {
1618 AuxDataTable::iterator ti = _aux_data.find((
TypedWritable *)NULL);
1620 if (ti != _aux_data.end()) {
1621 if (_aux_data.size() > 1) {
1623 AuxDataTable new_aux_data;
1624 AuxDataTable::iterator nti =
1625 new_aux_data.insert(AuxDataTable::value_type((
TypedWritable *)NULL, AuxDataNames())).first;
1626 (*nti).second.swap((*ti).second);
1627 _aux_data.swap(new_aux_data);
1641 BamReader::AuxData::
This is our own Panda specialization on the default STL map.
void read_file_data(SubfileInfo &info)
Reads a block of auxiliary file data from the Bam file.
TypeHandle find_type(const string &name) const
Looks for a previously-registered type of the given name.
void set_source(DatagramGenerator *source)
Changes the source of future datagrams for this BamReader.
bool get_bool()
Extracts a boolean value.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Stores auxiliary data that may be piggybacked on the BamReader during each object's read pass...
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
const Filename & get_filename() const
If a BAM is a file, then the BamReader should contain the name of the file.
A Factory can be used to create an instance of a particular subclass of some general base class...
virtual ReferenceCount * as_reference_count()
Returns the pointer cast to a ReferenceCount pointer, if it is in fact of that type.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
bool resolve()
This may be called at any time during processing of the Bam file to resolve all the known pointers so...
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Type * make_instance_more_general(TypeHandle handle, const FactoryParams ¶ms=FactoryParams())
Attempts to create an instance of the type requested, or some base type of the type requested...
TypedWritable * read_object()
Reads a single object from the Bam file.
void * get_pta(DatagramIterator &scan)
This function works in conjection with register_pta(), below, to read a PointerToArray (PTA) from the...
A single page of data maintained by a PipelineCycler.
Base class for objects that can be written to and read from Bam files.
string get_name(TypedObject *object=(TypedObject *) NULL) const
Returns the name of the type.
void skip_pointer(DatagramIterator &scan)
Reads and discards a pointer value from the Bam file.
This is the trivial, non-threaded implementation of PipelineCyclerBase.
BamReaderAuxData * get_aux_tag(const string &tag) const
Returns the value previously set via set_aux_tag().
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
CycleData * write(Thread *current_thread)
Returns a non-const CycleData pointer, filled with a unique copy of the data for the current stage of...
string get_string()
Extracts a variable-length string.
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
void register_change_this(ChangeThisFunc func, TypedWritable *whom)
Called by an object reading itself from the bam file to indicate that the object pointer that will be...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
TypeHandle register_dynamic_type(const string &name)
Registers a new type on-the-fly, presumably at runtime.
int get_remaining_size() const
Return the bytes left in the datagram.
AuxData * get_aux_data(TypedWritable *obj, const string &name) const
Returns the pointer previously associated with the bam reader by a previous call to set_aux_data()...
bool init()
Initializes the BamReader prior to reading any objects from its source.
virtual bool save_datagram(SubfileInfo &info)
Skips over the next datagram without extracting it, but saves the relevant file information in the Su...
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
bool change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer)
Indicates that an object recently read from the bam stream should be replaced with a new object...
int get_int_tag(const string &tag) const
Returns the value previously set via set_int_tag().
An instance of this class is passed to the Factory when requesting it to do its business and construc...
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
static TypeRegistry * ptr()
Returns the pointer to the global TypeRegistry object.
A base class for all things that want to be reference-counted.
void release_write(CycleData *pointer)
Releases a pointer previously obtained via a call to write().
TypeHandle get_parent_towards(TypeHandle ancestor, TypedObject *object=(TypedObject *) NULL) const
Returns the parent class that is in a direct line of inheritance to the indicated ancestor class...
void set_aux_tag(const string &tag, BamReaderAuxData *value)
Allows the creating object to store a temporary data value on the BamReader.
This class records a particular byte sub-range within an existing file on disk.
void set_int_tag(const string &tag, int value)
Allows the creating object to store a temporary data value on the BamReader.
A class to retrieve the individual data elements previously stored in a Datagram. ...
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
TypeHandle is the identifier used to differentiate C++ class types.
The parameters that are passed through the Factory to any object constructing itself from a Bam file...
This class defines the abstract interace to any source of datagrams, whether it be from a file or fro...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void record_derivation(TypeHandle child, TypeHandle parent)
Records that the type referenced by child inherits directly from the type referenced by parent...
void set_aux_data(TypedWritable *obj, const string &name, AuxData *data)
Associates an arbitrary block of data with the indicated object (or NULL), and the indicated name...
TypeHandle read_handle(DatagramIterator &scan)
Reads a TypeHandle out of the Datagram.
void register_pta(void *ptr)
The second part of read_pta(), this should be called with the pointer to the array that was read in a...
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.