00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021 #include <string.h>
00022 #include <unistd.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <fcntl.h>
00026
00027 #include <archon/util/stream.H>
00028
00029 namespace Archon
00030 {
00031 namespace Utilities
00032 {
00033 namespace Stream
00034 {
00035 using namespace std;
00036
00037 struct StringReader: ReaderBase<char>
00038 {
00039 string s;
00040 int pos;
00041
00042 int read(char *buffer, int size)
00043 throw(ReadException, UnexpectedException)
00044 {
00045 Mutex::Lock l(*this);
00046 int n = min(unsigned(size), s.size()-pos);
00047 s.copy(buffer, n, pos);
00048 pos += n;
00049 return n;
00050 }
00051
00052 StringReader(string s): s(s), pos(0) {}
00053 };
00054
00055 struct FileReader: ReaderBase<char>
00056 {
00057 int fildes;
00058
00059 int read(char *buffer, int size)
00060 throw(ReadException, UnexpectedException)
00061 {
00062 int n = static_cast<int>(::read(fildes, buffer, size));
00063 if(n < 0) ARCHON_THROW1(ReadException, strerror(errno));
00064 return n;
00065 }
00066
00067 FileReader(int fildes): fildes(fildes) {}
00068
00069 virtual ~FileReader()
00070 {{
00071 ::close(fildes);
00072 }}
00073 };
00074
00075 struct FileWriter: WriterBase<char>
00076 {
00077 int fildes;
00078
00079 int write(const char *buffer, int size)
00080 throw(WriteException, UnexpectedException)
00081 {
00082 int n = static_cast<int>(::write(fildes, buffer, size));
00083 if(n < 0) ARCHON_THROW1(WriteException, strerror(errno));
00084 return n;
00085 }
00086
00087 FileWriter(int fildes): fildes(fildes) {}
00088
00089 virtual ~FileWriter()
00090 {{
00091 ::close(fildes);
00092 }}
00093 };
00094
00095 struct Utf8StreamReader: ReaderBase<uchar>
00096 {
00097 Ref<Reader> subReader;
00098 static const int utf8BufferSize = 1024;
00099 char utf8Buffer[utf8BufferSize];
00100 int utf8BufferOffset;
00101
00102 int read(uchar *buffer, int size)
00103 throw(ReadException, UnexpectedException)
00104 {
00105 Mutex::Lock l(*this);
00106 const int n = subReader->read(utf8Buffer+utf8BufferOffset,
00107 utf8BufferSize-utf8BufferOffset);
00108
00109 const int m = Unicode::decodeUtf8(utf8Buffer, utf8BufferOffset+n,
00110 buffer, size);
00111
00112 if(m) copy(utf8Buffer+m, utf8Buffer+utf8BufferOffset+n, utf8Buffer);
00113 utf8BufferOffset += n-m;
00114
00115 return size;
00116 }
00117
00118 Utf8StreamReader(Ref<Reader> subReader):
00119 subReader(subReader), utf8BufferOffset(0) {}
00120 };
00121
00122 struct Utf8FileReader: ReaderBase<uchar>
00123 {
00124 int fildes;
00125 static const int utf8BufferSize = 1024;
00126 char utf8Buffer[utf8BufferSize];
00127 int utf8BufferOffset;
00128
00129 int read(uchar *buffer, int size)
00130 throw(ReadException, UnexpectedException)
00131 {
00132 Mutex::Lock l(*this);
00133 const int n = static_cast<int>(::read(fildes, utf8Buffer+utf8BufferOffset,
00134 utf8BufferSize-utf8BufferOffset));
00135
00136 if(n < 0) ARCHON_THROW1(ReadException, strerror(errno));
00137
00138 const int m = Unicode::decodeUtf8(utf8Buffer, utf8BufferOffset+n,
00139 buffer, size);
00140
00141 if(m) copy(utf8Buffer+m, utf8Buffer+utf8BufferOffset+n, utf8Buffer);
00142 utf8BufferOffset += n-m;
00143
00144 return size;
00145 }
00146
00147 Utf8FileReader(int fildes):
00148 fildes(fildes), utf8BufferOffset(0) {}
00149 virtual ~Utf8FileReader()
00150 {{
00151 ::close(fildes);
00152 }}
00153 };
00154
00155
00156 Ref<Reader> makeStringReader(string s)
00157 {
00158 return new StringReader(s);
00159 }
00160
00161
00162 Ref<Reader> makeFileReader(string fileName) throw(FileOpenException)
00163 {
00164 const int fildes = open(fileName.c_str(), O_RDONLY);
00165 if(fildes<0)
00166 ARCHON_THROW1(FileOpenException,
00167 "Could not open \"" + fileName + "\" for reding: " +
00168 strerror(errno));
00169 return new FileReader(fildes);
00170 }
00171
00172 Ref<Reader> makeFileReader(int fildes)
00173 {
00174 return new FileReader(fildes);
00175 }
00176
00177
00178 Ref<Writer> makeFileWriter(string fileName) throw(FileOpenException)
00179 {
00180 const int fildes =
00181 creat(fileName.c_str(),
00182 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
00183 if(fildes<0)
00184 ARCHON_THROW1(FileOpenException,
00185 "Could not open \"" + fileName + "\" for writing: " +
00186 strerror(errno));
00187 return new FileWriter(fildes);
00188 }
00189
00190 Ref<Writer> makeFileWriter(int fildes)
00191 {
00192 return new FileWriter(fildes);
00193 }
00194
00195
00196 Ref<UReader> makeUtf8StreamReader(Ref<Reader> r)
00197 {
00198 return new Utf8StreamReader(r);
00199 }
00200
00201 Ref<UReader> makeUtf8FileReader(string fileName)
00202 throw(FileOpenException)
00203 {
00204 const int fildes = open(fileName.c_str(), O_RDONLY);
00205 if(fildes<0)
00206 ARCHON_THROW1(FileOpenException,
00207 "Could not open \"" + fileName + "\" for reading: " +
00208 strerror(errno));
00209 return new Utf8FileReader(fildes);
00210 }
00211
00212 Ref<UReader> makeUtf8FileReader(int fildes)
00213 {
00214 return new Utf8FileReader(fildes);
00215 }
00216
00217 string readIntoString(Ref<Reader> r)
00218 throw(ReadException, UnexpectedException)
00219 {
00220 string s;
00221 char b[4096];
00222 for(;;)
00223 {
00224 int n = r->read(b, 4096);
00225 if(!n) break;
00226 s.append(b, n);
00227 }
00228 return s;
00229 }
00230 }
00231 }
00232 }