From 1892ffa1d0637652c8e652513de13247d8b92fa0 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 9 May 2001 18:08:36 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/egg/eggData.cxx | 11 +- panda/src/putil/bamReader.cxx | 34 +-- panda/src/putil/bamReader.h | 7 +- panda/src/putil/bamWriter.I | 14 -- panda/src/putil/bamWriter.cxx | 424 +++++++++++++++++++--------------- panda/src/putil/bamWriter.h | 117 ++++++---- 6 files changed, 334 insertions(+), 273 deletions(-) diff --git a/panda/src/egg/eggData.cxx b/panda/src/egg/eggData.cxx index 1585176b8b..708a6aa2ae 100644 --- a/panda/src/egg/eggData.cxx +++ b/panda/src/egg/eggData.cxx @@ -32,9 +32,14 @@ TypeHandle EggData::_type_handle; //////////////////////////////////////////////////////////////////// bool EggData:: resolve_egg_filename(Filename &egg_filename, const DSearchPath &searchpath) { - egg_filename.resolve_filename(searchpath, "egg"); - egg_filename.resolve_filename(get_egg_path(), "egg"); - egg_filename.resolve_filename(get_model_path(), "egg"); + if (egg_filename.is_fully_qualified() && egg_filename.exists()) { + return true; + } + + egg_filename.resolve_filename(searchpath, "egg") || + egg_filename.resolve_filename(get_egg_path(), "egg") || + egg_filename.resolve_filename(get_model_path(), "egg"); + return egg_filename.exists(); } diff --git a/panda/src/putil/bamReader.cxx b/panda/src/putil/bamReader.cxx index 1ba3114bd9..d7c4d22222 100644 --- a/panda/src/putil/bamReader.cxx +++ b/panda/src/putil/bamReader.cxx @@ -45,7 +45,8 @@ BamReader:: // Function: BamReader::init // Access: Public // Description: Initializes the BamReader prior to reading any -// objects from its source. +// objects from its source. This includes reading the +// Bam header. // // This returns true if the BamReader successfully // initialized, false otherwise. @@ -277,7 +278,7 @@ TypeHandle BamReader:: read_handle(DatagramIterator &scan) { // We encode TypeHandles within the Bam file by writing a unique // index number for each one to the file. When we write a - // particular TypeHandle for the first type, we assign it a new + // particular TypeHandle for the first time, we assign it a new // index number and then immediately follow it by its definition; // when we write the same TypeHandle on subsequent times we only // write the index number. @@ -291,15 +292,6 @@ read_handle(DatagramIterator &scan) { if (id == 0) { // Index number 0 is always, by convention, TypeHandle::none(). - - // This indicates an object that should have already been read in, - // so return TypeHandle::none() to indicate this. -#ifndef NDEBUG - if (bam_cat.is_spam()) { - bam_cat.spam() - << "Read TypeHandle::none().\n"; - } -#endif return TypeHandle::none(); } @@ -309,13 +301,6 @@ read_handle(DatagramIterator &scan) { // no type definition following the id. Simply return the // TypeHandle we previously associated with the id. TypeHandle type = (*mi).second; - -#ifndef NDEBUG - if (bam_cat.is_spam()) { - bam_cat.spam() - << "Read TypeHandle for " << type << ".\n"; - } -#endif return type; } @@ -510,8 +495,8 @@ get_pta(DatagramIterator &scan) { return (void *)NULL; } - PTAMap::iterator pi = _ptamap.find(id); - if (pi == _ptamap.end()) { + PTAMap::iterator pi = _pta_map.find(id); + if (pi == _pta_map.end()) { // This is the first time we've encountered this particular ID, // meaning we need to read the data now and register it. _pta_id = id; @@ -537,7 +522,7 @@ get_pta(DatagramIterator &scan) { void BamReader:: register_pta(void *ptr) { if (_pta_id != -1) { - bool inserted = _ptamap.insert(PTAMap::value_type(_pta_id, ptr)).second; + bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second; _pta_id = -1; nassertv(inserted); } @@ -640,13 +625,6 @@ p_read_object() { } } -#ifndef NDEBUG - if (bam_cat.is_spam()) { - bam_cat.spam() - << "Emptying queue.\n"; - } -#endif - return object_id; } diff --git a/panda/src/putil/bamReader.h b/panda/src/putil/bamReader.h index 7c017909ef..bf7a46e1e9 100644 --- a/panda/src/putil/bamReader.h +++ b/panda/src/putil/bamReader.h @@ -18,7 +18,7 @@ #include -//Useful define for reading pta's +// A handy macro for reading PointerToArrays. #define READ_PTA(Manager, source, Read_func, array) \ { \ void *t; \ @@ -44,7 +44,8 @@ // that inherits, directly or indirectly, from // TypedWriteable. The objects may include pointers to // other objects within the Bam file; the BamReader -// automatically manages these and restores the pointers +// automatically manages these (with help from code +// within each class) and restores the pointers // correctly. // // This is the abstract interface and does not @@ -148,7 +149,7 @@ private: // These are used by get_pta() and register_pta() to unify multiple // references to the same PointerToArray. typedef map PTAMap; - PTAMap _ptamap; + PTAMap _pta_map; int _pta_id; int _file_major, _file_minor; diff --git a/panda/src/putil/bamWriter.I b/panda/src/putil/bamWriter.I index 12687ae0e4..bfa1110328 100644 --- a/panda/src/putil/bamWriter.I +++ b/panda/src/putil/bamWriter.I @@ -1,17 +1,3 @@ // Filename: bamWriter.I // Created by: jason (08Jun00) // - -//////////////////////////////////////////////////////////////////// -// Function: BamWriter::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE BamWriter:: -BamWriter(DatagramSink *sink) : - //_current needs to start from 1, as a value of 0 - //for a unique object ID will be used to indicate a null pointer - _target(sink), _writing(false), _current(1), - _current_pta(1), _emptying(false) -{ -} diff --git a/panda/src/putil/bamWriter.cxx b/panda/src/putil/bamWriter.cxx index 64298a8315..db50304aec 100644 --- a/panda/src/putil/bamWriter.cxx +++ b/panda/src/putil/bamWriter.cxx @@ -10,59 +10,43 @@ #include "bamWriter.h" //////////////////////////////////////////////////////////////////// -// Function: BamWriter::Destructor +// Function: BamWriter::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -BamWriter::~BamWriter(void) +BamWriter:: +BamWriter(DatagramSink *sink) : + _target(sink) { } //////////////////////////////////////////////////////////////////// -// Function: BamWriter::write_handle +// Function: BamWriter::Destructor // Access: Public -// Description: Writes a type handle into the file. If the handle -// has already been encountered then a number -// identifying that handle is written instead. +// Description: //////////////////////////////////////////////////////////////////// -void BamWriter:: -write_handle(Datagram &packet, TypeHandle type) -{ - //No class should have a type handle index of 0 - nassertv(type.get_index() != 0); - - packet.add_uint16(type.get_index()); - if (_type_map.find(type.get_index()) == _type_map.end()) - { - // This is the first time this TypeHandle has been written, so - // also write out its name. - _type_map.insert(type.get_index()); - packet.add_string(type.get_name()); - - // We also need to write the derivation of the TypeHandle, in case - // the program reading this file later has never heard of this - // type before. - int num_parent_classes = type.get_num_parent_classes(); - nassertv(num_parent_classes <= 255); // Good grief! - packet.add_uint8(num_parent_classes); - for (int i = 0; i < num_parent_classes; i++) { - write_handle(packet, type.get_parent_class(i)); - } - } +BamWriter:: +~BamWriter() { } //////////////////////////////////////////////////////////////////// // Function: BamWriter::init // Access: Public -// Description: This function initializes the BamWriter, setting -// up whatever needs to be set up before the BamWriter -// is ready to write out objects. It returns true if -// successful, false on failure. +// Description: Initializes the BamWriter prior to writing any +// objects to its output stream. This includes writing +// out the Bam header. +// +// This returns true if the BamWriter successfully +// initialized, false otherwise. //////////////////////////////////////////////////////////////////// bool BamWriter:: -init(void) -{ - //Write out the current major and minor BAM file version numbers +init() { + // Initialize the next object and PTA ID's. These start counting at + // 1, since 0 is reserved for NULL. + _next_object_id = 1; + _next_pta_id = 1; + + // Write out the current major and minor BAM file version numbers. Datagram header; header.add_uint16(_bam_major_ver); @@ -79,205 +63,279 @@ init(void) //////////////////////////////////////////////////////////////////// // Function: BamWriter::write_object // Access: Public -// Description: Main function for performing the processing of -// writing an object to some Binary target. Combined -// with write_pointer this function can correctly handle -// and break circular references, while still writing out -// the necessary information for re-constructing those -// references when the objects are read back in. +// Description: Writes a single object to the Bam file, so that the +// BamReader::read_object() can later correctly restore +// the object and all its pointers. +// +// This implicitly also writes any additional objects +// this object references (if they haven't already been +// written), so that pointers may be fully resolved. +// +// This may be called repeatedly to write a sequence of +// objects to the Bam file, but typically (especially +// for scene graph files, indicated with the .bam +// extension), only one object is written directly from +// the Bam file: the root of the scene graph. The +// remaining objects will all be written recursively by +// the first object. // // Returns true if the object is successfully written, // false otherwise. //////////////////////////////////////////////////////////////////// bool BamWriter:: -write_object(TypedWriteable* obj) -{ - Datagram objData; +write_object(TypedWriteable *object) { + nassertr(_object_queue.empty(), false); - nassertr(obj != TypedWriteable::Null, false); + int object_id = enqueue_object(object); + nassertr(object_id != 0, false); - //No object should ever be written out that is not - //registered as a child of TypedWriteable. The - //only way this can get in here and have that true is - //if someone forgot to set the classes init_type correctly. - //So nassert on that to make it easy for them to track - //down the error, because that will be an error, but one - //that won't show up on the writing, it will show up in - //reading, so could be potentially difficult to track down - nassertr(obj->is_of_type(TypedWriteable::get_class_type()), false); + // Now we write out all the objects in the queue, in order. The + // first one on the queue will, of course, be this object we just + // queued up, but each object we write may append more to the queue. + while (!_object_queue.empty()) { + object = _object_queue.front(); + _object_queue.pop_front(); - //Need to keep track of the state of any objects written - //or queued. So every time write_object is called, - //check to see if has been encountered before, if not - //insert it into a map with a Key of the pointer to - //the object and the value being a class that contains - //the unigue object ID for that object and a flag of - //whether it has been written yet or no - if (_statemap.find(obj) == _statemap.end()) - { - //If the object is not already in the map, then - //add it and assign it and unique object number - _statemap[obj].objId = _current; - _current++; - //We are making the assumption that there will never - //be more than the max of an unsigned short in objects - //in one file, but just in case, this nassert will make - //it easy to find that possible error - nassertr(_current != 0, false); - } + // Look up the object in the map. It had better be there! + StateMap::iterator si = _state_map.find(object); + nassertr(si != _state_map.end(), false); - bool okflag = true; + int object_id = (*si).second._object_id; + bool already_written = (*si).second._written; - if (_writing) - { - enqueue(obj); - } - else - { - _writing = true; + Datagram dg; - if (!_statemap[obj].written) - { - //Write the type handle of the object - write_handle(objData, obj->get_type()); - //Write the unique ID of the object into the datagram - //so that when it is read back, and there is a back - //reference to this object, we know what indices correspond - //to what objects - objData.add_uint16(_statemap[obj].objId); - obj->write_datagram(this, objData); - _statemap[obj].written = true; - } - else - { - //If it is in the map, then we don't want to try - //and write it again, so write the unique ID of the - //object into the datagram so that when we read in - //later, we can resolve back references. Write - //0 for the type handle to identify back references - objData.add_uint16(0); - objData.add_uint16(_statemap[obj].objId); + if (!already_written) { + // The first time we write a particular object, we do so by + // writing its TypeHandle (which had better not be + // TypeHandle::none(), since that's our code for a + // previously-written object), followed by the object ID number, + // followed by the object definition. + + TypeHandle type = object->get_type(); + nassertr(type != TypeHandle::none(), false); + + write_handle(dg, type); + dg.add_uint16(object_id); + + object->write_datagram(this, dg); + (*si).second._written = true; + + } else { + // On subsequent times when we write a particular object, we + // write simply TypeHandle::none(), followed by the object ID. + // The occurrence of TypeHandle::none() is an indicator to the + // BamReader that this is a previously-written object. + + write_handle(dg, TypeHandle::none()); + dg.add_uint16(object_id); } - if (!_target->put_datagram(objData)) { + if (!_target->put_datagram(dg)) { util_cat.error() << "Unable to write datagram to file.\n"; - okflag = false; - } - _writing = false; - if (!_emptying) - { - if (!empty_queue()) { - okflag = false; - } + return false; } } - return okflag; + return true; } //////////////////////////////////////////////////////////////////// // Function: BamWriter::write_pointer // Access: Public -// Description: Utility function to be called by the objects writing -// themselves to a Datagram. Basically amounts to a -// request to BamWriter to queue an object to be written -// and to write into the Datagram the necessary information -// to reference that object +// Description: The interface for writing a pointer to another object +// to a Bam file. This is intended to be called by the +// various objects that write themselves to the Bam +// file, within the write_datagram() method. +// +// This writes the pointer out in such a way that the +// BamReader will be able to restore the pointer later. +// If the pointer is to an object that has not yet +// itself been written to the Bam file, that object will +// automatically be written. //////////////////////////////////////////////////////////////////// void BamWriter:: -write_pointer(Datagram &packet , TypedWriteable *dest) -{ - //Write a zero for the object ID if the pointer is null - if (dest == TypedWriteable::Null) - { +write_pointer(Datagram &packet, TypedWriteable *object) { + // If the pointer is NULL, we always simply write a zero for an + // object ID and leave it at that. + if (object == (TypedWriteable *)NULL) { packet.add_uint16(0); - } - else - { - if (_statemap.find(dest) == _statemap.end()) - { - write_object(dest); + + } else { + StateMap::iterator si = _state_map.find(object); + if (si == _state_map.end()) { + // We have not written this pointer out yet. This means we must + // queue the object definition up for later. + int object_id = enqueue_object(object); + packet.add_uint16(object_id); + + } else { + // We have already assigned this pointer an ID; thus, we can + // simply write out the ID. + packet.add_uint16((*si).second._object_id); } - - packet.add_uint16(_statemap[dest].objId); } } //////////////////////////////////////////////////////////////////// // Function: BamWriter::register_pta // Access: Public -// Description: Utility function to be called by the objects writing -// themselves to a Datagram. Registers a PTA to be written -// into the Datagram, and allows for shared references -// to be captured in the datagram +// Description: Prepares to write a PointerToArray to the Bam file, +// unifying references to the same pointer across the +// Bam file. +// +// The writing object should call this prior to writing +// out a PointerToArray. It will return true if the +// same pointer has been previously, in which case the +// writing object need do nothing further; or it will +// return false if this particular pointer has not yet +// been written, in which case the writing object must +// then write out the contents of the array. +// +// Also see the WRITE_PTA() macro, which consolidates +// the work that must be done to write a PTA. //////////////////////////////////////////////////////////////////// bool BamWriter:: -register_pta(Datagram &packet, void *ptr) -{ - if (ptr != (void*)NULL) - { - if (_ptamap.find(ptr) == _ptamap.end()) - { - _ptamap[ptr] = _current_pta; - packet.add_uint16(_current_pta); - _current_pta++; - return false; - } - - packet.add_uint16(_ptamap[ptr]); - } - else - { - //A zero for the PTA ID indicates a NULL ptr +register_pta(Datagram &packet, void *ptr) { + if (ptr == (void *)NULL) { + // A zero for the PTA ID indicates a NULL pointer. This is a + // special case. packet.add_uint16(0); + + // We return false to indicate the user must now write out the + // "definition" of the NULL pointer. This is necessary because of + // a quirk in the BamReader's design, which forces callers to read + // the definition of every NULL pointer. Presumably, the caller + // will be able to write the definition in a concise way that will + // clearly indicate a NULL pointer; in the case of a + // PointerToArray, this will generally be simply a zero element + // count. return false; } - return true; + PTAMap::iterator pi = _pta_map.find(ptr); + if (pi == _pta_map.end()) { + // We have not encountered this pointer before. + int pta_id = _next_pta_id; + _next_pta_id++; + + // Make sure our PTA ID will fit within the PN_uint16 we have + // allocated for it. + nassertr(pta_id <= 65535, 0); + + bool inserted = _pta_map.insert(PTAMap::value_type(ptr, pta_id)).second; + nassertr(inserted, false); + + packet.add_uint16(pta_id); + + // Return false to indicate the caller must now write out the + // array definition. + return false; + + } else { + // We have encountered this pointer before. + int pta_id = (*pi).second; + packet.add_uint16(pta_id); + + // Return true to indicate the caller need do nothing further. + return true; + } } //////////////////////////////////////////////////////////////////// -// Function: BamWriter::enqueue -// Access: Private -// Description: Queue an object to be written +// Function: BamWriter::write_handle +// Access: Public +// Description: Writes a TypeHandle to the file in such a way that +// the BamReader can read the same TypeHandle later via +// read_handle(). //////////////////////////////////////////////////////////////////// void BamWriter:: -enqueue(TypedWriteable *obj) -{ - _deferred.push_back(obj); -} +write_handle(Datagram &packet, TypeHandle type) { + // We encode TypeHandles within the Bam file by writing a unique + // index number for each one to the file. When we write a + // particular TypeHandle for the first time, we assign it a new + // index number and then immediately follow it by its definition; + // when we write the same TypeHandle on subsequent times we only + // write the index number. -//////////////////////////////////////////////////////////////////// -// Function: BamWriter::empty_queue -// Access: Private -// Description: For each object in the queue call write_object on it. -// Returns true of all write_object calls returned true, -// false otherwise. -//////////////////////////////////////////////////////////////////// -bool BamWriter:: -empty_queue(void) -{ - _emptying = true; - bool okflag = true; - while(!_deferred.empty()) - { - if (!write_object(_deferred.front())) { - okflag = false; + // The unique number we choose is actually the internal index number + // of the TypeHandle. Why not? + int index = type.get_index(); + + // Also make sure the index number fits within a PN_uint16. + nassertv(index <= 65535); + + packet.add_uint16(index); + + if (index != 0) { + bool inserted = _types_written.insert(index).second; + + if (inserted) { + // This is the first time this TypeHandle has been written, so + // also write out its definition. + packet.add_string(type.get_name()); + + // We also need to write the derivation of the TypeHandle, in case + // the program reading this file later has never heard of this + // type before. + int num_parent_classes = type.get_num_parent_classes(); + nassertv(num_parent_classes <= 255); // Good grief! + packet.add_uint8(num_parent_classes); + for (int i = 0; i < num_parent_classes; i++) { + write_handle(packet, type.get_parent_class(i)); + } } - _deferred.pop_front(); } - _emptying = false; - return okflag; } +//////////////////////////////////////////////////////////////////// +// Function: BamWriter::enqueue_object +// Access: Private +// Description: Assigns an object ID to the object and queues it up +// for later writing to the Bam file. +// +// The return value is the object ID, or 0 if there is +// an error. +//////////////////////////////////////////////////////////////////// +int BamWriter:: +enqueue_object(TypedWriteable *object) { + Datagram dg; + nassertr(object != TypedWriteable::Null, 0); + // No object should ever be written out that is not registered as a + // child of TypedWriteable. The only way this can happen is if + // someone failed to initialize their type correctly in init_type(). + nassertr(object->is_of_type(TypedWriteable::get_class_type()), 0); + // We need to assign a unique index number to every object we write + // out. Has this object been assigned a number yet? + int object_id; + bool already_written; + StateMap::iterator si = _state_map.find(object); + if (si == _state_map.end()) { + // No, it hasn't, so assign it the next number in sequence + // arbitrarily. + object_id = _next_object_id; + already_written = false; + + // Make sure our object ID will fit within the PN_uint16 we have + // allocated for it. + nassertr(object_id <= 65535, 0); + bool inserted = + _state_map.insert(StateMap::value_type(object, StoreState(_next_object_id))).second; + nassertr(inserted, false); + _next_object_id++; + } else { + // Yes, it has; get the object ID. + object_id = (*si).second._object_id; + already_written = (*si).second._written; + } - - - + _object_queue.push_back(object); + return object_id; +} diff --git a/panda/src/putil/bamWriter.h b/panda/src/putil/bamWriter.h index eba31c796d..58b8eac8cf 100644 --- a/panda/src/putil/bamWriter.h +++ b/panda/src/putil/bamWriter.h @@ -12,6 +12,7 @@ #include "datagramSink.h" #include +// A handy macro for writing PointerToArrays. #define WRITE_PTA(Manager, dest, Write_func, array) \ if (!Manager->register_pta(dest, array.p())) \ { \ @@ -21,60 +22,92 @@ //////////////////////////////////////////////////////////////////// // Class : BamWriter -// Description : This class manages all aspects of writing data -// structures to some Binary form. It writes to a -// a DatagramSink which is an abstraction that could -// be a file, the net, etc... The two basic functions -// used are write_object and write_pointer. write_object -// is called to write any TypedWriteable object out. -// BamWriter actually asks the object passed to write -// itself out to a datagram, and then it writes that -// datagram to the DatagramSink. write_pointer is called -// by the objects themselves to resolve writing out -// pointers to other objects. BamWriter will handle all -// circular references correctly +// Description : This is the fundamental interface for writing binary +// objects to a Bam file, to be extracted later by a +// BamReader. +// +// A Bam file can be thought of as a linear collection +// of objects. Each object is an instance of a class +// that inherits, directly or indirectly, from +// TypedWriteable. The objects may include pointers to +// other objects; the BamWriter automatically manages +// these (with help from code within each class) and +// writes all referenced objects to the file in such a +// way that the pointers may be correctly restored +// later. +// +// This is the abstract interface and does not +// specifically deal with disk files, but rather with a +// DatagramSink of some kind, which simply accepts a +// linear stream of Datagrams. It is probably written +// to a disk file, but it might conceivably be streamed +// directly to a network or some such nonsense. +// +// Bam files are most often used to store scene graphs +// or subgraphs, and by convention they are given +// filenames ending in the extension ".bam" when they +// are used for this purpose. However, a Bam file may +// store any arbitrary list of TypedWriteable objects; +// in this more general usage, they are given filenames +// ending in ".boo" to differentiate them from the more +// common scene graph files. +// +// See also BamFile, which defines a higher-level +// interface to read and write Bam files on disk. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA BamWriter{ public: - INLINE BamWriter(DatagramSink *sink); - ~BamWriter(void); + BamWriter(DatagramSink *sink); + ~BamWriter(); + + // The primary interface for a caller. - bool init(void); + bool init(); bool write_object(TypedWriteable *obj); + +public: + // Functions to support classes that write themselves to the Bam. + void write_pointer(Datagram &packet, TypedWriteable *dest); - - //This function is provided for writing out shared pointers - //to PTA's. You should pass in a pointer to the PTA you want - //to write. If BamWriter has not already been asked to register - //this pointer, it will register it, write the appropriate info - //into the Datagram and return false. If it has, it will write - //the reference into the Datagram and return true. If false is - //returned, then the class registering the PTA should write out - //the info into the Datagram itself - bool register_pta(Datagram &packet, void* ptr); - + bool register_pta(Datagram &packet, void *ptr); void write_handle(Datagram &packet, TypeHandle type); + private: - class storeState { + int enqueue_object(TypedWriteable *object); + + + // This is the set of all TypeHandles already written. + set _types_written; + + // This keeps track of all of the objects we have written out + // already (or are about to write out), and associates a unique + // object ID number to each one. + class StoreState { public: - PN_uint16 objId; - bool written; + int _object_id; + bool _written; - storeState(void) : objId(0), written(false) {} - ~storeState(void) {} + StoreState(int object_id) : _object_id(object_id), _written(false) {} }; - - void enqueue(TypedWriteable *obj); - bool empty_queue(void); - + typedef map StateMap; + StateMap _state_map; + + // This is the next object ID that will be assigned to a new object. + int _next_object_id; + + // This is the queue of objects that need to be written when the + // current object is finished. + typedef deque ObjectQueue; + ObjectQueue _object_queue; + + // These are used by register_pta() to unify multiple references to + // the same PointerToArray. + typedef map PTAMap; + PTAMap _pta_map; + int _next_pta_id; + + // The destination to write all the output to. DatagramSink *_target; - bool _writing; - deque _deferred; - set _type_map; - map _statemap; - map _ptamap; - PN_uint16 _current, _current_pta; - bool _emptying; }; #include "bamWriter.I"