aboutsummaryrefslogtreecommitdiff
path: root/system/include/libcxx/fstream
diff options
context:
space:
mode:
Diffstat (limited to 'system/include/libcxx/fstream')
-rw-r--r--system/include/libcxx/fstream75
1 files changed, 48 insertions, 27 deletions
diff --git a/system/include/libcxx/fstream b/system/include/libcxx/fstream
index 7034aab1..1b8e7a0a 100644
--- a/system/include/libcxx/fstream
+++ b/system/include/libcxx/fstream
@@ -171,7 +171,11 @@ typedef basic_fstream<wchar_t> wfstream;
#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
@@ -230,6 +234,7 @@ private:
FILE* __file_;
const codecvt<char_type, char, state_type>* __cv_;
state_type __st_;
+ state_type __st_last_;
ios_base::openmode __om_;
ios_base::openmode __cm_;
bool __owns_eb_;
@@ -249,14 +254,20 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf()
__intbuf_(0),
__ibs_(0),
__file_(0),
- __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())),
+ __cv_(nullptr),
__st_(),
+ __st_last_(),
__om_(0),
__cm_(0),
__owns_eb_(false),
__owns_ib_(false),
- __always_noconv_(__cv_->always_noconv())
+ __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);
}
@@ -284,6 +295,7 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf(basic_filebuf&& __rhs)
__file_ = __rhs.__file_;
__cv_ = __rhs.__cv_;
__st_ = __rhs.__st_;
+ __st_last_ = __rhs.__st_last_;
__om_ = __rhs.__om_;
__cm_ = __rhs.__cm_;
__owns_eb_ = __rhs.__owns_eb_;
@@ -316,6 +328,7 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf(basic_filebuf&& __rhs)
__rhs.__ibs_ = 0;
__rhs.__file_ = 0;
__rhs.__st_ = state_type();
+ __rhs.__st_last_ = state_type();
__rhs.__om_ = 0;
__rhs.__cm_ = 0;
__rhs.__owns_eb_ = false;
@@ -331,6 +344,7 @@ basic_filebuf<_CharT, _Traits>::operator=(basic_filebuf&& __rhs)
{
close();
swap(__rhs);
+ return *this;
}
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
@@ -393,6 +407,7 @@ basic_filebuf<_CharT, _Traits>::swap(basic_filebuf& __rhs)
_VSTD::swap(__file_, __rhs.__file_);
_VSTD::swap(__cv_, __rhs.__cv_);
_VSTD::swap(__st_, __rhs.__st_);
+ _VSTD::swap(__st_last_, __rhs.__st_last_);
_VSTD::swap(__om_, __rhs.__om_);
_VSTD::swap(__cm_, __rhs.__cm_);
_VSTD::swap(__owns_eb_, __rhs.__owns_eb_);
@@ -545,7 +560,7 @@ basic_filebuf<_CharT, _Traits>::close()
{
__rt = this;
unique_ptr<FILE, int(*)(FILE*)> __h(__file_, fclose);
- if ((__cm_ & ios_base::out) && sync())
+ if (sync())
__rt = 0;
if (fclose(__h.release()) == 0)
__file_ = 0;
@@ -587,18 +602,22 @@ basic_filebuf<_CharT, _Traits>::underflow()
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>(this->egptr() - this->eback() - __unget_sz),
+ size_t __nmemb = _VSTD::min(static_cast<size_t>(__ibs_ - __unget_sz),
static_cast<size_t>(__extbufend_ - __extbufnext_));
codecvt_base::result __r;
- state_type __svs = __st_;
+ __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->egptr(), __inext);
+ this->eback() + __ibs_, __inext);
if (__r == codecvt_base::noconv)
{
this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
@@ -672,6 +691,10 @@ basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
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);
@@ -761,6 +784,10 @@ 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));
@@ -795,6 +822,7 @@ basic_filebuf<_CharT, _Traits>::seekpos(pos_type __sp, ios_base::openmode)
return pos_type(off_type(-1));
if (fseeko(__file_, __sp, SEEK_SET))
return pos_type(off_type(-1));
+ __st_ = __sp.state();
return __sp;
}
@@ -804,6 +832,10 @@ 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())
@@ -826,6 +858,8 @@ basic_filebuf<_CharT, _Traits>::sync()
else if (__cm_ & ios_base::in)
{
off_type __c;
+ state_type __state = __st_last_;
+ bool __update_st = false;
if (__always_noconv_)
__c = this->egptr() - this->gptr();
else
@@ -838,32 +872,19 @@ basic_filebuf<_CharT, _Traits>::sync()
{
if (this->gptr() != this->egptr())
{
- reverse(this->gptr(), this->egptr());
- codecvt_base::result __r;
- const char_type* __e = this->gptr();
- char* __extbe;
- do
- {
- __r = __cv_->out(__st_, __e, this->egptr(), __e,
- __extbuf_, __extbuf_ + __ebs_, __extbe);
- switch (__r)
- {
- case codecvt_base::noconv:
- __c += this->egptr() - this->gptr();
- break;
- case codecvt_base::ok:
- case codecvt_base::partial:
- __c += __extbe - __extbuf_;
- break;
- default:
- return -1;
- }
- } while (__r == codecvt_base::partial);
+ const int __off = __cv_->length(__state, __extbuf_,
+ __extbufnext_,
+ this->gptr() - this->eback());
+ __c += __extbufnext_ - __extbuf_ - __off;
+ __update_st = true;
}
}
}
if (fseeko(__file_, -__c, SEEK_CUR))
return -1;
+ if (__update_st)
+ __st_ = __state;
+ __extbufnext_ = __extbufend_ = __extbuf_;
this->setg(0, 0, 0);
__cm_ = 0;
}