|
- #ifndef BOOSTER_NOWIDE_FSTREAM_H
- #define BOOSTER_NOWIDE_FSTREAM_H
-
- #include <booster/config.h>
- #include <booster/nowide/convert.h>
- #include <fstream>
- #include <booster/auto_ptr_inc.h>
-
- #if defined BOOSTER_WIN_NATIVE || defined BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN
- #include <booster/streambuf.h>
- #include <booster/nowide/cstdio.h>
- #endif
-
- namespace booster {
- ///
- /// \brief This namespace includes implementation of basic STL's / STDLIb's functions
- /// such that they accept UTF-8 strings. on Windows. Otherwise it is just an alias
- /// of std namespace (i.e. not on Windows)
- ///
- namespace nowide {
- #if !defined BOOSTER_WIN_NATIVE && !defined(BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN)
-
- using std::basic_ifstream;
- using std::basic_ofstream;
- using std::basic_fstream;
- using std::basic_filebuf;
- using std::filebuf;
- using std::ifstream;
- using std::ofstream;
- using std::fstream;
-
- #endif
- #if defined(BOOSTER_WIN_NATIVE) || defined(BOOSTER_DOXYGEN_DOCS) || defined(BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN)
-
- #if defined BOOSTER_MSVC
-
- template<typename CharType,typename Traits = std::char_traits<CharType> >
- class basic_filebuf : public std::basic_filebuf<CharType,Traits> {
- public:
- typedef std::basic_filebuf<CharType,Traits> my_base_type;
- basic_filebuf *open(char const *s,std::ios_base::openmode mode)
- {
- try {
- if(my_base_type::open(convert(s).c_str(),mode)) {
- return this;
- }
- return 0;
- }
- catch(bad_utf const &e) {
- return 0;
- }
- }
- };
-
- #else // not msvc
-
- /// \cond INTERNAL
-
- namespace details {
- class stdio_iodev : public booster::io_device {
- stdio_iodev(stdio_iodev const &);
- void operator=(stdio_iodev const &);
- public:
- stdio_iodev(FILE *f) :
- file_(f)
- {
-
- }
- size_t read(char *p,size_t n)
- {
- return fread(p,1,n,file_);
- }
- size_t write(char const *p,size_t n)
- {
- size_t res = fwrite(p,1,n,file_);
- fflush(file_);
- return res;
- }
- long long seek(long long pos,io_device::pos_type t=set)
- {
- switch(t) {
- case cur:
- fseek(file_,pos,SEEK_CUR);
- break;
- case set:
- fseek(file_,pos,SEEK_SET);
- break;
- case end:
- fseek(file_,pos,SEEK_END);
- break;
- default:
- return -1;
- }
- return ftell(file_);
- }
- ~stdio_iodev()
- {
- fclose(file_);
- }
- private:
- FILE *file_;
- };
- } // details
-
- /// \endcond
-
- template<typename CharType,typename Traits = std::char_traits<CharType> >
- class basic_filebuf;
-
- ///
- /// Same as std::basic_filebuf<char> but accepts UTF-8 strings under Windows
- ///
-
- template<>
- class basic_filebuf<char> : public booster::streambuf {
- public:
-
- basic_filebuf() : opened_(false)
- {
- }
- ~basic_filebuf()
- {
- }
- basic_filebuf *open(char const *s,std::ios_base::openmode mode)
- {
- reset_device();
- bool seek_end = mode & std::ios_base::ate;
- if(seek_end)
- mode ^= std::ios_base::ate;
- wchar_t const *smode = get_mode(mode);
- if(!smode)
- return 0;
- std::wstring name;
- try {
- name = convert(s);
- }
- catch(bad_utf const &) {
- return 0;
- }
- FILE *f = _wfopen(name.c_str(),smode);
- if(!f)
- return 0;
- if(seek_end) {
- if(fseek(f,0,SEEK_END)!=0) {
- fclose(f);
- return 0;
- }
- }
- std::auto_ptr<io_device> dev(new details::stdio_iodev(f));
- device(dev);
- opened_ = true;
- return this;
- }
- basic_filebuf *close()
- {
-
- bool res = sync();
- reset_device();
- opened_ = false;
- return res ? this : 0;
- }
- bool is_open() const
- {
- return opened_;
- }
- private:
- static wchar_t const *get_mode(std::ios_base::openmode mode)
- {
- //
- // done according to n2914 table 106 27.9.1.4
- //
-
- // note can't use switch case as overload operator can't be used
- // in constant expression
- if(mode == (std::ios_base::out))
- return L"w";
- if(mode == (std::ios_base::out | std::ios_base::app))
- return L"a";
- if(mode == (std::ios_base::app))
- return L"a";
- if(mode == (std::ios_base::out | std::ios_base::trunc))
- return L"w";
- if(mode == (std::ios_base::in))
- return L"r";
- if(mode == (std::ios_base::in | std::ios_base::out))
- return L"r+";
- if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
- return L"w+";
- if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app))
- return L"a+";
- if(mode == (std::ios_base::in | std::ios_base::app))
- return L"a+";
- if(mode == (std::ios_base::binary | std::ios_base::out))
- return L"wb";
- if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app))
- return L"ab";
- if(mode == (std::ios_base::binary | std::ios_base::app))
- return L"ab";
- if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc))
- return L"wb";
- if(mode == (std::ios_base::binary | std::ios_base::in))
- return L"rb";
- if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out))
- return L"r+b";
- if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
- return L"w+b";
- if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app))
- return L"a+b";
- if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app))
- return L"a+b";
- return 0;
- }
-
- bool opened_;
- };
-
- #endif
-
- ///
- /// Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows
- ///
- template<typename CharType,typename Traits = std::char_traits<CharType> >
- class basic_ifstream : public std::basic_istream<CharType,Traits>
- {
- public:
- typedef basic_filebuf<CharType,Traits> internal_buffer_type;
- typedef std::basic_istream<CharType,Traits> internal_stream_type;
-
- basic_ifstream() :
- internal_stream_type(new internal_buffer_type())
- {
- buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
- }
- explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) :
- internal_stream_type(new internal_buffer_type())
- {
- buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
- open(file_name,mode);
- }
- void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::in)
- {
- if(!buf_->open(file_name,mode | std::ios_base::in)) {
- this->setstate(std::ios_base::failbit);
- }
- else {
- this->clear();
- }
- }
- bool is_open()
- {
- return buf_->is_open();
- }
- bool is_open() const
- {
- return buf_->is_open();
- }
- void close()
- {
- if(!buf_->close())
- this->setstate(std::ios_base::failbit);
- else
- this->clear();
- }
-
- internal_buffer_type *rdbuf() const
- {
- return buf_.get();
- }
- ~basic_ifstream()
- {
- buf_->close();
- }
-
- private:
- std::auto_ptr<internal_buffer_type> buf_;
- };
-
- ///
- /// Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows
- ///
-
- template<typename CharType,typename Traits = std::char_traits<CharType> >
- class basic_ofstream : public std::basic_ostream<CharType,Traits>
- {
- public:
- typedef basic_filebuf<CharType,Traits> internal_buffer_type;
- typedef std::basic_ostream<CharType,Traits> internal_stream_type;
-
- basic_ofstream() :
- internal_stream_type(new internal_buffer_type())
- {
- buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
- }
- explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) :
- internal_stream_type(new internal_buffer_type())
- {
- buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
- open(file_name,mode);
- }
- void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out)
- {
- if(!buf_->open(file_name,mode | std::ios_base::out)) {
- this->setstate(std::ios_base::failbit);
- }
- else {
- this->clear();
- }
- }
- bool is_open()
- {
- return buf_->is_open();
- }
- bool is_open() const
- {
- return buf_->is_open();
- }
- void close()
- {
- if(!buf_->close())
- this->setstate(std::ios_base::failbit);
- else
- this->clear();
- }
-
- internal_buffer_type *rdbuf() const
- {
- return buf_.get();
- }
- ~basic_ofstream()
- {
- buf_->close();
- }
-
- private:
- std::auto_ptr<internal_buffer_type> buf_;
- };
-
- ///
- /// Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows
- ///
-
- template<typename CharType,typename Traits = std::char_traits<CharType> >
- class basic_fstream : public std::basic_iostream<CharType,Traits>
- {
- public:
- typedef basic_filebuf<CharType,Traits> internal_buffer_type;
- typedef std::basic_iostream<CharType,Traits> internal_stream_type;
-
- basic_fstream() :
- internal_stream_type(new internal_buffer_type())
- {
- buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
- }
- explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) :
- internal_stream_type(new internal_buffer_type())
- {
- buf_.reset(static_cast<internal_buffer_type *>(internal_stream_type::rdbuf()));
- open(file_name,mode);
- }
- void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out)
- {
- if(!buf_->open(file_name,mode)) {
- this->setstate(std::ios_base::failbit);
- }
- else {
- this->clear();
- }
- }
- bool is_open()
- {
- return buf_->is_open();
- }
- bool is_open() const
- {
- return buf_->is_open();
- }
- void close()
- {
- if(!buf_->close())
- this->setstate(std::ios_base::failbit);
- else
- this->clear();
- }
-
- internal_buffer_type *rdbuf() const
- {
- return buf_.get();
- }
- ~basic_fstream()
- {
- buf_->close();
- }
-
- private:
- std::auto_ptr<internal_buffer_type> buf_;
- };
-
-
- ///
- /// Same as std::filebuf but accepts UTF-8 strings under Windows
- ///
- typedef basic_filebuf<char> filebuf;
- ///
- /// Same as std::ifstream but accepts UTF-8 strings under Windows
- ///
- typedef basic_ifstream<char> ifstream;
- ///
- /// Same as std::ofstream but accepts UTF-8 strings under Windows
- ///
- typedef basic_ofstream<char> ofstream;
- ///
- /// Same as std::fstream but accepts UTF-8 strings under Windows
- ///
- typedef basic_fstream<char> fstream;
-
- #endif
- } // nowide
- } // booster
-
-
-
- #endif
|