Panda3D
 All Classes Functions Variables Enumerations
bamReader.h
1 // Filename: bamReader.h
2 // Created by: jason (12Jun00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef __BAM_READER_
16 #define __BAM_READER_
17 
18 #include "pandabase.h"
19 #include "pnotify.h"
20 
21 #include "typedWritable.h"
22 #include "typedWritableReferenceCount.h"
23 #include "pointerTo.h"
24 #include "datagramGenerator.h"
25 #include "datagramIterator.h"
26 #include "bamReaderParam.h"
27 #include "bamEnums.h"
28 #include "subfileInfo.h"
29 #include "loaderOptions.h"
30 #include "factory.h"
31 #include "vector_int.h"
32 #include "pset.h"
33 #include "pmap.h"
34 #include "pdeque.h"
35 #include "dcast.h"
36 #include "pipelineCyclerBase.h"
37 #include "referenceCount.h"
38 
39 #include <algorithm>
40 
41 
42 // A handy macro for reading PointerToArrays.
43 #define READ_PTA(Manager, source, Read_func, array) \
44 { \
45  void *t; \
46  if ((t = Manager->get_pta(source)) == (void*)NULL) \
47  { \
48  array = Read_func(Manager, source); \
49  Manager->register_pta(array.get_void_ptr()); \
50  } \
51  else \
52  { \
53  array.set_void_ptr(t); \
54  } \
55 }
56 
57 ////////////////////////////////////////////////////////////////////
58 // Class : BamReaderAuxData
59 // Description : Stores auxiliary data that may be piggybacked on the
60 // BamReader during each object's read pass. To use
61 // this, subclass BamReaderAuxData and add whatever
62 // additional data you require.
63 ////////////////////////////////////////////////////////////////////
64 class EXPCL_PANDA_PGRAPH BamReaderAuxData : public TypedReferenceCount {
65 public:
66  INLINE BamReaderAuxData();
67 
68 public:
69  virtual TypeHandle get_type() const {
70  return get_class_type();
71  }
72  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
73  static TypeHandle get_class_type() {
74  return _type_handle;
75  }
76 
77 public:
78  static void init_type() {
79  TypedReferenceCount::init_type();
80  register_type(_type_handle, "BamReaderAuxData",
81  TypedReferenceCount::get_class_type());
82  }
83 
84 private:
85  static TypeHandle _type_handle;
86 };
87 
88 ////////////////////////////////////////////////////////////////////
89 // Class : BamReader
90 // Description : This is the fundamental interface for extracting
91 // binary objects from a Bam file, as generated by a
92 // BamWriter.
93 //
94 // A Bam file can be thought of as a linear collection
95 // of objects. Each object is an instance of a class
96 // that inherits, directly or indirectly, from
97 // TypedWritable. The objects may include pointers to
98 // other objects within the Bam file; the BamReader
99 // automatically manages these (with help from code
100 // within each class) and restores the pointers
101 // correctly.
102 //
103 // This is the abstract interface and does not
104 // specifically deal with disk files, but rather with a
105 // DatagramGenerator of some kind, which is simply a
106 // linear source of Datagrams. It is probably from a
107 // disk file, but it might conceivably be streamed
108 // directly from a network or some such nonsense.
109 //
110 // Bam files are most often used to store scene graphs
111 // or subgraphs, and by convention they are given
112 // filenames ending in the extension ".bam" when they
113 // are used for this purpose. However, a Bam file may
114 // store any arbitrary list of TypedWritable objects;
115 // in this more general usage, they are given filenames
116 // ending in ".boo" to differentiate them from the more
117 // common scene graph files.
118 //
119 // See also BamFile, which defines a higher-level
120 // interface to read and write Bam files on disk.
121 ////////////////////////////////////////////////////////////////////
122 class EXPCL_PANDA_PUTIL BamReader : public BamEnums {
123 public:
125  static BamReader *const Null;
126  static WritableFactory *const NullFactory;
127 
128 PUBLISHED:
129  // The primary interface for a caller.
130  BamReader(DatagramGenerator *source = NULL);
131  ~BamReader();
132 
133  void set_source(DatagramGenerator *source);
134  INLINE DatagramGenerator *get_source();
135 
136  bool init();
137 
138  class AuxData;
139  void set_aux_data(TypedWritable *obj, const string &name, AuxData *data);
140  AuxData *get_aux_data(TypedWritable *obj, const string &name) const;
141 
142  INLINE const Filename &get_filename() const;
143 
144  INLINE const LoaderOptions &get_loader_options() const;
145  INLINE void set_loader_options(const LoaderOptions &options);
146 
147  TypedWritable *read_object();
148  bool read_object(TypedWritable *&ptr, ReferenceCount *&ref_ptr);
149 
150  INLINE bool is_eof() const;
151  bool resolve();
152 
153  bool change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer);
154 
155  INLINE int get_file_major_ver() const;
156  INLINE int get_file_minor_ver() const;
157  INLINE BamEndian get_file_endian() const;
158  INLINE bool get_file_stdfloat_double() const;
159 
160  INLINE int get_current_major_ver() const;
161  INLINE int get_current_minor_ver() const;
162 
163 public:
164  // Functions to support classes that read themselves from the Bam.
165 
166  void read_pointer(DatagramIterator &scan);
167  void read_pointers(DatagramIterator &scan, int count);
168  void skip_pointer(DatagramIterator &scan);
169 
170  void read_file_data(SubfileInfo &info);
171 
172  void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler);
173  void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler,
174  void *extra_data);
175 
176  void set_int_tag(const string &tag, int value);
177  int get_int_tag(const string &tag) const;
178 
179  void set_aux_tag(const string &tag, BamReaderAuxData *value);
180  BamReaderAuxData *get_aux_tag(const string &tag) const;
181 
182  void register_finalize(TypedWritable *whom);
183 
184  typedef TypedWritable *(*ChangeThisFunc)(TypedWritable *object, BamReader *manager);
185  typedef PT(TypedWritableReferenceCount) (*ChangeThisRefFunc)(TypedWritableReferenceCount *object, BamReader *manager);
186  void register_change_this(ChangeThisFunc func, TypedWritable *whom);
187  void register_change_this(ChangeThisRefFunc func, TypedWritableReferenceCount *whom);
188 
189  void finalize_now(TypedWritable *whom);
190 
191  void *get_pta(DatagramIterator &scan);
192  void register_pta(void *ptr);
193 
194  TypeHandle read_handle(DatagramIterator &scan);
195 
196  INLINE const FileReference *get_file();
197  INLINE VirtualFile *get_vfile();
198  INLINE streampos get_file_pos();
199 
200 public:
201  INLINE static WritableFactory *get_factory();
202 private:
203  INLINE static void create_factory();
204 
205 private:
206  class PointerReference;
207 
208  void free_object_ids(DatagramIterator &scan);
209  int read_object_id(DatagramIterator &scan);
210  int read_pta_id(DatagramIterator &scan);
211  int p_read_object();
212  bool resolve_object_pointers(TypedWritable *object, PointerReference &pref);
213  bool resolve_cycler_pointers(PipelineCyclerBase *cycler, const vector_int &pointer_ids,
214  bool require_fully_complete);
215  void finalize();
216 
217  INLINE bool get_datagram(Datagram &datagram);
218 
219 public:
220  // Inherit from this class to piggyback additional temporary data on
221  // the bamReader (via set_aux_data() and get_aux_data()) for any
222  // particular objects during the bam reading process.
223  class AuxData : public ReferenceCount {
224  public:
225  INLINE AuxData();
226  virtual ~AuxData();
227  };
228 
229 private:
230  static WritableFactory *_factory;
231 
232  DatagramGenerator *_source;
233  bool _needs_init;
234 
235  bool _long_object_id;
236  bool _long_pta_id;
237 
238  // This maps the type index numbers encountered within the Bam file
239  // to actual TypeHandles.
240  typedef phash_map<int, TypeHandle, int_hash> IndexMap;
241  IndexMap _index_map;
242 
243  LoaderOptions _loader_options;
244 
245  // This maps the object ID numbers encountered within the Bam file
246  // to the actual pointers of the corresponding generated objects.
247  class CreatedObj {
248  public:
249  INLINE CreatedObj();
250  INLINE ~CreatedObj();
251  INLINE void set_ptr(TypedWritable *ptr, ReferenceCount *ref_ptr);
252 
253  public:
254  bool _created;
255  TypedWritable *_ptr;
256  ReferenceCount *_ref_ptr;
257  ChangeThisFunc _change_this;
258  ChangeThisRefFunc _change_this_ref;
259  };
260  typedef phash_map<int, CreatedObj, int_hash> CreatedObjs;
261  CreatedObjs _created_objs;
262  // This is the iterator into the above map for the object we are
263  // currently reading in p_read_object(). It is carefully maintained
264  // during recursion. We need this so we can associate
265  // read_pointer() calls with the proper objects.
266  CreatedObjs::iterator _now_creating;
267  // This is the pointer to the current PipelineCycler we are reading,
268  // if we are within a read_cdata() call.
269  PipelineCyclerBase *_reading_cycler;
270 
271  // This is the reverse lookup into the above map.
272  typedef phash_map<const TypedWritable *, vector_int, pointer_hash> CreatedObjsByPointer;
273  CreatedObjsByPointer _created_objs_by_pointer;
274 
275  // This records all the objects that still need their pointers
276  // completed, along with the object ID's of the pointers they need,
277  // in the order in which read_pointer() was called, so that we may
278  // call the appropriate complete_pointers() later.
279  typedef phash_map<PipelineCyclerBase *, vector_int, pointer_hash> CyclerPointers;
280  typedef pmap<string, int> IntTags;
281  typedef pmap<string, PT(BamReaderAuxData) > AuxTags;
282  class PointerReference {
283  public:
284  vector_int _objects;
285  CyclerPointers _cycler_pointers;
286  IntTags _int_tags;
287  AuxTags _aux_tags;
288  };
289  typedef phash_map<int, PointerReference, int_hash> ObjectPointers;
290  ObjectPointers _object_pointers;
291 
292  // This is the number of extra objects that must still be read (and
293  // saved in the _created_objs map) before returning from
294  // read_object(). It is only used when read bam versions prior to
295  // 6.20.
296  int _num_extra_objects;
297 
298  // The current nesting level. We are not done reading an object
299  // until we return to our starting nesting level. It is only used
300  // when reading bam versions of 6.20 or higher.
301  int _nesting_level;
302 
303  // This is the set of all objects that registered themselves for
304  // finalization.
305  typedef phash_set<TypedWritable *, pointer_hash> Finalize;
306  Finalize _finalize_list;
307 
308  // These are used by get_pta() and register_pta() to unify multiple
309  // references to the same PointerToArray.
310  typedef phash_map<int, void *, int_hash> PTAMap;
311  PTAMap _pta_map;
312  int _pta_id;
313 
314  // This is a queue of the currently-pending file data blocks that we
315  // have recently encountered in the stream and still expect a
316  // subsequent object to request.
317  typedef pdeque<SubfileInfo> FileDataRecords;
318  FileDataRecords _file_data_records;
319 
320  // This is used internally to record all of the new types created
321  // on-the-fly to satisfy bam requirements. We keep track of this
322  // just so we can suppress warning messages from attempts to create
323  // objects of these types.
324  typedef phash_set<TypeHandle> NewTypes;
325  static NewTypes _new_types;
326 
327  // This is used in support of set_aux_data() and get_aux_data().
328  typedef pmap<string, PT(AuxData)> AuxDataNames;
329  typedef phash_map<TypedWritable *, AuxDataNames, pointer_hash> AuxDataTable;
330  AuxDataTable _aux_data;
331 
332  int _file_major, _file_minor;
333  BamEndian _file_endian;
334  bool _file_stdfloat_double;
335  static const int _cur_major;
336  static const int _cur_minor;
337 };
338 
340 
341 // Useful function for taking apart the Factory Params in the static
342 // functions that need to be defined in each writable class that will
343 // be generated by a factory. Sets the DatagramIterator and the
344 // BamReader pointers.
345 INLINE void
346 parse_params(const FactoryParams &params,
347  DatagramIterator &scan, BamReader *&manager);
348 
349 #include "bamReader.I"
350 
351 #endif
Keeps a reference-counted pointer to a file on disk.
Definition: fileReference.h:29
Stores auxiliary data that may be piggybacked on the BamReader during each object&#39;s read pass...
Definition: bamReader.h:64
A Factory can be used to create an instance of a particular subclass of some general base class...
Definition: factory.h:41
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
Specifies parameters that may be passed to the loader.
Definition: loaderOptions.h:26
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
This is the trivial, non-threaded implementation of PipelineCyclerBase.
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
The abstract base class for a file or directory within the VirtualFileSystem.
Definition: virtualFile.h:37
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
A base class for things which need to inherit from both TypedWritable and from ReferenceCount.
A base class for all things that want to be reference-counted.
This class records a particular byte sub-range within an existing file on disk.
Definition: subfileInfo.h:29
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
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 ...
Definition: datagram.h:43
This class exists just to provide scoping for the enums shared by BamReader and BamWriter.
Definition: bamEnums.h:25