00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00223
00224 typedef ReaderBase<char> Reader;
00225 typedef WriterBase<char> Writer;
00226 typedef ReaderBase<uchar> UReader;
00227 typedef WriterBase<uchar> UWriter;
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
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