00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00029
00030
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
00043
00044
00045
00046 IffInputFile::
00047 ~IffInputFile() {
00048 if (_owns_istream) {
00049 delete _input;
00050 }
00051 }
00052
00053
00054
00055
00056
00057
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
00074
00075
00076
00077
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
00093
00094
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
00108
00109
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
00123
00124
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
00138
00139
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
00153
00154
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
00168
00169
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
00183
00184
00185
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
00199
00200
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
00219
00220
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
00234
00235
00236
00237
00238
00239
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
00287
00288
00289
00290
00291
00292
00293
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
00341
00342
00343
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
00359
00360
00361
00362
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
00385
00386
00387
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
00406
00407
00408
00409
00410 IffChunk *IffInputFile::
00411 make_new_chunk(IffId) {
00412 return new IffGenericChunk;
00413 }