| // -*- C++ -*- | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef _LIBCPP_STREAMBUF | |
| #define _LIBCPP_STREAMBUF | |
| /* | |
| streambuf synopsis | |
| namespace std | |
| { | |
| template <class charT, class traits = char_traits<charT> > | |
| class basic_streambuf | |
| { | |
| public: | |
| // types: | |
| 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; | |
| virtual ~basic_streambuf(); | |
| // 27.6.2.2.1 locales: | |
| locale pubimbue(const locale& loc); | |
| locale getloc() const; | |
| // 27.6.2.2.2 buffer and positioning: | |
| basic_streambuf* pubsetbuf(char_type* s, streamsize n); | |
| pos_type pubseekoff(off_type off, ios_base::seekdir way, | |
| ios_base::openmode which = ios_base::in | ios_base::out); | |
| pos_type pubseekpos(pos_type sp, | |
| ios_base::openmode which = ios_base::in | ios_base::out); | |
| int pubsync(); | |
| // Get and put areas: | |
| // 27.6.2.2.3 Get area: | |
| streamsize in_avail(); | |
| int_type snextc(); | |
| int_type sbumpc(); | |
| int_type sgetc(); | |
| streamsize sgetn(char_type* s, streamsize n); | |
| // 27.6.2.2.4 Putback: | |
| int_type sputbackc(char_type c); | |
| int_type sungetc(); | |
| // 27.6.2.2.5 Put area: | |
| int_type sputc(char_type c); | |
| streamsize sputn(const char_type* s, streamsize n); | |
| protected: | |
| basic_streambuf(); | |
| basic_streambuf(const basic_streambuf& rhs); | |
| basic_streambuf& operator=(const basic_streambuf& rhs); | |
| void swap(basic_streambuf& rhs); | |
| // 27.6.2.3.2 Get area: | |
| char_type* eback() const; | |
| char_type* gptr() const; | |
| char_type* egptr() const; | |
| void gbump(int n); | |
| void setg(char_type* gbeg, char_type* gnext, char_type* gend); | |
| // 27.6.2.3.3 Put area: | |
| char_type* pbase() const; | |
| char_type* pptr() const; | |
| char_type* epptr() const; | |
| void pbump(int n); | |
| void setp(char_type* pbeg, char_type* pend); | |
| // 27.6.2.4 virtual functions: | |
| // 27.6.2.4.1 Locales: | |
| virtual void imbue(const locale& loc); | |
| // 27.6.2.4.2 Buffer management and positioning: | |
| virtual basic_streambuf* 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(); | |
| // 27.6.2.4.3 Get area: | |
| virtual streamsize showmanyc(); | |
| virtual streamsize xsgetn(char_type* s, streamsize n); | |
| virtual int_type underflow(); | |
| virtual int_type uflow(); | |
| // 27.6.2.4.4 Putback: | |
| virtual int_type pbackfail(int_type c = traits_type::eof()); | |
| // 27.6.2.4.5 Put area: | |
| virtual streamsize xsputn(const char_type* s, streamsize n); | |
| virtual int_type overflow (int_type c = traits_type::eof()); | |
| }; | |
| } // std | |
| */ | |
| #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) | |
| # include <__cxx03/streambuf> | |
| #else | |
| # include <__config> | |
| # if _LIBCPP_HAS_LOCALIZATION | |
| # include <__assert> | |
| # include <__fwd/streambuf.h> | |
| # include <__locale_dir/locale.h> | |
| # include <__memory/valid_range.h> | |
| # include <__type_traits/is_same.h> | |
| # include <__utility/scope_guard.h> | |
| # include <climits> | |
| # include <ios> | |
| # include <iosfwd> | |
| # include <version> | |
| # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| # pragma GCC system_header | |
| # endif | |
| _LIBCPP_PUSH_MACROS | |
| # include <__undef_macros> | |
| _LIBCPP_BEGIN_NAMESPACE_STD | |
| _LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS | |
| template <class _CharT, class _Traits> | |
| class basic_streambuf { | |
| public: | |
| // types: | |
| 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; | |
| struct _GetArea { | |
| char_type* __begin_; | |
| char_type* __current_; | |
| char_type* __end_; | |
| }; | |
| struct _PutArea { | |
| char_type* __begin_; | |
| char_type* __current_; | |
| char_type* __end_; | |
| }; | |
| static_assert(is_same<_CharT, typename traits_type::char_type>::value, | |
| "traits_type::char_type must be the same type as CharT"); | |
| virtual ~basic_streambuf() {} | |
| // 27.6.2.2.1 locales: | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 locale pubimbue(const locale& __loc) { | |
| imbue(__loc); | |
| locale __r = __loc_; | |
| __loc_ = __loc; | |
| return __r; | |
| } | |
| [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 locale getloc() const { return __loc_; } | |
| // 27.6.2.2.2 buffer and positioning: | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 basic_streambuf* pubsetbuf(char_type* __s, streamsize __n) { | |
| return setbuf(__s, __n); | |
| } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 pos_type | |
| pubseekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which = ios_base::in | ios_base::out) { | |
| return seekoff(__off, __way, __which); | |
| } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 pos_type | |
| pubseekpos(pos_type __sp, ios_base::openmode __which = ios_base::in | ios_base::out) { | |
| return seekpos(__sp, __which); | |
| } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int pubsync() { return sync(); } | |
| // Get and put areas: | |
| // 27.6.2.2.3 Get area: | |
| [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 streamsize in_avail() { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (gptr() < egptr()) | |
| return static_cast<streamsize>(egptr() - gptr()); | |
| return showmanyc(); | |
| } | |
| [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type snextc() { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (sbumpc() == traits_type::eof()) | |
| return traits_type::eof(); | |
| return sgetc(); | |
| } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sbumpc() { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (gptr() == egptr()) | |
| return uflow(); | |
| int_type __c = traits_type::to_int_type(*gptr()); | |
| this->gbump(1); | |
| return __c; | |
| } | |
| [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sgetc() { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (gptr() == egptr()) | |
| return underflow(); | |
| return traits_type::to_int_type(*gptr()); | |
| } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 streamsize sgetn(char_type* __s, streamsize __n) { return xsgetn(__s, __n); } | |
| // 27.6.2.2.4 Putback: | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sputbackc(char_type __c) { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (eback() == gptr() || !traits_type::eq(__c, *(gptr() - 1))) | |
| return pbackfail(traits_type::to_int_type(__c)); | |
| this->gbump(-1); | |
| return traits_type::to_int_type(*gptr()); | |
| } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sungetc() { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (eback() == gptr()) | |
| return pbackfail(); | |
| this->gbump(-1); | |
| return traits_type::to_int_type(*gptr()); | |
| } | |
| // 27.6.2.2.5 Put area: | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 int_type sputc(char_type __c) { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (pptr() == epptr()) | |
| return overflow(traits_type::to_int_type(__c)); | |
| *pptr() = __c; | |
| this->pbump(1); | |
| return traits_type::to_int_type(__c); | |
| } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 streamsize sputn(const char_type* __s, streamsize __n) { | |
| return xsputn(__s, __n); | |
| } | |
| protected: | |
| basic_streambuf() {} | |
| basic_streambuf(const basic_streambuf& __sb) | |
| : __loc_(__sb.__loc_), __get_area_(__sb.__get_area_), __put_area_(__sb.__put_area_) {} | |
| basic_streambuf& operator=(const basic_streambuf& __sb) { | |
| __loc_ = __sb.__loc_; | |
| __get_area_ = __sb.__get_area_; | |
| __put_area_ = __sb.__put_area_; | |
| return *this; | |
| } | |
| void swap(basic_streambuf& __sb) { | |
| std::swap(__loc_, __sb.__loc_); | |
| std::swap(__get_area_, __sb.__get_area_); | |
| std::swap(__put_area_, __sb.__put_area_); | |
| } | |
| // 27.6.2.3.2 Get area: | |
| _LIBCPP_HIDE_FROM_ABI char_type* eback() const { return __get_area_.__begin_; } | |
| _LIBCPP_HIDE_FROM_ABI char_type* gptr() const { return __get_area_.__current_; } | |
| _LIBCPP_HIDE_FROM_ABI char_type* egptr() const { return __get_area_.__end_; } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void gbump(int __n) { __get_area_.__current_ += __n; } | |
| // gbump takes an int, so it might not be able to represent the offset we want to add. | |
| _LIBCPP_HIDE_FROM_ABI void __gbump_ptrdiff(ptrdiff_t __n) { __get_area_.__current_ += __n; } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void setg(char_type* __begin, char_type* __current, char_type* __end) { | |
| _LIBCPP_ASSERT_VALID_INPUT_RANGE( | |
| std::__is_valid_range(__begin, __current), "[begin, current) must be a valid range"); | |
| _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__begin, __end), "[begin, end) must be a valid range"); | |
| _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__current, __end), "[current, end) must be a valid range"); | |
| _GetArea __tmp = {__begin, __current, __end}; // This is a temporary for C++03 compatibility | |
| __get_area_ = __tmp; | |
| } | |
| // 27.6.2.3.3 Put area: | |
| _LIBCPP_HIDE_FROM_ABI char_type* pbase() const { return __put_area_.__begin_; } | |
| _LIBCPP_HIDE_FROM_ABI char_type* pptr() const { return __put_area_.__current_; } | |
| _LIBCPP_HIDE_FROM_ABI char_type* epptr() const { return __put_area_.__end_; } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void pbump(int __n) { __put_area_.__current_ += __n; } | |
| _LIBCPP_HIDE_FROM_ABI void __pbump(streamsize __n) { __put_area_.__current_ += __n; } | |
| inline _LIBCPP_HIDE_FROM_ABI_SINCE_LLVM8 void setp(char_type* __begin, char_type* __end) { | |
| _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__begin, __end), "[begin, end) must be a valid range"); | |
| _PutArea __tmp = {__begin, __begin, __end}; // This is a temporary for C++03 compatibility | |
| __put_area_ = __tmp; | |
| } | |
| // 27.6.2.4 virtual functions: | |
| // 27.6.2.4.1 Locales: | |
| virtual void imbue(const locale&) {} | |
| // 27.6.2.4.2 Buffer management and positioning: | |
| virtual basic_streambuf* setbuf(char_type*, streamsize) { return this; } | |
| virtual pos_type seekoff(off_type, ios_base::seekdir, ios_base::openmode = ios_base::in | ios_base::out) { | |
| return pos_type(off_type(-1)); | |
| } | |
| virtual pos_type seekpos(pos_type, ios_base::openmode = ios_base::in | ios_base::out) { | |
| return pos_type(off_type(-1)); | |
| } | |
| virtual int sync() { return 0; } | |
| // 27.6.2.4.3 Get area: | |
| virtual streamsize showmanyc() { return 0; } | |
| virtual streamsize xsgetn(char_type* __s, streamsize __n) { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| int_type __c; | |
| streamsize __i = 0; | |
| while (__i < __n) { | |
| if (gptr() < egptr()) { | |
| const streamsize __len = std::min(static_cast<streamsize>(INT_MAX), std::min(egptr() - gptr(), __n - __i)); | |
| traits_type::copy(__s, gptr(), __len); | |
| __s += __len; | |
| __i += __len; | |
| this->gbump(__len); | |
| } else if ((__c = uflow()) != traits_type::eof()) { | |
| *__s = traits_type::to_char_type(__c); | |
| ++__s; | |
| ++__i; | |
| } else | |
| break; | |
| } | |
| return __i; | |
| } | |
| virtual int_type underflow() { return traits_type::eof(); } | |
| virtual int_type uflow() { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| if (underflow() == traits_type::eof()) | |
| return traits_type::eof(); | |
| int_type __c = traits_type::to_int_type(*gptr()); | |
| this->gbump(1); | |
| return __c; | |
| } | |
| // 27.6.2.4.4 Putback: | |
| virtual int_type pbackfail(int_type = traits_type::eof()) { return traits_type::eof(); } | |
| // 27.6.2.4.5 Put area: | |
| virtual streamsize xsputn(const char_type* __s, streamsize __n) { | |
| __check_invariants(); | |
| auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); }); | |
| streamsize __i = 0; | |
| while (__i < __n) { | |
| if (pptr() >= epptr()) { | |
| if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof()) | |
| break; | |
| ++__s; | |
| ++__i; | |
| } else { | |
| streamsize __chunk_size = std::min(epptr() - pptr(), __n - __i); | |
| traits_type::copy(pptr(), __s, __chunk_size); | |
| __pbump(__chunk_size); | |
| __s += __chunk_size; | |
| __i += __chunk_size; | |
| } | |
| } | |
| return __i; | |
| } | |
| virtual int_type overflow(int_type = traits_type::eof()) { return traits_type::eof(); } | |
| // This function checks some invariants of the class (it isn't exhaustive). | |
| _LIBCPP_HIDE_FROM_ABI void __check_invariants() const { | |
| _LIBCPP_ASSERT_INTERNAL(pbase() <= pptr(), "this is an invariant of the class"); | |
| _LIBCPP_ASSERT_INTERNAL(pptr() <= epptr(), "this is an invariant of the class"); | |
| _LIBCPP_ASSERT_INTERNAL(eback() <= gptr(), "this is an invariant of the class"); | |
| _LIBCPP_ASSERT_INTERNAL(gptr() <= egptr(), "this is an invariant of the class"); | |
| } | |
| private: | |
| locale __loc_; | |
| _GetArea __get_area_ = {}; | |
| _PutArea __put_area_ = {}; | |
| template <class _CharT2, class _Traits2, class _Allocator> | |
| _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT2, _Traits2>& | |
| getline(basic_istream<_CharT2, _Traits2>&, basic_string<_CharT2, _Traits2, _Allocator>&, _CharT2); | |
| }; | |
| extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<char>; | |
| # if _LIBCPP_HAS_WIDE_CHARACTERS | |
| extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<wchar_t>; | |
| # endif | |
| _LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS | |
| _LIBCPP_END_NAMESPACE_STD | |
| _LIBCPP_POP_MACROS | |
| # endif // _LIBCPP_HAS_LOCALIZATION | |
| #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) | |
| #endif // _LIBCPP_STREAMBUF |