From ac48fa90ad54d626c1a4ae10f6cfbc3aa3967d5d Mon Sep 17 00:00:00 2001 From: David Rose Date: Sun, 4 Aug 2002 18:18:50 +0000 Subject: [PATCH] define StreamReader, StreamWriter --- panda/src/express/Sources.pp | 3 + panda/src/express/express_composite2.cxx | 2 + panda/src/express/multifile.cxx | 98 +++--- panda/src/express/streamReader.I | 350 +++++++++++++++++++++ panda/src/express/streamReader.cxx | 117 +++++++ panda/src/express/streamReader.h | 79 +++++ panda/src/express/streamWriter.I | 384 +++++++++++++++++++++++ panda/src/express/streamWriter.cxx | 35 +++ panda/src/express/streamWriter.h | 85 +++++ 9 files changed, 1102 insertions(+), 51 deletions(-) create mode 100644 panda/src/express/streamReader.I create mode 100644 panda/src/express/streamReader.cxx create mode 100644 panda/src/express/streamReader.h create mode 100644 panda/src/express/streamWriter.I create mode 100644 panda/src/express/streamWriter.cxx create mode 100644 panda/src/express/streamWriter.h diff --git a/panda/src/express/Sources.pp b/panda/src/express/Sources.pp index 042f68a658..27e2e5d13e 100644 --- a/panda/src/express/Sources.pp +++ b/panda/src/express/Sources.pp @@ -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 \ diff --git a/panda/src/express/express_composite2.cxx b/panda/src/express/express_composite2.cxx index 51f62da9da..c6bd7e37d8 100644 --- a/panda/src/express/express_composite2.cxx +++ b/panda/src/express/express_composite2.cxx @@ -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" diff --git a/panda/src/express/multifile.cxx b/panda/src/express/multifile.cxx index bedc48f89e..21aa2cbe65 100644 --- a/panda/src/express/multifile.cxx +++ b/panda/src/express/multifile.cxx @@ -19,6 +19,9 @@ #include "multifile.h" #include "config_express.h" +#include "streamWriter.h" +#include "streamReader.h" + #include // 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); } diff --git a/panda/src/express/streamReader.I b/panda/src/express/streamReader.I new file mode 100644 index 0000000000..7f69a6022e --- /dev/null +++ b/panda/src/express/streamReader.I @@ -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 ©) : + _in(copy._in) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: StreamReader::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void StreamReader:: +operator = (const StreamReader ©) { + _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; +} diff --git a/panda/src/express/streamReader.cxx b/panda/src/express/streamReader.cxx new file mode 100644 index 0000000000..987db4c676 --- /dev/null +++ b/panda/src/express/streamReader.cxx @@ -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; +} + diff --git a/panda/src/express/streamReader.h b/panda/src/express/streamReader.h new file mode 100644 index 0000000000..5d758b75ea --- /dev/null +++ b/panda/src/express/streamReader.h @@ -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 ©); + INLINE void operator = (const StreamReader ©); + 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 diff --git a/panda/src/express/streamWriter.I b/panda/src/express/streamWriter.I new file mode 100644 index 0000000000..975010d832 --- /dev/null +++ b/panda/src/express/streamWriter.I @@ -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 ©) : + _out(copy._out) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: StreamWriter::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void StreamWriter:: +operator = (const StreamWriter ©) { + _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()); +} diff --git a/panda/src/express/streamWriter.cxx b/panda/src/express/streamWriter.cxx new file mode 100644 index 0000000000..db6da27431 --- /dev/null +++ b/panda/src/express/streamWriter.cxx @@ -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--; + } +} diff --git a/panda/src/express/streamWriter.h b/panda/src/express/streamWriter.h new file mode 100644 index 0000000000..4f4a41d187 --- /dev/null +++ b/panda/src/express/streamWriter.h @@ -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 ©); + INLINE void operator = (const StreamWriter ©); + 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