1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
23e519524SHoward Hinnant //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63e519524SHoward Hinnant //
73e519524SHoward Hinnant //===----------------------------------------------------------------------===//
83e519524SHoward Hinnant 
9*f87aa19bSLouis Dionne #include <__assert>
102a8f9a5eSNikolas Klauser #include <__utility/unreachable.h>
11bbb0f2c7SArthur O'Dwyer #include <algorithm>
12bbb0f2c7SArthur O'Dwyer #include <climits>
13bbb0f2c7SArthur O'Dwyer #include <cstdlib>
14bbb0f2c7SArthur O'Dwyer #include <cstring>
15bbb0f2c7SArthur O'Dwyer #include <strstream>
16bbb0f2c7SArthur O'Dwyer 
17bbb0f2c7SArthur O'Dwyer _LIBCPP_PUSH_MACROS
18bbb0f2c7SArthur O'Dwyer #include <__undef_macros>
193e519524SHoward Hinnant 
203e519524SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD
213e519524SHoward Hinnant 
strstreambuf(streamsize __alsize)223e519524SHoward Hinnant strstreambuf::strstreambuf(streamsize __alsize)
233e519524SHoward Hinnant     : __strmode_(__dynamic),
243e519524SHoward Hinnant       __alsize_(__alsize),
253e519524SHoward Hinnant       __palloc_(nullptr),
263e519524SHoward Hinnant       __pfree_(nullptr)
273e519524SHoward Hinnant {
283e519524SHoward Hinnant }
293e519524SHoward Hinnant 
strstreambuf(void * (* __palloc)(size_t),void (* __pfree)(void *))303e519524SHoward Hinnant strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
313e519524SHoward Hinnant     : __strmode_(__dynamic),
323e519524SHoward Hinnant       __alsize_(__default_alsize),
333e519524SHoward Hinnant       __palloc_(__palloc),
343e519524SHoward Hinnant       __pfree_(__pfree)
353e519524SHoward Hinnant {
363e519524SHoward Hinnant }
373e519524SHoward Hinnant 
383e519524SHoward Hinnant void
__init(char * __gnext,streamsize __n,char * __pbeg)393e519524SHoward Hinnant strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
403e519524SHoward Hinnant {
413e519524SHoward Hinnant     if (__n == 0)
42c206366fSHoward Hinnant         __n = static_cast<streamsize>(strlen(__gnext));
433e519524SHoward Hinnant     else if (__n < 0)
443e519524SHoward Hinnant         __n = INT_MAX;
453e519524SHoward Hinnant     if (__pbeg == nullptr)
463e519524SHoward Hinnant         setg(__gnext, __gnext, __gnext + __n);
473e519524SHoward Hinnant     else
483e519524SHoward Hinnant     {
493e519524SHoward Hinnant         setg(__gnext, __gnext, __pbeg);
503e519524SHoward Hinnant         setp(__pbeg, __pbeg + __n);
513e519524SHoward Hinnant     }
523e519524SHoward Hinnant }
533e519524SHoward Hinnant 
strstreambuf(char * __gnext,streamsize __n,char * __pbeg)543e519524SHoward Hinnant strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
553e519524SHoward Hinnant     : __strmode_(),
563e519524SHoward Hinnant       __alsize_(__default_alsize),
573e519524SHoward Hinnant       __palloc_(nullptr),
583e519524SHoward Hinnant       __pfree_(nullptr)
593e519524SHoward Hinnant {
603e519524SHoward Hinnant     __init(__gnext, __n, __pbeg);
613e519524SHoward Hinnant }
623e519524SHoward Hinnant 
strstreambuf(const char * __gnext,streamsize __n)633e519524SHoward Hinnant strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
643e519524SHoward Hinnant     : __strmode_(__constant),
653e519524SHoward Hinnant       __alsize_(__default_alsize),
663e519524SHoward Hinnant       __palloc_(nullptr),
673e519524SHoward Hinnant       __pfree_(nullptr)
683e519524SHoward Hinnant {
69634b9dd7SJoerg Sonnenberger     __init(const_cast<char *>(__gnext), __n, nullptr);
703e519524SHoward Hinnant }
713e519524SHoward Hinnant 
strstreambuf(signed char * __gnext,streamsize __n,signed char * __pbeg)723e519524SHoward Hinnant strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
733e519524SHoward Hinnant     : __strmode_(),
743e519524SHoward Hinnant       __alsize_(__default_alsize),
753e519524SHoward Hinnant       __palloc_(nullptr),
763e519524SHoward Hinnant       __pfree_(nullptr)
773e519524SHoward Hinnant {
78634b9dd7SJoerg Sonnenberger     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
793e519524SHoward Hinnant }
803e519524SHoward Hinnant 
strstreambuf(const signed char * __gnext,streamsize __n)813e519524SHoward Hinnant strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
823e519524SHoward Hinnant     : __strmode_(__constant),
833e519524SHoward Hinnant       __alsize_(__default_alsize),
843e519524SHoward Hinnant       __palloc_(nullptr),
853e519524SHoward Hinnant       __pfree_(nullptr)
863e519524SHoward Hinnant {
87634b9dd7SJoerg Sonnenberger     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
883e519524SHoward Hinnant }
893e519524SHoward Hinnant 
strstreambuf(unsigned char * __gnext,streamsize __n,unsigned char * __pbeg)903e519524SHoward Hinnant strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
913e519524SHoward Hinnant     : __strmode_(),
923e519524SHoward Hinnant       __alsize_(__default_alsize),
933e519524SHoward Hinnant       __palloc_(nullptr),
943e519524SHoward Hinnant       __pfree_(nullptr)
953e519524SHoward Hinnant {
96634b9dd7SJoerg Sonnenberger     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
973e519524SHoward Hinnant }
983e519524SHoward Hinnant 
strstreambuf(const unsigned char * __gnext,streamsize __n)993e519524SHoward Hinnant strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
1003e519524SHoward Hinnant     : __strmode_(__constant),
1013e519524SHoward Hinnant       __alsize_(__default_alsize),
1023e519524SHoward Hinnant       __palloc_(nullptr),
1033e519524SHoward Hinnant       __pfree_(nullptr)
1043e519524SHoward Hinnant {
105634b9dd7SJoerg Sonnenberger     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
1063e519524SHoward Hinnant }
1073e519524SHoward Hinnant 
~strstreambuf()1083e519524SHoward Hinnant strstreambuf::~strstreambuf()
1093e519524SHoward Hinnant {
1103e519524SHoward Hinnant     if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
1113e519524SHoward Hinnant     {
1123e519524SHoward Hinnant         if (__pfree_)
1133e519524SHoward Hinnant             __pfree_(eback());
1143e519524SHoward Hinnant         else
1153e519524SHoward Hinnant             delete [] eback();
1163e519524SHoward Hinnant     }
1173e519524SHoward Hinnant }
1183e519524SHoward Hinnant 
1193e519524SHoward Hinnant void
swap(strstreambuf & __rhs)1203e519524SHoward Hinnant strstreambuf::swap(strstreambuf& __rhs)
1213e519524SHoward Hinnant {
1223e519524SHoward Hinnant     streambuf::swap(__rhs);
123ce48a113SHoward Hinnant     _VSTD::swap(__strmode_, __rhs.__strmode_);
124ce48a113SHoward Hinnant     _VSTD::swap(__alsize_, __rhs.__alsize_);
125ce48a113SHoward Hinnant     _VSTD::swap(__palloc_, __rhs.__palloc_);
126ce48a113SHoward Hinnant     _VSTD::swap(__pfree_, __rhs.__pfree_);
1273e519524SHoward Hinnant }
1283e519524SHoward Hinnant 
1293e519524SHoward Hinnant void
freeze(bool __freezefl)1303e519524SHoward Hinnant strstreambuf::freeze(bool __freezefl)
1313e519524SHoward Hinnant {
1323e519524SHoward Hinnant     if (__strmode_ & __dynamic)
1333e519524SHoward Hinnant     {
1343e519524SHoward Hinnant         if (__freezefl)
1353e519524SHoward Hinnant             __strmode_ |= __frozen;
1363e519524SHoward Hinnant         else
1373e519524SHoward Hinnant             __strmode_ &= ~__frozen;
1383e519524SHoward Hinnant     }
1393e519524SHoward Hinnant }
1403e519524SHoward Hinnant 
1413e519524SHoward Hinnant char*
str()1423e519524SHoward Hinnant strstreambuf::str()
1433e519524SHoward Hinnant {
1443e519524SHoward Hinnant     if (__strmode_ & __dynamic)
1453e519524SHoward Hinnant         __strmode_ |= __frozen;
1463e519524SHoward Hinnant     return eback();
1473e519524SHoward Hinnant }
1483e519524SHoward Hinnant 
1493e519524SHoward Hinnant int
pcount() const1503e519524SHoward Hinnant strstreambuf::pcount() const
1513e519524SHoward Hinnant {
1523e519524SHoward Hinnant     return static_cast<int>(pptr() - pbase());
1533e519524SHoward Hinnant }
1543e519524SHoward Hinnant 
1553e519524SHoward Hinnant strstreambuf::int_type
overflow(int_type __c)1563e519524SHoward Hinnant strstreambuf::overflow(int_type __c)
1573e519524SHoward Hinnant {
1583e519524SHoward Hinnant     if (__c == EOF)
1593e519524SHoward Hinnant         return int_type(0);
1603e519524SHoward Hinnant     if (pptr() == epptr())
1613e519524SHoward Hinnant     {
1623e519524SHoward Hinnant         if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
1633e519524SHoward Hinnant             return int_type(EOF);
164a8c7c154SMarshall Clow         size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
165a8c7c154SMarshall Clow         size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
1664bb98d09SHoward Hinnant         if (new_size == 0)
1674bb98d09SHoward Hinnant             new_size = __default_alsize;
1683e519524SHoward Hinnant         char* buf = nullptr;
1693e519524SHoward Hinnant         if (__palloc_)
170a8c7c154SMarshall Clow             buf = static_cast<char*>(__palloc_(new_size));
1713e519524SHoward Hinnant         else
1723e519524SHoward Hinnant             buf = new char[new_size];
1733e519524SHoward Hinnant         if (buf == nullptr)
1743e519524SHoward Hinnant             return int_type(EOF);
175990952b6SEric Fiselier         if (old_size != 0) {
176990952b6SEric Fiselier             _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
177c206366fSHoward Hinnant             memcpy(buf, eback(), static_cast<size_t>(old_size));
178990952b6SEric Fiselier         }
1793e519524SHoward Hinnant         ptrdiff_t ninp = gptr()  - eback();
1803e519524SHoward Hinnant         ptrdiff_t einp = egptr() - eback();
1813e519524SHoward Hinnant         ptrdiff_t nout = pptr()  - pbase();
1823e519524SHoward Hinnant         if (__strmode_ & __allocated)
1833e519524SHoward Hinnant         {
1843e519524SHoward Hinnant             if (__pfree_)
1853e519524SHoward Hinnant                 __pfree_(eback());
1863e519524SHoward Hinnant             else
1873e519524SHoward Hinnant                 delete [] eback();
1883e519524SHoward Hinnant         }
1893e519524SHoward Hinnant         setg(buf, buf + ninp, buf + einp);
1902556b769SAkira Hatanaka         setp(buf + einp, buf + new_size);
191d90758e2SMarshall Clow         __pbump(nout);
1923e519524SHoward Hinnant         __strmode_ |= __allocated;
1933e519524SHoward Hinnant     }
1943e519524SHoward Hinnant     *pptr() = static_cast<char>(__c);
1953e519524SHoward Hinnant     pbump(1);
196634b9dd7SJoerg Sonnenberger     return int_type(static_cast<unsigned char>(__c));
1973e519524SHoward Hinnant }
1983e519524SHoward Hinnant 
1993e519524SHoward Hinnant strstreambuf::int_type
pbackfail(int_type __c)2003e519524SHoward Hinnant strstreambuf::pbackfail(int_type __c)
2013e519524SHoward Hinnant {
2023e519524SHoward Hinnant     if (eback() == gptr())
2033e519524SHoward Hinnant         return EOF;
2043e519524SHoward Hinnant     if (__c == EOF)
2053e519524SHoward Hinnant     {
2063e519524SHoward Hinnant         gbump(-1);
2073e519524SHoward Hinnant         return int_type(0);
2083e519524SHoward Hinnant     }
2093e519524SHoward Hinnant     if (__strmode_ & __constant)
2103e519524SHoward Hinnant     {
2113e519524SHoward Hinnant         if (gptr()[-1] == static_cast<char>(__c))
2123e519524SHoward Hinnant         {
2133e519524SHoward Hinnant             gbump(-1);
2143e519524SHoward Hinnant             return __c;
2153e519524SHoward Hinnant         }
2163e519524SHoward Hinnant         return EOF;
2173e519524SHoward Hinnant     }
2183e519524SHoward Hinnant     gbump(-1);
2193e519524SHoward Hinnant     *gptr() = static_cast<char>(__c);
2203e519524SHoward Hinnant     return __c;
2213e519524SHoward Hinnant }
2223e519524SHoward Hinnant 
2233e519524SHoward Hinnant strstreambuf::int_type
underflow()2243e519524SHoward Hinnant strstreambuf::underflow()
2253e519524SHoward Hinnant {
2263e519524SHoward Hinnant     if (gptr() == egptr())
2273e519524SHoward Hinnant     {
2283e519524SHoward Hinnant         if (egptr() >= pptr())
2293e519524SHoward Hinnant             return EOF;
2303e519524SHoward Hinnant         setg(eback(), gptr(), pptr());
2313e519524SHoward Hinnant     }
232634b9dd7SJoerg Sonnenberger     return int_type(static_cast<unsigned char>(*gptr()));
2333e519524SHoward Hinnant }
2343e519524SHoward Hinnant 
2353e519524SHoward Hinnant strstreambuf::pos_type
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __which)2363e519524SHoward Hinnant strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
2373e519524SHoward Hinnant {
2383e519524SHoward Hinnant     off_type __p(-1);
2399f21325aSMarshall Clow     bool pos_in = (__which & ios::in) != 0;
2409f21325aSMarshall Clow     bool pos_out = (__which & ios::out) != 0;
2413e519524SHoward Hinnant     bool legal = false;
2423e519524SHoward Hinnant     switch (__way)
2433e519524SHoward Hinnant     {
2443e519524SHoward Hinnant     case ios::beg:
2453e519524SHoward Hinnant     case ios::end:
2463e519524SHoward Hinnant         if (pos_in || pos_out)
2473e519524SHoward Hinnant             legal = true;
2483e519524SHoward Hinnant         break;
2493e519524SHoward Hinnant     case ios::cur:
2503e519524SHoward Hinnant         if (pos_in != pos_out)
2513e519524SHoward Hinnant             legal = true;
2523e519524SHoward Hinnant         break;
2533e519524SHoward Hinnant     }
2543e519524SHoward Hinnant     if (pos_in && gptr() == nullptr)
2553e519524SHoward Hinnant         legal = false;
2563e519524SHoward Hinnant     if (pos_out && pptr() == nullptr)
2573e519524SHoward Hinnant         legal = false;
2583e519524SHoward Hinnant     if (legal)
2593e519524SHoward Hinnant     {
2603e519524SHoward Hinnant         off_type newoff;
2613e519524SHoward Hinnant         char* seekhigh = epptr() ? epptr() : egptr();
2623e519524SHoward Hinnant         switch (__way)
2633e519524SHoward Hinnant         {
2643e519524SHoward Hinnant         case ios::beg:
2653e519524SHoward Hinnant             newoff = 0;
2663e519524SHoward Hinnant             break;
2673e519524SHoward Hinnant         case ios::cur:
2683e519524SHoward Hinnant             newoff = (pos_in ? gptr() : pptr()) - eback();
2693e519524SHoward Hinnant             break;
2703e519524SHoward Hinnant         case ios::end:
2713e519524SHoward Hinnant             newoff = seekhigh - eback();
2723e519524SHoward Hinnant             break;
273f6ac5650SEric Fiselier         default:
2742a8f9a5eSNikolas Klauser             __libcpp_unreachable();
2753e519524SHoward Hinnant         }
2763e519524SHoward Hinnant         newoff += __off;
2773e519524SHoward Hinnant         if (0 <= newoff && newoff <= seekhigh - eback())
2783e519524SHoward Hinnant         {
2793e519524SHoward Hinnant             char* newpos = eback() + newoff;
2803e519524SHoward Hinnant             if (pos_in)
281ce48a113SHoward Hinnant                 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
2823e519524SHoward Hinnant             if (pos_out)
2833e519524SHoward Hinnant             {
2843e519524SHoward Hinnant                 // min(pbase, newpos), newpos, epptr()
2853e519524SHoward Hinnant                 __off = epptr() - newpos;
2863e519524SHoward Hinnant                 setp(min(pbase(), newpos), epptr());
287d90758e2SMarshall Clow                 __pbump((epptr() - pbase()) - __off);
2883e519524SHoward Hinnant             }
2893e519524SHoward Hinnant             __p = newoff;
2903e519524SHoward Hinnant         }
2913e519524SHoward Hinnant     }
2923e519524SHoward Hinnant     return pos_type(__p);
2933e519524SHoward Hinnant }
2943e519524SHoward Hinnant 
2953e519524SHoward Hinnant strstreambuf::pos_type
seekpos(pos_type __sp,ios_base::openmode __which)2963e519524SHoward Hinnant strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
2973e519524SHoward Hinnant {
2983e519524SHoward Hinnant     off_type __p(-1);
2999f21325aSMarshall Clow     bool pos_in = (__which & ios::in) != 0;
3009f21325aSMarshall Clow     bool pos_out = (__which & ios::out) != 0;
3013e519524SHoward Hinnant     if (pos_in || pos_out)
3023e519524SHoward Hinnant     {
3033e519524SHoward Hinnant         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
3043e519524SHoward Hinnant         {
3053e519524SHoward Hinnant             off_type newoff = __sp;
3063e519524SHoward Hinnant             char* seekhigh = epptr() ? epptr() : egptr();
3073e519524SHoward Hinnant             if (0 <= newoff && newoff <= seekhigh - eback())
3083e519524SHoward Hinnant             {
3093e519524SHoward Hinnant                 char* newpos = eback() + newoff;
3103e519524SHoward Hinnant                 if (pos_in)
311ce48a113SHoward Hinnant                     setg(eback(), newpos, _VSTD::max(newpos, egptr()));
3123e519524SHoward Hinnant                 if (pos_out)
3133e519524SHoward Hinnant                 {
3143e519524SHoward Hinnant                     // min(pbase, newpos), newpos, epptr()
3153e519524SHoward Hinnant                     off_type temp = epptr() - newpos;
3163e519524SHoward Hinnant                     setp(min(pbase(), newpos), epptr());
317d90758e2SMarshall Clow                     __pbump((epptr() - pbase()) - temp);
3183e519524SHoward Hinnant                 }
3193e519524SHoward Hinnant                 __p = newoff;
3203e519524SHoward Hinnant             }
3213e519524SHoward Hinnant         }
3223e519524SHoward Hinnant     }
3233e519524SHoward Hinnant     return pos_type(__p);
3243e519524SHoward Hinnant }
3253e519524SHoward Hinnant 
~istrstream()3263e519524SHoward Hinnant istrstream::~istrstream()
3273e519524SHoward Hinnant {
3283e519524SHoward Hinnant }
3293e519524SHoward Hinnant 
~ostrstream()3303e519524SHoward Hinnant ostrstream::~ostrstream()
3313e519524SHoward Hinnant {
3323e519524SHoward Hinnant }
3333e519524SHoward Hinnant 
~strstream()3343e519524SHoward Hinnant strstream::~strstream()
3353e519524SHoward Hinnant {
3363e519524SHoward Hinnant }
3373e519524SHoward Hinnant 
3383e519524SHoward Hinnant _LIBCPP_END_NAMESPACE_STD
339bbb0f2c7SArthur O'Dwyer 
340bbb0f2c7SArthur O'Dwyer _LIBCPP_POP_MACROS
341