define StreamReader, StreamWriter

This commit is contained in:
David Rose 2002-08-04 18:18:50 +00:00
parent 4ed9f1c353
commit ac48fa90ad
9 changed files with 1102 additions and 51 deletions

View File

@ -35,6 +35,7 @@
pta_uchar.h referenceCount.I referenceCount.h \
register_type.I register_type.h \
reversedNumericData.I reversedNumericData.h \
streamReader.I streamReader.h streamWriter.I streamWriter.h \
subStream.I subStream.h subStreamBuf.h \
tokenBoard.I \
tokenBoard.h trueClock.I trueClock.h typeHandle.I \
@ -61,6 +62,7 @@
profileTimer.cxx \
pta_uchar.cxx referenceCount.cxx register_type.cxx \
reversedNumericData.cxx \
streamReader.cxx streamWriter.cxx \
subStream.cxx subStreamBuf.cxx \
trueClock.cxx typeHandle.cxx \
typedObject.cxx typedReferenceCount.cxx \
@ -88,6 +90,7 @@
profileTimer.h pta_uchar.h referenceCount.I referenceCount.h \
register_type.I register_type.h \
reversedNumericData.I reversedNumericData.h \
streamReader.I streamReader.h streamWriter.I streamWriter.h \
subStream.I subStream.h subStreamBuf.h \
tokenBoard.I \
tokenBoard.h trueClock.I trueClock.h typeHandle.I typeHandle.h \

View File

@ -8,6 +8,8 @@
#include "referenceCount.cxx"
#include "register_type.cxx"
#include "reversedNumericData.cxx"
#include "streamReader.cxx"
#include "streamWriter.cxx"
#include "subStream.cxx"
#include "subStreamBuf.cxx"
#include "trueClock.cxx"

View File

