Panda3D
bamWriter.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 bamWriter.h
10  * @author jason
11  * @date 2000-06-08
12  */
13 
14 #ifndef __BAM_WRITER_
15 #define __BAM_WRITER_
16 
17 #include "pandabase.h"
18 #include "pnotify.h"
19 #include "bamEnums.h"
20 #include "typedWritable.h"
21 #include "datagramSink.h"
22 #include "pdeque.h"
23 #include "pset.h"
24 #include "pmap.h"
25 #include "vector_int.h"
26 #include "pipelineCyclerBase.h"
27 
28 
29 // A handy macro for writing PointerToArrays.
30 #define WRITE_PTA(Manager, dest, Write_func, array) \
31  if (!Manager->register_pta(dest, array.p())) \
32  { \
33  Write_func(Manager, dest, array); \
34  } \
35 
36 
37 /**
38  * This is the fundamental interface for writing binary objects to a Bam file,
39  * to be extracted later by a BamReader.
40  *
41  * A Bam file can be thought of as a linear collection of objects. Each
42  * object is an instance of a class that inherits, directly or indirectly,
43  * from TypedWritable. The objects may include pointers to other objects; the
44  * BamWriter automatically manages these (with help from code within each
45  * class) and writes all referenced objects to the file in such a way that the
46  * pointers may be correctly restored later.
47  *
48  * This is the abstract interface and does not specifically deal with disk
49  * files, but rather with a DatagramSink of some kind, which simply accepts a
50  * linear stream of Datagrams. It is probably written to a disk file, but it
51  * might conceivably be streamed directly to a network or some such nonsense.
52  *
53  * Bam files are most often used to store scene graphs or subgraphs, and by
54  * convention they are given filenames ending in the extension ".bam" when
55  * they are used for this purpose. However, a Bam file may store any
56  * arbitrary list of TypedWritable objects; in this more general usage, they
57  * are given filenames ending in ".boo" to differentiate them from the more
58  * common scene graph files.
59  *
60  * See also BamFile, which defines a higher-level interface to read and write
61  * Bam files on disk.
62  */
63 class EXPCL_PANDA_PUTIL BamWriter : public BamEnums {
64 PUBLISHED:
65  explicit BamWriter(DatagramSink *target = nullptr);
66  ~BamWriter();
67 
68  void set_target(DatagramSink *target);
69  INLINE DatagramSink *get_target();
70 
71  bool init();
72  INLINE const Filename &get_filename() const;
73  bool write_object(const TypedWritable *obj);
74  bool has_object(const TypedWritable *obj) const;
75  void flush();
76 
77  INLINE int get_file_major_ver() const;
78  INLINE int get_file_minor_ver() const;
79  INLINE void set_file_minor_ver(int minor_ver);
80 
81  INLINE BamEndian get_file_endian() const;
82  INLINE bool get_file_stdfloat_double() const;
83 
84  INLINE BamTextureMode get_file_texture_mode() const;
85  INLINE void set_file_texture_mode(BamTextureMode file_texture_mode);
86 
87  INLINE TypedWritable *get_root_node() const;
88  INLINE void set_root_node(TypedWritable *root_node);
89 
90 PUBLISHED:
91  MAKE_PROPERTY(target, get_target, set_target);
92  MAKE_PROPERTY(filename, get_filename);
93  MAKE_PROPERTY(file_endian, get_file_endian);
94  MAKE_PROPERTY(file_stdfloat_double, get_file_stdfloat_double);
95  MAKE_PROPERTY(file_texture_mode, get_file_texture_mode);
96  MAKE_PROPERTY(root_node, get_root_node, set_root_node);
97 
98 public:
99  // Functions to support classes that write themselves to the Bam.
100 
101  void consider_update(const TypedWritable *obj);
102 
103  void write_pointer(Datagram &packet, const TypedWritable *dest);
104 
105  void write_file_data(SubfileInfo &result, const Filename &filename);
106  void write_file_data(SubfileInfo &result, const SubfileInfo &source);
107 
108  void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler);
109  void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler,
110  void *extra_data);
111  bool register_pta(Datagram &packet, const void *ptr);
112  void write_handle(Datagram &packet, TypeHandle type);
113 
114  static std::string get_obsolete_type_name(TypeHandle type, int major, int minor);
115  static void record_obsolete_type_name(TypeHandle type, std::string name,
116  int before_major, int before_minor);
117 
118 private:
119  void object_destructs(TypedWritable *object);
120 
121  void write_object_id(Datagram &dg, int object_id);
122  void write_pta_id(Datagram &dg, int pta_id);
123  int enqueue_object(const TypedWritable *object);
124  bool flush_queue();
125 
126  int _file_major, _file_minor;
127  BamEndian _file_endian;
128  bool _file_stdfloat_double;
129  BamTextureMode _file_texture_mode;
130 
131  // Stores the PandaNode representing the root of the node hierarchy we are
132  // currently writing, if any, for the purpose of writing NodePaths. This is
133  // a TypedWritable since PandaNode is defined in pgraph.
134  TypedWritable *_root_node;
135 
136  // This is the set of all TypeHandles already written.
137  pset<int, int_hash> _types_written;
138 
139  // This keeps track of all of the objects we have written out already (or
140  // are about to write out), and associates a unique object ID number to each
141  // one.
142  class StoreState {
143  public:
144  int _object_id;
145  UpdateSeq _written_seq;
146  UpdateSeq _modified;
147  const ReferenceCount *_refcount;
148 
149  StoreState(int object_id) : _object_id(object_id), _refcount(nullptr) {}
150  };
151  typedef phash_map<const TypedWritable *, StoreState, pointer_hash> StateMap;
152  StateMap _state_map;
153 
154  // This seq number is incremented each time we write a new object using the
155  // top-level write_object() call. It indicates the current sequence number
156  // we are writing, which is updated in the StoreState, above, and used to
157  // keep track of which objects may need to be checked for internal updates.
158  UpdateSeq _writing_seq;
159 
160  // This is initialized to BOC_push in write_object(), then cleared to
161  // BOC_adjunct as each object is written, so that only the first object gets
162  // written with BOC_push.
163  BamObjectCode _next_boc;
164 
165  // This is the next object ID that will be assigned to a new object.
166  int _next_object_id;
167  bool _long_object_id;
168 
169  // This is the queue of objects that need to be written when the current
170  // object is finished.
171  typedef pdeque<const TypedWritable *> ObjectQueue;
172  ObjectQueue _object_queue;
173 
174  // This is the set of object_id's that we won't be using any more; we'll
175  // encode this set into the bam stream so the BamReader will be able to
176  // clean up its internal structures.
177  typedef vector_int FreedObjectIds;
178  FreedObjectIds _freed_object_ids;
179 
180  // These are used by register_pta() to unify multiple references to the same
181  // PointerToArray.
182  typedef phash_map<const void *, int, pointer_hash> PTAMap;
183  PTAMap _pta_map;
184  int _next_pta_id;
185  bool _long_pta_id;
186 
187  // The destination to write all the output to.
188  DatagramSink *_target;
189  bool _needs_init;
190 
191  friend class TypedWritable;
192 };
193 
194 #include "bamWriter.I"
195 
196 #endif
UpdateSeq
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
vector_int.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pandabase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ReferenceCount
A base class for all things that want to be reference-counted.
Definition: referenceCount.h:38
typedWritable.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bamWriter.I
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
datagramSink.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
pnotify.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamEnums::BamEndian
BamEndian
This defines an enumerated type used to represent the endianness of certain numeric values stored in ...
Definition: bamEnums.h:32
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
pmap.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamEnums
This class exists just to provide scoping for the enums shared by BamReader and BamWriter.
Definition: bamEnums.h:23
pdeque< const TypedWritable * >
DatagramSink
This class defines the abstract interface to sending datagrams to any target, whether it be into a fi...
Definition: datagramSink.h:29
PipelineCyclerTrivialImpl
This is the trivial, non-threaded implementation of PipelineCyclerBase.
Definition: pipelineCyclerTrivialImpl.h:41
pipelineCyclerBase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pset.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bamEnums.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
SubfileInfo
This class records a particular byte sub-range within an existing file on disk.
Definition: subfileInfo.h:26
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
pdeque.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pset
This is our own Panda specialization on the default STL set.
Definition: pset.h:49