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

pandatool/src/lwo/iffInputFile.cxx

Go to the documentation of this file.
00001 // Filename: iffInputFile.cxx
00002 // Created by:  drose (24Apr01)
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 "iffInputFile.h"
00020 #include "iffGenericChunk.h"
00021 
00022 #include <datagram.h>
00023 #include <datagramIterator.h>
00024 
00025 TypeHandle IffInputFile::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: IffInputFile::Constructor
00029 //       Access: Public
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 IffInputFile::
00033 IffInputFile() {
00034   _input = (istream *)NULL;
00035   _owns_istream = false;
00036   _eof = true;
00037   _unexpected_eof = false;
00038   _bytes_read = 0;
00039 }
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: IffInputFile::Destructor
00043 //       Access: Public, Virtual
00044 //  Description:
00045 ////////////////////////////////////////////////////////////////////
00046 IffInputFile::
00047 ~IffInputFile() {
00048   if (_owns_istream) {
00049     delete _input;
00050   }
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: IffInputFile::open_read
00055 //       Access: Public
00056 //  Description: Attempts to open the indicated filename for reading.
00057 //               Returns true if successful, false otherwise.
00058 ////////////////////////////////////////////////////////////////////
00059 bool IffInputFile::
00060 open_read(Filename filename) {
00061   filename.set_binary();
00062   ifstream *in = new ifstream;
00063   if (filename.open_read(*in)) {
00064     set_input(in, true);
00065     set_filename(filename);
00066     return true;
00067   }
00068 
00069   return false;
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: IffInputFile::set_input
00074 //       Access: Public
00075 //  Description: Sets up the input to use an arbitrary istream.  If
00076 //               owns_istream is true, the istream will be deleted
00077 //               when the IffInputFile destructs.
00078 ////////////////////////////////////////////////////////////////////
00079 void IffInputFile::
00080 set_input(istream *input, bool owns_istream) {
00081   if (_owns_istream) {
00082     delete _input;
00083   }
00084   _input = input;
00085   _owns_istream = owns_istream;
00086   _eof = false;
00087   _unexpected_eof = false;
00088   _bytes_read = 0;
00089 }
00090 
00091 ////////////////////////////////////////////////////////////////////
00092 //     Function: IffInputFile::get_int8
00093 //       Access: Public
00094 //  Description: Extracts a signed 8-bit integer.
00095 ////////////////////////////////////////////////////////////////////
00096 PN_int8 IffInputFile::
00097 get_int8() {
00098   Datagram dg;
00099   if (!read_bytes(dg, 1)) {
00100     return 0;
00101   }
00102   DatagramIterator dgi(dg);
00103   return dgi.get_int8();
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: IffInputFile::get_uint8
00108 //       Access: Public
00109 //  Description: Extracts an unsigned 8-bit integer.
00110 ////////////////////////////////////////////////////////////////////
00111 PN_uint8 IffInputFile::
00112 get_uint8() {
00113   Datagram dg;
00114   if (!read_bytes(dg, 1)) {
00115     return 0;
00116   }
00117   DatagramIterator dgi(dg);
00118   return dgi.get_int8();
00119 }
00120 
00121 ////////////////////////////////////////////////////////////////////
00122 //     Function: IffInputFile::get_be_int16
00123 //       Access: Public
00124 //  Description: Extracts a signed 16-bit big-endian integer.
00125 ////////////////////////////////////////////////////////////////////
00126 PN_int16 IffInputFile::
00127 get_be_int16() {
00128   Datagram dg;
00129   if (!read_bytes(dg, 2)) {
00130     return 0;
00131   }
00132   DatagramIterator dgi(dg);
00133   return dgi.get_be_int16();
00134 }
00135 
00136 ////////////////////////////////////////////////////////////////////
00137 //     Function: IffInputFile::get_be_int32
00138 //       Access: Public
00139 //  Description: Extracts a signed 32-bit big-endian integer.
00140 ////////////////////////////////////////////////////////////////////
00141 PN_int32 IffInputFile::
00142 get_be_int32() {
00143   Datagram dg;
00144   if (!read_bytes(dg, 4)) {
00145     return 0;
00146   }
00147   DatagramIterator dgi(dg);
00148   return dgi.get_be_int32();
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: IffInputFile::get_be_uint16
00153 //       Access: Public
00154 //  Description: Extracts an unsigned 16-bit big-endian integer.
00155 ////////////////////////////////////////////////////////////////////
00156 PN_uint16 IffInputFile::
00157 get_be_uint16() {
00158   Datagram dg;
00159   if (!read_bytes(dg, 2)) {
00160     return 0;
00161   }
00162   DatagramIterator dgi(dg);
00163   return dgi.get_be_uint16();
00164 }
00165 
00166 ////////////////////////////////////////////////////////////////////
00167 //     Function: IffInputFile::get_be_uint32
00168 //       Access: Public
00169 //  Description: Extracts an unsigned 32-bit big-endian integer.
00170 ////////////////////////////////////////////////////////////////////
00171 PN_uint32 IffInputFile::
00172 get_be_uint32() {
00173   Datagram dg;
00174   if (!read_bytes(dg, 4)) {
00175     return 0;
00176   }
00177   DatagramIterator dgi(dg);
00178   return dgi.get_be_uint32();
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: IffInputFile::get_be_float32
00183 //       Access: Public
00184 //  Description: Extracts a 32-bit big-endian single-precision
00185 //               floating-point number.
00186 ////////////////////////////////////////////////////////////////////
00187 float IffInputFile::
00188 get_be_float32() {
00189   Datagram dg;
00190   if (!read_bytes(dg, 4)) {
00191     return 0;
00192   }
00193   DatagramIterator dgi(dg);
00194   return dgi.get_be_float32();
00195 }
00196 
00197 ////////////////////////////////////////////////////////////////////
00198 //     Function: IffInputFile::get_string
00199 //       Access: Public
00200 //  Description: Extracts a null-terminated string.
00201 ////////////////////////////////////////////////////////////////////
00202 string IffInputFile::
00203 get_string() {
00204   string result;
00205   char byte;
00206   while (read_byte(byte)) {
00207     if (byte == 0) {
00208       break;
00209     }
00210     result += byte;
00211   }
00212 
00213   align();
00214   return result;
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: IffInputFile::get_id
00219 //       Access: Public
00220 //  Description: Extracts a 4-character IFF ID.
00221 ////////////////////////////////////////////////////////////////////
00222 IffId IffInputFile::
00223 get_id() {
00224   Datagram dg;
00225   if (!read_bytes(dg, 4)) {
00226     return IffId();
00227   }
00228   const char *id = (const char *)dg.get_data();
00229   return IffId(id);
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: IffInputFile::get_chunk
00234 //       Access: Public
00235 //  Description: Reads a single IffChunk, determining its type based
00236 //               on its ID.  Allocates and returns a new IffChunk
00237 //               object of the appropriate type.  Returns NULL if EOF
00238 //               is reached before the chunk can be read completely,
00239 //               or if there is some other error in reading the chunk.
00240 ////////////////////////////////////////////////////////////////////
00241 PT(IffChunk) IffInputFile::
00242 get_chunk() {
00243   if (is_eof()) {
00244     return (IffChunk *)NULL;
00245   }
00246 
00247   IffId id = get_id();
00248   PN_uint32 length = get_be_uint32();
00249 
00250   if (!is_eof()) {
00251     PT(IffChunk) chunk = make_new_chunk(id);
00252     chunk->set_id(id);
00253 
00254     size_t start_point = get_bytes_read();
00255     size_t end_point = start_point + length;
00256 
00257     if (chunk->read_iff(this, end_point)) {
00258       if (is_eof()) {
00259         if (!_unexpected_eof) {
00260           nout << "Unexpected EOF on file reading " << *chunk << "\n";
00261           _unexpected_eof = true;
00262         }
00263         return (IffChunk *)NULL;
00264       }
00265 
00266       size_t num_bytes_read = get_bytes_read() - start_point;
00267       if (num_bytes_read > length) {
00268         nout << *chunk << " read " << num_bytes_read
00269              << " instead of " << length << " bytes.\n";
00270         return (IffChunk *)NULL;
00271 
00272       } else if (num_bytes_read < length) {
00273         size_t skip_count = length - num_bytes_read;
00274         nout << "Ignoring " << skip_count << " bytes at the end of "
00275              << *chunk << "\n";
00276         skip_bytes(skip_count);
00277       }
00278       return chunk;
00279     }
00280   }
00281 
00282   return (IffChunk *)NULL;
00283 }
00284 
00285 ////////////////////////////////////////////////////////////////////
00286 //     Function: IffInputFile::get_subchunk
00287 //       Access: Public
00288 //  Description: Similar to get_chunk(), except the chunk size is only
00289 //               a 16-bit number instead of 32-bit, and it takes a
00290 //               context, which is the chunk in which this chunk is
00291 //               encountered.  The parent chunk may (or may not)
00292 //               decide what kind of chunk is meant by the various
00293 //               id's encountered.
00294 ////////////////////////////////////////////////////////////////////
00295 PT(IffChunk) IffInputFile::
00296 get_subchunk(IffChunk *context) {
00297   if (is_eof()) {
00298     return (IffChunk *)NULL;
00299   }
00300 
00301   IffId id = get_id();
00302   PN_uint16 length = get_be_uint16();
00303 
00304   if (!is_eof()) {
00305     PT(IffChunk) chunk = context->make_new_chunk(this, id);
00306     chunk->set_id(id);
00307 
00308     size_t start_point = get_bytes_read();
00309     size_t end_point = start_point + length;
00310 
00311     if (chunk->read_iff(this, end_point)) {
00312       if (is_eof()) {
00313         if (!_unexpected_eof) {
00314           nout << "Unexpected EOF on file reading " << *chunk << "\n";
00315           _unexpected_eof = true;
00316         }
00317         return (IffChunk *)NULL;
00318       }
00319 
00320       size_t num_bytes_read = get_bytes_read() - start_point;
00321       if (num_bytes_read > length) {
00322         nout << *chunk << " read " << num_bytes_read
00323              << " instead of " << length << " bytes.\n";
00324         return (IffChunk *)NULL;
00325 
00326       } else if (num_bytes_read < length) {
00327         size_t skip_count = length - num_bytes_read;
00328         nout << "Ignoring " << skip_count << " bytes at the end of "
00329              << *chunk << "\n";
00330         skip_bytes(skip_count);
00331       }
00332       return chunk;
00333     }
00334   }
00335 
00336   return (IffChunk *)NULL;
00337 }
00338 
00339 ////////////////////////////////////////////////////////////////////
00340 //     Function: IffInputFile::read_byte
00341 //       Access: Public
00342 //  Description: Reads a single byte.  Returns true if successful,
00343 //               false otherwise.
00344 ////////////////////////////////////////////////////////////////////
00345 bool IffInputFile::
00346 read_byte(char &byte) {
00347   if (is_eof()) {
00348     return false;
00349   }
00350 
00351   _input->get(byte);
00352   _bytes_read++;
00353   _eof = _input->eof() || _input->fail();
00354   return !is_eof();
00355 }
00356 
00357 ////////////////////////////////////////////////////////////////////
00358 //     Function: IffInputFile::read_bytes
00359 //       Access: Public
00360 //  Description: Reads a series of bytes, and stores them in the
00361 //               indicated Datagram.  Returns true if successful,
00362 //               false otherwise.
00363 ////////////////////////////////////////////////////////////////////
00364 bool IffInputFile::
00365 read_bytes(Datagram &datagram, int length) {
00366   if (is_eof()) {
00367     return false;
00368   }
00369 
00370   char *buffer = new char[length];
00371   _input->read(buffer, length);
00372   _eof = (_input->gcount() != length);
00373   if (is_eof()) {
00374     return false;
00375   }
00376 
00377   _bytes_read += length;
00378   datagram = Datagram(buffer, length);
00379   delete[] buffer;
00380   return true;
00381 }
00382 
00383 ////////////////////////////////////////////////////////////////////
00384 //     Function: IffInputFile::skip_bytes
00385 //       Access: Public
00386 //  Description: Reads a series of bytes, but does not store them.
00387 //               Returns true if successful, false otherwise.
00388 ////////////////////////////////////////////////////////////////////
00389 bool IffInputFile::
00390 skip_bytes(int length) {
00391   if (is_eof()) {
00392     return false;
00393   }
00394 
00395   char byte;
00396   while (length > 0 && !is_eof()) {
00397     read_byte(byte);
00398     length--;
00399   }
00400 
00401   return !is_eof();
00402 }
00403 
00404 ////////////////////////////////////////////////////////////////////
00405 //     Function: IffInputFile::make_new_chunk
00406 //       Access: Protected, Virtual
00407 //  Description: Allocates and returns a new chunk of the appropriate
00408 //               type based on the given ID.
00409 ////////////////////////////////////////////////////////////////////
00410 IffChunk *IffInputFile::
00411 make_new_chunk(IffId) {
00412   return new IffGenericChunk;
00413 }

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