Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

Xostream.cxx

Go to the documentation of this file.
00001 //     $Header: /nfs/slac/g/glast/ground/cvs/gui/src/Xostream.cxx,v 1.2 2001/01/25 23:15:13 tlindner Exp $
00002 //  author:  Toby Burnett
00003 
00004 
00005 #ifndef WIN32
00006 
00007 #include "Xostream.h"
00008 
00009 
00010 #include <errno.h>
00011 #include <strstream>
00012 #include <iostream>
00013 #include <cstring>
00014 #include <cstdlib>
00015 
00016 #include <cstdio>
00017 
00019 //          private streambuf used by Xostream (from LAT)
00020 class logbuf : public std::streambuf
00021 {
00022     
00023 public:
00024     enum { SIZE = 32 };
00025 
00026     logbuf (void);
00027     ~logbuf (void);
00028 
00029 #if  !defined(__GNUG__)
00030     virtual int_type            overflow (int_type c /* = traits::eof()*/);
00031     virtual std::streamsize     xsputn (const char_type *string,
00032                                         std::streamsize length);
00033 #else
00034     virtual int                 overflow (int c /* = EOF */);
00035     virtual int                 xsputn (const char *string, int length);
00036 #endif
00037 private:
00038     int                         m_pos;
00039 #if  !defined(__GNUG__)
00040     char_type                   m_buffer [SIZE];
00041 #else
00042     char                        m_buffer [SIZE];
00043 #endif
00044 };
00045 
00047 //         Xostream implementations
00049 //                constructor
00050 Xostream::Xostream(const char* /*name*/)
00051 : std::ostream(new logbuf)
00052 {
00053 }
00054 //------------------------------------------------------------------------
00055 //                        flush
00056 void Xostream::flush()
00057 {
00058     std::ostream::flush();
00059     // TODO: do I need this now?
00060 }
00061 //------------------------------------------------------------------------
00062 //                           clear
00063 
00064 void Xostream::clear()
00065 {
00066     //TODO: figure out how to clear console
00067    flush();
00068 
00069 }
00071 //            logbuf implementations
00073 
00074 //<doc>         Initialize the log buffer.
00075 logbuf::logbuf ()
00076     : m_pos (0)
00077 {
00078     setp (0, 0);
00079     setg (0, 0, 0);
00080 }
00081 
00082 //<doc>         Flush the buffer.
00083 logbuf::~logbuf (void)
00084 {
00085 #if  !defined(__GNUG__)
00086     overflow (traits_type::eof ());
00087 #else
00088     overflow (EOF);
00089 #endif
00090 }
00091 
00092 //<doc>         Handle buffer output.
00093 //
00094 //              Since the put area is empty we are in effect unbuffered, and
00095 //              this method will be called every time there is output.  We
00096 //              take the opportunity to adjust the line prefix here and then
00097 //              buffer <<SIZE>> characters, or till end of the line, which
00098 //              ever is less.  When the buffer must be flushed, it is sent
00099 //              back to the <<logstream>>.
00100 //
00101 //<args>        ch                      Character to consume or end of file
00102 //                                      indicator to flush. 
00103 //
00104 //<return>      End of file indicator on failure, zero on success.
00105 #if  !defined(__GNUG__)
00106 std::streambuf::int_type
00107 logbuf::overflow (int_type ch)
00108 #else
00109 int
00110 logbuf::overflow (int ch)
00111 #endif
00112 {
00113     if (
00114 #if !defined(__GNUG__)
00115         ch != traits_type::eof ()
00116 #else
00117         ch != EOF
00118 #endif
00119         )
00120     {
00121         m_buffer [m_pos++] = (char) ch;
00122 
00123         // FIXME: should use the following, but MSVC++ does not have
00124         // `newline' in traits
00125         //   ch == traits_type::newline ()
00126         if (ch == '\n' || m_pos == SIZE)
00127         {
00128             std::cout.write (m_buffer, m_pos);
00129             m_pos = 0;
00130         }
00131     }
00132     else if (m_pos)
00133     {
00134         std::cout.write (m_buffer, m_pos);
00135         m_pos = 0;
00136     }
00137 
00138     return 0;
00139 }
00140 
00141 //<doc>         Handle lengthy buffer output.
00142 //
00143 //              This function permits faster output when a longer sequence of
00144 //              known characters will be written.  Instead of writing every
00145 //              character separately it prints out the whole thing.
00146 //
00147 //<args>        string                  The sequence of characters to output.
00148 //              length                  The number of characters in the
00149 //                                      sequence.
00150 //
00151 //<return>      The number of characters delivered to output; the value is
00152 //              always equal to <<length>>.
00153 #if !defined(__GNUG__)
00154 std::streamsize
00155 logbuf::xsputn (const char_type *string, std::streamsize length)
00156 #else
00157 int
00158 logbuf::xsputn (const char *string, int length)
00159 #endif
00160 {
00161     for (int start = 0, end = 0; start < length; start = end) {
00162         // FIXME: should use: `&& string [end] != traits_type::newline ()'
00163         while (end < length && string [end] != '\n')
00164             ++end;
00165 
00166         if (end < length)
00167             // Include the newline
00168             ++end;
00169 
00170         // Copy either via buffer (if there was already something
00171         // there) or emit directly (if the buffer was empty or if
00172         // there are too many characters).  We use the buffer only on
00173         // the first string segment if the buffer is non-empty and on
00174         // the last segment if there isn't a trailing newline and the
00175         // segments fit into the buffer.
00176         if (m_pos) {
00177             // Use the buffer since there is already something there.
00178             while (m_pos < SIZE && start < end)
00179                 m_buffer [m_pos++] = string [start++];
00180             if (m_pos == SIZE) {
00181                 std::cout.write (m_buffer, m_pos);
00182                 m_pos = 0;
00183             }
00184         }
00185         if (end - start < SIZE - m_pos)
00186             // Copy a trailing, not newline-terminated segment that is
00187             // short enough to fit to the buffer.  Note that the
00188             // previous `if' might have already flushed out a first
00189             // part of this string.
00190             while (start < end) m_buffer [m_pos++] = string [start++];
00191         else if (start < end)
00192             // Just write it out.  Either it is newline terminated or
00193             // it is the rest of a too long string, or it is part of a
00194             // multiline string.
00195             std::cout.write (string + start, end - start);
00196     }
00197     return length;
00198 }
00199 #endif

Generated at Mon Nov 26 18:18:12 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000