Panda3D
bamFile.cxx
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 bamFile.cxx
10  * @author drose
11  * @date 2000-07-02
12  */
13 
14 #include "bamFile.h"
15 #include "config_pgraph.h"
16 
17 #include "bam.h"
18 #include "bamCacheRecord.h"
19 #include "config_putil.h"
20 #include "bamReader.h"
21 #include "bamWriter.h"
22 #include "filename.h"
23 #include "config_express.h"
24 #include "virtualFileSystem.h"
25 #include "dcast.h"
26 
27 using std::string;
28 
29 /**
30  *
31  */
32 BamFile::
33 BamFile() {
34  _reader = nullptr;
35  _writer = nullptr;
36 }
37 
38 /**
39  *
40  */
41 BamFile::
42 ~BamFile() {
43  close();
44 }
45 
46 /**
47  * Attempts to open the indicated filename for reading. Returns true if
48  * successful, false on error.
49  */
51 open_read(const Filename &bam_filename, bool report_errors) {
52  close();
53 
54  if (!_din.open(bam_filename)) {
55  return false;
56  }
57 
58  return continue_open_read(bam_filename, report_errors);
59 }
60 
61 /**
62  * Attempts to open the indicated stream for reading. The filename is just
63  * for information purposes only. Returns true if successful, false on error.
64  */
66 open_read(std::istream &in, const string &bam_filename, bool report_errors) {
67  close();
68 
69  if (!_din.open(in)) {
70  return false;
71  }
72 
73  return continue_open_read(bam_filename, report_errors);
74 }
75 
76 /**
77  * Reads and returns the next object from the Bam file, or NULL if the end of
78  * the file has been reached, or if there is an error condition. Use is_eof()
79  * to differentiate these two cases.
80  *
81  * The pointers returned by this method will not be valid for use until
82  * resolve() is subsequently called.
83  */
85 read_object() {
86  if (_reader == nullptr) {
87  return nullptr;
88  }
89 
90  return _reader->read_object();
91 }
92 
93 /**
94  * Returns true if the reader has reached end-of-file, false otherwise. This
95  * call is only valid after a call to read_object().
96  */
98 is_eof() const {
99  return _reader != nullptr && _reader->is_eof();
100 }
101 
102 /**
103  * This must be called after one or more objects have been read via calls to
104  * read_object() in order to resolve all internal pointer references in the
105  * objects read and make all the pointers valid. It returns true if all
106  * objects are successfully resolved, or false if some have not been (in which
107  * case you must call resolve() again later).
108  */
110 resolve() {
111  if (_reader == nullptr) {
112  return false;
113  }
114 
115  return _reader->resolve();
116 }
117 
118 /**
119  * Although the bam file format is general enough to store a list of objects
120  * of arbitrary type, bam files on disk usually contain just one object, a
121  * PandaNode that is the root of a scene graph. (Bam files that store other
122  * kinds of things are usually given the extension "boo", for "binary other
123  * objects", to differentiate them from the normal scene graph type file.)
124  *
125  * This is a convenience method for when you believe you are reading a scene
126  * graph bam file. It reads the one PandaNode and returns it. It also calls
127  * resolve() to fully resolve the object, since we expect this will be the
128  * only object in the file.
129  *
130  * If the bam file contains something other than a PandaNode, an error is
131  * printed and NULL is returned.
132  */
133 PT(PandaNode) BamFile::
134 read_node(bool report_errors) {
135  PT(PandaNode) result;
136 
137  TypedWritable *object = read_object();
138 
139  if (object != nullptr &&
140  object->is_exact_type(BamCacheRecord::get_class_type())) {
141  // Here's a special case: if the first object in the file is a
142  // BamCacheRecord, it's really a cache data file and not a true bam file;
143  // but skip over the cache data record and let the user treat it like an
144  // ordinary bam file.
145  object = read_object();
146  }
147 
148  if (object == TypedWritable::Null) {
149  if (report_errors) {
150  loader_cat.error() << "Bam file " << _bam_filename << " is empty.\n";
151  }
152 
153  } else if (!object->is_of_type(PandaNode::get_class_type())) {
154  if (report_errors) {
155  loader_cat.error()
156  << "Bam file " << _bam_filename
157  << " contains a " << object->get_type() << ", not a PandaNode.\n";
158  }
159 
160  } else {
161  result = DCAST(PandaNode, object);
162 
163  if (report_errors) {
164  read_object();
165  if (!is_eof()) {
166  loader_cat.warning()
167  << "Ignoring extra objects in " << _bam_filename << "\n";
168  }
169  }
170  }
171 
172  if (!resolve()) {
173  if (report_errors) {
174  loader_cat.error()
175  << "Unable to resolve Bam file.\n";
176  }
177  result = nullptr;
178  }
179 
180  return result;
181 }
182 
183 
184 /**
185  * Attempts to open the indicated file for writing. If another file by the
186  * same name already exists, it will be silently removed. Returns true if
187  * successful, false otherwise.
188  */
190 open_write(const Filename &bam_filename, bool report_errors) {
191  close();
192 
194  vfs->delete_file(bam_filename);
195  if (!_dout.open(bam_filename)) {
196  if (report_errors) {
197  loader_cat.error() << "Unable to open " << bam_filename << "\n";
198  }
199  return false;
200  }
201 
202  return continue_open_write(bam_filename, report_errors);
203 }
204 
205 /**
206  * Attempts to open the indicated stream for writing. The filename is just
207  * for information purposes only. Returns true if successful, false on error.
208  */
210 open_write(std::ostream &out, const string &bam_filename, bool report_errors) {
211  close();
212 
213  if (!_dout.open(out)) {
214  loader_cat.error() << "Could not write bam: " << bam_filename << "\n";
215  return false;
216  }
217 
218  return continue_open_write(bam_filename, report_errors);
219 }
220 
221 /**
222  * Writes the indicated object to the Bam file. Returns true if successful,
223  * false on error.
224  */
226 write_object(const TypedWritable *object) {
227  if (_writer == nullptr) {
228  return false;
229  }
230 
231  if (!_writer->write_object(object)) {
232  close();
233  return false;
234  }
235 
236  return true;
237 }
238 
239 /**
240  * Closes the input or output stream.
241  */
243 close() {
244  if (_reader != nullptr) {
245  // resolve();
246  delete _reader;
247  _reader = nullptr;
248  }
249  if (_writer != nullptr) {
250  delete _writer;
251  _writer = nullptr;
252  }
253  _din.close();
254  _dout.close();
255 }
256 
257 
258 /**
259  * Returns the major version number of the file currently being read, or the
260  * system current major version number if no file is currently open for
261  * reading.
262  */
265  if (_reader == nullptr) {
266  return _bam_major_ver;
267  }
268  return _reader->get_file_major_ver();
269 }
270 
271 /**
272  * Returns the minor version number of the file currently being read, or the
273  * system current minor version number if no file is currently open for
274  * reading.
275  */
278  if (_reader == nullptr) {
279  return _bam_minor_ver;
280  }
281  return _reader->get_file_minor_ver();
282 }
283 
284 /**
285  * Returns the endian preference indicated by the Bam file currently being
286  * read or written.
287  */
289 get_file_endian() const {
290  if (_writer != nullptr) {
291  return _writer->get_file_endian();
292  }
293  if (_reader != nullptr) {
294  return _reader->get_file_endian();
295  }
296 
297  return bam_endian;
298 }
299 
300 /**
301  * Returns true if the file stores all "standard" floats as 64-bit doubles, or
302  * false if they are 32-bit floats.
303  */
304 bool BamFile::
305 get_file_stdfloat_double() const {
306  if (_writer != nullptr) {
307  return _writer->get_file_stdfloat_double();
308  }
309  if (_reader != nullptr) {
310  return _reader->get_file_stdfloat_double();
311  }
312 
313  return bam_stdfloat_double;
314 }
315 
316 /**
317  * Returns the system current major version number. This is the version
318  * number that will be assigned to any generated Bam files.
319  */
322  return _bam_major_ver;
323 }
324 
325 /**
326  * Returns the system current minor version number. This is the version
327  * number that will be assigned to any generated Bam files.
328  */
331  return _bam_minor_ver;
332 }
333 
334 /**
335  * Returns the BamReader in charge of performing the read operations. This
336  * will return NULL unless open_read() was called.
337  */
339 get_reader() {
340  return _reader;
341 }
342 
343 /**
344  * Returns the BamWriter in charge of performing the write operations. This
345  * will return NULL unless open_write() was called.
346  */
348 get_writer() {
349  return _writer;
350 }
351 
352 /**
353  * Reads the header of the recently-opened bam stream and prepares to read the
354  * contents of the file. Returns true if successful, false otherwise.
355  */
356 bool BamFile::
357 continue_open_read(const string &bam_filename, bool report_errors) {
358  _bam_filename = bam_filename;
359 
360  if (!_bam_filename.empty()) {
361  loader_cat.info()
362  << "Reading " << _bam_filename << "\n";
363  }
364 
365  string head;
366  if (!_din.read_header(head, _bam_header.size())) {
367  if (report_errors) {
368  loader_cat.error() << _bam_filename << " is not a valid BAM file.\n";
369  }
370  return false;
371  }
372 
373  if (head != _bam_header) {
374  if (report_errors) {
375  loader_cat.error() << _bam_filename << " is not a valid BAM file.\n";
376  }
377  return false;
378  }
379 
380  _reader = new BamReader(&_din);
381  if (!_reader->init()) {
382  close();
383  return false;
384  }
385 
386  return true;
387 }
388 
389 /**
390  * Writers the header of the recently-opened bam stream and prepares to write
391  * the contents of the file. Returns true if successful, false otherwise.
392  */
393 bool BamFile::
394 continue_open_write(const string &bam_filename, bool report_errors) {
395  _bam_filename = bam_filename;
396 
397  if (!_bam_filename.empty()) {
398  loader_cat.info() << "Writing " << _bam_filename << "\n";
399  }
400 
401  if (!_dout.write_header(_bam_header)) {
402  if (report_errors) {
403  loader_cat.error() << "Unable to write to " << _bam_filename << "\n";
404  }
405  return false;
406  }
407 
408  _writer = new BamWriter(&_dout);
409 
410  if (!_writer->init()) {
411  close();
412  return false;
413  }
414 
415  return true;
416 }
BamFile::get_current_minor_ver
int get_current_minor_ver()
Returns the system current minor version number.
Definition: bamFile.cxx:330
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DatagramInputFile::read_header
bool read_header(std::string &header, size_t num_bytes)
Reads a sequence of bytes from the beginning of the datagram file.
Definition: datagramInputFile.cxx:104
BamWriter::get_file_stdfloat_double
get_file_stdfloat_double
Returns true if the file will store all "standard" floats as 64-bit doubles, or false if they are 32-...
Definition: bamWriter.h:94
BamFile::open_read
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
Definition: bamFile.cxx:51
BamFile::open_write
bool open_write(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated file for writing.
Definition: bamFile.cxx:190
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
DatagramOutputFile::close
void close()
Closes the file.
Definition: datagramOutputFile.cxx:73
DatagramInputFile::close
void close()
Closes the file.
Definition: datagramInputFile.cxx:80
bamCacheRecord.h
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
bam.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DatagramInputFile::open
bool open(const FileReference *file)
Opens the indicated filename for reading.
Definition: datagramInputFile.cxx:33
filename.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamFile::get_file_stdfloat_double
get_file_stdfloat_double
Returns true if the file stores all "standard" floats as 64-bit doubles, or false if they are 32-bit ...
Definition: bamFile.h:79
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
PT
PT(PandaNode) BamFile
Although the bam file format is general enough to store a list of objects of arbitrary type,...
Definition: bamFile.cxx:133
bamFile.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
BamReader::get_file_endian
get_file_endian
Returns the endian preference indicated by the Bam file currently being read.
Definition: bamReader.h:159
BamReader::init
bool init()
Initializes the BamReader prior to reading any objects from its source.
Definition: bamReader.cxx:85
BamFile::get_file_endian
get_file_endian
Returns the endian preference indicated by the Bam file currently being read or written.
Definition: bamFile.h:78
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
BamReader::read_object
TypedWritable * read_object()
Reads a single object from the Bam file.
Definition: bamReader.cxx:224
BamWriter::write_object
bool write_object(const TypedWritable *obj)
Writes a single object to the Bam file, so that the BamReader::read_object() can later correctly rest...
Definition: bamWriter.cxx:204
BamWriter::get_file_endian
get_file_endian
Returns the endian preference indicated by the Bam file currently being written.
Definition: bamWriter.h:93
BamFile::write_object
bool write_object(const TypedWritable *object)
Writes the indicated object to the Bam file.
Definition: bamFile.cxx:226
DatagramOutputFile::write_header
bool write_header(const std::string &header)
Writes a sequence of bytes to the beginning of the datagram file.
Definition: datagramOutputFile.cxx:96
BamFile::get_reader
get_reader
Returns the BamReader in charge of performing the read operations.
Definition: bamFile.h:81
BamFile::resolve
bool resolve()
This must be called after one or more objects have been read via calls to read_object() in order to r...
Definition: bamFile.cxx:110
BamFile::get_file_minor_ver
int get_file_minor_ver()
Returns the minor version number of the file currently being read, or the system current minor versio...
Definition: bamFile.cxx:277
BamFile::is_eof
bool is_eof() const
Returns true if the reader has reached end-of-file, false otherwise.
Definition: bamFile.cxx:98
BamFile::read_object
TypedWritable * read_object()
Reads and returns the next object from the Bam file, or NULL if the end of the file has been reached,...
Definition: bamFile.cxx:85
BamFile::get_file_major_ver
int get_file_major_ver()
Returns the major version number of the file currently being read, or the system current major versio...
Definition: bamFile.cxx:264
BamReader::resolve
bool resolve()
This may be called at any time during processing of the Bam file to resolve all the known pointers so...
Definition: bamReader.cxx:325
VirtualFileSystem::delete_file
bool delete_file(const Filename &filename)
Attempts to delete the indicated file or directory.
Definition: virtualFileSystem.cxx:575
BamFile::get_writer
get_writer
Returns the BamWriter in charge of performing the write operations.
Definition: bamFile.h:82
VirtualFileSystem::get_global_ptr
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Definition: virtualFileSystem.cxx:741
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamWriter::init
bool init()
Initializes the BamWriter prior to writing any objects to its output stream.
Definition: bamWriter.cxx:147
BamReader::get_file_minor_ver
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
BamReader::is_eof
bool is_eof() const
Returns true if the reader has reached end-of-file, false otherwise.
Definition: bamReader.I:66
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamFile::close
void close()
Closes the input or output stream.
Definition: bamFile.cxx:243
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
config_express.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedObject::is_exact_type
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
BamReader::get_file_major_ver
int get_file_major_ver() const
Returns the major version number of the Bam file currently being read.
Definition: bamReader.I:75
config_pgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DatagramOutputFile::open
bool open(const FileReference *file)
Opens the indicated filename for writing.
Definition: datagramOutputFile.cxx:28
BamFile::get_current_major_ver
int get_current_major_ver()
Returns the system current major version number.
Definition: bamFile.cxx:321
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
BamReader::get_file_stdfloat_double
get_file_stdfloat_double
Returns true if the file stores all "standard" floats as 64-bit doubles, or false if they are 32-bit ...
Definition: bamReader.h:160