Panda3D
|
00001 // Filename: fltRecordWriter.cxx 00002 // Created by: drose (24Aug00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "fltRecordWriter.h" 00016 #include "fltInstanceDefinition.h" 00017 #include "fltHeader.h" 00018 #include "config_flt.h" 00019 00020 #include "datagram.h" 00021 00022 #include <assert.h> 00023 00024 // Don't attempt to write more than this number of bytes in one 00025 // record. If the record requires more than this, use continuation 00026 // records. 00027 static const int max_write_length = 65532; 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: FltRecordWriter::Constructor 00031 // Access: Public 00032 // Description: 00033 //////////////////////////////////////////////////////////////////// 00034 FltRecordWriter:: 00035 FltRecordWriter(ostream &out) : 00036 _out(out) 00037 { 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: FltRecordWriter::Destructor 00042 // Access: Public 00043 // Description: 00044 //////////////////////////////////////////////////////////////////// 00045 FltRecordWriter:: 00046 ~FltRecordWriter() { 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: FltRecordWriter::set_opcode 00051 // Access: Public 00052 // Description: Sets the opcode associated with the current record. 00053 //////////////////////////////////////////////////////////////////// 00054 void FltRecordWriter:: 00055 set_opcode(FltOpcode opcode) { 00056 _opcode = opcode; 00057 } 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: FltRecordWriter::set_datagram 00061 // Access: Public 00062 // Description: Sets the datagram that will be written when advance() 00063 // is called. 00064 //////////////////////////////////////////////////////////////////// 00065 void FltRecordWriter:: 00066 set_datagram(const Datagram &datagram) { 00067 _datagram = datagram; 00068 } 00069 00070 //////////////////////////////////////////////////////////////////// 00071 // Function: FltRecordWriter::update_datagram 00072 // Access: Public 00073 // Description: Returns a modifiable reference to the datagram 00074 // associated with the current record. This datagram 00075 // should then be stuffed with data corresponding to the 00076 // data in the record, in preparation for calling 00077 // advance() to write the data. 00078 //////////////////////////////////////////////////////////////////// 00079 Datagram &FltRecordWriter:: 00080 update_datagram() { 00081 return _datagram; 00082 } 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: FltRecordWriter::advance 00086 // Access: Public 00087 // Description: Writes the current record to the flt file, and resets 00088 // the current record to receive new data. Returns 00089 // FE_ok on success, or something else on error. 00090 //////////////////////////////////////////////////////////////////// 00091 FltError FltRecordWriter:: 00092 advance() { 00093 int start_byte = 0; 00094 int write_length = 00095 min((int)_datagram.get_length() - start_byte, max_write_length - header_size); 00096 FltOpcode opcode = _opcode; 00097 00098 do { 00099 if (flt_cat.is_debug()) { 00100 flt_cat.debug() 00101 << "Writing " << opcode << " of length " 00102 << write_length + header_size << "\n"; 00103 } 00104 00105 // Build a mini-datagram to write the header. 00106 Datagram dg; 00107 dg.add_be_int16(opcode); 00108 dg.add_be_int16(write_length + header_size); 00109 00110 nassertr((int)dg.get_length() == header_size, FE_internal); 00111 00112 _out.write((const char *)dg.get_data(), dg.get_length()); 00113 if (_out.fail()) { 00114 assert(!flt_error_abort); 00115 return FE_write_error; 00116 } 00117 00118 // Now write the rest of the record. 00119 _out.write((const char *)_datagram.get_data() + start_byte, write_length); 00120 if (_out.fail()) { 00121 assert(!flt_error_abort); 00122 return FE_write_error; 00123 } 00124 00125 start_byte += write_length; 00126 write_length = 00127 min((int)_datagram.get_length() - start_byte, max_write_length - header_size); 00128 opcode = FO_continuation; 00129 } while (write_length > 0); 00130 00131 _datagram.clear(); 00132 _opcode = FO_none; 00133 00134 return FE_ok; 00135 } 00136 00137 //////////////////////////////////////////////////////////////////// 00138 // Function: FltRecordWriter::write_record 00139 // Access: Public 00140 // Description: A convenience function to quickly write a simple 00141 // record that consists of an opcode and possibly a 00142 // datagram. 00143 //////////////////////////////////////////////////////////////////// 00144 FltError FltRecordWriter:: 00145 write_record(FltOpcode opcode, const Datagram &datagram) { 00146 _opcode = opcode; 00147 _datagram = datagram; 00148 return advance(); 00149 } 00150 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: FltRecordWriter::write_instance_def 00153 // Access: Public 00154 // Description: Ensures that the given instance definition has 00155 // already been written to the file. If it has not, 00156 // writes it now. 00157 //////////////////////////////////////////////////////////////////// 00158 FltError FltRecordWriter:: 00159 write_instance_def(FltHeader *header, int instance_index) { 00160 bool inserted = _instances_written.insert(instance_index).second; 00161 00162 if (!inserted) { 00163 // It's already been written. 00164 return FE_ok; 00165 } 00166 00167 FltInstanceDefinition *instance = header->get_instance(instance_index); 00168 if (instance == (FltInstanceDefinition *)NULL) { 00169 assert(!flt_error_abort); 00170 return FE_undefined_instance; 00171 } 00172 00173 return instance->write_record_and_children(*this); 00174 }