stream.H

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #ifndef ARCHON_UTILITIES_STREAM_H
00021 #define ARCHON_UTILITIES_STREAM_H
00022 
00023 #include <stdio.h>
00024 
00025 #include <string>
00026 
00027 #include <archon/util/memory.H>
00028 #include <archon/util/text.H>
00029 #include <archon/util/unicode.H>
00030 #include <archon/util/thread.H>
00031 
00032 namespace Archon
00033 {
00034   namespace Utilities
00035   {
00043     namespace Stream
00044     {
00045       using namespace std;
00046 
00047       struct ReadException: IOException
00048       {
00049         ReadException(string l, string m): IOException(l, m) {}
00050       };
00051 
00052       struct WriteException: IOException
00053       {
00054         WriteException(string l, string m): IOException(l, m) {}
00055       };
00056 
00057       struct FileOpenException: IOException
00058       {
00059         FileOpenException(string l, string m): IOException(l, m) {}
00060       };
00061 
00062 
00069       template<class C>
00070       struct ReaderBase: RefObjectBase
00071       {
00072         typedef C CharType;
00073 
00081         virtual int read(C *buffer, int size)
00082           throw(ReadException, UnexpectedException) = 0;
00083 
00091         int readAll(C *buffer, int size)
00092           throw(ReadException, UnexpectedException)
00093         {
00094           int n = 0;
00095           while(n < size)
00096           {
00097             const int m = read(buffer + n, size - n);
00098             if(!m) break;
00099             n += m;
00100           }
00101           return n;
00102         }
00103 
00104         unsigned long getReadCount() const
00105         {
00106           return getUseCount();
00107         }
00108 
00109       protected:
00110         unsigned long getReadCountNoLock() const
00111         {
00112           return getUseCountNoLock();
00113         }
00114       };
00115 
00116 
00123       template<class C>
00124       struct WriterBase: RefObjectBase
00125       {
00126         typedef C CharType;
00127 
00133         virtual int write(const C *buffer, int size)
00134           throw(WriteException, UnexpectedException) = 0;
00135 
00139         void writeAll(const C *buffer, int size)
00140           throw(WriteException, UnexpectedException)
00141         {
00142           int n = 0;
00143           while(n < size) n += write(buffer + n, size - n);
00144         }
00145 
00146         void writeAll(string s)
00147         {
00148           writeAll(s.c_str(), s.size());
00149         }
00150 
00151         unsigned long getWriteCount() const
00152         {
00153           return getUseCount();
00154         }
00155 
00156       protected:
00160         unsigned long getWriteCountNoLock() const
00161         {
00162           return getUseCountNoLock();
00163         }
00164       };
00165 
00166 
00179       template<typename C>
00180       struct BasicRewindReader: ReaderBase<C>
00181       {
00187         static Ref<BasicRewindReader> get(Ref<ReaderBase<C> > r)
00188         {
00189           return new BasicRewindReader(r);
00190         }
00191 
00192         int read(C *buffer, int size)
00193           throw(ReadException, UnexpectedException);
00194 
00198         void rewind() { bufferStart = 0; }
00199 
00208         void release() { released = true; }
00209 
00210       private:
00211         BasicRewindReader(Ref<ReaderBase<C> > r):
00212           reader(r), bufferStart(0), released(false) {}
00213 
00214         Ref<ReaderBase<C> > reader;
00215         basic_string<C> buffer;
00216         unsigned bufferStart;
00217         bool released;
00218       };
00219 
00220 
00221       /*
00222        * Shorthand names
00223        */
00224       typedef ReaderBase<char> Reader;
00225       typedef WriterBase<char> Writer;
00226       typedef ReaderBase<uchar> UReader; // Unicode
00227       typedef WriterBase<uchar> UWriter; // Unicode
00228       typedef BasicRewindReader<char> RewindReader;
00229 
00234       Ref<Reader> makeStringReader(string);
00235 
00243       Ref<Reader> makeFileReader(int fildes);
00244 
00252       Ref<Reader> makeFileReader(string fileName)
00253         throw(FileOpenException);
00254 
00262       Ref<Writer> makeFileWriter(int fildes);
00263 
00271       Ref<Writer> makeFileWriter(string fileName)
00272         throw(FileOpenException);
00273 
00278       Ref<UReader> makeUtf8StreamReader(Ref<Reader>);
00279 
00289       Ref<UReader> makeUtf8FileReader(int fildes);
00290 
00300       Ref<UReader> makeUtf8FileReader(string fileName)
00301         throw(FileOpenException);
00302 
00307       string readIntoString(Ref<Reader>)
00308         throw(ReadException, UnexpectedException);
00309 
00319       template<typename C>
00320       struct Connector: Thread
00321       {
00322         Connector(Ref<ReaderBase<C> > r,
00323                   Ref<WriterBase<C> > w,
00324                   int bufferSize = 4096):
00325           r(r), w(w), buffer(bufferSize), bufferSize(bufferSize) {}
00326 
00327         void main()
00328         {
00329           for(;;)
00330           {
00331             const int n = r->read(buffer.get(), bufferSize);
00332             if(!n) break;
00333             w->write(buffer.get(), n);
00334           }
00335 
00336           r.reset();
00337           w.reset();
00338         }
00339 
00340       private:
00341         Ref<ReaderBase<C> > r;
00342         Ref<WriterBase<C> > w;
00343         Array<C> buffer;
00344         int bufferSize;
00345       };
00346 
00347 
00348 
00349       /*
00350        * Template implementations
00351        */
00352 
00353       template<typename C>
00354       int BasicRewindReader<C>::read(C *b, int size)
00355         throw(ReadException, UnexpectedException)
00356       {
00357         if(bufferStart == buffer.size())
00358         {
00359           int n = reader->read(b, size);
00360           if(!released) buffer.append(b, n);
00361           return n;
00362         }
00363 
00364         int left = buffer.size() - bufferStart;
00365         if(size < left)
00366         {
00367           buffer.copy(b, size, bufferStart);
00368           bufferStart += size;
00369           return size;
00370         }
00371 
00372         buffer.copy(b, left, bufferStart);
00373         if(released)
00374         {
00375           buffer.erase();
00376           bufferStart = 0;
00377         }
00378         else bufferStart += left;
00379         return left;
00380       }
00381     }
00382   }
00383 }
00384 
00385 #endif // ARCHON_UTILITIES_STREAM_H

Generated on Sun Jul 30 22:55:45 2006 for Archon by  doxygen 1.4.4