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
strstreambuf(streamsize __alsize)220b57cec5SDimitry Andric strstreambuf::strstreambuf(streamsize __alsize)
235f757f3fSDimitry Andric : __strmode_(__dynamic), __alsize_(__alsize), __palloc_(nullptr), __pfree_(nullptr) {}
240b57cec5SDimitry Andric
strstreambuf(void * (* __palloc)(size_t),void (* __pfree)(void *))250b57cec5SDimitry Andric strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
265f757f3fSDimitry Andric : __strmode_(__dynamic), __alsize_(__default_alsize), __palloc_(__palloc), __pfree_(__pfree) {}
270b57cec5SDimitry Andric
__init(char * __gnext,streamsize __n,char * __pbeg)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
strstreambuf(char * __gnext,streamsize __n,char * __pbeg)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
strstreambuf(const char * __gnext,streamsize __n)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
strstreambuf(signed char * __gnext,streamsize __n,signed char * __pbeg)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
strstreambuf(const signed char * __gnext,streamsize __n)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
strstreambuf(unsigned char * __gnext,streamsize __n,unsigned char * __pbeg)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
strstreambuf(const unsigned char * __gnext,streamsize __n)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
~strstreambuf()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
swap(strstreambuf & __rhs)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
freeze(bool __freezefl)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
str()975f757f3fSDimitry Andric char* strstreambuf::str() {
980b57cec5SDimitry Andric if (__strmode_ & __dynamic)
990b57cec5SDimitry Andric __strmode_ |= __frozen;
1000b57cec5SDimitry Andric return eback();
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
pcount() const1035f757f3fSDimitry Andric int strstreambuf::pcount() const { return static_cast<int>(pptr() - pbase()); }
1040b57cec5SDimitry Andric
overflow(int_type __c)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
pbackfail(int_type __c)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
underflow()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
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __which)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
seekpos(pos_type __sp,ios_base::openmode __which)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
~istrstream()2505f757f3fSDimitry Andric istrstream::~istrstream() {}
2510b57cec5SDimitry Andric
~ostrstream()2525f757f3fSDimitry Andric ostrstream::~ostrstream() {}
2530b57cec5SDimitry Andric
~strstream()2545f757f3fSDimitry Andric strstream::~strstream() {}
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
25781ad6265SDimitry Andric
25881ad6265SDimitry Andric _LIBCPP_POP_MACROS
259