Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

BufStream.H

Go to the documentation of this file.
00001 // Copyright (C) 2004, Kenneth C. Schalk
00002 
00003 // This file is part of Vesta.
00004 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Sat Sep 18 11:17:34 EDT 2004 by ken@xorian.net        
00020 
00021 // ----------------------------------------------------------------------
00022 
00023 // BufStream.H
00024 
00025 // A simple stream class for formatting text into a character buffer.
00026 // Similar to the old ostrstream class.  Able to avoid heap
00027 // allocations if a buffer is provided, unlike the ostringstream
00028 // class.
00029 
00030 #ifndef BUFSTREAM_H
00031 #define BUFSTREAM_H
00032 
00033 #include <assert.h>
00034 #include <iosfwd>
00035 #include <iostream>
00036 
00037 namespace Basics
00038 {
00039   class BufStreambuf : public std::streambuf
00040   {
00041   public:
00042 #if defined(__GNUC__) && (__GNUC__ < 3)
00043     typedef streampos pos_type;
00044     typedef streamoff off_type;
00045     typedef ios::seek_dir seekdir;
00046     typedef int openmode;
00047 #else
00048     typedef std::streambuf::pos_type pos_type;
00049     typedef std::streambuf::off_type off_type;
00050     typedef std::ios_base::seekdir seekdir;
00051     typedef std::ios_base::openmode openmode;
00052 #endif
00053 
00054   private:
00055     // Buffer where we're putting more characters.
00056     char *buf;
00057 
00058     // The length of the buffer
00059     unsigned int buf_len;
00060 
00061     // The current get/put positions.
00062     pos_type get_pos, put_pos;
00063 
00064     // The maximum number of bytes that have been written into the buffer.
00065     pos_type valid_limit;
00066 
00067     // Should we delete the current buffer?  (Did we allocate it, or was
00068     // it provided to us?)
00069     bool delete_buf;
00070 
00071     // Should we allocate a new buffer if the size of the current one is
00072     // exceeded, or should that be an error?
00073     bool allocate_new_buf;
00074 
00075     void update_get_pos();
00076     void update_put_pos();
00077 
00078     bool alloc_if_needed(unsigned int new_byte_count);
00079 
00080   public:
00081     // Construct a buffer that allocates its own storage and grows as
00082     // needed.
00083     BufStreambuf(unsigned int initial_buf_len = 256);
00084 
00085     // Construct a buffer that uses the supplied storage (at least
00086     // initially).
00087     BufStreambuf(char *initial_buf, unsigned int initial_buf_len,
00088                  unsigned int initial_valid_len = 0,
00089                  bool allocate_replacement = false)
00090       : buf(initial_buf), buf_len(initial_buf_len),
00091         delete_buf(false), allocate_new_buf(allocate_replacement),
00092         get_pos(0), put_pos(0), valid_limit(initial_valid_len)
00093     {
00094       setp(buf, buf+(buf_len-1));
00095       setg(buf, buf, buf+valid_limit);
00096     }
00097 
00098     ~BufStreambuf()
00099     {
00100       if(delete_buf)
00101         delete [] buf;
00102     }
00103 
00104     inline const char *str()
00105     {
00106       // Update valid_limit
00107       update_put_pos();
00108 
00109       // Add terminating null byte.  (We always save space in the
00110       // buffer for the terminating null.)
00111       assert(buf != 0);
00112       assert(valid_limit < (pos_type) buf_len);
00113       buf[valid_limit] = 0;
00114 
00115       // Return the buffer.
00116       return buf;
00117     }
00118 
00119     pos_type seekoff(off_type offset,
00120                      seekdir way,
00121                      openmode mode=(std::ios::in|
00122                                     std::ios::out));
00123     pos_type seekpos(pos_type pos, 
00124                      openmode mode=(std::ios::in|
00125                                     std::ios::out));
00126 
00127   protected:
00128     int underflow();
00129     std::streamsize xsgetn(char* s, std::streamsize n);
00130     int overflow(int c);
00131     std::streamsize xsputn(const char* s, std::streamsize n);
00132   };
00133 
00134   class BufStreamBase : virtual public std::ios
00135   {
00136   protected:
00137     BufStreambuf my_buf;
00138   public:
00139     BufStreamBase(unsigned int initial_buf_len = 256)
00140       : my_buf(initial_buf_len)
00141     {
00142       init(&my_buf);
00143     }
00144 
00145     BufStreamBase(char *initial_buf, unsigned int initial_buf_len,
00146                   unsigned int initial_valid_len = 0,
00147                   bool allocate_replacement = false)
00148       : my_buf(initial_buf, initial_buf_len,
00149                initial_valid_len, allocate_replacement)
00150     {
00151       init(&my_buf);
00152     }
00153 
00154     BufStreambuf *rdbuf() { return &my_buf; }
00155   };
00156 
00157   class IBufStream : public BufStreamBase, public std::istream
00158   {
00159   public:
00160     IBufStream(unsigned int initial_buf_len = 256)
00161       : BufStreamBase(initial_buf_len),
00162         std::istream(&my_buf)
00163     { }
00164 
00165     IBufStream(char *initial_buf, unsigned int initial_buf_len,
00166                unsigned int initial_valid_len = 0,
00167                bool allocate_replacement = false)
00168       : BufStreamBase(initial_buf, initial_buf_len,
00169                       initial_valid_len, allocate_replacement),
00170         std::istream(&my_buf)
00171     { }
00172 
00173     inline const char *str()
00174     {
00175       return my_buf.str();
00176     }
00177   };
00178 
00179   class OBufStream : public BufStreamBase, public std::ostream
00180   {
00181   public:
00182     OBufStream(unsigned int initial_buf_len = 256)
00183       : BufStreamBase(initial_buf_len),
00184         std::ostream(&my_buf)
00185     { }
00186 
00187     OBufStream(char *initial_buf, unsigned int initial_buf_len,
00188                unsigned int initial_valid_len = 0,
00189                bool allocate_replacement = false)
00190       : BufStreamBase(initial_buf, initial_buf_len,
00191                       initial_valid_len, allocate_replacement),
00192         std::ostream(&my_buf)
00193     { }
00194 
00195     inline const char *str()
00196     {
00197       return my_buf.str();
00198     }
00199   };
00200 
00201   class BufStream : public BufStreamBase, public std::iostream
00202   {
00203   public:
00204     BufStream(unsigned int initial_buf_len = 256)
00205       : BufStreamBase(initial_buf_len),
00206         std::iostream(&my_buf)
00207     { }
00208 
00209     BufStream(char *initial_buf, unsigned int initial_buf_len,
00210               unsigned int initial_valid_len = 0,
00211               bool allocate_replacement = false)
00212       : BufStreamBase(initial_buf, initial_buf_len,
00213                       initial_valid_len, allocate_replacement),
00214         std::iostream(&my_buf)
00215     { }
00216 
00217     inline const char *str()
00218     {
00219       return my_buf.str();
00220     }
00221   };
00222 }
00223 
00224 #endif

Generated on Mon May 8 00:48:28 2006 for Vesta by  doxygen 1.4.2