Explorar el Código

*** empty log message ***

David Rose hace 25 años
padre
commit
56dd8577d9

+ 7 - 2
panda/src/express/Sources.pp

@@ -18,7 +18,9 @@
     indent.I indent.cxx indent.h littleEndian.I				\
     littleEndian.cxx littleEndian.h memoryUsage.I memoryUsage.cxx	\
     memoryUsage.h memoryUsagePointers.I memoryUsagePointers.cxx		\
-    memoryUsagePointers.h multifile.I multifile.cxx multifile.h		\
+    memoryUsagePointers.h multifile.I multifile.cxx multifile.h \
+    multiplexStream.I multiplexStream.cxx multiplexStream.h \
+    multiplexStreamBuf.I multiplexStreamBuf.cxx multiplexStreamBuf.h \
     namable.I namable.cxx namable.h numeric_types.h patchfile.I		\
     patchfile.cxx patchfile.h pointerTo.I pointerTo.h referenceCount.I	\
     referenceCount.cxx referenceCount.h tokenBoard.I tokenBoard.h	\
@@ -35,7 +37,10 @@
     datagramGenerator.h get_config_path.h				\
     indent.I indent.h littleEndian.I littleEndian.h			\
     memoryUsage.I memoryUsage.h memoryUsagePointers.I			\
-    memoryUsagePointers.h multifile.I multifile.h numeric_types.h	\
+    memoryUsagePointers.h multifile.I multifile.h \
+    multiplexStream.I multiplexStream.h \
+    multiplexStreamBuf.I multiplexStreamBuf.I \
+    numeric_types.h	\
     pointerTo.I pointerTo.h referenceCount.I referenceCount.h		\
     tokenBoard.h trueClock.I trueClock.h typeHandle.I typeHandle.h	\
     typedReferenceCount.I typedReferenceCount.h typedef.h		\

+ 90 - 0
panda/src/express/multiplexStream.I

