Przeglądaj źródła

define StreamReader, StreamWriter

David Rose 23 lat temu
rodzic
commit
ac48fa90ad

+ 3 - 0
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 \

+ 2 - 0
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"

+ 47 - 51
panda/src/express/multifile.cxx

@@ -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);
 }

+ 350 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     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;
+}

+ 117 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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;
+}
+

+ 79 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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

+ 384 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     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());
+}

+ 35 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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--;
+  }
+}

+ 85 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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