Panda3D
fltRecordWriter.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 fltRecordWriter.cxx
10  * @author drose
11  * @date 2000-08-24
12  */
13 
14 #include "fltRecordWriter.h"
15 #include "fltInstanceDefinition.h"
16 #include "fltHeader.h"
17 #include "config_flt.h"
18 
19 #include "datagram.h"
20 
21 #include <assert.h>
22 
23 // Don't attempt to write more than this number of bytes in one record. If
24 // the record requires more than this, use continuation records.
25 static const int max_write_length = 65532;
26 
27 /**
28  *
29  */
30 FltRecordWriter::
31 FltRecordWriter(std::ostream &out) :
32  _out(out)
33 {
34 }
35 
36 /**
37  *
38  */
39 FltRecordWriter::
40 ~FltRecordWriter() {
41 }
42 
43 /**
44  * Sets the opcode associated with the current record.
45  */
47 set_opcode(FltOpcode opcode) {
48  _opcode = opcode;
49 }
50 
51 /**
52  * Sets the datagram that will be written when advance() is called.
53  */
55 set_datagram(const Datagram &datagram) {
56  _datagram = datagram;
57 }
58 
59 /**
60  * Returns a modifiable reference to the datagram associated with the current
61  * record. This datagram should then be stuffed with data corresponding to
62  * the data in the record, in preparation for calling advance() to write the
63  * data.
64  */
67  return _datagram;
68 }
69 
70 /**
71  * Writes the current record to the flt file, and resets the current record to
72  * receive new data. Returns FE_ok on success, or something else on error.
73  */
74 FltError FltRecordWriter::
76  int start_byte = 0;
77  int write_length =
78  std::min((int)_datagram.get_length() - start_byte, max_write_length - header_size);
79  FltOpcode opcode = _opcode;
80 
81  do {
82  if (flt_cat.is_debug()) {
83  flt_cat.debug()
84  << "Writing " << opcode << " of length "
85  << write_length + header_size << "\n";
86  }
87 
88  // Build a mini-datagram to write the header.
89  Datagram dg;
90  dg.add_be_int16(opcode);
91  dg.add_be_int16(write_length + header_size);
92 
93  nassertr((int)dg.get_length() == header_size, FE_internal);
94 
95  _out.write((const char *)dg.get_data(), dg.get_length());
96  if (_out.fail()) {
97  assert(!flt_error_abort);
98  return FE_write_error;
99  }
100 
101  // Now write the rest of the record.
102  _out.write((const char *)_datagram.get_data() + start_byte, write_length);
103  if (_out.fail()) {
104  assert(!flt_error_abort);
105  return FE_write_error;
106  }
107 
108  start_byte += write_length;
109  write_length =
110  std::min((int)_datagram.get_length() - start_byte, max_write_length - header_size);
111  opcode = FO_continuation;
112  } while (write_length > 0);
113 
114  _datagram.clear();
115  _opcode = FO_none;
116 
117  return FE_ok;
118 }
119 
120 /**
121  * A convenience function to quickly write a simple record that consists of an
122  * opcode and possibly a datagram.
123  */
124 FltError FltRecordWriter::
125 write_record(FltOpcode opcode, const Datagram &datagram) {
126  _opcode = opcode;
127  _datagram = datagram;
128  return advance();
129 }
130 
131 /**
132  * Ensures that the given instance definition has already been written to the
133  * file. If it has not, writes it now.
134  */
135 FltError FltRecordWriter::
136 write_instance_def(FltHeader *header, int instance_index) {
137  bool inserted = _instances_written.insert(instance_index).second;
138 
139  if (!inserted) {
140  // It's already been written.
141  return FE_ok;
142  }
143 
144  FltInstanceDefinition *instance = header->get_instance(instance_index);
145  if (instance == nullptr) {
146  assert(!flt_error_abort);
147  return FE_undefined_instance;
148  }
149 
150  return instance->write_record_and_children(*this);
151 }
void set_datagram(const Datagram &datagram)
Sets the datagram that will be written when advance() is called.
virtual void clear()
Resets the datagram to empty, in preparation for building up a new datagram.
Definition: datagram.cxx:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:44
FltError write_instance_def(FltHeader *header, int instance_index)
Ensures that the given instance definition has already been written to the file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_be_int16(int16_t value)
Adds a signed 16-bit big-endian integer to the datagram.
Definition: datagram.I:145
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FltInstanceDefinition * get_instance(int instance_index) const
Returns the instance subtree associated with the given index, or NULL if there is no such instance.
Definition: fltHeader.cxx:422
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FltError advance()
Writes the current record to the flt file, and resets the current record to receive new data.
void set_opcode(FltOpcode opcode)
Sets the opcode associated with the current record.
Datagram & update_datagram()
Returns a modifiable reference to the datagram associated with the current record.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
This special kind of record marks the top node of an instance subtree.
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:335
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
Definition: datagram.I:327
FltError write_record(FltOpcode opcode, const Datagram &datagram=Datagram())
A convenience function to quickly write a simple record that consists of an opcode and possibly a dat...