Panda3D
 All Classes Functions Variables Enumerations
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 }
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
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
size_t get_length() const
Returns the number of bytes in the datagram.
Definition: datagram.I:457
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.
FltError advance()
Writes the current record to the flt file, and resets the current record to receive new data...
const void * get_data() const
Returns a pointer to the beginning of the datagram&#39;s data.
Definition: datagram.I:447
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
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...