00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "data/fstream.hpp"
00035 #include "data/exception.hpp"
00036 #include "data/string.hpp"
00037 #include "data/pointer.hpp"
00038
00039 #include <cstdio>
00040 #include <cstring>
00041 #include <cwchar>
00042 #include <cerrno>
00043
00044 #ifdef WIN32
00045 #pragma warning (disable : 4996)
00046 #endif
00047
00048 namespace gsgl
00049 {
00050
00051 namespace io
00052 {
00053
00054
00055
00056 file_stream::file_stream(void *fp, gsgl::flags_t mode)
00057 : data_object(), fname(L"???"), fp(fp), mode(mode)
00058 {
00059 }
00060
00061
00062 file_stream::file_stream(const string & fname, gsgl::flags_t mode)
00063 : data_object(), fname(fname), fp(0), mode(mode)
00064 {
00065 string mode_string;
00066
00067 if (mode & FILE_OPEN_READ)
00068 {
00069 if (mode & FILE_OPEN_WRITE)
00070 {
00071 if (mode & FILE_OPEN_APPEND)
00072 mode_string = L"a+";
00073 else
00074 mode_string = L"w+";
00075 }
00076 else
00077 {
00078 mode_string = L"r+";
00079 }
00080 }
00081 else if (mode & FILE_OPEN_WRITE)
00082 {
00083 if (mode & FILE_OPEN_APPEND)
00084 mode_string = L"a";
00085 else
00086 mode_string = L"w";
00087 }
00088 else
00089 {
00090 throw runtime_exception(L"invalid file open mode %ls opening %ls", mode_string.w_string(), fname.w_string());
00091 }
00092
00093 if (mode & FILE_OPEN_BINARY && mode & FILE_OPEN_TEXT)
00094 throw runtime_exception(L"You cannot open a file in both text and binary mode.");
00095
00096 if (mode & FILE_OPEN_BINARY)
00097 mode_string.append(L"b");
00098 else if (mode & FILE_OPEN_TEXT)
00099 mode_string.append(L"t");
00100
00101 FILE *f = ::fopen(fname.c_string(), mode_string.c_string());
00102
00103 if (f && !::ferror(f))
00104 {
00105 fp = f;
00106 }
00107 else
00108 {
00109 throw runtime_exception(L"Unable to open %ls: %hs", fname.w_string(), strerror(errno));
00110 }
00111 }
00112
00113
00114 file_stream::~file_stream()
00115 {
00116 if (fp)
00117 ::fclose(static_cast<FILE *>(fp));
00118 }
00119
00120
00121 bool file_stream::at_end() const
00122 {
00123 return ::feof(static_cast<FILE *>(fp)) != 0;
00124 }
00125
00126
00127
00128 ft_stream ft_stream::out(stdout, FILE_OPEN_WRITE | FILE_OPEN_APPEND | FILE_OPEN_TEXT);
00129 ft_stream ft_stream::err(stderr, FILE_OPEN_WRITE | FILE_OPEN_APPEND | FILE_OPEN_TEXT);
00130 ft_stream ft_stream::in(stdin, FILE_OPEN_READ | FILE_OPEN_TEXT);
00131
00132
00133
00134
00135 ft_stream::ft_stream(void *fp, gsgl::flags_t mode)
00136 : file_stream(fp, mode | FILE_OPEN_TEXT), text_stream()
00137 {
00138 }
00139
00140
00141 ft_stream::ft_stream(const string & fname, gsgl::flags_t mode)
00142 : file_stream(fname, mode | FILE_OPEN_TEXT), text_stream()
00143 {
00144 }
00145
00146 ft_stream::~ft_stream()
00147 {
00148 }
00149
00150 wchar_t ft_stream::peek()
00151 {
00152 if (mode & FILE_OPEN_READ)
00153 {
00154 wchar_t ch = ::fgetwc(static_cast<FILE *>(fp));
00155 ::ungetwc(ch, static_cast<FILE *>(fp));
00156 return ch;
00157 }
00158 else
00159 {
00160 throw io_exception(L"Cannot read from write-only stream %ls", fname.w_string());
00161 }
00162 }
00163
00164 wchar_t ft_stream::get()
00165 {
00166 if (mode & FILE_OPEN_READ)
00167 {
00168 wchar_t ch = ::fgetwc(static_cast<FILE *>(fp));
00169 return ch;
00170 }
00171 else
00172 {
00173 throw io_exception(L"cannot read from a write-only file");
00174 }
00175 }
00176
00177 void ft_stream::unget(wchar_t ch)
00178 {
00179 if (mode & FILE_OPEN_READ)
00180 {
00181 ::ungetwc(ch, static_cast<FILE *>(fp));
00182 }
00183 else
00184 {
00185 throw io_exception(L"cannot read from a write-only file");
00186 }
00187 }
00188
00189 bool ft_stream::at_end() const
00190 {
00191 return file_stream::at_end();
00192 }
00193
00194 gsgl::index_t ft_stream::read(wchar_t *buf, const gsgl::index_t num)
00195 {
00196 if (mode & FILE_OPEN_READ)
00197 {
00198
00199 data::smart_pointer<char, true> cbuf(new char[num+1]);
00200 int num_read = (gsgl::index_t) ::fread(cbuf, 1, num, static_cast<FILE *>(fp));
00201 for (int i = 0; i < num_read; ++i)
00202 buf[i] = cbuf[i];
00203 return num_read;
00204 }
00205 else
00206 {
00207 throw io_exception(L"cannot read from a write-only file");
00208 }
00209 }
00210
00211 gsgl::index_t ft_stream::write(const wchar_t *buf, const gsgl::index_t num)
00212 {
00213 if (mode & FILE_OPEN_WRITE)
00214 {
00215
00216 data::smart_pointer<char, true> cbuf (new char[num+1]);
00217 for (int i = 0; i < num; ++i)
00218 cbuf[i] = (char) buf[i];
00219
00220 return (gsgl::index_t) ::fwrite(cbuf, 1, num, static_cast<FILE *>(fp));
00221 }
00222 else
00223 {
00224 throw io_exception(L"cannot write to a read-only file");
00225 }
00226 }
00227
00228
00229
00230
00231
00232 fd_stream::fd_stream(const string & fname, gsgl::flags_t mode)
00233 : file_stream(fname, mode | FILE_OPEN_BINARY), data_stream()
00234 {
00235 }
00236
00237
00238 fd_stream::~fd_stream()
00239 {
00240 }
00241
00242
00243 bool fd_stream::at_end() const
00244 {
00245 return file_stream::at_end();
00246 }
00247
00248 gsgl::index_t fd_stream::read(unsigned char *ptr, gsgl::index_t num)
00249 {
00250 return static_cast<gsgl::index_t>(::fread(ptr, 1, num, static_cast<FILE *>(fp)));
00251 }
00252
00253
00254 gsgl::index_t fd_stream::write(const unsigned char * ptr, gsgl::index_t num)
00255 {
00256 return static_cast<gsgl::index_t>(::fwrite(ptr, 1, num, static_cast<FILE *>(fp)));
00257 }
00258
00259 }
00260
00261 }