David Rose преди 23 години
родител
ревизия
e202ad39ad

+ 9 - 3
panda/src/express/Sources.pp

@@ -35,7 +35,9 @@
     profileTimer.I profileTimer.h \
     profileTimer.I profileTimer.h \
     pta_uchar.h referenceCount.I referenceCount.h \
     pta_uchar.h referenceCount.I referenceCount.h \
     register_type.I register_type.h \
     register_type.I register_type.h \
-    reversedNumericData.I reversedNumericData.h tokenBoard.I \
+    reversedNumericData.I reversedNumericData.h \
+    subStream.I subStream.h subStreamBuf.h \
+    tokenBoard.I \
     tokenBoard.h trueClock.I trueClock.h typeHandle.I \
     tokenBoard.h trueClock.I trueClock.h typeHandle.I \
     typeHandle.h typedObject.I typedObject.h \
     typeHandle.h typedObject.I typedObject.h \
     typedReferenceCount.I typedReferenceCount.h typedef.h \
     typedReferenceCount.I typedReferenceCount.h typedef.h \
@@ -59,7 +61,9 @@
     ordered_vector.cxx \
     ordered_vector.cxx \
     profileTimer.cxx \
     profileTimer.cxx \
     pta_uchar.cxx referenceCount.cxx register_type.cxx \
     pta_uchar.cxx referenceCount.cxx register_type.cxx \
-    reversedNumericData.cxx trueClock.cxx typeHandle.cxx \
+    reversedNumericData.cxx \
+    subStream.cxx subStreamBuf.cxx \
+    trueClock.cxx typeHandle.cxx \
     typedObject.cxx typedReferenceCount.cxx \
     typedObject.cxx typedReferenceCount.cxx \
     typeRegistry.cxx typeRegistryNode.cxx vector_uchar.cxx
     typeRegistry.cxx typeRegistryNode.cxx vector_uchar.cxx
 
 
@@ -85,7 +89,9 @@
     pointerToArray.I pointerToArray.h profileTimer.I \
     pointerToArray.I pointerToArray.h profileTimer.I \
     profileTimer.h pta_uchar.h referenceCount.I referenceCount.h \
     profileTimer.h pta_uchar.h referenceCount.I referenceCount.h \
     register_type.I register_type.h \
     register_type.I register_type.h \
-    reversedNumericData.I reversedNumericData.h tokenBoard.I \
+    reversedNumericData.I reversedNumericData.h \
+    subStream.I subStream.h subStreamBuf.h \
+    tokenBoard.I \
     tokenBoard.h trueClock.I trueClock.h typeHandle.I typeHandle.h \
     tokenBoard.h trueClock.I trueClock.h typeHandle.I typeHandle.h \
     typedObject.I typedObject.h typedReferenceCount.I \
     typedObject.I typedObject.h typedReferenceCount.I \
     typedReferenceCount.h typedef.h \
     typedReferenceCount.h typedef.h \

+ 2 - 0
panda/src/express/express_composite2.cxx

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

+ 37 - 20
panda/src/express/multifile.cxx

