Main Page   Class Hierarchy   Alphabetical List   Compound List   Examples  

streambufs.h

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