diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-09-24 19:06:33 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-09-24 19:06:33 -0700 |
commit | 1ea039eea38dad37c5b0c836cf98829bad6013ce (patch) | |
tree | 6d851de99c00b4aa1c45624df570b5cb7f89fed5 /system/include/libcxx/__std_stream | |
parent | dd0230c9cf09a7b19712a4acefe0ae27ea40ea85 (diff) |
include libcxx
Diffstat (limited to 'system/include/libcxx/__std_stream')
-rw-r--r-- | system/include/libcxx/__std_stream | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/system/include/libcxx/__std_stream b/system/include/libcxx/__std_stream new file mode 100644 index 00000000..6ab0fd60 --- /dev/null +++ b/system/include/libcxx/__std_stream @@ -0,0 +1,313 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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___STD_STREAM +#define _LIBCPP___STD_STREAM + +#include <__config> +#include <ostream> +#include <istream> +#include <__locale> +#include <cstdio> + +#pragma GCC system_header + +_LIBCPP_BEGIN_NAMESPACE_STD + +static const unsigned __limit = 8; + +// __stdinbuf + +template <class _CharT> +class _LIBCPP_HIDDEN __stdinbuf + : public basic_streambuf<_CharT, char_traits<_CharT> > +{ +public: + typedef _CharT char_type; + typedef char_traits<char_type> 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; + + explicit __stdinbuf(FILE* __fp); + +protected: + virtual int_type underflow(); + virtual int_type uflow(); + virtual int_type pbackfail(int_type __c = traits_type::eof()); + virtual void imbue(const locale& __loc); + +private: + + FILE* __file_; + const codecvt<char_type, char, state_type>* __cv_; + state_type __st_; + int __encoding_; + bool __always_noconv_; + + __stdinbuf(const __stdinbuf&); + __stdinbuf& operator=(const __stdinbuf&); + + int_type __getchar(bool __consume); +}; + +template <class _CharT> +__stdinbuf<_CharT>::__stdinbuf(FILE* __fp) + : __file_(__fp), + __st_() +{ + imbue(this->getloc()); +} + +template <class _CharT> +void +__stdinbuf<_CharT>::imbue(const locale& __loc) +{ + __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); + __encoding_ = __cv_->encoding(); + __always_noconv_ = __cv_->always_noconv(); + if (__encoding_ > __limit) + __throw_runtime_error("unsupported locale for standard input"); +} + +template <class _CharT> +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::underflow() +{ + return __getchar(false); +} + +template <class _CharT> +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::uflow() +{ + return __getchar(true); +} + +template <class _CharT> +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::__getchar(bool __consume) +{ + char __extbuf[__limit]; + int __nread = _VSTD::max(1, __encoding_); + for (int __i = 0; __i < __nread; ++__i) + { + char __c = getc(__file_); + if (__c == EOF) + return traits_type::eof(); + __extbuf[__i] = static_cast<char>(__c); + } + char_type __1buf; + if (__always_noconv_) + __1buf = static_cast<char_type>(__extbuf[0]); + else + { + const char* __enxt; + char_type* __inxt; + codecvt_base::result __r; + do + { + state_type __sv_st = __st_; + __r = __cv_->in(__st_, __extbuf, __extbuf + __nread, __enxt, + &__1buf, &__1buf + 1, __inxt); + switch (__r) + { + case _VSTD::codecvt_base::ok: + break; + case codecvt_base::partial: + __st_ = __sv_st; + if (__nread == sizeof(__extbuf)) + return traits_type::eof(); + { + char __c = getc(__file_); + if (__c == EOF) + return traits_type::eof(); + __extbuf[__nread] = static_cast<char>(__c); + } + ++__nread; + break; + case codecvt_base::error: + return traits_type::eof(); + case _VSTD::codecvt_base::noconv: + __1buf = static_cast<char_type>(__extbuf[0]); + break; + } + } while (__r == _VSTD::codecvt_base::partial); + } + if (!__consume) + { + for (int __i = __nread; __i > 0;) + { + if (ungetc(__extbuf[--__i], __file_) == EOF) + return traits_type::eof(); + } + } + return traits_type::to_int_type(__1buf); +} + +template <class _CharT> +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(); + } + while (__enxt > __extbuf) + if (ungetc(*--__enxt, __file_) == EOF) + return traits_type::eof(); + return traits_type::not_eof(__c); +} + +// __stdoutbuf + +template <class _CharT> +class _LIBCPP_HIDDEN __stdoutbuf + : public basic_streambuf<_CharT, char_traits<_CharT> > +{ +public: + typedef _CharT char_type; + typedef char_traits<char_type> 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; + + explicit __stdoutbuf(FILE* __fp); + +protected: + virtual int_type overflow (int_type __c = traits_type::eof()); + virtual int sync(); + virtual void imbue(const locale& __loc); + +private: + FILE* __file_; + const codecvt<char_type, char, state_type>* __cv_; + state_type __st_; + bool __always_noconv_; + + __stdoutbuf(const __stdoutbuf&); + __stdoutbuf& operator=(const __stdoutbuf&); +}; + +template <class _CharT> +__stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp) + : __file_(__fp), + __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())), + __st_(), + __always_noconv_(__cv_->always_noconv()) +{ +} + +template <class _CharT> +typename __stdoutbuf<_CharT>::int_type +__stdoutbuf<_CharT>::overflow(int_type __c) +{ + char __extbuf[__limit]; + 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); + if (__always_noconv_) + { + if (fwrite(this->pbase(), sizeof(char_type), 1, __file_) != 1) + return traits_type::eof(); + } + else + { + char* __extbe = __extbuf; + codecvt_base::result __r; + do + { + const char_type* __e; + __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, + __extbuf, + __extbuf + sizeof(__extbuf), + __extbe); + if (__e == this->pbase()) + return traits_type::eof(); + if (__r == codecvt_base::noconv) + { + if (fwrite(this->pbase(), 1, 1, __file_) != 1) + 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(0, 0); + } + return traits_type::not_eof(__c); +} + +template <class _CharT> +int +__stdoutbuf<_CharT>::sync() +{ + char __extbuf[__limit]; + codecvt_base::result __r; + do + { + char* __extbe; + __r = __cv_->unshift(__st_, __extbuf, + __extbuf + sizeof(__extbuf), + __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; + return 0; +} + +template <class _CharT> +void +__stdoutbuf<_CharT>::imbue(const locale& __loc) +{ + sync(); + __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); + __always_noconv_ = __cv_->always_noconv(); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STD_STREAM |