275 lines
7.8 KiB
C++
275 lines
7.8 KiB
C++
// Filename: fltRecordReader.cxx
|
|
// Created by: drose (24Aug00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "fltRecordReader.h"
|
|
#include "config_flt.h"
|
|
|
|
#include "datagramIterator.h"
|
|
|
|
#include <assert.h>
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
FltRecordReader::
|
|
FltRecordReader(istream &in) :
|
|
_in(in)
|
|
{
|
|
_opcode = FO_none;
|
|
_record_length = 0;
|
|
_iterator = (DatagramIterator *)NULL;
|
|
_state = S_begin;
|
|
_next_error = FE_ok;
|
|
_next_opcode = FO_none;
|
|
_next_record_length = 0;
|
|
|
|
// Read the first header to get us going.
|
|
read_next_header();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::Destructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
FltRecordReader::
|
|
~FltRecordReader() {
|
|
if (_iterator != (DatagramIterator *)NULL) {
|
|
delete _iterator;
|
|
_iterator = (DatagramIterator *)NULL;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::get_opcode
|
|
// Access: Public
|
|
// Description: Returns the opcode associated with the current
|
|
// record.
|
|
////////////////////////////////////////////////////////////////////
|
|
FltOpcode FltRecordReader::
|
|
get_opcode() const {
|
|
nassertr(_state == S_normal, FO_none);
|
|
return _opcode;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::get_iterator
|
|
// Access: Public
|
|
// Description: Returns an iterator suitable for extracting data from
|
|
// the current record.
|
|
////////////////////////////////////////////////////////////////////
|
|
DatagramIterator &FltRecordReader::
|
|
get_iterator() {
|
|
nassertr(_state == S_normal, *_iterator);
|
|
return *_iterator;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::get_datagram
|
|
// Access: Public
|
|
// Description: Returns the datagram representing the entire record,
|
|
// less the four-byte header.
|
|
////////////////////////////////////////////////////////////////////
|
|
const Datagram &FltRecordReader::
|
|
get_datagram() {
|
|
#ifndef NDEBUG
|
|
static Datagram bogus_datagram;
|
|
nassertr(_state == S_normal, bogus_datagram);
|
|
#endif
|
|
return _iterator->get_datagram();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::get_record_length
|
|
// Access: Public
|
|
// Description: Returns the entire length of the record, including
|
|
// the four-byte header.
|
|
////////////////////////////////////////////////////////////////////
|
|
int FltRecordReader::
|
|
get_record_length() const {
|
|
return _record_length;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::advance
|
|
// Access: Public
|
|
// Description: Extracts the next record from the file. Returns true
|
|
// if there is another record, or false if the end of
|
|
// file has been reached.
|
|
////////////////////////////////////////////////////////////////////
|
|
FltError FltRecordReader::
|
|
advance(bool ok_eof) {
|
|
if (_state == S_eof) {
|
|
assert(!flt_error_abort);
|
|
return FE_end_of_file;
|
|
}
|
|
if (_state == S_error) {
|
|
assert(!flt_error_abort);
|
|
return FE_read_error;
|
|
}
|
|
if (_iterator != (DatagramIterator *)NULL) {
|
|
delete _iterator;
|
|
_iterator = (DatagramIterator *)NULL;
|
|
}
|
|
|
|
if (_next_error == FE_end_of_file) {
|
|
_state = S_eof;
|
|
if (ok_eof) {
|
|
return FE_ok;
|
|
}
|
|
assert(!flt_error_abort);
|
|
return FE_end_of_file;
|
|
|
|
} else if (_next_error != FE_ok) {
|
|
_state = S_error;
|
|
assert(!flt_error_abort);
|
|
return _next_error;
|
|
}
|
|
|
|
_opcode = _next_opcode;
|
|
_record_length = _next_record_length;
|
|
|
|
if (flt_cat.is_debug()) {
|
|
flt_cat.debug()
|
|
<< "Reading " << _opcode
|
|
<< " of length " << _record_length << "\n";
|
|
}
|
|
|
|
// And now read the full record based on the length.
|
|
int length = _next_record_length - header_size;
|
|
char *buffer = new char[length];
|
|
if (length > 0) {
|
|
_in.read(buffer, length);
|
|
}
|
|
_datagram = Datagram(buffer, length);
|
|
delete[] buffer;
|
|
|
|
if (_in.eof()) {
|
|
_state = S_eof;
|
|
assert(!flt_error_abort);
|
|
return FE_end_of_file;
|
|
}
|
|
|
|
if (_in.fail()) {
|
|
_state = S_error;
|
|
assert(!flt_error_abort);
|
|
return FE_read_error;
|
|
}
|
|
|
|
// Check out the next header in case it's a continuation.
|
|
read_next_header();
|
|
while (_next_error == FE_ok && _next_opcode == FO_continuation) {
|
|
if (flt_cat.is_debug()) {
|
|
flt_cat.debug()
|
|
<< "Reading continuation of length " << _next_record_length << "\n";
|
|
}
|
|
|
|
// Read the continuation and tack it on.
|
|
_record_length += _next_record_length;
|
|
length = _next_record_length - header_size;
|
|
|
|
buffer = new char[length];
|
|
if (length > 0) {
|
|
_in.read(buffer, length);
|
|
}
|
|
_datagram.append_data(buffer, length);
|
|
delete[] buffer;
|
|
|
|
if (_in.eof()) {
|
|
_state = S_eof;
|
|
assert(!flt_error_abort);
|
|
return FE_end_of_file;
|
|
}
|
|
|
|
if (_in.fail()) {
|
|
_state = S_error;
|
|
assert(!flt_error_abort);
|
|
return FE_read_error;
|
|
}
|
|
|
|
read_next_header();
|
|
}
|
|
|
|
// Finally, create a new iterator to read this record.
|
|
_iterator = new DatagramIterator(_datagram);
|
|
_state = S_normal;
|
|
|
|
return FE_ok;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::eof
|
|
// Access: Public
|
|
// Description: Returns true if end-of-file has been reached without
|
|
// error.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool FltRecordReader::
|
|
eof() const {
|
|
return _state == S_eof;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::error
|
|
// Access: Public
|
|
// Description: Returns true if some error has been encountered while
|
|
// reading (for instance, a truncated file).
|
|
////////////////////////////////////////////////////////////////////
|
|
bool FltRecordReader::
|
|
error() const {
|
|
return _state == S_error;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: FltRecordReader::read_next_header
|
|
// Access: Private
|
|
// Description: Reads the four-byte header for the next record, which
|
|
// contains the next opcode and record length.
|
|
//
|
|
// We need read the next header in advance so we can
|
|
// check to see if it happens to be a continuation
|
|
// record. If it is, we will need to concatenate the
|
|
// records together before returning.
|
|
////////////////////////////////////////////////////////////////////
|
|
void FltRecordReader::
|
|
read_next_header() {
|
|
char bytes[header_size];
|
|
_in.read(bytes, header_size);
|
|
|
|
if (_in.eof()) {
|
|
_next_error = FE_end_of_file;
|
|
return;
|
|
|
|
} else if (_in.fail()) {
|
|
_next_error = FE_read_error;
|
|
return;
|
|
}
|
|
|
|
// Now extract out the opcode and length.
|
|
Datagram dg(bytes, header_size);
|
|
DatagramIterator dgi(dg);
|
|
_next_opcode = (FltOpcode)dgi.get_be_int16();
|
|
_next_record_length = dgi.get_be_uint16();
|
|
|
|
if (_next_record_length < header_size) {
|
|
_next_error = FE_invalid_record;
|
|
return;
|
|
}
|
|
}
|