00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "iffInputFile.h"
00016 #include "iffGenericChunk.h"
00017 #include "datagram.h"
00018 #include "datagramIterator.h"
00019 #include "virtualFileSystem.h"
00020
00021 TypeHandle IffInputFile::_type_handle;
00022
00023
00024
00025
00026
00027
00028 IffInputFile::
00029 IffInputFile() {
00030 _input = (istream *)NULL;
00031 _owns_istream = false;
00032 _eof = true;
00033 _unexpected_eof = false;
00034 _bytes_read = 0;
00035 }
00036
00037
00038
00039
00040
00041
00042 IffInputFile::
00043 ~IffInputFile() {
00044 if (_owns_istream) {
00045 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00046 vfs->close_read_file(_input);
00047 }
00048 }
00049
00050
00051
00052
00053
00054
00055
00056 bool IffInputFile::
00057 open_read(Filename filename) {
00058 filename.set_binary();
00059
00060 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00061 istream *in = vfs->open_read_file(filename, true);
00062 if (in == (istream *)NULL) {
00063 return false;
00064 }
00065
00066 set_input(in, true);
00067 set_filename(filename);
00068
00069 return true;
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 void IffInputFile::
00081 set_input(istream *input, bool owns_istream) {
00082 if (_owns_istream) {
00083 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00084 vfs->close_read_file(_input);
00085 }
00086 _input = input;
00087 _owns_istream = owns_istream;
00088 _eof = false;
00089 _unexpected_eof = false;
00090 _bytes_read = 0;
00091 }
00092
00093
00094
00095
00096
00097
00098 PN_int8 IffInputFile::
00099 get_int8() {
00100 Datagram dg;
00101 if (!read_bytes(dg, 1)) {
00102 return 0;
00103 }
00104 DatagramIterator dgi(dg);
00105 return dgi.get_int8();
00106 }
00107
00108
00109
00110
00111
00112
00113 PN_uint8 IffInputFile::
00114 get_uint8() {
00115 Datagram dg;
00116 if (!read_bytes(dg, 1)) {
00117 return 0;
00118 }
00119 DatagramIterator dgi(dg);
00120 return dgi.get_int8();
00121 }
00122
00123
00124
00125
00126
00127
00128 PN_int16 IffInputFile::
00129 get_be_int16() {
00130 Datagram dg;
00131 if (!read_bytes(dg, 2)) {
00132 return 0;
00133 }
00134 DatagramIterator dgi(dg);
00135 return dgi.get_be_int16();
00136 }
00137
00138
00139
00140
00141
00142
00143 PN_int32 IffInputFile::
00144 get_be_int32() {
00145 Datagram dg;
00146 if (!read_bytes(dg, 4)) {
00147 return 0;
00148 }
00149 DatagramIterator dgi(dg);
00150 return dgi.get_be_int32();
00151 }
00152
00153
00154
00155
00156
00157
00158 PN_uint16 IffInputFile::
00159 get_be_uint16() {
00160 Datagram dg;
00161 if (!read_bytes(dg, 2)) {
00162 return 0;
00163 }
00164 DatagramIterator dgi(dg);
00165 return dgi.get_be_uint16();
00166 }
00167
00168
00169
00170
00171
00172
00173 PN_uint32 IffInputFile::
00174 get_be_uint32() {
00175 Datagram dg;
00176 if (!read_bytes(dg, 4)) {
00177 return 0;
00178 }
00179 DatagramIterator dgi(dg);
00180 return dgi.get_be_uint32();
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 PN_stdfloat IffInputFile::
00190 get_be_float32() {
00191 Datagram dg;
00192 if (!read_bytes(dg, 4)) {
00193 return 0;
00194 }
00195 DatagramIterator dgi(dg);
00196 return dgi.get_be_float32();
00197 }
00198
00199
00200
00201
00202
00203
00204 string IffInputFile::
00205 get_string() {
00206 string result;
00207 char byte;
00208 while (read_byte(byte)) {
00209 if (byte == 0) {
00210 break;
00211 }
00212 result += byte;
00213 }
00214
00215 align();
00216 return result;
00217 }
00218
00219
00220
00221
00222
00223
00224 IffId IffInputFile::
00225 get_id() {
00226 Datagram dg;
00227 if (!read_bytes(dg, 4)) {
00228 return IffId();
00229 }
00230 const char *id = (const char *)dg.get_data();
00231 return IffId(id);
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 PT(IffChunk) IffInputFile::
00244 get_chunk() {
00245 if (is_eof()) {
00246 return (IffChunk *)NULL;
00247 }
00248
00249 IffId id = get_id();
00250 PN_uint32 length = get_be_uint32();
00251
00252 if (!is_eof()) {
00253 PT(IffChunk) chunk = make_new_chunk(id);
00254 chunk->set_id(id);
00255
00256 size_t start_point = get_bytes_read();
00257 size_t end_point = start_point + length;
00258
00259 if (chunk->read_iff(this, end_point)) {
00260 if (is_eof()) {
00261 if (!_unexpected_eof) {
00262 nout << "Unexpected EOF on file reading " << *chunk << "\n";
00263 _unexpected_eof = true;
00264 }
00265 return (IffChunk *)NULL;
00266 }
00267
00268 size_t num_bytes_read = get_bytes_read() - start_point;
00269 if (num_bytes_read > length) {
00270 nout << *chunk << " read " << num_bytes_read
00271 << " instead of " << length << " bytes.\n";
00272 return (IffChunk *)NULL;
00273
00274 } else if (num_bytes_read < length) {
00275 size_t skip_count = length - num_bytes_read;
00276 nout << "Ignoring " << skip_count << " bytes at the end of "
00277 << *chunk << "\n";
00278 skip_bytes(skip_count);
00279 }
00280 return chunk;
00281 }
00282 }
00283
00284 return (IffChunk *)NULL;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 PT(IffChunk) IffInputFile::
00298 get_subchunk(IffChunk *context) {
00299 if (is_eof()) {
00300 return (IffChunk *)NULL;
00301 }
00302
00303 IffId id = get_id();
00304 PN_uint16 length = get_be_uint16();
00305
00306 if (!is_eof()) {
00307 PT(IffChunk) chunk = context->make_new_chunk(this, id);
00308 chunk->set_id(id);
00309
00310 size_t start_point = get_bytes_read();
00311 size_t end_point = start_point + length;
00312
00313 if (chunk->read_iff(this, end_point)) {
00314 if (is_eof()) {
00315 if (!_unexpected_eof) {
00316 nout << "Unexpected EOF on file reading " << *chunk << "\n";
00317 _unexpected_eof = true;
00318 }
00319 return (IffChunk *)NULL;
00320 }
00321
00322 size_t num_bytes_read = get_bytes_read() - start_point;
00323 if (num_bytes_read > length) {
00324 nout << *chunk << " read " << num_bytes_read
00325 << " instead of " << length << " bytes.\n";
00326 return (IffChunk *)NULL;
00327
00328 } else if (num_bytes_read < length) {
00329 size_t skip_count = length - num_bytes_read;
00330 nout << "Ignoring " << skip_count << " bytes at the end of "
00331 << *chunk << "\n";
00332 skip_bytes(skip_count);
00333 }
00334 return chunk;
00335 }
00336 }
00337
00338 return (IffChunk *)NULL;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 bool IffInputFile::
00348 read_byte(char &byte) {
00349 if (is_eof()) {
00350 return false;
00351 }
00352
00353 _input->get(byte);
00354 _bytes_read++;
00355 _eof = _input->eof() || _input->fail();
00356 return !is_eof();
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366 bool IffInputFile::
00367 read_bytes(Datagram &datagram, int length) {
00368 if (is_eof()) {
00369 return false;
00370 }
00371
00372 char *buffer = new char[length];
00373 _input->read(buffer, length);
00374 _eof = (_input->gcount() != length);
00375 if (is_eof()) {
00376 return false;
00377 }
00378
00379 _bytes_read += length;
00380 datagram = Datagram(buffer, length);
00381 delete[] buffer;
00382 return true;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391 bool IffInputFile::
00392 skip_bytes(int length) {
00393 if (is_eof()) {
00394 return false;
00395 }
00396
00397 char byte;
00398 while (length > 0 && !is_eof()) {
00399 read_byte(byte);
00400 length--;
00401 }
00402
00403 return !is_eof();
00404 }
00405
00406
00407
00408
00409
00410
00411
00412 IffChunk *IffInputFile::
00413 make_new_chunk(IffId) {
00414 return new IffGenericChunk;
00415 }