1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 981ad6265SDimitry Andric #include <__assert> 1081ad6265SDimitry Andric #include <__utility/unreachable.h> 1181ad6265SDimitry Andric #include <algorithm> 1281ad6265SDimitry Andric #include <climits> 1381ad6265SDimitry Andric #include <cstdlib> 1481ad6265SDimitry Andric #include <cstring> 1581ad6265SDimitry Andric #include <strstream> 1681ad6265SDimitry Andric 1781ad6265SDimitry Andric _LIBCPP_PUSH_MACROS 1881ad6265SDimitry Andric #include <__undef_macros> 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric strstreambuf::strstreambuf(streamsize __alsize) 235f757f3fSDimitry Andric : __strmode_(__dynamic), __alsize_(__alsize), __palloc_(nullptr), __pfree_(nullptr) {} 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*)) 265f757f3fSDimitry Andric : __strmode_(__dynamic), __alsize_(__default_alsize), __palloc_(__palloc), __pfree_(__pfree) {} 270b57cec5SDimitry Andric 285f757f3fSDimitry Andric void strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) { 290b57cec5SDimitry Andric if (__n == 0) 300b57cec5SDimitry Andric __n = static_cast<streamsize>(strlen(__gnext)); 310b57cec5SDimitry Andric else if (__n < 0) 320b57cec5SDimitry Andric __n = INT_MAX; 330b57cec5SDimitry Andric if (__pbeg == nullptr) 340b57cec5SDimitry Andric setg(__gnext, __gnext, __gnext + __n); 355f757f3fSDimitry Andric else { 360b57cec5SDimitry Andric setg(__gnext, __gnext, __pbeg); 370b57cec5SDimitry Andric setp(__pbeg, __pbeg + __n); 380b57cec5SDimitry Andric } 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg) 425f757f3fSDimitry Andric : __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) { 430b57cec5SDimitry Andric __init(__gnext, __n, __pbeg); 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric strstreambuf::strstreambuf(const char* __gnext, streamsize __n) 475f757f3fSDimitry Andric : __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) { 480b57cec5SDimitry Andric __init(const_cast<char*>(__gnext), __n, nullptr); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg) 525f757f3fSDimitry Andric : __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) { 530b57cec5SDimitry Andric __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n) 575f757f3fSDimitry Andric : __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) { 580b57cec5SDimitry Andric __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg) 625f757f3fSDimitry Andric : __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) { 630b57cec5SDimitry Andric __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n) 675f757f3fSDimitry Andric : __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) { 680b57cec5SDimitry Andric __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 715f757f3fSDimitry Andric strstreambuf::~strstreambuf() { 725f757f3fSDimitry Andric if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) { 730b57cec5SDimitry Andric if (__pfree_) 740b57cec5SDimitry Andric __pfree_(eback()); 750b57cec5SDimitry Andric else 760b57cec5SDimitry Andric delete[] eback(); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 805f757f3fSDimitry Andric void strstreambuf::swap(strstreambuf& __rhs) { 810b57cec5SDimitry Andric streambuf::swap(__rhs); 825f757f3fSDimitry Andric std::swap(__strmode_, __rhs.__strmode_); 835f757f3fSDimitry Andric std::swap(__alsize_, __rhs.__alsize_); 845f757f3fSDimitry Andric std::swap(__palloc_, __rhs.__palloc_); 855f757f3fSDimitry Andric std::swap(__pfree_, __rhs.__pfree_); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 885f757f3fSDimitry Andric void strstreambuf::freeze(bool __freezefl) { 895f757f3fSDimitry Andric if (__strmode_ & __dynamic) { 900b57cec5SDimitry Andric if (__freezefl) 910b57cec5SDimitry Andric __strmode_ |= __frozen; 920b57cec5SDimitry Andric else 930b57cec5SDimitry Andric __strmode_ &= ~__frozen; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 975f757f3fSDimitry Andric char* strstreambuf::str() { 980b57cec5SDimitry Andric if (__strmode_ & __dynamic) 990b57cec5SDimitry Andric __strmode_ |= __frozen; 1000b57cec5SDimitry Andric return eback(); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1035f757f3fSDimitry Andric int strstreambuf::pcount() const { return static_cast<int>(pptr() - pbase()); } 1040b57cec5SDimitry Andric 1055f757f3fSDimitry Andric strstreambuf::int_type strstreambuf::overflow(int_type __c) { 1060b57cec5SDimitry Andric if (__c == EOF) 1070b57cec5SDimitry Andric return int_type(0); 1085f757f3fSDimitry Andric if (pptr() == epptr()) { 1090b57cec5SDimitry Andric if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0) 1100b57cec5SDimitry Andric return int_type(EOF); 1110b57cec5SDimitry Andric size_t old_size = static_cast<size_t>((epptr() ? epptr() : egptr()) - eback()); 1120b57cec5SDimitry Andric size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2 * old_size); 1130b57cec5SDimitry Andric if (new_size == 0) 1140b57cec5SDimitry Andric new_size = __default_alsize; 1150b57cec5SDimitry Andric char* buf = nullptr; 1160b57cec5SDimitry Andric if (__palloc_) 1170b57cec5SDimitry Andric buf = static_cast<char*>(__palloc_(new_size)); 1180b57cec5SDimitry Andric else 1190b57cec5SDimitry Andric buf = new char[new_size]; 1200b57cec5SDimitry Andric if (buf == nullptr) 1210b57cec5SDimitry Andric return int_type(EOF); 1220b57cec5SDimitry Andric if (old_size != 0) { 123*1db9f3b2SDimitry Andric _LIBCPP_ASSERT_INTERNAL(eback(), "strstreambuf::overflow reallocating but the get area is a null pointer"); 1240b57cec5SDimitry Andric memcpy(buf, eback(), static_cast<size_t>(old_size)); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric ptrdiff_t ninp = gptr() - eback(); 1270b57cec5SDimitry Andric ptrdiff_t einp = egptr() - eback(); 1280b57cec5SDimitry Andric ptrdiff_t nout = pptr() - pbase(); 1295f757f3fSDimitry Andric if (__strmode_ & __allocated) { 1300b57cec5SDimitry Andric if (__pfree_) 1310b57cec5SDimitry Andric __pfree_(eback()); 1320b57cec5SDimitry Andric else 1330b57cec5SDimitry Andric delete[] eback(); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric setg(buf, buf + ninp, buf + einp); 1360b57cec5SDimitry Andric setp(buf + einp, buf + new_size); 1370b57cec5SDimitry Andric __pbump(nout); 1380b57cec5SDimitry Andric __strmode_ |= __allocated; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric *pptr() = static_cast<char>(__c); 1410b57cec5SDimitry Andric pbump(1); 1420b57cec5SDimitry Andric return int_type(static_cast<unsigned char>(__c)); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1455f757f3fSDimitry Andric strstreambuf::int_type strstreambuf::pbackfail(int_type __c) { 1460b57cec5SDimitry Andric if (eback() == gptr()) 1470b57cec5SDimitry Andric return EOF; 1485f757f3fSDimitry Andric if (__c == EOF) { 1490b57cec5SDimitry Andric gbump(-1); 1500b57cec5SDimitry Andric return int_type(0); 1510b57cec5SDimitry Andric } 1525f757f3fSDimitry Andric if (__strmode_ & __constant) { 1535f757f3fSDimitry Andric if (gptr()[-1] == static_cast<char>(__c)) { 1540b57cec5SDimitry Andric gbump(-1); 1550b57cec5SDimitry Andric return __c; 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric return EOF; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric gbump(-1); 1600b57cec5SDimitry Andric *gptr() = static_cast<char>(__c); 1610b57cec5SDimitry Andric return __c; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1645f757f3fSDimitry Andric strstreambuf::int_type strstreambuf::underflow() { 1655f757f3fSDimitry Andric if (gptr() == egptr()) { 1660b57cec5SDimitry Andric if (egptr() >= pptr()) 1670b57cec5SDimitry Andric return EOF; 1680b57cec5SDimitry Andric setg(eback(), gptr(), pptr()); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric return int_type(static_cast<unsigned char>(*gptr())); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1735f757f3fSDimitry Andric strstreambuf::pos_type strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) { 1740b57cec5SDimitry Andric bool pos_in = (__which & ios::in) != 0; 1750b57cec5SDimitry Andric bool pos_out = (__which & ios::out) != 0; 1765f757f3fSDimitry Andric switch (__way) { 1770b57cec5SDimitry Andric case ios::beg: 1780b57cec5SDimitry Andric case ios::end: 1795f757f3fSDimitry Andric if (!pos_in && !pos_out) 1805f757f3fSDimitry Andric return pos_type(off_type(-1)); 1810b57cec5SDimitry Andric break; 1820b57cec5SDimitry Andric case ios::cur: 1835f757f3fSDimitry Andric if (pos_in == pos_out) 1845f757f3fSDimitry Andric return pos_type(off_type(-1)); 1850b57cec5SDimitry Andric break; 1860b57cec5SDimitry Andric } 1875f757f3fSDimitry Andric 1880b57cec5SDimitry Andric if (pos_in && gptr() == nullptr) 1895f757f3fSDimitry Andric return pos_type(off_type(-1)); 1900b57cec5SDimitry Andric if (pos_out && pptr() == nullptr) 1915f757f3fSDimitry Andric return pos_type(off_type(-1)); 1925f757f3fSDimitry Andric 1930b57cec5SDimitry Andric off_type newoff; 1940b57cec5SDimitry Andric char* seekhigh = epptr() ? epptr() : egptr(); 1955f757f3fSDimitry Andric switch (__way) { 1960b57cec5SDimitry Andric case ios::beg: 1970b57cec5SDimitry Andric newoff = 0; 1980b57cec5SDimitry Andric break; 1990b57cec5SDimitry Andric case ios::cur: 2000b57cec5SDimitry Andric newoff = (pos_in ? gptr() : pptr()) - eback(); 2010b57cec5SDimitry Andric break; 2020b57cec5SDimitry Andric case ios::end: 2030b57cec5SDimitry Andric newoff = seekhigh - eback(); 2040b57cec5SDimitry Andric break; 2050b57cec5SDimitry Andric default: 20681ad6265SDimitry Andric __libcpp_unreachable(); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric newoff += __off; 2095f757f3fSDimitry Andric if (newoff < 0 || newoff > seekhigh - eback()) 2105f757f3fSDimitry Andric return pos_type(off_type(-1)); 2115f757f3fSDimitry Andric 2120b57cec5SDimitry Andric char* newpos = eback() + newoff; 2130b57cec5SDimitry Andric if (pos_in) 2145f757f3fSDimitry Andric setg(eback(), newpos, std::max(newpos, egptr())); 2155f757f3fSDimitry Andric if (pos_out) { 2160b57cec5SDimitry Andric // min(pbase, newpos), newpos, epptr() 2170b57cec5SDimitry Andric __off = epptr() - newpos; 2180b57cec5SDimitry Andric setp(min(pbase(), newpos), epptr()); 2190b57cec5SDimitry Andric __pbump((epptr() - pbase()) - __off); 2200b57cec5SDimitry Andric } 2215f757f3fSDimitry Andric return pos_type(newoff); 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2245f757f3fSDimitry Andric strstreambuf::pos_type strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) { 2250b57cec5SDimitry Andric bool pos_in = (__which & ios::in) != 0; 2260b57cec5SDimitry Andric bool pos_out = (__which & ios::out) != 0; 2275f757f3fSDimitry Andric if (!pos_in && !pos_out) 2285f757f3fSDimitry Andric return pos_type(off_type(-1)); 2295f757f3fSDimitry Andric 2305f757f3fSDimitry Andric if ((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)) 2315f757f3fSDimitry Andric return pos_type(off_type(-1)); 2325f757f3fSDimitry Andric 2330b57cec5SDimitry Andric off_type newoff = __sp; 2340b57cec5SDimitry Andric char* seekhigh = epptr() ? epptr() : egptr(); 2355f757f3fSDimitry Andric if (newoff < 0 || newoff > seekhigh - eback()) 2365f757f3fSDimitry Andric return pos_type(off_type(-1)); 2375f757f3fSDimitry Andric 2380b57cec5SDimitry Andric char* newpos = eback() + newoff; 2390b57cec5SDimitry Andric if (pos_in) 2405f757f3fSDimitry Andric setg(eback(), newpos, std::max(newpos, egptr())); 2415f757f3fSDimitry Andric if (pos_out) { 2420b57cec5SDimitry Andric // min(pbase, newpos), newpos, epptr() 2430b57cec5SDimitry Andric off_type temp = epptr() - newpos; 2440b57cec5SDimitry Andric setp(min(pbase(), newpos), epptr()); 2450b57cec5SDimitry Andric __pbump((epptr() - pbase()) - temp); 2460b57cec5SDimitry Andric } 2475f757f3fSDimitry Andric return pos_type(newoff); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2505f757f3fSDimitry Andric istrstream::~istrstream() {} 2510b57cec5SDimitry Andric 2525f757f3fSDimitry Andric ostrstream::~ostrstream() {} 2530b57cec5SDimitry Andric 2545f757f3fSDimitry Andric strstream::~strstream() {} 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 25781ad6265SDimitry Andric 25881ad6265SDimitry Andric _LIBCPP_POP_MACROS 259