cxx/include/fstream

1432 lines
43 KiB
Plaintext
Raw Normal View History

// -*- C++ -*-
//===------------------------- fstream ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_FSTREAM
#define _LIBCPP_FSTREAM
/*
fstream synopsis
template <class charT, class traits = char_traits<charT> >
class basic_filebuf
: public basic_streambuf<charT, traits>
{
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
// 27.9.1.2 Constructors/destructor:
basic_filebuf();
basic_filebuf(basic_filebuf&& rhs);
virtual ~basic_filebuf();
// 27.9.1.3 Assign/swap:
basic_filebuf& operator=(basic_filebuf&& rhs);
void swap(basic_filebuf& rhs);
// 27.9.1.4 Members:
bool is_open() const;
basic_filebuf* open(const char* s, ios_base::openmode mode);
basic_filebuf* open(const string& s, ios_base::openmode mode);
basic_filebuf* close();
protected:
// 27.9.1.5 Overridden virtual functions:
virtual streamsize showmanyc();
virtual int_type underflow();
virtual int_type uflow();
virtual int_type pbackfail(int_type c = traits_type::eof());
virtual int_type overflow (int_type c = traits_type::eof());
virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* s, streamsize n);
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which = ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type sp,
ios_base::openmode which = ios_base::in | ios_base::out);
virtual int sync();
virtual void imbue(const locale& loc);
};
template <class charT, class traits>
void
swap(basic_filebuf<charT, traits>& x, basic_filebuf<charT, traits>& y);
typedef basic_filebuf<char> filebuf;
typedef basic_filebuf<wchar_t> wfilebuf;
template <class charT, class traits = char_traits<charT> >
class basic_ifstream
: public basic_istream<charT,traits>
{
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_ifstream();
explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in);
explicit basic_ifstream(const string& s, ios_base::openmode mode = ios_base::in);
basic_ifstream(basic_ifstream&& rhs);
basic_ifstream& operator=(basic_ifstream&& rhs);
void swap(basic_ifstream& rhs);
basic_filebuf<char_type, traits_type>* rdbuf() const;
bool is_open() const;
void open(const char* s, ios_base::openmode mode = ios_base::in);
void open(const string& s, ios_base::openmode mode = ios_base::in);
void close();
};
template <class charT, class traits>
void
swap(basic_ifstream<charT, traits>& x, basic_ifstream<charT, traits>& y);
typedef basic_ifstream<char> ifstream;
typedef basic_ifstream<wchar_t> wifstream;
template <class charT, class traits = char_traits<charT> >
class basic_ofstream
: public basic_ostream<charT,traits>
{
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_ofstream();
explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out);
explicit basic_ofstream(const string& s, ios_base::openmode mode = ios_base::out);
basic_ofstream(basic_ofstream&& rhs);
basic_ofstream& operator=(basic_ofstream&& rhs);
void swap(basic_ofstream& rhs);
basic_filebuf<char_type, traits_type>* rdbuf() const;
bool is_open() const;
void open(const char* s, ios_base::openmode mode = ios_base::out);
void open(const string& s, ios_base::openmode mode = ios_base::out);
void close();
};
template <class charT, class traits>
void
swap(basic_ofstream<charT, traits>& x, basic_ofstream<charT, traits>& y);
typedef basic_ofstream<char> ofstream;
typedef basic_ofstream<wchar_t> wofstream;
template <class charT, class traits=char_traits<charT> >
class basic_fstream
: public basic_iostream<charT,traits>
{
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_fstream();
explicit basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out);
explicit basic_fstream(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);
basic_fstream(basic_fstream&& rhs);
basic_fstream& operator=(basic_fstream&& rhs);
void swap(basic_fstream& rhs);
basic_filebuf<char_type, traits_type>* rdbuf() const;
bool is_open() const;
void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out);
void open(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);
void close();
};
template <class charT, class traits>
void swap(basic_fstream<charT, traits>& x, basic_fstream<charT, traits>& y);
typedef basic_fstream<char> fstream;
typedef basic_fstream<wchar_t> wfstream;
} // std
*/
#include <__config>
#include <ostream>
#include <istream>
#include <__locale>
#include <cstdio>
#include <__undef_min_max>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _CharT, class _Traits>
class _LIBCPP_TYPE_VIS_ONLY basic_filebuf
: public basic_streambuf<_CharT, _Traits>
{
public:
typedef _CharT char_type;
typedef _Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
typedef typename traits_type::state_type state_type;
// 27.9.1.2 Constructors/destructor:
basic_filebuf();
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_filebuf(basic_filebuf&& __rhs);
#endif
virtual ~basic_filebuf();
// 27.9.1.3 Assign/swap:
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_filebuf& operator=(basic_filebuf&& __rhs);
#endif
void swap(basic_filebuf& __rhs);
// 27.9.1.4 Members:
bool is_open() const;
basic_filebuf* open(const char* __s, ios_base::openmode __mode);
basic_filebuf* open(const string& __s, ios_base::openmode __mode);
basic_filebuf* close();
protected:
// 27.9.1.5 Overridden virtual functions:
virtual int_type underflow();
virtual int_type pbackfail(int_type __c = traits_type::eof());
virtual int_type overflow (int_type __c = traits_type::eof());
virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s, streamsize __n);
virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
ios_base::openmode __wch = ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type __sp,
ios_base::openmode __wch = ios_base::in | ios_base::out);
virtual int sync();
virtual void imbue(const locale& __loc);
private:
char* __extbuf_;
const char* __extbufnext_;
const char* __extbufend_;
char __extbuf_min_[8];
size_t __ebs_;
char_type* __intbuf_;
size_t __ibs_;
FILE* __file_;
const codecvt<char_type, char, state_type>* __cv_;
state_type __st_;
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
state_type __st_last_;
ios_base::openmode __om_;
ios_base::openmode __cm_;
bool __owns_eb_;
bool __owns_ib_;
bool __always_noconv_;
bool __read_mode();
void __write_mode();
};
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>::basic_filebuf()
: __extbuf_(0),
__extbufnext_(0),
__extbufend_(0),
__ebs_(0),
__intbuf_(0),
__ibs_(0),
__file_(0),
__cv_(nullptr),
__st_(),
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
__st_last_(),
__om_(0),
__cm_(0),
__owns_eb_(false),
__owns_ib_(false),
__always_noconv_(false)
{
if (has_facet<codecvt<char_type, char, state_type> >(this->getloc()))
{
__cv_ = &use_facet<codecvt<char_type, char, state_type> >(this->getloc());
__always_noconv_ = __cv_->always_noconv();
}
setbuf(0, 4096);
}
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>::basic_filebuf(basic_filebuf&& __rhs)
: basic_streambuf<_CharT, _Traits>(__rhs)
{
if (__rhs.__extbuf_ == __rhs.__extbuf_min_)
{
__extbuf_ = __extbuf_min_;
__extbufnext_ = __extbuf_ + (__rhs.__extbufnext_ - __rhs.__extbuf_);
__extbufend_ = __extbuf_ + (__rhs.__extbufend_ - __rhs.__extbuf_);
}
else
{
__extbuf_ = __rhs.__extbuf_;
__extbufnext_ = __rhs.__extbufnext_;
__extbufend_ = __rhs.__extbufend_;
}
__ebs_ = __rhs.__ebs_;
__intbuf_ = __rhs.__intbuf_;
__ibs_ = __rhs.__ibs_;
__file_ = __rhs.__file_;
__cv_ = __rhs.__cv_;
__st_ = __rhs.__st_;
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
__st_last_ = __rhs.__st_last_;
__om_ = __rhs.__om_;
__cm_ = __rhs.__cm_;
__owns_eb_ = __rhs.__owns_eb_;
__owns_ib_ = __rhs.__owns_ib_;
__always_noconv_ = __rhs.__always_noconv_;
if (__rhs.pbase())
{
if (__rhs.pbase() == __rhs.__intbuf_)
this->setp(__intbuf_, __intbuf_ + (__rhs. epptr() - __rhs.pbase()));
else
this->setp((char_type*)__extbuf_,
(char_type*)__extbuf_ + (__rhs. epptr() - __rhs.pbase()));
this->pbump(__rhs. pptr() - __rhs.pbase());
}
else if (__rhs.eback())
{
if (__rhs.eback() == __rhs.__intbuf_)
this->setg(__intbuf_, __intbuf_ + (__rhs.gptr() - __rhs.eback()),
__intbuf_ + (__rhs.egptr() - __rhs.eback()));
else
this->setg((char_type*)__extbuf_,
(char_type*)__extbuf_ + (__rhs.gptr() - __rhs.eback()),
(char_type*)__extbuf_ + (__rhs.egptr() - __rhs.eback()));
}
__rhs.__extbuf_ = 0;
__rhs.__extbufnext_ = 0;
__rhs.__extbufend_ = 0;
__rhs.__ebs_ = 0;
__rhs.__intbuf_ = 0;
__rhs.__ibs_ = 0;
__rhs.__file_ = 0;
__rhs.__st_ = state_type();
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
__rhs.__st_last_ = state_type();
__rhs.__om_ = 0;
__rhs.__cm_ = 0;
__rhs.__owns_eb_ = false;
__rhs.__owns_ib_ = false;
__rhs.setg(0, 0, 0);
__rhs.setp(0, 0);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_filebuf<_CharT, _Traits>&
basic_filebuf<_CharT, _Traits>::operator=(basic_filebuf&& __rhs)
{
close();
swap(__rhs);
return *this;
}
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>::~basic_filebuf()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
close();
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
}
#endif // _LIBCPP_NO_EXCEPTIONS
if (__owns_eb_)
delete [] __extbuf_;
if (__owns_ib_)
delete [] __intbuf_;
}
template <class _CharT, class _Traits>
void
basic_filebuf<_CharT, _Traits>::swap(basic_filebuf& __rhs)
{
basic_streambuf<char_type, traits_type>::swap(__rhs);
if (__extbuf_ != __extbuf_min_ && __rhs.__extbuf_ != __rhs.__extbuf_min_)
{
_VSTD::swap(__extbuf_, __rhs.__extbuf_);
_VSTD::swap(__extbufnext_, __rhs.__extbufnext_);
_VSTD::swap(__extbufend_, __rhs.__extbufend_);
}
else
{
ptrdiff_t __ln = __extbufnext_ - __extbuf_;
ptrdiff_t __le = __extbufend_ - __extbuf_;
ptrdiff_t __rn = __rhs.__extbufnext_ - __rhs.__extbuf_;
ptrdiff_t __re = __rhs.__extbufend_ - __rhs.__extbuf_;
if (__extbuf_ == __extbuf_min_ && __rhs.__extbuf_ != __rhs.__extbuf_min_)
{
__extbuf_ = __rhs.__extbuf_;
__rhs.__extbuf_ = __rhs.__extbuf_min_;
}
else if (__extbuf_ != __extbuf_min_ && __rhs.__extbuf_ == __rhs.__extbuf_min_)
{
__rhs.__extbuf_ = __extbuf_;
__extbuf_ = __extbuf_min_;
}
__extbufnext_ = __extbuf_ + __rn;
__extbufend_ = __extbuf_ + __re;
__rhs.__extbufnext_ = __rhs.__extbuf_ + __ln;
__rhs.__extbufend_ = __rhs.__extbuf_ + __le;
}
_VSTD::swap(__ebs_, __rhs.__ebs_);
_VSTD::swap(__intbuf_, __rhs.__intbuf_);
_VSTD::swap(__ibs_, __rhs.__ibs_);
_VSTD::swap(__file_, __rhs.__file_);
_VSTD::swap(__cv_, __rhs.__cv_);
_VSTD::swap(__st_, __rhs.__st_);
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
_VSTD::swap(__st_last_, __rhs.__st_last_);
_VSTD::swap(__om_, __rhs.__om_);
_VSTD::swap(__cm_, __rhs.__cm_);
_VSTD::swap(__owns_eb_, __rhs.__owns_eb_);
_VSTD::swap(__owns_ib_, __rhs.__owns_ib_);
_VSTD::swap(__always_noconv_, __rhs.__always_noconv_);
if (this->eback() == (char_type*)__rhs.__extbuf_min_)
{
ptrdiff_t __n = this->gptr() - this->eback();
ptrdiff_t __e = this->egptr() - this->eback();
this->setg((char_type*)__extbuf_min_,
(char_type*)__extbuf_min_ + __n,
(char_type*)__extbuf_min_ + __e);
}
else if (this->pbase() == (char_type*)__rhs.__extbuf_min_)
{
ptrdiff_t __n = this->pptr() - this->pbase();
ptrdiff_t __e = this->epptr() - this->pbase();
this->setp((char_type*)__extbuf_min_,
(char_type*)__extbuf_min_ + __e);
this->pbump(__n);
}
if (__rhs.eback() == (char_type*)__extbuf_min_)
{
ptrdiff_t __n = __rhs.gptr() - __rhs.eback();
ptrdiff_t __e = __rhs.egptr() - __rhs.eback();
__rhs.setg((char_type*)__rhs.__extbuf_min_,
(char_type*)__rhs.__extbuf_min_ + __n,
(char_type*)__rhs.__extbuf_min_ + __e);
}
else if (__rhs.pbase() == (char_type*)__extbuf_min_)
{
ptrdiff_t __n = __rhs.pptr() - __rhs.pbase();
ptrdiff_t __e = __rhs.epptr() - __rhs.pbase();
__rhs.setp((char_type*)__rhs.__extbuf_min_,
(char_type*)__rhs.__extbuf_min_ + __e);
__rhs.pbump(__n);
}
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
swap(basic_filebuf<_CharT, _Traits>& __x, basic_filebuf<_CharT, _Traits>& __y)
{
__x.swap(__y);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
bool
basic_filebuf<_CharT, _Traits>::is_open() const
{
return __file_ != 0;
}
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
{
basic_filebuf<_CharT, _Traits>* __rt = 0;
if (__file_ == 0)
{
__rt = this;
const char* __mdstr;
switch (__mode & ~ios_base::ate)
{
case ios_base::out:
case ios_base::out | ios_base::trunc:
__mdstr = "w";
break;
case ios_base::out | ios_base::app:
case ios_base::app:
__mdstr = "a";
break;
case ios_base::in:
__mdstr = "r";
break;
case ios_base::in | ios_base::out:
__mdstr = "r+";
break;
case ios_base::in | ios_base::out | ios_base::trunc:
__mdstr = "w+";
break;
case ios_base::in | ios_base::out | ios_base::app:
case ios_base::in | ios_base::app:
__mdstr = "a+";
break;
case ios_base::out | ios_base::binary:
case ios_base::out | ios_base::trunc | ios_base::binary:
__mdstr = "wb";
break;
case ios_base::out | ios_base::app | ios_base::binary:
case ios_base::app | ios_base::binary:
__mdstr = "ab";
break;
case ios_base::in | ios_base::binary:
__mdstr = "rb";
break;
case ios_base::in | ios_base::out | ios_base::binary:
__mdstr = "r+b";
break;
case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
__mdstr = "w+b";
break;
case ios_base::in | ios_base::out | ios_base::app | ios_base::binary:
case ios_base::in | ios_base::app | ios_base::binary:
__mdstr = "a+b";
break;
default:
__rt = 0;
break;
}
if (__rt)
{
__file_ = fopen(__s, __mdstr);
if (__file_)
{
__om_ = __mode;
if (__mode & ios_base::ate)
{
if (fseek(__file_, 0, SEEK_END))
{
fclose(__file_);
__file_ = 0;
__rt = 0;
}
}
}
else
__rt = 0;
}
}
return __rt;
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_filebuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode)
{
return open(__s.c_str(), __mode);
}
template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::close()
{
basic_filebuf<_CharT, _Traits>* __rt = 0;
if (__file_)
{
__rt = this;
unique_ptr<FILE, int(*)(FILE*)> __h(__file_, fclose);
if (sync())
__rt = 0;
if (fclose(__h.release()) == 0)
__file_ = 0;
else
__rt = 0;
}
return __rt;
}
template <class _CharT, class _Traits>
typename basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::underflow()
{
if (__file_ == 0)
return traits_type::eof();
bool __initial = __read_mode();
char_type __1buf;
if (this->gptr() == 0)
this->setg(&__1buf, &__1buf+1, &__1buf+1);
const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
int_type __c = traits_type::eof();
if (this->gptr() == this->egptr())
{
memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
if (__always_noconv_)
{
size_t __nmemb = static_cast<size_t>(this->egptr() - this->eback() - __unget_sz);
__nmemb = fread(this->eback() + __unget_sz, 1, __nmemb, __file_);
if (__nmemb != 0)
{
this->setg(this->eback(),
this->eback() + __unget_sz,
this->eback() + __unget_sz + __nmemb);
__c = traits_type::to_int_type(*this->gptr());
}
}
else
{
memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
__extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
__extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
size_t __nmemb = _VSTD::min(static_cast<size_t>(__ibs_ - __unget_sz),
static_cast<size_t>(__extbufend_ - __extbufnext_));
codecvt_base::result __r;
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
__st_last_ = __st_;
size_t __nr = fread((void*)__extbufnext_, 1, __nmemb, __file_);
if (__nr != 0)
{
#ifndef _LIBCPP_NO_EXCEPTIONS
if (!__cv_)
throw bad_cast();
#endif
__extbufend_ = __extbufnext_ + __nr;
char_type* __inext;
__r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
this->eback() + __unget_sz,
this->eback() + __ibs_, __inext);
if (__r == codecvt_base::noconv)
{
this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
__c = traits_type::to_int_type(*this->gptr());
}
else if (__inext != this->eback() + __unget_sz)
{
this->setg(this->eback(), this->eback() + __unget_sz, __inext);
__c = traits_type::to_int_type(*this->gptr());
}
}
}
}
else
__c = traits_type::to_int_type(*this->gptr());
if (this->eback() == &__1buf)
this->setg(0, 0, 0);
return __c;
}
template <class _CharT, class _Traits>
typename basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c)
{
if (__file_ && this->eback() < this->gptr())
{
if (traits_type::eq_int_type(__c, traits_type::eof()))
{
this->gbump(-1);
return traits_type::not_eof(__c);
}
if ((__om_ & ios_base::out) ||
traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
{
this->gbump(-1);
*this->gptr() = traits_type::to_char_type(__c);
return __c;
}
}
return traits_type::eof();
}
template <class _CharT, class _Traits>
typename basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
{
if (__file_ == 0)
return traits_type::eof();
__write_mode();
char_type __1buf;
char_type* __pb_save = this->pbase();
char_type* __epb_save = this->epptr();
if (!traits_type::eq_int_type(__c, traits_type::eof()))
{
if (this->pptr() == 0)
this->setp(&__1buf, &__1buf+1);
*this->pptr() = traits_type::to_char_type(__c);
this->pbump(1);
}
if (this->pptr() != this->pbase())
{
if (__always_noconv_)
{
size_t __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
if (fwrite(this->pbase(), sizeof(char_type), __nmemb, __file_) != __nmemb)
return traits_type::eof();
}
else
{
char* __extbe = __extbuf_;
codecvt_base::result __r;
do
{
#ifndef _LIBCPP_NO_EXCEPTIONS
if (!__cv_)
throw bad_cast();
#endif
const char_type* __e;
__r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
__extbuf_, __extbuf_ + __ebs_, __extbe);
if (__e == this->pbase())
return traits_type::eof();
if (__r == codecvt_base::noconv)
{
size_t __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
if (fwrite(this->pbase(), 1, __nmemb, __file_) != __nmemb)
return traits_type::eof();
}
else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
{
size_t __nmemb = static_cast<size_t>(__extbe - __extbuf_);
if (fwrite(__extbuf_, 1, __nmemb, __file_) != __nmemb)
return traits_type::eof();
if (__r == codecvt_base::partial)
{
this->setp((char_type*)__e, this->pptr());
this->pbump(this->epptr() - this->pbase());
}
}
else
return traits_type::eof();
} while (__r == codecvt_base::partial);
}
this->setp(__pb_save, __epb_save);
}
return traits_type::not_eof(__c);
}
template <class _CharT, class _Traits>
basic_streambuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::setbuf(char_type* __s, streamsize __n)
{
this->setg(0, 0, 0);
this->setp(0, 0);
if (__owns_eb_)
delete [] __extbuf_;
if (__owns_ib_)
delete [] __intbuf_;
__ebs_ = __n;
if (__ebs_ > sizeof(__extbuf_min_))
{
if (__always_noconv_ && __s)
{
__extbuf_ = (char*)__s;
__owns_eb_ = false;
}
else
{
__extbuf_ = new char[__ebs_];
__owns_eb_ = true;
}
}
else
{
__extbuf_ = __extbuf_min_;
__ebs_ = sizeof(__extbuf_min_);
__owns_eb_ = false;
}
if (!__always_noconv_)
{
__ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
if (__s && __ibs_ >= sizeof(__extbuf_min_))
{
__intbuf_ = __s;
__owns_ib_ = false;
}
else
{
__intbuf_ = new char_type[__ibs_];
__owns_ib_ = true;
}
}
else
{
__ibs_ = 0;
__intbuf_ = 0;
__owns_ib_ = false;
}
return this;
}
template <class _CharT, class _Traits>
typename basic_filebuf<_CharT, _Traits>::pos_type
basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __way,
ios_base::openmode)
{
#ifndef _LIBCPP_NO_EXCEPTIONS
if (!__cv_)
throw bad_cast();
#endif
int __width = __cv_->encoding();
if (__file_ == 0 || (__width <= 0 && __off != 0) || sync())
return pos_type(off_type(-1));
// __width > 0 || __off == 0
int __whence;
switch (__way)
{
case ios_base::beg:
__whence = SEEK_SET;
break;
case ios_base::cur:
__whence = SEEK_CUR;
break;
case ios_base::end:
__whence = SEEK_END;
break;
default:
return pos_type(off_type(-1));
}
#if _WIN32
if (fseek(__file_, __width > 0 ? __width * __off : 0, __whence))
return pos_type(off_type(-1));
pos_type __r = ftell(__file_);
#else
if (fseeko(__file_, __width > 0 ? __width * __off : 0, __whence))
return pos_type(off_type(-1));
pos_type __r = ftello(__file_);
#endif
__r.state(__st_);
return __r;
}
template <class _CharT, class _Traits>
typename basic_filebuf<_CharT, _Traits>::pos_type
basic_filebuf<_CharT, _Traits>::seekpos(pos_type __sp, ios_base::openmode)
{
if (__file_ == 0 || sync())
return pos_type(off_type(-1));
#if _WIN32
if (fseek(__file_, __sp, SEEK_SET))
return pos_type(off_type(-1));
#else
if (fseeko(__file_, __sp, SEEK_SET))
return pos_type(off_type(-1));
#endif
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
__st_ = __sp.state();
return __sp;
}
template <class _CharT, class _Traits>
int
basic_filebuf<_CharT, _Traits>::sync()
{
if (__file_ == 0)
return 0;
#ifndef _LIBCPP_NO_EXCEPTIONS
if (!__cv_)
throw bad_cast();
#endif
if (__cm_ & ios_base::out)
{
if (this->pptr() != this->pbase())
if (overflow() == traits_type::eof())
return -1;
codecvt_base::result __r;
do
{
char* __extbe;
__r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
size_t __nmemb = static_cast<size_t>(__extbe - __extbuf_);
if (fwrite(__extbuf_, 1, __nmemb, __file_) != __nmemb)
return -1;
} while (__r == codecvt_base::partial);
if (__r == codecvt_base::error)
return -1;
if (fflush(__file_))
return -1;
}
else if (__cm_ & ios_base::in)
{
off_type __c;
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
state_type __state = __st_last_;
bool __update_st = false;
if (__always_noconv_)
__c = this->egptr() - this->gptr();
else
{
int __width = __cv_->encoding();
__c = __extbufend_ - __extbufnext_;
if (__width > 0)
__c += __width * (this->egptr() - this->gptr());
else
{
if (this->gptr() != this->egptr())
{
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
const int __off = __cv_->length(__state, __extbuf_,
__extbufnext_,
this->gptr() - this->eback());
__c += __extbufnext_ - __extbuf_ - __off;
__update_st = true;
}
}
}
#if _WIN32
if (fseek(__file_, -__c, SEEK_CUR))
return -1;
#else
if (fseeko(__file_, -__c, SEEK_CUR))
return -1;
#endif
Hyeon-Bin Jeong: 1. sync() should reset it’s external buffer pointers. Remaining characters should be discarded once sync() called. If don’t, garbage characters can be inserted to the front of external buffer in underflow(). Because underflow() copies remaining characters in external buffer to it’s front. This results wrong characters insertion when seekpos() or seekoff() is called. this line should be inserted in sync() just before return: __extbufnext_ = __extbufend_ = __extbuf_; 2. sync() should use length() rather than out() to calculate offset. Reversing iterators and calling out() to calculate offset from behind is working fine in stateless character encoding. However, in stateful encoding, escape sequences could differ in length. As a result, out() could return wrong length. For example, if we have internal buffer converted from this external sequence: (capital letters mean escape sequence) … a a a a B b b b b out() produces this sequence. b b b b A a a a a Because out() inserts escape sequence A rather than B, result sequence doesn't match to external sequence. A and B could have different lengths, result offset could be wrong value too. length() method in codecvt is right for calculating offset, but it counts offset from the beginning of buffer. So it requires another state member variable to hold state before conversion. Fixes http://llvm.org/bugs/show_bug.cgi?id=13667 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@162601 91177308-0d34-0410-b5e6-96231b3b80d8
2012-08-24 23:20:56 +02:00
if (__update_st)
__st_ = __state;
__extbufnext_ = __extbufend_ = __extbuf_;
this->setg(0, 0, 0);
__cm_ = 0;
}
return 0;
}
template <class _CharT, class _Traits>
void
basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc)
{
sync();
__cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc);
bool __old_anc = __always_noconv_;
__always_noconv_ = __cv_->always_noconv();
if (__old_anc != __always_noconv_)
{
this->setg(0, 0, 0);
this->setp(0, 0);
// invariant, char_type is char, else we couldn't get here
if (__always_noconv_) // need to dump __intbuf_
{
if (__owns_eb_)
delete [] __extbuf_;
__owns_eb_ = __owns_ib_;
__ebs_ = __ibs_;
__extbuf_ = (char*)__intbuf_;
__ibs_ = 0;
__intbuf_ = 0;
__owns_ib_ = false;
}
else // need to obtain an __intbuf_.
{ // If __extbuf_ is user-supplied, use it, else new __intbuf_
if (!__owns_eb_ && __extbuf_ != __extbuf_min_)
{
__ibs_ = __ebs_;
__intbuf_ = (char_type*)__extbuf_;
__owns_ib_ = false;
__extbuf_ = new char[__ebs_];
__owns_eb_ = true;
}
else
{
__ibs_ = __ebs_;
__intbuf_ = new char_type[__ibs_];
__owns_ib_ = true;
}
}
}
}
template <class _CharT, class _Traits>
bool
basic_filebuf<_CharT, _Traits>::__read_mode()
{
if (!(__cm_ & ios_base::in))
{
this->setp(0, 0);
if (__always_noconv_)
this->setg((char_type*)__extbuf_,
(char_type*)__extbuf_ + __ebs_,
(char_type*)__extbuf_ + __ebs_);
else
this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
__cm_ = ios_base::in;
return true;
}
return false;
}
template <class _CharT, class _Traits>
void
basic_filebuf<_CharT, _Traits>::__write_mode()
{
if (!(__cm_ & ios_base::out))
{
this->setg(0, 0, 0);
if (__ebs_ > sizeof(__extbuf_min_))
{
if (__always_noconv_)
this->setp((char_type*)__extbuf_,
(char_type*)__extbuf_ + (__ebs_ - 1));
else
this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
}
else
this->setp(0, 0);
__cm_ = ios_base::out;
}
}
// basic_ifstream
template <class _CharT, class _Traits>
class _LIBCPP_TYPE_VIS_ONLY basic_ifstream
: public basic_istream<_CharT, _Traits>
{
public:
typedef _CharT char_type;
typedef _Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_ifstream();
explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in);
explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in);
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_ifstream(basic_ifstream&& __rhs);
#endif
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_ifstream& operator=(basic_ifstream&& __rhs);
#endif
void swap(basic_ifstream& __rhs);
basic_filebuf<char_type, traits_type>* rdbuf() const;
bool is_open() const;
void open(const char* __s, ios_base::openmode __mode = ios_base::in);
void open(const string& __s, ios_base::openmode __mode = ios_base::in);
void close();
private:
basic_filebuf<char_type, traits_type> __sb_;
};
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ifstream<_CharT, _Traits>::basic_ifstream()
: basic_istream<char_type, traits_type>(&__sb_)
{
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ifstream<_CharT, _Traits>::basic_ifstream(const char* __s, ios_base::openmode __mode)
: basic_istream<char_type, traits_type>(&__sb_)
{
if (__sb_.open(__s, __mode | ios_base::in) == 0)
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_base::openmode __mode)
: basic_istream<char_type, traits_type>(&__sb_)
{
if (__sb_.open(__s, __mode | ios_base::in) == 0)
this->setstate(ios_base::failbit);
}
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ifstream<_CharT, _Traits>::basic_ifstream(basic_ifstream&& __rhs)
: basic_istream<char_type, traits_type>(_VSTD::move(__rhs)),
__sb_(_VSTD::move(__rhs.__sb_))
{
this->set_rdbuf(&__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ifstream<_CharT, _Traits>&
basic_ifstream<_CharT, _Traits>::operator=(basic_ifstream&& __rhs)
{
basic_istream<char_type, traits_type>::operator=(_VSTD::move(__rhs));
__sb_ = _VSTD::move(__rhs.__sb_);
return *this;
}
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
basic_ifstream<_CharT, _Traits>::swap(basic_ifstream& __rhs)
{
basic_istream<char_type, traits_type>::swap(__rhs);
__sb_.swap(__rhs.__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
swap(basic_ifstream<_CharT, _Traits>& __x, basic_ifstream<_CharT, _Traits>& __y)
{
__x.swap(__y);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_filebuf<_CharT, _Traits>*
basic_ifstream<_CharT, _Traits>::rdbuf() const
{
return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
bool
basic_ifstream<_CharT, _Traits>::is_open() const
{
return __sb_.is_open();
}
template <class _CharT, class _Traits>
void
basic_ifstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
{
if (__sb_.open(__s, __mode | ios_base::in))
this->clear();
else
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
void
basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode)
{
if (__sb_.open(__s, __mode | ios_base::in))
this->clear();
else
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
basic_ifstream<_CharT, _Traits>::close()
{
if (__sb_.close() == 0)
this->setstate(ios_base::failbit);
}
// basic_ofstream
template <class _CharT, class _Traits>
class _LIBCPP_TYPE_VIS_ONLY basic_ofstream
: public basic_ostream<_CharT, _Traits>
{
public:
typedef _CharT char_type;
typedef _Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_ofstream();
explicit basic_ofstream(const char* __s, ios_base::openmode __mode = ios_base::out);
explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out);
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_ofstream(basic_ofstream&& __rhs);
#endif
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_ofstream& operator=(basic_ofstream&& __rhs);
#endif
void swap(basic_ofstream& __rhs);
basic_filebuf<char_type, traits_type>* rdbuf() const;
bool is_open() const;
void open(const char* __s, ios_base::openmode __mode = ios_base::out);
void open(const string& __s, ios_base::openmode __mode = ios_base::out);
void close();
private:
basic_filebuf<char_type, traits_type> __sb_;
};
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ofstream<_CharT, _Traits>::basic_ofstream()
: basic_ostream<char_type, traits_type>(&__sb_)
{
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ofstream<_CharT, _Traits>::basic_ofstream(const char* __s, ios_base::openmode __mode)
: basic_ostream<char_type, traits_type>(&__sb_)
{
if (__sb_.open(__s, __mode | ios_base::out) == 0)
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_base::openmode __mode)
: basic_ostream<char_type, traits_type>(&__sb_)
{
if (__sb_.open(__s, __mode | ios_base::out) == 0)
this->setstate(ios_base::failbit);
}
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ofstream<_CharT, _Traits>::basic_ofstream(basic_ofstream&& __rhs)
: basic_ostream<char_type, traits_type>(_VSTD::move(__rhs)),
__sb_(_VSTD::move(__rhs.__sb_))
{
this->set_rdbuf(&__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_ofstream<_CharT, _Traits>&
basic_ofstream<_CharT, _Traits>::operator=(basic_ofstream&& __rhs)
{
basic_ostream<char_type, traits_type>::operator=(_VSTD::move(__rhs));
__sb_ = _VSTD::move(__rhs.__sb_);
return *this;
}
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
basic_ofstream<_CharT, _Traits>::swap(basic_ofstream& __rhs)
{
basic_ostream<char_type, traits_type>::swap(__rhs);
__sb_.swap(__rhs.__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
swap(basic_ofstream<_CharT, _Traits>& __x, basic_ofstream<_CharT, _Traits>& __y)
{
__x.swap(__y);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_filebuf<_CharT, _Traits>*
basic_ofstream<_CharT, _Traits>::rdbuf() const
{
return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
bool
basic_ofstream<_CharT, _Traits>::is_open() const
{
return __sb_.is_open();
}
template <class _CharT, class _Traits>
void
basic_ofstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
{
if (__sb_.open(__s, __mode | ios_base::out))
this->clear();
else
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
void
basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode)
{
if (__sb_.open(__s, __mode | ios_base::out))
this->clear();
else
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
basic_ofstream<_CharT, _Traits>::close()
{
if (__sb_.close() == 0)
this->setstate(ios_base::failbit);
}
// basic_fstream
template <class _CharT, class _Traits>
class _LIBCPP_TYPE_VIS_ONLY basic_fstream
: public basic_iostream<_CharT, _Traits>
{
public:
typedef _CharT char_type;
typedef _Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
basic_fstream();
explicit basic_fstream(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_fstream(basic_fstream&& __rhs);
#endif
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
basic_fstream& operator=(basic_fstream&& __rhs);
#endif
void swap(basic_fstream& __rhs);
basic_filebuf<char_type, traits_type>* rdbuf() const;
bool is_open() const;
void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
void close();
private:
basic_filebuf<char_type, traits_type> __sb_;
};
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_fstream<_CharT, _Traits>::basic_fstream()
: basic_iostream<char_type, traits_type>(&__sb_)
{
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_fstream<_CharT, _Traits>::basic_fstream(const char* __s, ios_base::openmode __mode)
: basic_iostream<char_type, traits_type>(&__sb_)
{
if (__sb_.open(__s, __mode) == 0)
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_fstream<_CharT, _Traits>::basic_fstream(const string& __s, ios_base::openmode __mode)
: basic_iostream<char_type, traits_type>(&__sb_)
{
if (__sb_.open(__s, __mode) == 0)
this->setstate(ios_base::failbit);
}
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_fstream<_CharT, _Traits>::basic_fstream(basic_fstream&& __rhs)
: basic_iostream<char_type, traits_type>(_VSTD::move(__rhs)),
__sb_(_VSTD::move(__rhs.__sb_))
{
this->set_rdbuf(&__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_fstream<_CharT, _Traits>&
basic_fstream<_CharT, _Traits>::operator=(basic_fstream&& __rhs)
{
basic_iostream<char_type, traits_type>::operator=(_VSTD::move(__rhs));
__sb_ = _VSTD::move(__rhs.__sb_);
return *this;
}
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
basic_fstream<_CharT, _Traits>::swap(basic_fstream& __rhs)
{
basic_iostream<char_type, traits_type>::swap(__rhs);
__sb_.swap(__rhs.__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
swap(basic_fstream<_CharT, _Traits>& __x, basic_fstream<_CharT, _Traits>& __y)
{
__x.swap(__y);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
basic_filebuf<_CharT, _Traits>*
basic_fstream<_CharT, _Traits>::rdbuf() const
{
return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
bool
basic_fstream<_CharT, _Traits>::is_open() const
{
return __sb_.is_open();
}
template <class _CharT, class _Traits>
void
basic_fstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode)
{
if (__sb_.open(__s, __mode))
this->clear();
else
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
void
basic_fstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode)
{
if (__sb_.open(__s, __mode))
this->clear();
else
this->setstate(ios_base::failbit);
}
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
void
basic_fstream<_CharT, _Traits>::close()
{
if (__sb_.close() == 0)
this->setstate(ios_base::failbit);
}
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_FSTREAM