fstream.h
#ifndef BOOSTER_NOWIDE_FSTREAM_H
#define BOOSTER_NOWIDE_FSTREAM_H
#include <booster/config.h>
#include <booster/nowide/convert.h>
#include <fstream>
#include <memory>
#if defined BOOSTER_WIN_NATIVE || defined BOOSTER_WORKAROUND_BROKEN_GCC_ON_DARWIN
#include <booster/streambuf.h>
#include <booster/nowide/cstdio.h>
#endif
namespace booster {
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
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
template<typename CharType,typename Traits = std::char_traits<CharType> >
class basic_filebuf;
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();
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;
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
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_;
};
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_;
};
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_;
};
typedef basic_filebuf<char> filebuf;
typedef basic_ifstream<char> ifstream;
typedef basic_ofstream<char> ofstream;
typedef basic_fstream<char> fstream;
#endif
} // nowide
} // booster
#endif
booster::nowide::basic_ofstream
Definition: fstream.h:274
booster::streambuf
this is an implementation of generic streambuffer
Definition: streambuf.h:70
booster::io_device
This class is a base class of generic I/O device that can be used in very simple manner with booster:...
Definition: streambuf.h:19
booster::nowide::convert
BOOSTER_API std::string convert(wchar_t const *s)
booster::nowide::basic_fstream
Definition: fstream.h:334
booster::io_device::pos_type
pos_type
Definition: streambuf.h:24
booster::nowide::filebuf
basic_filebuf< char > filebuf
Definition: fstream.h:393
booster::nowide::ofstream
basic_ofstream< char > ofstream
Definition: fstream.h:401
booster::nowide::basic_filebuf
Definition: fstream.h:108
booster::nowide::basic_filebuf< char >
Definition: fstream.h:115
booster::nowide::basic_ifstream
Definition: fstream.h:214
booster::nowide::ifstream
basic_ifstream< char > ifstream
Definition: fstream.h:397
booster::nowide::fstream
basic_fstream< char > fstream
Definition: fstream.h:405
booster::nowide::bad_utf
This exception is thrown if invalid UTF-8 or UTF-16 is given as input.
Definition: convert.h:14