diff options
Diffstat (limited to 'contrib/libc++/include/__std_stream')
-rw-r--r-- | contrib/libc++/include/__std_stream | 88 |
1 files changed, 58 insertions, 30 deletions
diff --git a/contrib/libc++/include/__std_stream b/contrib/libc++/include/__std_stream index 8ca413e..cff4331 100644 --- a/contrib/libc++/include/__std_stream +++ b/contrib/libc++/include/__std_stream @@ -55,6 +55,8 @@ private: const codecvt<char_type, char, state_type>* __cv_; state_type* __st_; int __encoding_; + int_type __last_consumed_; + bool __last_consumed_is_next_; bool __always_noconv_; __stdinbuf(const __stdinbuf&); @@ -66,7 +68,9 @@ private: template <class _CharT> __stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st) : __file_(__fp), - __st_(__st) + __st_(__st), + __last_consumed_(traits_type::eof()), + __last_consumed_is_next_(false) { imbue(this->getloc()); } @@ -100,6 +104,16 @@ template <class _CharT> typename __stdinbuf<_CharT>::int_type __stdinbuf<_CharT>::__getchar(bool __consume) { + if (__last_consumed_is_next_) + { + int_type __result = __last_consumed_; + if (__consume) + { + __last_consumed_ = traits_type::eof(); + __last_consumed_is_next_ = false; + } + return __result; + } char __extbuf[__limit]; int __nread = _VSTD::max(1, __encoding_); for (int __i = 0; __i < __nread; ++__i) @@ -154,6 +168,8 @@ __stdinbuf<_CharT>::__getchar(bool __consume) return traits_type::eof(); } } + else + __last_consumed_ = traits_type::to_int_type(__1buf); return traits_type::to_int_type(__1buf); } @@ -162,28 +178,41 @@ typename __stdinbuf<_CharT>::int_type __stdinbuf<_CharT>::pbackfail(int_type __c) { if (traits_type::eq_int_type(__c, traits_type::eof())) - return __c; - char __extbuf[__limit]; - char* __enxt; - const char_type __ci = traits_type::to_char_type(__c); - const char_type* __inxt; - switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, - __extbuf, __extbuf + sizeof(__extbuf), __enxt)) { - case _VSTD::codecvt_base::ok: - break; - case _VSTD::codecvt_base::noconv: - __extbuf[0] = static_cast<char>(__c); - __enxt = __extbuf + 1; - break; - case codecvt_base::partial: - case codecvt_base::error: - return traits_type::eof(); + if (!__last_consumed_is_next_) + { + __c = __last_consumed_; + __last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, + traits_type::eof()); + } + return __c; } - while (__enxt > __extbuf) - if (ungetc(*--__enxt, __file_) == EOF) + if (__last_consumed_is_next_) + { + char __extbuf[__limit]; + char* __enxt; + const char_type __ci = traits_type::to_char_type(__last_consumed_); + const char_type* __inxt; + switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, + __extbuf, __extbuf + sizeof(__extbuf), __enxt)) + { + case _VSTD::codecvt_base::ok: + break; + case _VSTD::codecvt_base::noconv: + __extbuf[0] = static_cast<char>(__last_consumed_); + __enxt = __extbuf + 1; + break; + case codecvt_base::partial: + case codecvt_base::error: return traits_type::eof(); - return traits_type::not_eof(__c); + } + while (__enxt > __extbuf) + if (ungetc(*--__enxt, __file_) == EOF) + return traits_type::eof(); + } + __last_consumed_ = __c; + __last_consumed_is_next_ = true; + return __c; } // __stdoutbuf @@ -234,30 +263,31 @@ __stdoutbuf<_CharT>::overflow(int_type __c) char_type __1buf; if (!traits_type::eq_int_type(__c, traits_type::eof())) { - this->setp(&__1buf, &__1buf+1); - *this->pptr() = traits_type::to_char_type(__c); - this->pbump(1); + __1buf = traits_type::to_char_type(__c); if (__always_noconv_) { - if (fwrite(this->pbase(), sizeof(char_type), 1, __file_) != 1) + if (fwrite(&__1buf, sizeof(char_type), 1, __file_) != 1) return traits_type::eof(); } else { char* __extbe = __extbuf; codecvt_base::result __r; + char_type* pbase = &__1buf; + char_type* pptr = pbase + 1; + char_type* epptr = pptr; do { const char_type* __e; - __r = __cv_->out(*__st_, this->pbase(), this->pptr(), __e, + __r = __cv_->out(*__st_, pbase, pptr, __e, __extbuf, __extbuf + sizeof(__extbuf), __extbe); - if (__e == this->pbase()) + if (__e == pbase) return traits_type::eof(); if (__r == codecvt_base::noconv) { - if (fwrite(this->pbase(), 1, 1, __file_) != 1) + if (fwrite(pbase, 1, 1, __file_) != 1) return traits_type::eof(); } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) @@ -267,15 +297,13 @@ __stdoutbuf<_CharT>::overflow(int_type __c) return traits_type::eof(); if (__r == codecvt_base::partial) { - this->setp((char_type*)__e, this->pptr()); - this->pbump(static_cast<int>(this->epptr() - this->pbase())); + pbase = (char_type*)__e; } } else return traits_type::eof(); } while (__r == codecvt_base::partial); } - this->setp(0, 0); } return traits_type::not_eof(__c); } |