446 lines · plain
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP_STREAMBUF11#define _LIBCPP_STREAMBUF12 13/*14 streambuf synopsis15 16namespace std17{18 19template <class charT, class traits = char_traits<charT> >20class basic_streambuf21{22public:23 // types:24 typedef charT char_type;25 typedef traits traits_type;26 typedef typename traits_type::int_type int_type;27 typedef typename traits_type::pos_type pos_type;28 typedef typename traits_type::off_type off_type;29 30 virtual ~basic_streambuf();31 32 // 27.6.2.2.1 locales:33 locale pubimbue(const locale& loc);34 locale getloc() const;35 36 // 27.6.2.2.2 buffer and positioning:37 basic_streambuf* pubsetbuf(char_type* s, streamsize n);38 pos_type pubseekoff(off_type off, ios_base::seekdir way,39 ios_base::openmode which = ios_base::in | ios_base::out);40 pos_type pubseekpos(pos_type sp,41 ios_base::openmode which = ios_base::in | ios_base::out);42 int pubsync();43 44 // Get and put areas:45 // 27.6.2.2.3 Get area:46 streamsize in_avail();47 int_type snextc();48 int_type sbumpc();49 int_type sgetc();50 streamsize sgetn(char_type* s, streamsize n);51 52 // 27.6.2.2.4 Putback:53 int_type sputbackc(char_type c);54 int_type sungetc();55 56 // 27.6.2.2.5 Put area:57 int_type sputc(char_type c);58 streamsize sputn(const char_type* s, streamsize n);59 60protected:61 basic_streambuf();62 basic_streambuf(const basic_streambuf& rhs);63 basic_streambuf& operator=(const basic_streambuf& rhs);64 void swap(basic_streambuf& rhs);65 66 // 27.6.2.3.2 Get area:67 char_type* eback() const;68 char_type* gptr() const;69 char_type* egptr() const;70 void gbump(int n);71 void setg(char_type* gbeg, char_type* gnext, char_type* gend);72 73 // 27.6.2.3.3 Put area:74 char_type* pbase() const;75 char_type* pptr() const;76 char_type* epptr() const;77 void pbump(int n);78 void setp(char_type* pbeg, char_type* pend);79 80 // 27.6.2.4 virtual functions:81 // 27.6.2.4.1 Locales:82 virtual void imbue(const locale& loc);83 84 // 27.6.2.4.2 Buffer management and positioning:85 virtual basic_streambuf* setbuf(char_type* s, streamsize n);86 virtual pos_type seekoff(off_type off, ios_base::seekdir way,87 ios_base::openmode which = ios_base::in | ios_base::out);88 virtual pos_type seekpos(pos_type sp,89 ios_base::openmode which = ios_base::in | ios_base::out);90 virtual int sync();91 92 // 27.6.2.4.3 Get area:93 virtual streamsize showmanyc();94 virtual streamsize xsgetn(char_type* s, streamsize n);95 virtual int_type underflow();96 virtual int_type uflow();97 98 // 27.6.2.4.4 Putback:99 virtual int_type pbackfail(int_type c = traits_type::eof());100 101 // 27.6.2.4.5 Put area:102 virtual streamsize xsputn(const char_type* s, streamsize n);103 virtual int_type overflow (int_type c = traits_type::eof());104};105 106} // std107 108*/109 110#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)111# include <__cxx03/streambuf>112#else113# include <__config>114 115# if _LIBCPP_HAS_LOCALIZATION116 117# include <__assert>118# include <__fwd/streambuf.h>119# include <__locale>120# include <__type_traits/is_same.h>121# include <__utility/is_valid_range.h>122# include <__utility/scope_guard.h>123# include <climits>124# include <ios>125# include <iosfwd>126# include <version>127 128# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)129# pragma GCC system_header130# endif131 132_LIBCPP_PUSH_MACROS133# include <__undef_macros>134 135_LIBCPP_BEGIN_NAMESPACE_STD136 137template <class _CharT, class _Traits>138class basic_streambuf {139public:140 // types:141 typedef _CharT char_type;142 typedef _Traits traits_type;143 typedef typename traits_type::int_type int_type;144 typedef typename traits_type::pos_type pos_type;145 typedef typename traits_type::off_type off_type;146 147 static_assert(is_same<_CharT, typename traits_type::char_type>::value,148 "traits_type::char_type must be the same type as CharT");149 150 virtual ~basic_streambuf() {}151 152 // 27.6.2.2.1 locales:153 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 locale pubimbue(const locale& __loc) {154 imbue(__loc);155 locale __r = __loc_;156 __loc_ = __loc;157 return __r;158 }159 160 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 locale getloc() const { return __loc_; }161 162 // 27.6.2.2.2 buffer and positioning:163 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_streambuf* pubsetbuf(char_type* __s, streamsize __n) {164 return setbuf(__s, __n);165 }166 167 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type168 pubseekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which = ios_base::in | ios_base::out) {169 return seekoff(__off, __way, __which);170 }171 172 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type173 pubseekpos(pos_type __sp, ios_base::openmode __which = ios_base::in | ios_base::out) {174 return seekpos(__sp, __which);175 }176 177 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int pubsync() { return sync(); }178 179 // Get and put areas:180 // 27.6.2.2.3 Get area:181 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize in_avail() {182 __check_invariants();183 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });184 185 if (gptr() < egptr())186 return static_cast<streamsize>(egptr() - gptr());187 return showmanyc();188 }189 190 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type snextc() {191 __check_invariants();192 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });193 194 if (sbumpc() == traits_type::eof())195 return traits_type::eof();196 return sgetc();197 }198 199 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sbumpc() {200 __check_invariants();201 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });202 203 if (gptr() == egptr())204 return uflow();205 int_type __c = traits_type::to_int_type(*gptr());206 this->gbump(1);207 return __c;208 }209 210 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sgetc() {211 __check_invariants();212 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });213 214 if (gptr() == egptr())215 return underflow();216 return traits_type::to_int_type(*gptr());217 }218 219 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize sgetn(char_type* __s, streamsize __n) { return xsgetn(__s, __n); }220 221 // 27.6.2.2.4 Putback:222 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sputbackc(char_type __c) {223 __check_invariants();224 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });225 226 if (eback() == gptr() || !traits_type::eq(__c, *(gptr() - 1)))227 return pbackfail(traits_type::to_int_type(__c));228 this->gbump(-1);229 return traits_type::to_int_type(*gptr());230 }231 232 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sungetc() {233 __check_invariants();234 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });235 236 if (eback() == gptr())237 return pbackfail();238 this->gbump(-1);239 return traits_type::to_int_type(*gptr());240 }241 242 // 27.6.2.2.5 Put area:243 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sputc(char_type __c) {244 __check_invariants();245 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });246 247 if (pptr() == epptr())248 return overflow(traits_type::to_int_type(__c));249 *pptr() = __c;250 this->pbump(1);251 return traits_type::to_int_type(__c);252 }253 254 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize sputn(const char_type* __s, streamsize __n) {255 return xsputn(__s, __n);256 }257 258protected:259 basic_streambuf() {}260 basic_streambuf(const basic_streambuf& __sb)261 : __loc_(__sb.__loc_),262 __binp_(__sb.__binp_),263 __ninp_(__sb.__ninp_),264 __einp_(__sb.__einp_),265 __bout_(__sb.__bout_),266 __nout_(__sb.__nout_),267 __eout_(__sb.__eout_) {}268 269 basic_streambuf& operator=(const basic_streambuf& __sb) {270 __loc_ = __sb.__loc_;271 __binp_ = __sb.__binp_;272 __ninp_ = __sb.__ninp_;273 __einp_ = __sb.__einp_;274 __bout_ = __sb.__bout_;275 __nout_ = __sb.__nout_;276 __eout_ = __sb.__eout_;277 return *this;278 }279 280 void swap(basic_streambuf& __sb) {281 std::swap(__loc_, __sb.__loc_);282 std::swap(__binp_, __sb.__binp_);283 std::swap(__ninp_, __sb.__ninp_);284 std::swap(__einp_, __sb.__einp_);285 std::swap(__bout_, __sb.__bout_);286 std::swap(__nout_, __sb.__nout_);287 std::swap(__eout_, __sb.__eout_);288 }289 290 // 27.6.2.3.2 Get area:291 _LIBCPP_HIDE_FROM_ABI char_type* eback() const { return __binp_; }292 _LIBCPP_HIDE_FROM_ABI char_type* gptr() const { return __ninp_; }293 _LIBCPP_HIDE_FROM_ABI char_type* egptr() const { return __einp_; }294 295 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void gbump(int __n) { __ninp_ += __n; }296 297 // gbump takes an int, so it might not be able to represent the offset we want to add.298 _LIBCPP_HIDE_FROM_ABI void __gbump_ptrdiff(ptrdiff_t __n) { __ninp_ += __n; }299 300 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void setg(char_type* __gbeg, char_type* __gnext, char_type* __gend) {301 _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__gbeg, __gnext), "[gbeg, gnext) must be a valid range");302 _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__gbeg, __gend), "[gbeg, gend) must be a valid range");303 _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__gnext, __gend), "[gnext, gend) must be a valid range");304 __binp_ = __gbeg;305 __ninp_ = __gnext;306 __einp_ = __gend;307 }308 309 // 27.6.2.3.3 Put area:310 _LIBCPP_HIDE_FROM_ABI char_type* pbase() const { return __bout_; }311 _LIBCPP_HIDE_FROM_ABI char_type* pptr() const { return __nout_; }312 _LIBCPP_HIDE_FROM_ABI char_type* epptr() const { return __eout_; }313 314 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void pbump(int __n) { __nout_ += __n; }315 316 _LIBCPP_HIDE_FROM_ABI void __pbump(streamsize __n) { __nout_ += __n; }317 318 inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void setp(char_type* __pbeg, char_type* __pend) {319 _LIBCPP_ASSERT_VALID_INPUT_RANGE(std::__is_valid_range(__pbeg, __pend), "[pbeg, pend) must be a valid range");320 __bout_ = __nout_ = __pbeg;321 __eout_ = __pend;322 }323 324 // 27.6.2.4 virtual functions:325 // 27.6.2.4.1 Locales:326 virtual void imbue(const locale&) {}327 328 // 27.6.2.4.2 Buffer management and positioning:329 virtual basic_streambuf* setbuf(char_type*, streamsize) { return this; }330 virtual pos_type seekoff(off_type, ios_base::seekdir, ios_base::openmode = ios_base::in | ios_base::out) {331 return pos_type(off_type(-1));332 }333 virtual pos_type seekpos(pos_type, ios_base::openmode = ios_base::in | ios_base::out) {334 return pos_type(off_type(-1));335 }336 virtual int sync() { return 0; }337 338 // 27.6.2.4.3 Get area:339 virtual streamsize showmanyc() { return 0; }340 341 virtual streamsize xsgetn(char_type* __s, streamsize __n) {342 __check_invariants();343 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });344 345 int_type __c;346 streamsize __i = 0;347 while (__i < __n) {348 if (gptr() < egptr()) {349 const streamsize __len = std::min(static_cast<streamsize>(INT_MAX), std::min(egptr() - gptr(), __n - __i));350 traits_type::copy(__s, gptr(), __len);351 __s += __len;352 __i += __len;353 this->gbump(__len);354 } else if ((__c = uflow()) != traits_type::eof()) {355 *__s = traits_type::to_char_type(__c);356 ++__s;357 ++__i;358 } else359 break;360 }361 return __i;362 }363 364 virtual int_type underflow() { return traits_type::eof(); }365 virtual int_type uflow() {366 __check_invariants();367 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });368 369 if (underflow() == traits_type::eof())370 return traits_type::eof();371 int_type __c = traits_type::to_int_type(*gptr());372 this->gbump(1);373 return __c;374 }375 376 // 27.6.2.4.4 Putback:377 virtual int_type pbackfail(int_type = traits_type::eof()) { return traits_type::eof(); }378 379 // 27.6.2.4.5 Put area:380 virtual streamsize xsputn(const char_type* __s, streamsize __n) {381 __check_invariants();382 auto __guard = std::__make_scope_guard([this] { this->__check_invariants(); });383 384 streamsize __i = 0;385 while (__i < __n) {386 if (pptr() >= epptr()) {387 if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof())388 break;389 ++__s;390 ++__i;391 } else {392 streamsize __chunk_size = std::min(epptr() - pptr(), __n - __i);393 traits_type::copy(pptr(), __s, __chunk_size);394 __pbump(__chunk_size);395 __s += __chunk_size;396 __i += __chunk_size;397 }398 }399 return __i;400 }401 402 virtual int_type overflow(int_type = traits_type::eof()) { return traits_type::eof(); }403 404 // This function checks some invariants of the class (it isn't exhaustive).405 _LIBCPP_HIDE_FROM_ABI void __check_invariants() const {406 _LIBCPP_ASSERT_INTERNAL(pbase() <= pptr(), "this is an invariant of the class");407 _LIBCPP_ASSERT_INTERNAL(pptr() <= epptr(), "this is an invariant of the class");408 409 _LIBCPP_ASSERT_INTERNAL(eback() <= gptr(), "this is an invariant of the class");410 _LIBCPP_ASSERT_INTERNAL(gptr() <= egptr(), "this is an invariant of the class");411 }412 413private:414 locale __loc_;415 char_type* __binp_ = nullptr;416 char_type* __ninp_ = nullptr;417 char_type* __einp_ = nullptr;418 char_type* __bout_ = nullptr;419 char_type* __nout_ = nullptr;420 char_type* __eout_ = nullptr;421 422 template <class _CharT2, class _Traits2, class _Allocator>423 _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT2, _Traits2>&424 getline(basic_istream<_CharT2, _Traits2>&, basic_string<_CharT2, _Traits2, _Allocator>&, _CharT2);425};426 427extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<char>;428 429# if _LIBCPP_HAS_WIDE_CHARACTERS430extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<wchar_t>;431# endif432 433_LIBCPP_END_NAMESPACE_STD434 435_LIBCPP_POP_MACROS436 437# endif // _LIBCPP_HAS_LOCALIZATION438 439# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20440# include <cstdint>441# include <optional>442# endif443#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)444 445#endif // _LIBCPP_STREAMBUF446