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