Panda3D
fltRecordWriter.cxx
1 // Filename: fltRecordWriter.cxx
2 // Created by: drose (24Aug00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "fltRecordWriter.h"
16 #include "fltInstanceDefinition.h"
17 #include "fltHeader.h"
18 #include "config_flt.h"
19 
20 #include "datagram.h"
21 
22 #include <assert.h>
23 
24 // Don't attempt to write more than this number of bytes in one
25 // record. If the record requires more than this, use continuation
26 // records.
27 static const int max_write_length = 65532;
28 
29 ////////////////////////////////////////////////////////////////////
30 // Function: FltRecordWriter::Constructor
31 // Access: Public
32 // Description:
33 ////////////////////////////////////////////////////////////////////
34 FltRecordWriter::
35 FltRecordWriter(ostream &out) :
36  _out(out)
37 {
38 }
39 
40 ////////////////////////////////////////////////////////////////////
41 // Function: FltRecordWriter::Destructor
42 // Access: Public
43 // Description:
44 ////////////////////////////////////////////////////////////////////
45 FltRecordWriter::
46 ~FltRecordWriter() {
47 }
48 
49 ////////////////////////////////////////////////////////////////////
50 // Function: FltRecordWriter::set_opcode
51 // Access: Public
52 // Description: Sets the opcode associated with the current record.
53 ////////////////////////////////////////////////////////////////////
55 set_opcode(FltOpcode opcode) {
56  _opcode = opcode;
57 }
58 
59 ////////////////////////////////////////////////////////////////////
60 // Function: FltRecordWriter::set_datagram
61 // Access: Public
62 // Description: Sets the datagram that will be written when advance()
63 // is called.
64 ////////////////////////////////////////////////////////////////////
66 set_datagram(const Datagram &datagram) {
67  _datagram = datagram;
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: FltRecordWriter::update_datagram
72 // Access: Public
73 // Description: Returns a modifiable reference to the datagram
74 // associated with the current record. This datagram
75 // should then be stuffed with data corresponding to the
76 // data in the record, in preparation for calling
77 // advance() to write the data.
78 ////////////////////////////////////////////////////////////////////
81  return _datagram;
82 }
83 
84 ////////////////////////////////////////////////////////////////////
85 // Function: FltRecordWriter::advance
86 // Access: Public
87 // Description: Writes the current record to the flt file, and resets
88 // the current record to receive new data. Returns
89 // FE_ok on success, or something else on error.
90 ////////////////////////////////////////////////////////////////////
91 FltError FltRecordWriter::
93  int start_byte = 0;
94  int write_length =
95  min((int)_datagram.get_length() - start_byte, max_write_length - header_size);
96  FltOpcode opcode = _opcode;
97 
98  do {
99  if (flt_cat.is_debug()) {
100  flt_cat.debug()
101  << "Writing " << opcode << " of length "
102  << write_length + header_size << "\n";
103  }
104 
105  // Build a mini-datagram to write the header.
106  Datagram dg;
107  dg.add_be_int16(opcode);
108  dg.add_be_int16(write_length + header_size);
109 
110  nassertr((int)dg.get_length() == header_size, FE_internal);
111 
112  _out.write((const char *)dg.get_data(), dg.get_length());
113  if (_out.fail()) {
114  assert(!flt_error_abort);
115  return FE_write_error;
116  }
117 
118  // Now write the rest of the record.
119  _out.write((const char *)_datagram.get_data() + start_byte, write_length);
120  if (_out.fail()) {
121  assert(!flt_error_abort);
122  return FE_write_error;
123  }
124 
125  start_byte += write_length;
126  write_length =
127  min((int)_datagram.get_length() - start_byte, max_write_length - header_size);
128  opcode = FO_continuation;
129  } while (write_length > 0);
130 
131  _datagram.clear();
132  _opcode = FO_none;
133 
134  return FE_ok;
135 }
136 
137 ////////////////////////////////////////////////////////////////////
138 // Function: FltRecordWriter::write_record
139 // Access: Public
140 // Description: A convenience function to quickly write a simple
141 // record that consists of an opcode and possibly a
142 // datagram.
143 ////////////////////////////////////////////////////////////////////
144 FltError FltRecordWriter::
145 write_record(FltOpcode opcode, const Datagram &datagram) {
146  _opcode = opcode;
147  _datagram = datagram;
148  return advance();
149 }
150 
151 ////////////////////////////////////////////////////////////////////
152 // Function: FltRecordWriter::write_instance_def
153 // Access: Public
154 // Description: Ensures that the given instance definition has
155 // already been written to the file. If it has not,
156 // writes it now.
157 ////////////////////////////////////////////////////////////////////
158 FltError FltRecordWriter::
159 write_instance_def(FltHeader *header, int instance_index) {
160  bool inserted = _instances_written.insert(instance_index).second;
161 
162  if (!inserted) {
163  // It's already been written.
164  return FE_ok;
165  }
166 
167  FltInstanceDefinition *instance = header->get_instance(instance_index);
168  if (instance == (FltInstanceDefinition *)NULL) {
169  assert(!flt_error_abort);
170  return FE_undefined_instance;
171  }
172 
173  return instance->write_record_and_children(*this);
174 }
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:41
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:48
FltError write_instance_def(FltHeader *header, int instance_index)
Ensures that the given instance definition has already been written to the file.
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:491
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:43
This special kind of record marks the top node of an instance subtree.
void add_be_int16(PN_int16 value)
Adds a signed 16-bit big-endian integer to the datagram.
Definition: datagram.I:255
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:457
const void * get_data() const
Returns a pointer to the beginning of the datagram&#39;s data.
Definition: datagram.I:447
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...