@ -19,6 +19,9 @@
#include "multifile.h"
#include "config_express.h"
#include "streamWriter.h"
#include "streamReader.h"
#include <algorithm>
// This sequence of bytes begins each Multifile to identify it as a
@ -369,9 +372,8 @@ flush() {
// And update the forward link from the last_index to point to
// this new index location.
_write->seekp(_last_index);
Datagram dg;
dg.add_uint32(streampos_to_word(_next_index));
_write->write((const char *)dg.get_data(), dg.get_length());
StreamWriter writer(_write);
writer.add_uint32(streampos_to_word(_next_index));
}
_write->seekp(_next_index);
@ -389,9 +391,8 @@ flush() {
// Now we're at the end of the index. Write a 0 here to mark the
// end.
Datagram dg;
dg.add_uint32(0);
_write->write((const char *)dg.get_data(), dg.get_length());
StreamWriter writer(_write);
writer.add_uint32(0);
_next_index += 4;
_next_index = pad_to_streampos(_next_index);
@ -1008,11 +1009,10 @@ clear_subfiles() {
bool Multifile::
read_index() {
nassertr(_read != (istream *)NULL, false);
static const size_t header_followup_size = 2 + 2 + 4;
static const size_t total_header_size = _header_size + header_followup_size;
char this_header[total_header_size];
_read->read(this_header, total_header_size);
if (_read->fail() || _read->gcount() != total_header_size) {
char this_header[_header_size];
_read->read(this_header, _header_size);
if (_read->fail() || _read->gcount() != _header_size) {
express_cat.info()
<< "Unable to read Multifile header " << _multifile_name << ".\n";
close();
@ -1025,13 +1025,18 @@ read_index() {
}
// Now get the version numbers out.
Datagram dg(this_header + _header_size, header_followup_size);
DatagramIterator dgi(dg);
_file_major_ver = dgi.get_int16();
_file_minor_ver = dgi.get_int16();
_scale_factor = dgi.get_uint32();
StreamReader reader(_read);
_file_major_ver = reader.get_int16();
_file_minor_ver = reader.get_int16();
_scale_factor = reader.get_uint32();
_new_scale_factor = _scale_factor;
if (_read->eof() || _read->fail()) {
express_cat.info()
<< _multifile_name << " header is truncated.\n";
return false;
}
if (_file_major_ver != _current_major_ver ||
(_file_major_ver == _current_major_ver &&
_file_minor_ver > _current_minor_ver)) {
@ -1102,11 +1107,10 @@ write_header() {
nassertr(_write != (ostream *)NULL, false);
nassertr(_write->tellp() == (streampos)0, false);
_write->write(_header, _header_size);
Datagram dg;
dg.add_int16(_current_major_ver);
dg.add_int16(_current_minor_ver);
dg.add_uint32(_scale_factor);
_write->write((const char *)dg.get_data(), dg.get_length());
StreamWriter writer(_write);
writer.add_int16(_current_major_ver);
writer.add_int16(_current_minor_ver);
writer.add_uint32(_scale_factor);
_next_index = _write->tellp();
_next_index = pad_to_streampos(_next_index);
@ -1137,43 +1141,31 @@ read_index(istream &read, streampos fpos, Multifile *multifile) {
// First, get the next stream position. We do this separately,
// because if it is zero, we don't get anything else.
StreamReader reader(read);
static const size_t next_index_size = 4;
char next_index_buffer[next_index_size];
read.read(next_index_buffer, next_index_size);
if (read.fail() || read.gcount() != next_index_size) {
streampos next_index = multifile->word_to_streampos(reader.get_uint32());
if (read.eof() || read.fail()) {
_flags |= SF_index_invalid;
return 0;
}
Datagram idg(next_index_buffer, next_index_size);
DatagramIterator idgi(idg);
streampos next_index = multifile->word_to_streampos(idgi.get_uint32());
if (next_index == (streampos)0) {
return 0;
}
// Now get the rest of the index (except the name, which is variable
// length).
// Now get the rest of the index.
_index_start = fpos;
static const size_t index_size = 4 + 4 + 2 + 2;
char index_buffer[index_size];
read.read(index_buffer, index_size);
if (read.fail() || read.gcount() != index_size) {
_data_start = multifile->word_to_streampos(reader.get_uint32());
_data_length = reader.get_uint32();
_flags = reader.get_uint16();
size_t name_length = reader.get_uint16();
if (read.eof() || read.fail()) {
_flags |= SF_index_invalid;
return 0;
}
Datagram dg(index_buffer, index_size);
DatagramIterator dgi(dg);
_data_start = multifile->word_to_streampos(dgi.get_uint32());
_data_length = dgi.get_uint32();
_flags = dgi.get_uint16();
size_t name_length = dgi.get_uint16();
// And finally, get the rest of the name.
char *name_buffer = new char[name_length];
nassertr(name_buffer != (char *)NULL, next_index);
@ -1183,6 +1175,11 @@ read_index(istream &read, streampos fpos, Multifile *multifile) {
_name = string(name_buffer, name_length);
delete[] name_buffer;
if (read.eof() || read.fail()) {
_flags |= SF_index_invalid;
return 0;
}
return next_index;
}
@ -1204,7 +1201,8 @@ write_index(ostream &write, streampos fpos, Multifile *multifile) {
_index_start = fpos;
// This will be the contents of this particular index record.
// This will be the contents of this particular index record. We
// build it up first since it will be variable length.
Datagram dg;
dg.add_uint32(multifile->streampos_to_word(_data_start));
dg.add_uint32(_data_length);
@ -1333,10 +1331,9 @@ rewrite_index_data_start(ostream &write, Multifile *multifile) {
write.seekp(data_start_pos);
nassertv(!write.fail());
Datagram dg;
dg.add_uint32(multifile->streampos_to_word(_data_start));
dg.add_uint32(_data_length);
write.write((const char *)dg.get_data(), dg.get_length());
StreamWriter writer(write);
writer.add_uint32(multifile->streampos_to_word(_data_start));
writer.add_uint32(_data_length);
}
////////////////////////////////////////////////////////////////////
@ -1355,7 +1352,6 @@ rewrite_index_flags(ostream &write) {
write.seekp(flags_pos);
nassertv(!write.fail());
Datagram dg;
dg.add_uint16(_flags);
write.write((const char *)dg.get_data(), dg.get_length());
StreamWriter writer(write);
writer.add_uint16(_flags);
}

View File

@ -0,0 +1,350 @@
// Filename: streamReader.I
// Created by: drose (04Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: StreamReader::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamReader::
StreamReader(istream &in) :
_in(&in)
{
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamReader::
StreamReader(istream *in) :
_in(in)
{
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamReader::
StreamReader(const StreamReader &copy) :
_in(copy._in)
{
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void StreamReader::
operator = (const StreamReader &copy) {
_in = copy._in;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamReader::
~StreamReader() {
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_istream
// Access: Public
// Description: Returns the stream in use.
////////////////////////////////////////////////////////////////////
INLINE istream *StreamReader::
get_istream() const {
return _in;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_bool
// Access: Public
// Description: Extracts a boolean value.
////////////////////////////////////////////////////////////////////
INLINE bool StreamReader::
get_bool() {
return (get_uint8() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_int8
// Access: Public
// Description: Extracts a signed 8-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_int8 StreamReader::
get_int8() {
return (PN_int8)_in->get();
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_uint8
// Access: Public
// Description: Extracts an unsigned 8-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_uint8 StreamReader::
get_uint8() {
return (PN_uint8)_in->get();
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_int16
// Access: Public
// Description: Extracts a signed 16-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_int16 StreamReader::
get_int16() {
PN_int16 readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_int32
// Access: Public
// Description: Extracts a signed 32-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_int32 StreamReader::
get_int32() {
PN_int32 readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_int64
// Access: Public
// Description: Extracts a signed 64-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_int64 StreamReader::
get_int64() {
PN_int64 readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_uint16
// Access: Public
// Description: Extracts an unsigned 16-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_uint16 StreamReader::
get_uint16() {
PN_uint16 readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_uint32
// Access: Public
// Description: Extracts an unsigned 32-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_uint32 StreamReader::
get_uint32() {
PN_uint32 readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_uint64
// Access: Public
// Description: Extracts an unsigned 64-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_uint64 StreamReader::
get_uint64() {
PN_uint64 readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_float32
// Access: Public
// Description: Extracts a 32-bit single-precision floating-point
// number. Since this kind of float is not necessarily
// portable across different architectures, special care
// is required.
////////////////////////////////////////////////////////////////////
INLINE float StreamReader::
get_float32() {
// For now, we assume the float format is portable across all
// architectures we are concerned with. If we come across one that
// is different, we will have to convert.
nassertr(sizeof(float) == 4, 0.0f);
float readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_float64
// Access: Public
// Description: Extracts a 64-bit floating-point number.
////////////////////////////////////////////////////////////////////
INLINE PN_float64 StreamReader::
get_float64() {
PN_float64 readval, retval;
_in->read(&readval, sizeof(readval));
LittleEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_int16
// Access: Public
// Description: Extracts a signed big-endian 16-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_int16 StreamReader::
get_be_int16() {
PN_int16 readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_int32
// Access: Public
// Description: Extracts a signed big-endian 32-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_int32 StreamReader::
get_be_int32() {
PN_int32 readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_int64
// Access: Public
// Description: Extracts a signed big-endian 64-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_int64 StreamReader::
get_be_int64() {
PN_int64 readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_uint16
// Access: Public
// Description: Extracts an unsigned big-endian 16-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_uint16 StreamReader::
get_be_uint16() {
PN_uint16 readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_uint32
// Access: Public
// Description: Extracts an unsigned big-endian 32-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_uint32 StreamReader::
get_be_uint32() {
PN_uint32 readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_uint64
// Access: Public
// Description: Extracts an unsigned big-endian 64-bit integer.
////////////////////////////////////////////////////////////////////
INLINE PN_uint64 StreamReader::
get_be_uint64() {
PN_uint64 readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_float32
// Access: Public
// Description: Extracts a 32-bit single-precision big-endian
// floating-point number. Since this kind of float is
// not necessarily portable across different
// architectures, special care is required.
////////////////////////////////////////////////////////////////////
INLINE float StreamReader::
get_be_float32() {
// For now, we assume the float format is portable across all
// architectures we are concerned with. If we come across one that
// is different, we will have to convert.
nassertr(sizeof(float) == 4, 0.0f);
float readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_be_float64
// Access: Public
// Description: Extracts a 64-bit big-endian floating-point number.
////////////////////////////////////////////////////////////////////
INLINE PN_float64 StreamReader::
get_be_float64() {
PN_float64 readval, retval;
_in->read(&readval, sizeof(readval));
BigEndian s(&readval, 0, sizeof(readval));
s.store_value(&retval, sizeof(retval));
return retval;
}

View File

@ -0,0 +1,117 @@
// Filename: streamReader.cxx
// Created by: drose (04Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "streamReader.h"
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_string
// Access: Public
// Description: Extracts a variable-length string.
////////////////////////////////////////////////////////////////////
string StreamReader::
get_string() {
nassertr(!_in->eof() && !_in->fail(), string());
// First, get the length of the string
size_t s_len = get_uint16();
string result;
result.reserve(s_len);
for (size_t p = 0; !_in->eof() && !_in->fail() && p < s_len; p++) {
result += _in->get();
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_z_string
// Access: Public
// Description: Extracts a variable-length string, as a
// NULL-terminated string.
////////////////////////////////////////////////////////////////////
string StreamReader::
get_z_string() {
nassertr(!_in->eof() && !_in->fail(), string());
string result;
int ch = _in->get();
while (!_in->eof() && !_in->fail() && ch != '\0') {
result += ch;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::get_fixed_string
// Access: Public
// Description: Extracts a fixed-length string. However, if a zero
// byte occurs within the string, it marks the end of
// the string.
////////////////////////////////////////////////////////////////////
string StreamReader::
get_fixed_string(size_t size) {
nassertr(!_in->eof() && !_in->fail(), string());
string result;
result.reserve(size);
for (size_t p = 0; !_in->eof() && !_in->fail() && p < size; p++) {
result += _in->get();
}
size_t zero_byte = result.find('\0');
return result.substr(0, zero_byte);
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::skip_bytes
// Access: Public
// Description: Skips over the indicated number of bytes in the
// stream.
////////////////////////////////////////////////////////////////////
void StreamReader::
skip_bytes(size_t size) {
nassertv(!_in->eof() && !_in->fail());
nassertv((int)size >= 0);
while (size > 0) {
_in->get();
size--;
}
}
////////////////////////////////////////////////////////////////////
// Function: StreamReader::extract_bytes
// Access: Public
// Description: Extracts the indicated number of bytes in the
// stream and returns them as a string.
////////////////////////////////////////////////////////////////////
string StreamReader::
extract_bytes(size_t size) {
nassertr(!_in->eof() && !_in->fail(), string());
string result;
result.reserve(size);
for (size_t p = 0; !_in->eof() && !_in->fail() && p < size; p++) {
result += _in->get();
}
return result;
}

View File

@ -0,0 +1,79 @@
// Filename: streamReader.h
// Created by: drose (04Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef STREAMREADER_H
#define STREAMREADER_H
#include "pandabase.h"
#include "numeric_types.h"
#include "littleEndian.h"
#include "bigEndian.h"
////////////////////////////////////////////////////////////////////
// Class : StreamReader
// Description : A class to read sequential binary data directly from
// an istream. Its interface is similar to
// DatagramIterator by design; see also StreamWriter.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEXPRESS StreamReader {
public:
INLINE StreamReader(istream &in);
INLINE StreamReader(istream *in);
INLINE StreamReader(const StreamReader &copy);
INLINE void operator = (const StreamReader &copy);
INLINE ~StreamReader();
INLINE istream *get_istream() const;
INLINE bool get_bool();
INLINE PN_int8 get_int8();
INLINE PN_uint8 get_uint8();
INLINE PN_int16 get_int16();
INLINE PN_int32 get_int32();
INLINE PN_int64 get_int64();
INLINE PN_uint16 get_uint16();
INLINE PN_uint32 get_uint32();
INLINE PN_uint64 get_uint64();
INLINE float get_float32();
INLINE PN_float64 get_float64();
INLINE PN_int16 get_be_int16();
INLINE PN_int32 get_be_int32();
INLINE PN_int64 get_be_int64();
INLINE PN_uint16 get_be_uint16();
INLINE PN_uint32 get_be_uint32();
INLINE PN_uint64 get_be_uint64();
INLINE float get_be_float32();
INLINE PN_float64 get_be_float64();
string get_string();
string get_z_string();
string get_fixed_string(size_t size);
void skip_bytes(size_t size);
string extract_bytes(size_t size);
private:
istream *_in;
};
#include "streamReader.I"
#endif

View File

@ -0,0 +1,384 @@
// Filename: streamWriter.I
// Created by: drose (04Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamWriter::
StreamWriter(ostream &out) :
_out(&out)
{
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamWriter::
StreamWriter(ostream *out) :
_out(out)
{
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamWriter::
StreamWriter(const StreamWriter &copy) :
_out(copy._out)
{
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
operator = (const StreamWriter &copy) {
_out = copy._out;
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE StreamWriter::
~StreamWriter() {
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::get_ostream
// Access: Public
// Description: Returns the stream in use.
////////////////////////////////////////////////////////////////////
INLINE ostream *StreamWriter::
get_ostream() const {
return _out;
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_bool
// Access: Public
// Description: Adds a boolean value to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_bool(bool b) {
add_uint8(b);
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_int8
// Access: Public
// Description: Adds a signed 8-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_int8(PN_int8 value) {
append_data(&value, 1);
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_uint8
// Access: Public
// Description: Adds an unsigned 8-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_uint8(PN_uint8 value) {
append_data(&value, 1);
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_int16
// Access: Public
// Description: Adds a signed 16-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_int16(PN_int16 value) {
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_int32
// Access: Public
// Description: Adds a signed 32-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_int32(PN_int32 value) {
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_int64
// Access: Public
// Description: Adds a signed 64-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_int64(PN_int64 value) {
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_uint16
// Access: Public
// Description: Adds an unsigned 16-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_uint16(PN_uint16 value) {
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_uint32
// Access: Public
// Description: Adds an unsigned 32-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_uint32(PN_uint32 value) {
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_uint64
// Access: Public
// Description: Adds an unsigned 64-bit integer to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_uint64(PN_uint64 value) {
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_float32
// Access: Public
// Description: Adds a 32-bit single-precision floating-point number
// to the stream. Since this kind of float is not
// necessarily portable across different architectures,
// special care is required.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_float32(float value) {
// For now, we assume the float format is portable across all
// architectures we are concerned with. If we come across one that
// is different, we will have to convert.
nassertv(sizeof(value) == 4);
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_float64
// Access: Public
// Description: Adds a 64-bit floating-point number to the stream.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_float64(PN_float64 value) {
LittleEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_int16
// Access: Public
// Description: Adds a signed 16-bit big-endian integer to the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_int16(PN_int16 value) {
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_int32
// Access: Public
// Description: Adds a signed 32-bit big-endian integer to the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_int32(PN_int32 value) {
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_int64
// Access: Public
// Description: Adds a signed 64-bit big-endian integer to the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_int64(PN_int64 value) {
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_uint16
// Access: Public
// Description: Adds an unsigned 16-bit big-endian integer to the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_uint16(PN_uint16 value) {
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_uint32
// Access: Public
// Description: Adds an unsigned 32-bit big-endian integer to the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_uint32(PN_uint32 value) {
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_uint64
// Access: Public
// Description: Adds an unsigned 64-bit big-endian integer to the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_uint64(PN_uint64 value) {
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_float32
// Access: Public
// Description: Adds a 32-bit single-precision big-endian
// floating-point number to the stream. Since this
// kind of float is not necessarily portable across
// different architectures, special care is required.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_float32(float value) {
// For now, we assume the float format is portable across all
// architectures we are concerned with. If we come across one that
// is different, we will have to convert.
nassertv(sizeof(value) == 4);
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_be_float64
// Access: Public
// Description: Adds a 64-bit big-endian floating-point number to the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_be_float64(PN_float64 value) {
BigEndian s(&value, sizeof(value));
append_data(s.get_data(), sizeof(value));
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_string
// Access: Public
// Description: Adds a variable-length string to the stream. This
// actually adds a count followed by n bytes.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_string(const string &str) {
// The max sendable length for a string is 2^16.
nassertv(str.length() <= (PN_uint16)0xffff);
// Strings always are preceded by their length
add_uint16(str.length());
// Add the string
append_data(str);
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_z_string
// Access: Public
// Description: Adds a variable-length string to the stream, as a
// NULL-terminated string.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_z_string(string str) {
// We must not have any nested null characters in the string.
size_t null_pos = str.find('\0');
// Add the string (sans the null character).
append_data(str.substr(0, null_pos));
// And the null character.
add_uint8('\0');
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::add_fixed_string
// Access: Public
// Description: Adds a fixed-length string to the stream. If the
// string given is less than the requested size, this
// will pad the string out with zeroes; if it is greater
// than the requested size, this will silently truncate
// the string.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
add_fixed_string(const string &str, size_t size) {
if (str.length() < size) {
append_data(str);
pad_bytes(size - str.length());
} else { // str.length() >= size
append_data(str.substr(0, size));
}
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::append_data
// Access: Public
// Description: Appends some more raw data to the end of the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
append_data(const void *data, size_t size) {
_out->write((const char *)data, size);
}
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::append_data
// Access: Public
// Description: Appends some more raw data to the end of the
// streamWriter.
////////////////////////////////////////////////////////////////////
INLINE void StreamWriter::
append_data(const string &data) {
append_data(data.data(), data.length());
}

View File

@ -0,0 +1,35 @@
// Filename: streamWriter.cxx
// Created by: drose (04Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "streamWriter.h"
////////////////////////////////////////////////////////////////////
// Function: StreamWriter::pad_bytes
// Access: Public
// Description: Adds the indicated number of zero bytes to the
// stream.
////////////////////////////////////////////////////////////////////
void StreamWriter::
pad_bytes(size_t size) {
nassertv((int)size >= 0);
while (size > 0) {
_out->put('\0');
size--;
}
}

View File

@ -0,0 +1,85 @@
// Filename: streamWriter.h
// Created by: drose (04Aug02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef STREAMWRITER_H
#define STREAMWRITER_H
#include "pandabase.h"
#include "numeric_types.h"
#include "littleEndian.h"
#include "bigEndian.h"
////////////////////////////////////////////////////////////////////
// Class : StreamWriter
// Description : A StreamWriter object is used to write sequential
// binary data directly to an ostream. Its interface is
// very similar to Datagram by design; it's primarily
// intended as a convenience to eliminate the overhead
// of writing bytes to a Datagram and then writing the
// Datagram to a stream.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEXPRESS StreamWriter {
public:
INLINE StreamWriter(ostream &out);
INLINE StreamWriter(ostream *out);
INLINE StreamWriter(const StreamWriter &copy);
INLINE void operator = (const StreamWriter &copy);
INLINE ~StreamWriter();
INLINE ostream *get_ostream() const;
INLINE void add_bool(bool value);
INLINE void add_int8(PN_int8 value);
INLINE void add_uint8(PN_uint8 value);
// The default numeric packing is little-endian.
INLINE void add_int16(PN_int16 value);
INLINE void add_int32(PN_int32 value);
INLINE void add_int64(PN_int64 value);
INLINE void add_uint16(PN_uint16 value);
INLINE void add_uint32(PN_uint32 value);
INLINE void add_uint64(PN_uint64 value);
INLINE void add_float32(float value);
INLINE void add_float64(PN_float64 value);
// These functions pack numbers big-endian, in case that's desired.
INLINE void add_be_int16(PN_int16 value);
INLINE void add_be_int32(PN_int32 value);
INLINE void add_be_int64(PN_int64 value);
INLINE void add_be_uint16(PN_uint16 value);
INLINE void add_be_uint32(PN_uint32 value);
INLINE void add_be_uint64(PN_uint64 value);
INLINE void add_be_float32(float value);
INLINE void add_be_float64(PN_float64 value);
INLINE void add_string(const string &str);
INLINE void add_z_string(string str);
INLINE void add_fixed_string(const string &str, size_t size);
void pad_bytes(size_t size);
INLINE void append_data(const void *data, size_t size);
INLINE void append_data(const string &data);
private:
ostream *_out;
};
#include "streamWriter.I"
#endif