@@ -0,0 +1,90 @@
+// Filename: multiplexStream.I
+// Created by:  drose (27Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStream::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE MultiplexStream::
+MultiplexStream() : ostream(&_msb) { 
+  setf(ios::unitbuf);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStream::add_ostream
+//       Access: Public
+//  Description: Adds the indicated generic ostream to the multiplex
+//               output.  The ostream will receive whatever data is
+//               sent to the pipe.
+////////////////////////////////////////////////////////////////////
+INLINE void MultiplexStream::
+add_ostream(ostream *out, bool delete_later) {
+  _msb.add_output(MultiplexStreamBuf::BT_none, 
+		  MultiplexStreamBuf::OT_ostream,
+		  out, delete_later);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStream::add_standard_output
+//       Access: Public
+//  Description: Adds the standard output channel.
+////////////////////////////////////////////////////////////////////
+INLINE void MultiplexStream::
+add_standard_output() {
+  _msb.add_output(MultiplexStreamBuf::BT_none, 
+		  MultiplexStreamBuf::OT_ostream,
+		  &cout, false);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStream::add_file
+//       Access: Public
+//  Description: Adds the given file to the multiplex output.  The
+//               file is opened in append mode with line buffering.
+//               Returns false if the file cannot be opened.
+////////////////////////////////////////////////////////////////////
+INLINE bool MultiplexStream::
+add_file(Filename file) {
+  file.set_text();
+  ofstream *out = new ofstream;
+  if (!file.open_append(*out)) {
+    delete out;
+    return false;
+  }
+  out->setf(ios::unitbuf);
+
+  _msb.add_output(MultiplexStreamBuf::BT_line, 
+		  MultiplexStreamBuf::OT_ostream,
+		  out, true);
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStream::add_system_debug
+//       Access: Public
+//  Description: Adds the system debug output the the multiplex
+//               output.  This may map to a syslog or some such
+//               os-specific output system.  It may do nothing on a
+//               particular system.
+//
+//               Presently, this maps only to OutputDebugString() on
+//               Windows.
+////////////////////////////////////////////////////////////////////
+INLINE void MultiplexStream::
+add_system_debug() {
+  _msb.add_output(MultiplexStreamBuf::BT_line, 
+		  MultiplexStreamBuf::OT_system_debug);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStream::flush
+//       Access: Public
+//  Description: Forces out all output that hasn't yet been written.
+////////////////////////////////////////////////////////////////////
+INLINE void MultiplexStream::
+flush() {
+  _msb.flush();
+}

+ 6 - 0
panda/src/express/multiplexStream.cxx

@@ -0,0 +1,6 @@
+// Filename: multiplexStream.cxx
+// Created by:  drose (27Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "multiplexStream.h"

+ 41 - 0
panda/src/express/multiplexStream.h

@@ -0,0 +1,41 @@
+// Filename: multiplexStream.h
+// Created by:  drose (27Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef MULTIPLEXSTREAM_H
+#define MULTIPLEXSTREAM_H
+
+#include <pandabase.h>
+
+#include "multiplexStreamBuf.h"
+
+#include <filename.h>
+
+////////////////////////////////////////////////////////////////////
+//       Class : MultiplexStream
+// Description : This is a special ostream that forwards the data that
+//               is written to it to any number of other sources, for
+//               instance other ostreams, or explicitly to a disk file
+//               or to system logging utilities.  It's a very handy
+//               thing to set Notify to refer to when running in batch
+//               mode.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA MultiplexStream : public ostream {
+PUBLISHED:
+  INLINE MultiplexStream();
+
+  INLINE void add_ostream(ostream *out, bool delete_later = false);
+  INLINE void add_standard_output();
+  INLINE bool add_file(Filename file);
+  INLINE void add_system_debug();
+
+  INLINE void flush();
+
+private:
+  MultiplexStreamBuf _msb;
+};
+
+#include "multiplexStream.I"
+
+#endif

+ 35 - 0
panda/src/express/multiplexStreamBuf.I

@@ -0,0 +1,35 @@
+// Filename: multiplexStreamBuf.I
+// Created by:  drose (27Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::add_output
+//       Access: Public
+//  Description: Adds the indicated output destinition to the set of
+//               things that will be written to when characters are
+//               output to the MultiplexStream.
+////////////////////////////////////////////////////////////////////
+INLINE void MultiplexStreamBuf::
+add_output(MultiplexStreamBuf::BufferType buffer_type,
+	   MultiplexStreamBuf::OutputType output_type,
+	   ostream *out, bool owns_ostream) {
+  Output o;
+  o._buffer_type = buffer_type;
+  o._output_type = output_type;
+  o._out = out;
+  o._owns_ostream = owns_ostream;
+  _outputs.push_back(o);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::flush
+//       Access: Public
+//  Description: Forces out all output that hasn't yet been written.
+////////////////////////////////////////////////////////////////////
+INLINE void MultiplexStreamBuf::
+flush() {
+  write_chars("", 0, true);
+}

+ 156 - 0
panda/src/express/multiplexStreamBuf.cxx

@@ -0,0 +1,156 @@
+// Filename: multiplexStreamBuf.cxx
+// Created by:  drose (27Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "multiplexStreamBuf.h"
+
+// We use real assert() instead of nassert(), because we're likely
+// to be invoked directly by notify here, and we don't want to
+// risk infinite recursion.
+#include <assert.h>
+
+#ifndef HAVE_STREAMSIZE
+// Some compilers--notably SGI--don't define this for us.
+typedef int streamsize;
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::Output::wrinte_string
+//       Access: Public
+//  Description: Dumps the indicated string to the appropriate place.
+////////////////////////////////////////////////////////////////////
+void MultiplexStreamBuf::Output::
+write_string(const string &str) {
+  switch (_output_type) {
+  case OT_ostream:
+    assert(_out != (ostream *)NULL);
+    _out->write(str.data(), str.length());
+    break;
+
+  case OT_system_debug:
+    break;
+  }
+}
+
+static char test[1024];
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+MultiplexStreamBuf::
+MultiplexStreamBuf() {
+  allocate();
+  setp(base(), ebuf());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+MultiplexStreamBuf::
+~MultiplexStreamBuf() {
+  sync();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::sync
+//       Access: Public, Virtual
+//  Description: Called by the system ostream implementation when the
+//               buffer should be flushed to output (for instance, on
+//               destruction).
+////////////////////////////////////////////////////////////////////
+int MultiplexStreamBuf::
+sync() { 
+  streamsize n = pptr() - pbase();
+
+  // We pass in false for the flush value, even though our
+  // transmitting ostream said to sync.  This allows us to get better
+  // line buffering, since our transmitting ostream is often set
+  // unitbuf, and might call sync multiple times in one line.  We
+  // still have an explicit flush() call to force the issue.
+  write_chars(pbase(), n, false);
+  pbump(-n);
+
+  return 0;  // Return 0 for success, EOF to indicate write full.
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::overflow
+//       Access: Public, Virtual
+//  Description: Called by the system ostream implementation when its
+//               internal buffer is filled, plus one character.
+////////////////////////////////////////////////////////////////////
+int MultiplexStreamBuf::
+overflow(int ch) { 
+  streamsize n = pptr() - pbase();
+
+  if (n != 0) {
+    write_chars(pbase(), n, false);
+    pbump(-n);  // Reset pptr().
+  }
+
+  if (ch != EOF) {
+    // Write one more character.
+    char c = ch;
+    write_chars(&c, 1, false);
+  }
+
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MultiplexStreamBuf::write_chars
+//       Access: Private
+//  Description: An internal function called by sync() and overflow()
+//               to store one or more characters written to the stream
+//               into the memory buffer.
+////////////////////////////////////////////////////////////////////
+void MultiplexStreamBuf::
+write_chars(const char *start, int length, bool flush) {
+  size_t orig = _line_buffer.length();
+  string latest(start, length);
+  string line;
+
+  if (flush) {
+    // If we're to flush the stream now, we dump the whole thing
+    // regardless of whether we have reached end-of-line.
+    line = _line_buffer + latest;
+    _line_buffer = "";
+
+  } else {
+    // Otherwise, we check for the end-of-line character, for our
+    // ostreams that only want a complete line at a time.
+    _line_buffer += latest;
+    size_t eol = _line_buffer.rfind('\n', orig);
+    if (eol != string::npos) {
+      line = _line_buffer.substr(0, eol + 1);
+      _line_buffer = _line_buffer.substr(eol + 1);
+    }
+  }
+
+  Outputs::iterator oi;
+  for (oi = _outputs.begin(); oi != _outputs.end(); ++oi) {
+    Output &out = (*oi);
+    switch (out._buffer_type) {
+    case BT_none:
+      // No buffering: send all new characters directly to the ostream.
+      if (!latest.empty()) {
+	out.write_string(latest);
+      }
+      break;
+
+    case BT_line:
+      // Line buffering: send only when a complete line has been
+      // received.
+      if (!line.empty()) {
+	out.write_string(line);
+      }
+      break;
+    }
+  }
+  
+}

+ 66 - 0
panda/src/express/multiplexStreamBuf.h

@@ -0,0 +1,66 @@
+// Filename: multiplexStreamBuf.h
+// Created by:  drose (27Nov00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef MULTIPLEXSTREAMBUF_H
+#define MULTIPLEXSTREAMBUF_H
+
+#include <pandabase.h>
+
+#include <vector>
+
+////////////////////////////////////////////////////////////////////
+//       Class : MultiplexStreamBuf
+// Description : Used by MultiplexStream to implement an ostream that
+//               sends what is written to it to any number of
+//               additional sources, like other ostreams.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA MultiplexStreamBuf : public streambuf {
+public:
+  MultiplexStreamBuf();
+  virtual ~MultiplexStreamBuf();
+
+  enum BufferType {
+    BT_none,
+    BT_line,
+  };
+
+  enum OutputType {
+    OT_ostream,
+    OT_system_debug,
+  };
+
+  INLINE void add_output(BufferType buffer_type, OutputType output_type,
+			 ostream *out = (ostream *)NULL, 
+			 bool owns_ostream = false);
+
+  INLINE void flush();
+
+protected:
+  virtual int overflow(int c);
+  virtual int sync();
+
+private:
+  void write_chars(const char *start, int length, bool flush);
+
+
+  class Output {
+  public:
+    void write_string(const string &str);
+
+    BufferType _buffer_type;
+    OutputType _output_type;
+    ostream *_out;
+    bool _owns_ostream;
+  };
+
+  typedef vector<Output> Outputs;
+  Outputs _outputs;
+
+  string _line_buffer;
+};
+
+#include "multiplexStreamBuf.I"
+
+#endif