From 56dd8577d9ac5af7cff5e077ff2e75aa7d4b5847 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 28 Nov 2000 00:32:28 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/express/Sources.pp | 9 +- panda/src/express/multiplexStream.I | 90 +++++++++++++ panda/src/express/multiplexStream.cxx | 6 + panda/src/express/multiplexStream.h | 41 ++++++ panda/src/express/multiplexStreamBuf.I | 35 +++++ panda/src/express/multiplexStreamBuf.cxx | 156 +++++++++++++++++++++++ panda/src/express/multiplexStreamBuf.h | 66 ++++++++++ 7 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 panda/src/express/multiplexStream.I create mode 100644 panda/src/express/multiplexStream.cxx create mode 100644 panda/src/express/multiplexStream.h create mode 100644 panda/src/express/multiplexStreamBuf.I create mode 100644 panda/src/express/multiplexStreamBuf.cxx create mode 100644 panda/src/express/multiplexStreamBuf.h diff --git a/panda/src/express/Sources.pp b/panda/src/express/Sources.pp index 468d345f2e..b76926eb03 100644 --- a/panda/src/express/Sources.pp +++ b/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 \ diff --git a/panda/src/express/multiplexStream.I b/panda/src/express/multiplexStream.I new file mode 100644 index 0000000000..72de480a77 --- /dev/null +++ b/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(); +} diff --git a/panda/src/express/multiplexStream.cxx b/panda/src/express/multiplexStream.cxx new file mode 100644 index 0000000000..0b60b31c7b --- /dev/null +++ b/panda/src/express/multiplexStream.cxx @@ -0,0 +1,6 @@ +// Filename: multiplexStream.cxx +// Created by: drose (27Nov00) +// +//////////////////////////////////////////////////////////////////// + +#include "multiplexStream.h" diff --git a/panda/src/express/multiplexStream.h b/panda/src/express/multiplexStream.h new file mode 100644 index 0000000000..f4e952b18f --- /dev/null +++ b/panda/src/express/multiplexStream.h @@ -0,0 +1,41 @@ +// Filename: multiplexStream.h +// Created by: drose (27Nov00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef MULTIPLEXSTREAM_H +#define MULTIPLEXSTREAM_H + +#include + +#include "multiplexStreamBuf.h" + +#include + +//////////////////////////////////////////////////////////////////// +// 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 diff --git a/panda/src/express/multiplexStreamBuf.I b/panda/src/express/multiplexStreamBuf.I new file mode 100644 index 0000000000..7fa8fdceac --- /dev/null +++ b/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); +} diff --git a/panda/src/express/multiplexStreamBuf.cxx b/panda/src/express/multiplexStreamBuf.cxx new file mode 100644 index 0000000000..820c0c95ee --- /dev/null +++ b/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 + +#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; + } + } + +} diff --git a/panda/src/express/multiplexStreamBuf.h b/panda/src/express/multiplexStreamBuf.h new file mode 100644 index 0000000000..1ba527506b --- /dev/null +++ b/panda/src/express/multiplexStreamBuf.h @@ -0,0 +1,66 @@ +// Filename: multiplexStreamBuf.h +// Created by: drose (27Nov00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef MULTIPLEXSTREAMBUF_H +#define MULTIPLEXSTREAMBUF_H + +#include + +#include + +//////////////////////////////////////////////////////////////////// +// 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 Outputs; + Outputs _outputs; + + string _line_buffer; +}; + +#include "multiplexStreamBuf.I" + +#endif