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