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