@@ -532,10 +532,10 @@ read_subfile(int index, Datagram &data) {
   data.clear();
   data.clear();
 
 
   istream &in = open_read_subfile(index);
   istream &in = open_read_subfile(index);
-  size_t length = _subfiles[index]->_data_length;
-  for (size_t p = 0; p < length; p++) {
-    int byte = in.get();
+  int byte = in.get();
+  while (!in.eof() && !in.fail()) {
     data.add_int8(byte);
     data.add_int8(byte);
+    byte = in.get();
   }
   }
   bool failed = in.fail();
   bool failed = in.fail();
   close_subfile();
   close_subfile();
@@ -659,11 +659,13 @@ extract_subfile_to(int index, ostream &out) {
   nassertr(index >= 0 && index < (int)_subfiles.size(), false);
   nassertr(index >= 0 && index < (int)_subfiles.size(), false);
 
 
   istream &in = open_read_subfile(index);
   istream &in = open_read_subfile(index);
-  size_t length = _subfiles[index]->_data_length;
-  for (size_t p = 0; p < length; p++) {
-    int byte = in.get();
+
+  int byte = in.get();
+  while (!in.fail() && !in.eof()) {
     out.put(byte);
     out.put(byte);
+    byte = in.get();
   }
   }
+
   bool failed = in.fail();
   bool failed = in.fail();
   close_subfile();
   close_subfile();
   nassertr(!failed, false);
   nassertr(!failed, false);
@@ -675,16 +677,16 @@ extract_subfile_to(int index, ostream &out) {
 //     Function: Multifile::open_read_subfile
 //     Function: Multifile::open_read_subfile
 //       Access: Public
 //       Access: Public
 //  Description: Returns an istream that may be used to read the
 //  Description: Returns an istream that may be used to read the
-//               indicated subfile.  The istream may or may not be a
-//               reference within the Multifile itself, so relative
-//               seeks are acceptable but global seeks will fail.
-//               Also, checking for eof() may fail; you must use
-//               get_subfile_length() instead.
+//               indicated subfile.  You may seek() within this
+//               istream to your heart's content; even though it is
+//               probably a reference to the already-opened fstream of
+//               the Multifile itself, byte 0 appears to be the
+//               beginning of the subfile and EOF appears to be the
+//               end of the subfile.
 //
 //
-//               It is not valid to perform any other operations on
-//               this Multifile until the indicated subfile has been
-//               read to completion and close_subfile() has been
-//               called.
+//               It is not valid to perform any additional operations
+//               on this Multifile until close_subfile() has
+//               subsequently been called.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 istream &Multifile::
 istream &Multifile::
 open_read_subfile(int index) {
 open_read_subfile(int index) {
@@ -695,17 +697,27 @@ open_read_subfile(int index) {
   nassertr(index >= 0 && index < (int)_subfiles.size(), empty_stream);
   nassertr(index >= 0 && index < (int)_subfiles.size(), empty_stream);
 #endif
 #endif
   _open_subfile = _subfiles[index];
   _open_subfile = _subfiles[index];
+
   if (_open_subfile->_source != (istream *)NULL) {
   if (_open_subfile->_source != (istream *)NULL) {
+    // The subfile has not yet been incorporated, and it is defined
+    // with an istream; return the istream directly.
     _open_subfile->_source->seekg(0);
     _open_subfile->_source->seekg(0);
     return *_open_subfile->_source;
     return *_open_subfile->_source;
   }
   }
+
   if (!_open_subfile->_source_filename.empty()) {
   if (!_open_subfile->_source_filename.empty()) {
-    _open_subfile->_source_filename.open_read(_subfile_read);
-    return _subfile_read;
+    // The subfile has not yet been incorporated, and it is defined
+    // with a filename; open the filename and return that.
+    _open_subfile->_source_filename.open_read(_subfile_fstream);
+    return _subfile_fstream;
   }
   }
+
+  // The subfile has been incorporated; return an ISubStream object
+  // that references into the open Multifile istream.
   nassertr(_open_subfile->_data_start != (streampos)0, empty_stream);
   nassertr(_open_subfile->_data_start != (streampos)0, empty_stream);
-  _read->seekg(_open_subfile->_data_start);
-  return *_read;
+  _subfile_substream.open(_read, _open_subfile->_data_start,
+                          _open_subfile->_data_start + _open_subfile->_data_length); 
+  return _subfile_substream;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -717,8 +729,13 @@ open_read_subfile(int index) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Multifile::
 void Multifile::
 close_subfile() {
 close_subfile() {
+  if (_open_subfile != (Subfile *)NULL &&
+      _open_subfile->_source != (istream *)NULL) {
+    _open_subfile->_source->seekg(0);
+  }
   _open_subfile = (Subfile *)NULL;
   _open_subfile = (Subfile *)NULL;
-  _subfile_read.close();
+  _subfile_fstream.close();
+  _subfile_substream.close();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 4 - 4
panda/src/express/multifile.h

@@ -23,7 +23,7 @@
 
 
 #include "datagram.h"
 #include "datagram.h"
 #include "datagramIterator.h"
 #include "datagramIterator.h"
-
+#include "subStream.h"
 #include "filename.h"
 #include "filename.h"
 #include "ordered_vector.h"
 #include "ordered_vector.h"
 #include "indirectLess.h"
 #include "indirectLess.h"
@@ -138,10 +138,10 @@ private:
   int _file_major_ver;
   int _file_major_ver;
   int _file_minor_ver;
   int _file_minor_ver;
 
 
+  // These are used to open a subfile for reading.
   Subfile *_open_subfile;
   Subfile *_open_subfile;
-  // This is just to support open_read_subfile() for those subfiles
-  // that have recently been added but not flushed.
-  ifstream _subfile_read;
+  ifstream _subfile_fstream;
+  ISubStream _subfile_substream;
 
 
   static const char _header[];
   static const char _header[];
   static const size_t _header_size;
   static const size_t _header_size;

+ 55 - 0
panda/src/express/subStream.I

@@ -0,0 +1,55 @@
+// Filename: subStream.I
+// Created by:  drose (02Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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: ISubStream::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE ISubStream::
+ISubStream() : istream(&_buf) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ISubStream::open
+//       Access: Public
+//  Description: Starts the SubStream reading from the indicated
+//               source, with the first character being the character
+//               at position "start" within the source, for end -
+//               start total characters.  The character at "end"
+//               within the source will never be read; this will
+//               appear to be EOF.
+////////////////////////////////////////////////////////////////////
+INLINE void ISubStream::
+open(istream *source, streampos start, streampos end) {
+  clear(0);
+  _buf.open(source, start, end);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ISubStream::close
+//       Access: Public
+//  Description: Resets the SubStream to empty, but does not actually
+//               close its source istream.
+////////////////////////////////////////////////////////////////////
+INLINE void ISubStream::
+close() {
+  _buf.close();
+}
+

+ 19 - 0
panda/src/express/subStream.cxx

@@ -0,0 +1,19 @@
+// Filename: subStream.cxx
+// Created by:  drose (02Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "subStream.h"

+ 48 - 0
panda/src/express/subStream.h

@@ -0,0 +1,48 @@
+// Filename: subStream.h
+// Created by:  drose (02Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 SUBSTREAM_H
+#define SUBSTREAM_H
+
+#include "pandabase.h"
+#include "subStreamBuf.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : ISubStream
+// Description : An istream object that presents a subwindow into
+//               another istream.  The first character read from this
+//               stream will be the "start" character from the source
+//               istream; just before the file pointer reaches the
+//               "end" character, eof is returned.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS ISubStream : public istream {
+public:
+  INLINE ISubStream();
+
+  INLINE void open(istream *source, streampos start, streampos end);
+  INLINE void close();
+
+private:
+  SubStreamBuf _buf;
+};
+
+#include "subStream.I"
+
+#endif
+
+

+ 204 - 0
panda/src/express/subStreamBuf.cxx

@@ -0,0 +1,204 @@
+// Filename: subStreamBuf.cxx
+// Created by:  drose (02Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 "subStreamBuf.h"
+
+#ifndef HAVE_STREAMSIZE
+// Some compilers (notably SGI) don't define this for us
+typedef int streamsize;
+#endif /* HAVE_STREAMSIZE */
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+SubStreamBuf::
+SubStreamBuf() {
+  _source = (istream *)NULL;
+  _start = 0;
+  _end = 0;
+  _cur = 0;
+#ifndef WIN32_VC
+  // These lines, which are essential on Irix and Linux, seem to be
+  // unnecessary and not understood on Windows.
+  allocate();
+  setg(base(), ebuf(), ebuf());
+#endif /* WIN32_VC */
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+SubStreamBuf::
+~SubStreamBuf() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::open
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void SubStreamBuf::
+open(istream *source, streampos start, streampos end) {
+  _source = source;
+  _start = start;
+  _end = end;
+  _cur = _start;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::close
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void SubStreamBuf::
+close() {
+  sync();
+  _source = (istream *)NULL;
+  _start = 0;
+  _end = 0;
+  _cur = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::seekoff
+//       Access: Public, Virtual
+//  Description: Implements seeking within the stream.
+////////////////////////////////////////////////////////////////////
+streampos SubStreamBuf::
+seekoff(streamoff off, ios::seek_dir dir, int mode) {
+  switch (dir) {
+  case ios::beg:
+    _cur = _start + off;
+    break;
+
+  case ios::cur:
+    _cur += off;
+    break;
+
+  case ios::end:
+    _cur = _end + off;
+    break;
+  }
+
+  _cur = max(_start, _cur);
+  return _cur - _start;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::overflow
+//       Access: Protected, Virtual
+//  Description: Called by the system ostream implementation when its
+//               internal buffer is filled, plus one character.
+////////////////////////////////////////////////////////////////////
+int SubStreamBuf::
+SubStreamBuf::overflow(int c) {
+  // We don't support ostream.
+
+  /*
+  streamsize n = pptr() - pbase();
+  if (n != 0) {
+    write_chars(pbase(), n, false);
+    pbump(-n);  // reset pptr()
+  }
+  if (c != EOF) {
+    // write one more character
+    char ch = c;
+    write_chars(&ch, 1, false);
+  }
+  */
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::sync
+//       Access: Protected, Virtual
+//  Description: Called by the system iostream implementation to
+//               implement a flush operation.
+////////////////////////////////////////////////////////////////////
+int SubStreamBuf::
+sync() {
+  /*
+  streamsize n = pptr() - pbase();
+  if (n != 0) {
+    write_chars(pbase(), n, false);
+    pbump(-n);
+  }
+  */
+
+  streamsize n = egptr() - gptr();
+  if (n != 0) {
+    gbump(n);
+    _cur += n;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SubStreamBuf::underflow
+//       Access: Protected, Virtual
+//  Description: Called by the system istream implementation when its
+//               internal buffer needs more characters.
+////////////////////////////////////////////////////////////////////
+int SubStreamBuf::
+underflow() {
+  if ((eback() == (char *)NULL) || (gptr() == (char *)NULL) ||
+      (egptr() == (char *)NULL)) {
+    // No buffer; allocate a new one.  Rumor has it this is only
+    // possible in Win32.
+    char *buf = new char[4096];
+    char *ebuf = buf + 4096;
+    setg(buf, ebuf, ebuf);
+  }
+
+  // Sometimes underflow() is called even if the buffer is not empty.
+  if (gptr() >= egptr()) {
+    if (_cur >= _end) {
+      // We're done.
+      return EOF;
+    }
+    
+    size_t buffer_size = egptr() - eback();
+    size_t num_bytes;
+    if (_end - _cur > buffer_size) {
+      // We have enough bytes in the input stream to fill our buffer.
+      num_bytes = buffer_size;
+    } else {
+      // We won't quite fill the buffer.
+      num_bytes = (size_t)(_end - _cur);
+    }
+
+    _source->seekg(_cur);
+    gbump(-(int)num_bytes);
+    nassertr(gptr() + num_bytes <= egptr(), EOF);
+
+    _source->read(gptr(), num_bytes);
+    if (_source->gcount() != num_bytes) {
+      // Oops, something screwed up.
+      _cur = _end;
+      return EOF;
+    }
+
+    _cur += num_bytes;
+  }
+
+  return *gptr();
+}

+ 50 - 0
panda/src/express/subStreamBuf.h

@@ -0,0 +1,50 @@
+// Filename: subStreamBuf.h
+// Created by:  drose (02Aug02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 SUBSTREAMBUF_H
+#define SUBSTREAMBUF_H
+
+#include "pandabase.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : SubStreamBuf
+// Description : The streambuf object that implements ISubStream.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS SubStreamBuf : public streambuf {
+public:
+  SubStreamBuf();
+  virtual ~SubStreamBuf();
+
+  void open(istream *source, streampos start, streampos end);
+  void close();
+
+  virtual streampos seekoff(streamoff off, ios::seek_dir dir, int mode);
+
+protected:
+  virtual int overflow(int c);
+  virtual int sync(void);
+  virtual int underflow(void);
+
+private:
+  istream *_source;
+  streampos _start;
+  streampos _end;
+  streampos _cur;
+};
+
+#endif