CppCMS
|
00001 #ifndef BOOSTER_NOWIDE_FSTREAM_H 00002 #define BOOSTER_NOWIDE_FSTREAM_H 00003 00004 #include <booster/config.h> 00005 #include <booster/nowide/convert.h> 00006 #include <fstream> 00007 #include <memory> 00008 00009 #if defined BOOSTER_WIN_NATIVE || defined BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN 00010 #include <booster/streambuf.h> 00011 #include <booster/nowide/cstdio.h> 00012 #endif 00013 00014 namespace booster { 00020 namespace nowide { 00021 #if !defined BOOSTER_WIN_NATIVE && !defined(BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN) 00022 00023 using std::basic_ifstream; 00024 using std::basic_ofstream; 00025 using std::basic_fstream; 00026 using std::basic_filebuf; 00027 using std::filebuf; 00028 using std::ifstream; 00029 using std::ofstream; 00030 using std::fstream; 00031 00032 #endif 00033 #if defined(BOOSTER_WIN_NATIVE) || defined(BOOSTER_DOXYGEN_DOCS) || defined(BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN) 00034 00035 #if defined BOOSTER_MSVC 00036 00037 template<typename CharType,typename Traits = std::char_traits<CharType> > 00038 class basic_filebuf : public std::basic_filebuf<CharType,Traits> { 00039 public: 00040 typedef std::basic_filebuf<CharType,Traits> my_base_type; 00041 basic_filebuf *open(char const *s,std::ios_base::openmode mode) 00042 { 00043 try { 00044 if(my_base_type::open(convert(s).c_str(),mode)) { 00045 return this; 00046 } 00047 return 0; 00048 } 00049 catch(bad_utf const &e) { 00050 return 0; 00051 } 00052 } 00053 }; 00054 00055 #else // not msvc 00056 00058 00059 namespace details { 00060 class stdio_iodev : public booster::io_device { 00061 stdio_iodev(stdio_iodev const &); 00062 void operator=(stdio_iodev const &); 00063 public: 00064 stdio_iodev(FILE *f) : 00065 file_(f) 00066 { 00067 00068 } 00069 size_t read(char *p,size_t n) 00070 { 00071 return fread(p,1,n,file_); 00072 } 00073 size_t write(char const *p,size_t n) 00074 { 00075 size_t res = fwrite(p,1,n,file_); 00076 fflush(file_); 00077 return res; 00078 } 00079 long long seek(long long pos,io_device::pos_type t=set) 00080 { 00081 switch(t) { 00082 case cur: 00083 fseek(file_,pos,SEEK_CUR); 00084 break; 00085 case set: 00086 fseek(file_,pos,SEEK_SET); 00087 break; 00088 case end: 00089 fseek(file_,pos,SEEK_END); 00090 break; 00091 default: 00092 return -1; 00093 } 00094 return ftell(file_); 00095 } 00096 ~stdio_iodev() 00097 { 00098 fclose(file_); 00099 } 00100 private: 00101 FILE *file_; 00102 }; 00103 } // details 00104 00106 00107 template<typename CharType,typename Traits = std::char_traits<CharType> > 00108 class basic_filebuf; 00109 00113 00114 template<> 00115 class basic_filebuf<char> : public booster::streambuf { 00116 public: 00117 00118 basic_filebuf() : opened_(false) 00119 { 00120 } 00121 ~basic_filebuf() 00122 { 00123 } 00124 basic_filebuf *open(char const *s,std::ios_base::openmode mode) 00125 { 00126 reset_device(); 00127 wchar_t const *smode = get_mode(mode); 00128 if(!smode) 00129 return 0; 00130 std::wstring name; 00131 try { 00132 name = convert(s); 00133 } 00134 catch(bad_utf const &) { 00135 return 0; 00136 } 00137 FILE *f = _wfopen(name.c_str(),smode); 00138 if(!f) 00139 return 0; 00140 std::auto_ptr<io_device> dev(new details::stdio_iodev(f)); 00141 device(dev); 00142 opened_ = true; 00143 return this; 00144 } 00145 basic_filebuf *close() 00146 { 00147 00148 bool res = sync(); 00149 reset_device(); 00150 opened_ = false; 00151 return res ? this : 0; 00152 } 00153 bool is_open() const 00154 { 00155 return opened_; 00156 } 00157 private: 00158 static wchar_t const *get_mode(std::ios_base::openmode mode) 00159 { 00160 // 00161 // done according to n2914 table 106 27.9.1.4 00162 // 00163 00164 // note can't use switch case as overload operator can't be used 00165 // in constant expression 00166 if(mode == (std::ios_base::out)) 00167 return L"w"; 00168 if(mode == (std::ios_base::out | std::ios_base::app)) 00169 return L"a"; 00170 if(mode == (std::ios_base::app)) 00171 return L"a"; 00172 if(mode == (std::ios_base::out | std::ios_base::trunc)) 00173 return L"w"; 00174 if(mode == (std::ios_base::in)) 00175 return L"r"; 00176 if(mode == (std::ios_base::in | std::ios_base::out)) 00177 return L"r+"; 00178 if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) 00179 return L"w+"; 00180 if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app)) 00181 return L"a+"; 00182 if(mode == (std::ios_base::in | std::ios_base::app)) 00183 return L"a+"; 00184 if(mode == (std::ios_base::binary | std::ios_base::out)) 00185 return L"wb"; 00186 if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app)) 00187 return L"ab"; 00188 if(mode == (std::ios_base::binary | std::ios_base::app)) 00189 return L"ab"; 00190 if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc)) 00191 return L"wb"; 00192 if(mode == (std::ios_base::binary | std::ios_base::in)) 00193 return L"rb"; 00194 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out)) 00195 return L"r+b"; 00196 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc)) 00197 return L"w+b"; 00198 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app)) 00199 return L"a+b"; 00200 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app)) 00201 return L"a+b"; 00202 return 0; 00203 } 00204 00205 bool opened_; 00206 }; 00207 00208 #endif 00209 00213 template<typename CharType,typename Traits = std::char_traits<CharType> > 00214 class basic_ifstream : public std::basic_istream<CharType,Traits> 00215 { 00216 public: 00217 typedef basic_filebuf<CharType,Traits> internal_buffer_type; 00218 typedef std::basic_istream<CharType,Traits> internal_stream_type; 00219 00220 basic_ifstream() : 00221 internal_stream_type(new internal_buffer_type()) 00222 { 00223 buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf())); 00224 } 00225 explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) : 00226 internal_stream_type(new internal_buffer_type()) 00227 { 00228 buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf())); 00229 open(file_name,mode); 00230 } 00231 void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) 00232 { 00233 if(!buf_->open(file_name,mode | std::ios_base::in)) { 00234 this->setstate(std::ios_base::failbit); 00235 } 00236 else { 00237 this->clear(); 00238 } 00239 } 00240 bool is_open() 00241 { 00242 return buf_->is_open(); 00243 } 00244 bool is_open() const 00245 { 00246 return buf_->is_open(); 00247 } 00248 void close() 00249 { 00250 if(!buf_->close()) 00251 this->setstate(std::ios_base::failbit); 00252 else 00253 this->clear(); 00254 } 00255 00256 internal_buffer_type *rdbuf() const 00257 { 00258 return buf_.get(); 00259 } 00260 ~basic_ifstream() 00261 { 00262 buf_->close(); 00263 } 00264 00265 private: 00266 std::auto_ptr<internal_buffer_type> buf_; 00267 }; 00268 00272 00273 template<typename CharType,typename Traits = std::char_traits<CharType> > 00274 class basic_ofstream : public std::basic_ostream<CharType,Traits> 00275 { 00276 public: 00277 typedef basic_filebuf<CharType,Traits> internal_buffer_type; 00278 typedef std::basic_ostream<CharType,Traits> internal_stream_type; 00279 00280 basic_ofstream() : 00281 internal_stream_type(new internal_buffer_type()) 00282 { 00283 buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf())); 00284 } 00285 explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) : 00286 internal_stream_type(new internal_buffer_type()) 00287 { 00288 buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf())); 00289 open(file_name,mode); 00290 } 00291 void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) 00292 { 00293 if(!buf_->open(file_name,mode | std::ios_base::out)) { 00294 this->setstate(std::ios_base::failbit); 00295 } 00296 else { 00297 this->clear(); 00298 } 00299 } 00300 bool is_open() 00301 { 00302 return buf_->is_open(); 00303 } 00304 bool is_open() const 00305 { 00306 return buf_->is_open(); 00307 } 00308 void close() 00309 { 00310 if(!buf_->close()) 00311 this->setstate(std::ios_base::failbit); 00312 else 00313 this->clear(); 00314 } 00315 00316 internal_buffer_type *rdbuf() const 00317 { 00318 return buf_.get(); 00319 } 00320 ~basic_ofstream() 00321 { 00322 buf_->close(); 00323 } 00324 00325 private: 00326 std::auto_ptr<internal_buffer_type> buf_; 00327 }; 00328 00332 00333 template<typename CharType,typename Traits = std::char_traits<CharType> > 00334 class basic_fstream : public std::basic_iostream<CharType,Traits> 00335 { 00336 public: 00337 typedef basic_filebuf<CharType,Traits> internal_buffer_type; 00338 typedef std::basic_iostream<CharType,Traits> internal_stream_type; 00339 00340 basic_fstream() : 00341 internal_stream_type(new internal_buffer_type()) 00342 { 00343 buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf())); 00344 } 00345 explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) : 00346 internal_stream_type(new internal_buffer_type()) 00347 { 00348 buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf())); 00349 open(file_name,mode); 00350 } 00351 void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out) 00352 { 00353 if(!buf_->open(file_name,mode)) { 00354 this->setstate(std::ios_base::failbit); 00355 } 00356 else { 00357 this->clear(); 00358 } 00359 } 00360 bool is_open() 00361 { 00362 return buf_->is_open(); 00363 } 00364 bool is_open() const 00365 { 00366 return buf_->is_open(); 00367 } 00368 void close() 00369 { 00370 if(!buf_->close()) 00371 this->setstate(std::ios_base::failbit); 00372 else 00373 this->clear(); 00374 } 00375 00376 internal_buffer_type *rdbuf() const 00377 { 00378 return buf_.get(); 00379 } 00380 ~basic_fstream() 00381 { 00382 buf_->close(); 00383 } 00384 00385 private: 00386 std::auto_ptr<internal_buffer_type> buf_; 00387 }; 00388 00389 00393 typedef basic_filebuf<char> filebuf; 00397 typedef basic_ifstream<char> ifstream; 00401 typedef basic_ofstream<char> ofstream; 00405 typedef basic_fstream<char> fstream; 00406 00407 #endif 00408 } // nowide 00409 } // booster 00410 00411 00412 00413 #endif