Main Page   Class Hierarchy   Alphabetical List   Compound List   Examples  
streambufs.h
00001 /***************************************************************************
00002     copyright            : (C) 2002-2008 by Stefano Barbato
00003     email                : stefano@codesink.org
00004 
00005     $Id: streambufs.h,v 1.7 2008-10-07 11:06:26 tat Exp $
00006  ***************************************************************************/
00007 #ifndef _MIMETIC_MIMESTREAMBUF_H_
00008 #define _MIMETIC_MIMESTREAMBUF_H_
00009 #include <iostream>
00010 #include <string>
00011 #include <mimetic/libconfig.h>
00012 #include <mimetic/strutils.h>
00013 
00014 namespace mimetic
00015 {
00016 
00017 
00018 struct read_streambuf: public std::streambuf
00019 {
00020     enum { bufsz = 512 };
00021     typedef unsigned int size_type;
00022     read_streambuf()
00023     : m_iBuf(new char_type[bufsz])
00024     {
00025         setg(m_iBuf, m_iBuf + bufsz, m_iBuf + bufsz);
00026     }
00027     virtual ~read_streambuf()
00028     {
00029         if(m_iBuf)
00030             delete[] m_iBuf;
00031         m_iBuf = 0;
00032     } 
00033     int_type underflow()
00034     {
00035         int bread;
00036 
00037         if(gptr() < egptr())
00038             return traits_type::to_int_type(*gptr());
00039 
00040         if((bread = read(eback(), bufsz)) == 0)
00041             return traits_type::eof();
00042         else
00043             setg(eback(), eback(), eback() + bread);
00044 
00045         return traits_type::to_int_type(*gptr());
00046     }
00047     // must return number of bytes read or 0 on eof
00048     virtual int_type read(char*, int) = 0;
00049 private:
00050     read_streambuf(const read_streambuf&);
00051     read_streambuf& operator=(const read_streambuf&);
00052     char_type* m_iBuf;
00053 };
00054 
00055 
00056 template<typename InputIt>
00057 struct inputit_streambuf: public read_streambuf
00058 {
00059     inputit_streambuf(InputIt beg, InputIt end)
00060     : m_beg(beg), m_end(end)
00061     {
00062     }
00063     // returns number of  bytes read or 0 on eof
00064     int_type read(char* buf, int bufsz)
00065     {
00066         // fill buffer
00067         int c;
00068         for(c = 0; m_beg != m_end && c < bufsz; ++m_beg, ++buf, ++c)
00069             *buf = *m_beg;
00070         return c;
00071     }
00072 private:
00073     InputIt m_beg, m_end;
00074 };
00075 
00076 struct transform_streambuf: public std::streambuf
00077 {
00078     typedef unsigned int size_type;
00079     transform_streambuf()
00080     : m_oBuf(new char_type[512])
00081     {
00082         setp(m_oBuf, m_oBuf + 512);
00083     }
00084     virtual ~transform_streambuf()
00085     {
00086         if(m_oBuf)
00087         {
00088             sync();
00089             delete[] m_oBuf;
00090         }
00091     }
00092     int overflow(int meta = EOF)
00093     {
00094         if(sync() == -1)
00095             return EOF;
00096         if(meta != EOF)
00097         {
00098             *pptr() = meta;
00099             pbump(1);
00100         }
00101         return meta;
00102     }
00103     int sync()
00104     {
00105         int toSend = pptr() - pbase();
00106         if(toSend)
00107         {
00108             write(pbase(), pbase() + toSend);
00109             setp(m_oBuf, epptr());
00110         }
00111         return 0;
00112     }
00113     virtual void write(const char_type* beg, const char_type* end)=0;
00114 private:
00115     transform_streambuf(const transform_streambuf&);
00116     transform_streambuf& operator=(const transform_streambuf&);
00117     char_type* m_oBuf;
00118 };
00119 
00120 /*
00121  * stream buffer that does nothing except counting character written into it.
00122  * characters count is available through the size() method
00123  */
00124 struct count_streambuf: public transform_streambuf
00125 {
00126     count_streambuf()
00127     : m_count(0)
00128     {
00129     }
00130     void write(const char_type* beg, const char_type* end)
00131     {
00132         int toSend = end - beg;
00133         if(toSend)
00134             m_count += toSend;
00135     }
00136     size_type size()
00137     {
00138         return m_count;
00139     }
00140 private:
00141     size_type m_count;
00142 };
00143 
00144 
00145 
00146 /*
00147  * stream buffer that count char written into it and copy every char to the 
00148  * output iterator passed as ctor parameter
00149  * characters count is available through the size() method
00150  */
00151 template<typename OutputIt>
00152 struct passthrough_streambuf: public transform_streambuf
00153 {
00154     typedef unsigned int size_type;
00155     passthrough_streambuf(const OutputIt& out)
00156     : m_out(out), m_count(0)
00157     {
00158     }
00159     void write(const char_type* beg, const char_type* end)
00160     {
00161         int toSend = end - beg;
00162         if(toSend)
00163         {
00164             m_count += toSend;
00165             copy(beg, end, m_out);
00166         }
00167     }
00168     size_type size()
00169     {
00170         return m_count;
00171     }
00172 private:
00173     OutputIt m_out;
00174     size_type m_count;
00175 };
00176 
00177 
00178 
00179 struct crlftolf_streambuf: public transform_streambuf
00180 {
00181     typedef unsigned int size_type;
00182     crlftolf_streambuf(std::streambuf* osbuf)
00183     : m_osbuf(osbuf) 
00184     {
00185     }
00186     void write(const char_type* beg, const char_type* end)
00187     {
00188         enum { cr = 0xD, lf = 0xA };
00189         char_type c;
00190         bool got_cr = 0;
00191         for(; beg != end; ++beg)
00192         {
00193             c = *beg;
00194             if(got_cr)
00195             {
00196                 if(c == lf)
00197                     m_osbuf->sputc(lf);
00198                 else {
00199                     m_osbuf->sputc(cr);
00200                     m_osbuf->sputc(c);
00201                 }
00202                 got_cr = 0;
00203             } else if(c == cr) {
00204                 got_cr = 1;
00205                 continue;
00206             } else 
00207                 m_osbuf->sputc(c);
00208         }
00209         if(got_cr)
00210             m_osbuf->sputc(c);
00211     }
00212 private:
00213     std::streambuf* m_osbuf;
00214 };
00215 
00216 
00217 }
00218 
00219 #endif