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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the trivial, non-threaded implementation of PipelineCyclerBase.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class defines the abstract interface to sending datagrams to any target, whether it be into a fi...
Definition: datagramSink.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for all things that want to be reference-counted.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class records a particular byte sub-range within an existing file on disk.
Definition: subfileInfo.h:26
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class exists just to provide scoping for the enums shared by BamReader and BamWriter.
Definition: bamEnums.h:23