Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/flt/fltRecordReader.cxx

Go to the documentation of this file.
00001 // Filename: fltRecordReader.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 "fltRecordReader.h"
00020 #include "config_flt.h"
00021 
00022 #include <datagramIterator.h>
00023 
00024 #include <assert.h>
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: FltRecordReader::Constructor
00028 //       Access: Public
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 FltRecordReader::
00032 FltRecordReader(istream &in) :
00033   _in(in)
00034 {
00035   _opcode = FO_none;
00036   _record_length = 0;
00037   _iterator = (DatagramIterator *)NULL;
00038   _state = S_begin;
00039   _next_error = FE_ok;
00040   _next_opcode = FO_none;
00041   _next_record_length = 0;
00042 
00043   // Read the first header to get us going.
00044   read_next_header();
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: FltRecordReader::Destructor
00049 //       Access: Public
00050 //  Description:
00051 ////////////////////////////////////////////////////////////////////
00052 FltRecordReader::
00053 ~FltRecordReader() {
00054   if (_iterator != (DatagramIterator *)NULL) {
00055     delete _iterator;
00056     _iterator = (DatagramIterator *)NULL;
00057   }
00058 }
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: FltRecordReader::get_opcode
00062 //       Access: Public
00063 //  Description: Returns the opcode associated with the current
00064 //               record.
00065 ////////////////////////////////////////////////////////////////////
00066 FltOpcode FltRecordReader::
00067 get_opcode() const {
00068   nassertr(_state == S_normal, FO_none);
00069   return _opcode;
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: FltRecordReader::get_iterator
00074 //       Access: Public
00075 //  Description: Returns an iterator suitable for extracting data from
00076 //               the current record.
00077 ////////////////////////////////////////////////////////////////////
00078 DatagramIterator &FltRecordReader::
00079 get_iterator() {
00080   nassertr(_state == S_normal, *_iterator);
00081   return *_iterator;
00082 }
00083 
00084 ////////////////////////////////////////////////////////////////////
00085 //     Function: FltRecordReader::get_datagram
00086 //       Access: Public
00087 //  Description: Returns the datagram representing the entire record,
00088 //               less the four-byte header.
00089 ////////////////////////////////////////////////////////////////////
00090 const Datagram &FltRecordReader::
00091 get_datagram() {
00092 #ifndef NDEBUG
00093   static Datagram bogus_datagram;
00094   nassertr(_state == S_normal, bogus_datagram);
00095 #endif
00096   return _iterator->get_datagram();
00097 }
00098 
00099 ////////////////////////////////////////////////////////////////////
00100 //     Function: FltRecordReader::get_record_length
00101 //       Access: Public
00102 //  Description: Returns the entire length of the record, including
00103 //               the four-byte header.
00104 ////////////////////////////////////////////////////////////////////
00105 int FltRecordReader::
00106 get_record_length() const {
00107   return _record_length;
00108 }
00109 
00110 ////////////////////////////////////////////////////////////////////
00111 //     Function: FltRecordReader::advance
00112 //       Access: Public
00113 //  Description: Extracts the next record from the file.  Returns true
00114 //               if there is another record, or false if the end of
00115 //               file has been reached.
00116 ////////////////////////////////////////////////////////////////////
00117 FltError FltRecordReader::
00118 advance(bool ok_eof) {
00119   if (_state == S_eof) {
00120     assert(!flt_error_abort);
00121     return FE_end_of_file;
00122   }
00123   if (_state == S_error) {
00124     assert(!flt_error_abort);
00125     return FE_read_error;
00126   }
00127   if (_iterator != (DatagramIterator *)NULL) {
00128     delete _iterator;
00129     _iterator = (DatagramIterator *)NULL;
00130   }
00131 
00132   if (_next_error == FE_end_of_file) {
00133     _state = S_eof;
00134     if (ok_eof) {
00135       return FE_ok;
00136     }
00137     assert(!flt_error_abort);
00138     return FE_end_of_file;
00139 
00140   } else if (_next_error != FE_ok) {
00141     _state = S_error;
00142     assert(!flt_error_abort);
00143     return _next_error;
00144   }
00145 
00146   _opcode = _next_opcode;
00147   _record_length = _next_record_length;
00148 
00149   if (flt_cat.is_debug()) {
00150     flt_cat.debug()
00151       << "Reading " << _opcode
00152       << " of length " << _record_length << "\n";
00153   }
00154 
00155   // And now read the full record based on the length.
00156   int length = _next_record_length - header_size;
00157   char *buffer = new char[length];
00158   if (length > 0) {
00159     _in.read(buffer, length);
00160   }
00161   _datagram = Datagram(buffer, length);
00162   delete[] buffer;
00163 
00164   if (_in.eof()) {
00165     _state = S_eof;
00166     assert(!flt_error_abort);
00167     return FE_end_of_file;
00168   }
00169 
00170   if (_in.fail()) {
00171     _state = S_error;
00172     assert(!flt_error_abort);
00173     return FE_read_error;
00174   }
00175 
00176   // Check out the next header in case it's a continuation.
00177   read_next_header();
00178   while (_next_error == FE_ok && _next_opcode == FO_continuation) {
00179     if (flt_cat.is_debug()) {
00180       flt_cat.debug()
00181         << "Reading continuation of length " << _next_record_length << "\n";
00182     }
00183 
00184     // Read the continuation and tack it on.
00185     _record_length += _next_record_length;
00186     length = _next_record_length - header_size;
00187 
00188     buffer = new char[length];
00189     if (length > 0) {
00190       _in.read(buffer, length);
00191     }
00192     _datagram.append_data(buffer, length);
00193     delete[] buffer;
00194 
00195     if (_in.eof()) {
00196       _state = S_eof;
00197       assert(!flt_error_abort);
00198       return FE_end_of_file;
00199     }
00200 
00201     if (_in.fail()) {
00202       _state = S_error;
00203       assert(!flt_error_abort);
00204       return FE_read_error;
00205     }
00206 
00207     read_next_header();
00208   }
00209 
00210   // Finally, create a new iterator to read this record.
00211   _iterator = new DatagramIterator(_datagram);
00212   _state = S_normal;
00213 
00214   return FE_ok;
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: FltRecordReader::eof
00219 //       Access: Public
00220 //  Description: Returns true if end-of-file has been reached without
00221 //               error.
00222 ////////////////////////////////////////////////////////////////////
00223 bool FltRecordReader::
00224 eof() const {
00225   return _state == S_eof;
00226 }
00227 
00228 ////////////////////////////////////////////////////////////////////
00229 //     Function: FltRecordReader::error
00230 //       Access: Public
00231 //  Description: Returns true if some error has been encountered while
00232 //               reading (for instance, a truncated file).
00233 ////////////////////////////////////////////////////////////////////
00234 bool FltRecordReader::
00235 error() const {
00236   return _state == S_error;
00237 }
00238 
00239 ////////////////////////////////////////////////////////////////////
00240 //     Function: FltRecordReader::read_next_header
00241 //       Access: Private
00242 //  Description: Reads the four-byte header for the next record, which
00243 //               contains the next opcode and record length.
00244 //
00245 //               We need read the next header in advance so we can
00246 //               check to see if it happens to be a continuation
00247 //               record.  If it is, we will need to concatenate the
00248 //               records together before returning.
00249 ////////////////////////////////////////////////////////////////////
00250 void FltRecordReader::
00251 read_next_header() {
00252   char bytes[header_size];
00253   _in.read(bytes, header_size);
00254 
00255   if (_in.eof()) {
00256     _next_error = FE_end_of_file;
00257     return;
00258 
00259   } else if (_in.fail()) {
00260     _next_error = FE_read_error;
00261     return;
00262   }
00263 
00264   // Now extract out the opcode and length.
00265   Datagram dg(bytes, header_size);
00266   DatagramIterator dgi(dg);
00267   _next_opcode = (FltOpcode)dgi.get_be_int16();
00268   _next_record_length = dgi.get_be_uint16();
00269 
00270   if (_next_record_length < header_size) {
00271     _next_error = FE_invalid_record;
00272     return;
00273   }
00274 }

Generated on Fri May 2 03:19:33 2003 for Panda-Tool by doxygen1.3