Panda3D

bamReader.h

00001 // Filename: bamReader.h
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 #ifndef __BAM_READER_
00016 #define __BAM_READER_
00017 
00018 #include "pandabase.h"
00019 #include "pnotify.h"
00020 
00021 #include "typedWritable.h"
00022 #include "typedWritableReferenceCount.h"
00023 #include "pointerTo.h"
00024 #include "datagramGenerator.h"
00025 #include "datagramIterator.h"
00026 #include "bamReaderParam.h"
00027 #include "bamEnums.h"
00028 #include "loaderOptions.h"
00029 #include "factory.h"
00030 #include "vector_int.h"
00031 #include "pset.h"
00032 #include "pmap.h"
00033 #include "dcast.h"
00034 #include "pipelineCyclerBase.h"
00035 #include "referenceCount.h"
00036 
00037 #include <algorithm>
00038 
00039 
00040 // A handy macro for reading PointerToArrays.
00041 #define READ_PTA(Manager, source, Read_func, array)   \
00042 {                                                     \
00043   void *t;                                            \
00044   if ((t = Manager->get_pta(source)) == (void*)NULL)  \
00045   {                                                   \
00046     array = Read_func(Manager, source);               \
00047     Manager->register_pta(array.get_void_ptr());      \
00048   }                                                   \
00049   else                                                \
00050   {                                                   \
00051     array.set_void_ptr(t);                            \
00052   }                                                   \
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////////
00056 //       Class : BamReaderAuxData
00057 // Description : Stores auxiliary data that may be piggybacked on the
00058 //               BamReader during each object's read pass.  To use
00059 //               this, subclass BamReaderAuxData and add whatever
00060 //               additional data you require.
00061 ////////////////////////////////////////////////////////////////////
00062 class EXPCL_PANDA_PGRAPH BamReaderAuxData : public TypedReferenceCount {
00063 public:
00064   INLINE BamReaderAuxData();
00065 
00066 public:
00067   virtual TypeHandle get_type() const {
00068     return get_class_type();
00069   }
00070   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00071   static TypeHandle get_class_type() {
00072     return _type_handle;
00073   }
00074 
00075 public:
00076   static void init_type() {
00077     TypedReferenceCount::init_type();
00078     register_type(_type_handle, "BamReaderAuxData",
00079                   TypedReferenceCount::get_class_type());
00080   }
00081 
00082 private:
00083   static TypeHandle _type_handle;
00084 };  
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //       Class : BamReader
00088 // Description : This is the fundamental interface for extracting
00089 //               binary objects from a Bam file, as generated by a
00090 //               BamWriter.
00091 //
00092 //               A Bam file can be thought of as a linear collection
00093 //               of objects.  Each object is an instance of a class
00094 //               that inherits, directly or indirectly, from
00095 //               TypedWritable.  The objects may include pointers to
00096 //               other objects within the Bam file; the BamReader
00097 //               automatically manages these (with help from code
00098 //               within each class) and restores the pointers
00099 //               correctly.
00100 //
00101 //               This is the abstract interface and does not
00102 //               specifically deal with disk files, but rather with a
00103 //               DatagramGenerator of some kind, which is simply a
00104 //               linear source of Datagrams.  It is probably from a
00105 //               disk file, but it might conceivably be streamed
00106 //               directly from a network or some such nonsense.
00107 //
00108 //               Bam files are most often used to store scene graphs
00109 //               or subgraphs, and by convention they are given
00110 //               filenames ending in the extension ".bam" when they
00111 //               are used for this purpose.  However, a Bam file may
00112 //               store any arbitrary list of TypedWritable objects;
00113 //               in this more general usage, they are given filenames
00114 //               ending in ".boo" to differentiate them from the more
00115 //               common scene graph files.
00116 //
00117 //               See also BamFile, which defines a higher-level
00118 //               interface to read and write Bam files on disk.
00119 ////////////////////////////////////////////////////////////////////
00120 class EXPCL_PANDA_PUTIL BamReader : public BamEnums {
00121 public:
00122   typedef Factory<TypedWritable> WritableFactory;
00123   static BamReader *const Null;
00124   static WritableFactory *const NullFactory;
00125 
00126 PUBLISHED:
00127   // The primary interface for a caller.
00128   BamReader(DatagramGenerator *source = NULL, const Filename &name = "");
00129   ~BamReader();
00130 
00131   void set_source(DatagramGenerator *source);
00132 
00133   bool init();
00134 
00135   class AuxData;
00136   void set_aux_data(TypedWritable *obj, const string &name, AuxData *data);
00137   AuxData *get_aux_data(TypedWritable *obj, const string &name) const;
00138 
00139   INLINE const Filename &get_filename() const;
00140 
00141   INLINE const LoaderOptions &get_loader_options() const;
00142   INLINE void set_loader_options(const LoaderOptions &options);
00143   
00144   TypedWritable *read_object();
00145   bool read_object(TypedWritable *&ptr, ReferenceCount *&ref_ptr);
00146 
00147   INLINE bool is_eof() const;
00148   bool resolve();
00149 
00150   bool change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer);
00151 
00152   INLINE int get_file_major_ver() const;
00153   INLINE int get_file_minor_ver() const;
00154   INLINE BamEndian get_file_endian() const;
00155 
00156   INLINE int get_current_major_ver() const;
00157   INLINE int get_current_minor_ver() const;
00158 
00159 public:
00160   // Functions to support classes that read themselves from the Bam.
00161 
00162   void read_pointer(DatagramIterator &scan);
00163   void read_pointers(DatagramIterator &scan, int count);
00164   void skip_pointer(DatagramIterator &scan);
00165 
00166   void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler);
00167   void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler,
00168                   void *extra_data);
00169 
00170   void set_int_tag(const string &tag, int value);
00171   int get_int_tag(const string &tag) const;
00172 
00173   void set_aux_tag(const string &tag, BamReaderAuxData *value);
00174   BamReaderAuxData *get_aux_tag(const string &tag) const;
00175 
00176   void register_finalize(TypedWritable *whom);
00177 
00178   typedef TypedWritable *(*ChangeThisFunc)(TypedWritable *object, BamReader *manager);
00179   typedef PT(TypedWritableReferenceCount) (*ChangeThisRefFunc)(TypedWritableReferenceCount *object, BamReader *manager);
00180   void register_change_this(ChangeThisFunc func, TypedWritable *whom);
00181   void register_change_this(ChangeThisRefFunc func, TypedWritableReferenceCount *whom);
00182 
00183   void finalize_now(TypedWritable *whom);
00184 
00185   void *get_pta(DatagramIterator &scan);
00186   void register_pta(void *ptr);
00187 
00188   TypeHandle read_handle(DatagramIterator &scan);
00189 
00190   INLINE VirtualFile *get_file();
00191   INLINE streampos get_file_pos();
00192 
00193 public:
00194   INLINE static WritableFactory *get_factory();
00195 private:
00196   INLINE static void create_factory();
00197 
00198 private:
00199   class PointerReference;
00200 
00201   void free_object_ids(DatagramIterator &scan);
00202   int read_object_id(DatagramIterator &scan);
00203   int read_pta_id(DatagramIterator &scan);
00204   int p_read_object();
00205   bool resolve_object_pointers(TypedWritable *object, PointerReference &pref);
00206   bool resolve_cycler_pointers(PipelineCyclerBase *cycler, const vector_int &pointer_ids,
00207                                bool require_fully_complete);
00208   void finalize();
00209 
00210   INLINE bool get_datagram(Datagram &datagram);
00211 
00212 public:
00213   // Inherit from this class to piggyback additional temporary data on
00214   // the bamReader (via set_aux_data() and get_aux_data()) for any
00215   // particular objects during the bam reading process.
00216   class AuxData : public ReferenceCount {
00217   public:
00218     INLINE AuxData();
00219     virtual ~AuxData();
00220   };
00221 
00222 private:
00223   static WritableFactory *_factory;
00224 
00225   DatagramGenerator *_source;
00226   bool _needs_init;
00227   
00228   bool _long_object_id;
00229   bool _long_pta_id;
00230 
00231   // This maps the type index numbers encountered within the Bam file
00232   // to actual TypeHandles.
00233   typedef phash_map<int, TypeHandle, int_hash> IndexMap;
00234   IndexMap _index_map;
00235 
00236   // This is the filename of the BAM, or empty string if not in a file.
00237   Filename _filename;
00238 
00239   LoaderOptions _loader_options;
00240 
00241   // This maps the object ID numbers encountered within the Bam file
00242   // to the actual pointers of the corresponding generated objects.
00243   class CreatedObj {
00244   public:
00245     INLINE CreatedObj();
00246     INLINE ~CreatedObj();
00247     INLINE void set_ptr(TypedWritable *ptr, ReferenceCount *ref_ptr);
00248 
00249   public:
00250     bool _created;
00251     TypedWritable *_ptr;
00252     ReferenceCount *_ref_ptr;
00253     ChangeThisFunc _change_this;
00254     ChangeThisRefFunc _change_this_ref;
00255   };
00256   typedef phash_map<int, CreatedObj, int_hash> CreatedObjs;
00257   CreatedObjs _created_objs;
00258   // This is the iterator into the above map for the object we are
00259   // currently reading in p_read_object().  It is carefully maintained
00260   // during recursion.  We need this so we can associate
00261   // read_pointer() calls with the proper objects.
00262   CreatedObjs::iterator _now_creating;
00263   // This is the pointer to the current PipelineCycler we are reading,
00264   // if we are within a read_cdata() call.
00265   PipelineCyclerBase *_reading_cycler;
00266 
00267   // This is the reverse lookup into the above map.
00268   typedef phash_map<const TypedWritable *, vector_int, pointer_hash> CreatedObjsByPointer;
00269   CreatedObjsByPointer _created_objs_by_pointer;
00270 
00271   // This records all the objects that still need their pointers
00272   // completed, along with the object ID's of the pointers they need,
00273   // in the order in which read_pointer() was called, so that we may
00274   // call the appropriate complete_pointers() later.
00275   typedef phash_map<PipelineCyclerBase *, vector_int, pointer_hash> CyclerPointers;
00276   typedef pmap<string, int> IntTags;
00277   typedef pmap<string, PT(BamReaderAuxData) > AuxTags;
00278   class PointerReference {
00279   public:
00280     vector_int _objects;
00281     CyclerPointers _cycler_pointers;
00282     IntTags _int_tags;
00283     AuxTags _aux_tags;
00284   };
00285   typedef phash_map<int, PointerReference, int_hash> ObjectPointers;
00286   ObjectPointers _object_pointers;
00287 
00288   // This is the number of extra objects that must still be read (and
00289   // saved in the _created_objs map) before returning from
00290   // read_object().  It is only used when read bam versions prior to
00291   // 6.20.
00292   int _num_extra_objects;
00293 
00294   // The current nesting level.  We are not done reading an object
00295   // until we return to our starting nesting level.  It is only used
00296   // when reading bam versions of 6.20 or higher.
00297   int _nesting_level;
00298 
00299   // This is the set of all objects that registered themselves for
00300   // finalization.
00301   typedef phash_set<TypedWritable *, pointer_hash> Finalize;
00302   Finalize _finalize_list;
00303 
00304   // These are used by get_pta() and register_pta() to unify multiple
00305   // references to the same PointerToArray.
00306   typedef phash_map<int, void *, int_hash> PTAMap;
00307   PTAMap _pta_map;
00308   int _pta_id;
00309 
00310   // This is used internally to record all of the new types created
00311   // on-the-fly to satisfy bam requirements.  We keep track of this
00312   // just so we can suppress warning messages from attempts to create
00313   // objects of these types.
00314   typedef phash_set<TypeHandle> NewTypes;
00315   static NewTypes _new_types;
00316 
00317   // This is used in support of set_aux_data() and get_aux_data().
00318   typedef pmap<string, PT(AuxData)> AuxDataNames;
00319   typedef phash_map<TypedWritable *, AuxDataNames, pointer_hash> AuxDataTable;
00320   AuxDataTable _aux_data;
00321 
00322   int _file_major, _file_minor;
00323   BamEndian _file_endian;
00324   static const int _cur_major;
00325   static const int _cur_minor;
00326 };
00327 
00328 typedef BamReader::WritableFactory WritableFactory;
00329 
00330 // Useful function for taking apart the Factory Params in the static
00331 // functions that need to be defined in each writable class that will
00332 // be generated by a factory.  Sets the DatagramIterator and the
00333 // BamReader pointers.
00334 INLINE void
00335 parse_params(const FactoryParams &params,
00336              DatagramIterator &scan, BamReader *&manager);
00337 
00338 #include "bamReader.I"
00339 
00340 #endif
 All Classes Functions Variables Enumerations