1*0b57cec5SDimitry Andric //===------------------------ strstream.cpp -------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "strstream" 10*0b57cec5SDimitry Andric #include "algorithm" 11*0b57cec5SDimitry Andric #include "climits" 12*0b57cec5SDimitry Andric #include "cstring" 13*0b57cec5SDimitry Andric #include "cstdlib" 14*0b57cec5SDimitry Andric #include "__debug" 15*0b57cec5SDimitry Andric #include "__undef_macros" 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric strstreambuf::strstreambuf(streamsize __alsize) 20*0b57cec5SDimitry Andric : __strmode_(__dynamic), 21*0b57cec5SDimitry Andric __alsize_(__alsize), 22*0b57cec5SDimitry Andric __palloc_(nullptr), 23*0b57cec5SDimitry Andric __pfree_(nullptr) 24*0b57cec5SDimitry Andric { 25*0b57cec5SDimitry Andric } 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*)) 28*0b57cec5SDimitry Andric : __strmode_(__dynamic), 29*0b57cec5SDimitry Andric __alsize_(__default_alsize), 30*0b57cec5SDimitry Andric __palloc_(__palloc), 31*0b57cec5SDimitry Andric __pfree_(__pfree) 32*0b57cec5SDimitry Andric { 33*0b57cec5SDimitry Andric } 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric void 36*0b57cec5SDimitry Andric strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) 37*0b57cec5SDimitry Andric { 38*0b57cec5SDimitry Andric if (__n == 0) 39*0b57cec5SDimitry Andric __n = static_cast<streamsize>(strlen(__gnext)); 40*0b57cec5SDimitry Andric else if (__n < 0) 41*0b57cec5SDimitry Andric __n = INT_MAX; 42*0b57cec5SDimitry Andric if (__pbeg == nullptr) 43*0b57cec5SDimitry Andric setg(__gnext, __gnext, __gnext + __n); 44*0b57cec5SDimitry Andric else 45*0b57cec5SDimitry Andric { 46*0b57cec5SDimitry Andric setg(__gnext, __gnext, __pbeg); 47*0b57cec5SDimitry Andric setp(__pbeg, __pbeg + __n); 48*0b57cec5SDimitry Andric } 49*0b57cec5SDimitry Andric } 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg) 52*0b57cec5SDimitry Andric : __strmode_(), 53*0b57cec5SDimitry Andric __alsize_(__default_alsize), 54*0b57cec5SDimitry Andric __palloc_(nullptr), 55*0b57cec5SDimitry Andric __pfree_(nullptr) 56*0b57cec5SDimitry Andric { 57*0b57cec5SDimitry Andric __init(__gnext, __n, __pbeg); 58*0b57cec5SDimitry Andric } 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric strstreambuf::strstreambuf(const char* __gnext, streamsize __n) 61*0b57cec5SDimitry Andric : __strmode_(__constant), 62*0b57cec5SDimitry Andric __alsize_(__default_alsize), 63*0b57cec5SDimitry Andric __palloc_(nullptr), 64*0b57cec5SDimitry Andric __pfree_(nullptr) 65*0b57cec5SDimitry Andric { 66*0b57cec5SDimitry Andric __init(const_cast<char *>(__gnext), __n, nullptr); 67*0b57cec5SDimitry Andric } 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg) 70*0b57cec5SDimitry Andric : __strmode_(), 71*0b57cec5SDimitry Andric __alsize_(__default_alsize), 72*0b57cec5SDimitry Andric __palloc_(nullptr), 73*0b57cec5SDimitry Andric __pfree_(nullptr) 74*0b57cec5SDimitry Andric { 75*0b57cec5SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); 76*0b57cec5SDimitry Andric } 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n) 79*0b57cec5SDimitry Andric : __strmode_(__constant), 80*0b57cec5SDimitry Andric __alsize_(__default_alsize), 81*0b57cec5SDimitry Andric __palloc_(nullptr), 82*0b57cec5SDimitry Andric __pfree_(nullptr) 83*0b57cec5SDimitry Andric { 84*0b57cec5SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg) 88*0b57cec5SDimitry Andric : __strmode_(), 89*0b57cec5SDimitry Andric __alsize_(__default_alsize), 90*0b57cec5SDimitry Andric __palloc_(nullptr), 91*0b57cec5SDimitry Andric __pfree_(nullptr) 92*0b57cec5SDimitry Andric { 93*0b57cec5SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n) 97*0b57cec5SDimitry Andric : __strmode_(__constant), 98*0b57cec5SDimitry Andric __alsize_(__default_alsize), 99*0b57cec5SDimitry Andric __palloc_(nullptr), 100*0b57cec5SDimitry Andric __pfree_(nullptr) 101*0b57cec5SDimitry Andric { 102*0b57cec5SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric strstreambuf::~strstreambuf() 106*0b57cec5SDimitry Andric { 107*0b57cec5SDimitry Andric if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) 108*0b57cec5SDimitry Andric { 109*0b57cec5SDimitry Andric if (__pfree_) 110*0b57cec5SDimitry Andric __pfree_(eback()); 111*0b57cec5SDimitry Andric else 112*0b57cec5SDimitry Andric delete [] eback(); 113*0b57cec5SDimitry Andric } 114*0b57cec5SDimitry Andric } 115*0b57cec5SDimitry Andric 116*0b57cec5SDimitry Andric void 117*0b57cec5SDimitry Andric strstreambuf::swap(strstreambuf& __rhs) 118*0b57cec5SDimitry Andric { 119*0b57cec5SDimitry Andric streambuf::swap(__rhs); 120*0b57cec5SDimitry Andric _VSTD::swap(__strmode_, __rhs.__strmode_); 121*0b57cec5SDimitry Andric _VSTD::swap(__alsize_, __rhs.__alsize_); 122*0b57cec5SDimitry Andric _VSTD::swap(__palloc_, __rhs.__palloc_); 123*0b57cec5SDimitry Andric _VSTD::swap(__pfree_, __rhs.__pfree_); 124*0b57cec5SDimitry Andric } 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric void 127*0b57cec5SDimitry Andric strstreambuf::freeze(bool __freezefl) 128*0b57cec5SDimitry Andric { 129*0b57cec5SDimitry Andric if (__strmode_ & __dynamic) 130*0b57cec5SDimitry Andric { 131*0b57cec5SDimitry Andric if (__freezefl) 132*0b57cec5SDimitry Andric __strmode_ |= __frozen; 133*0b57cec5SDimitry Andric else 134*0b57cec5SDimitry Andric __strmode_ &= ~__frozen; 135*0b57cec5SDimitry Andric } 136*0b57cec5SDimitry Andric } 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric char* 139*0b57cec5SDimitry Andric strstreambuf::str() 140*0b57cec5SDimitry Andric { 141*0b57cec5SDimitry Andric if (__strmode_ & __dynamic) 142*0b57cec5SDimitry Andric __strmode_ |= __frozen; 143*0b57cec5SDimitry Andric return eback(); 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric int 147*0b57cec5SDimitry Andric strstreambuf::pcount() const 148*0b57cec5SDimitry Andric { 149*0b57cec5SDimitry Andric return static_cast<int>(pptr() - pbase()); 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric strstreambuf::int_type 153*0b57cec5SDimitry Andric strstreambuf::overflow(int_type __c) 154*0b57cec5SDimitry Andric { 155*0b57cec5SDimitry Andric if (__c == EOF) 156*0b57cec5SDimitry Andric return int_type(0); 157*0b57cec5SDimitry Andric if (pptr() == epptr()) 158*0b57cec5SDimitry Andric { 159*0b57cec5SDimitry Andric if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0) 160*0b57cec5SDimitry Andric return int_type(EOF); 161*0b57cec5SDimitry Andric size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback()); 162*0b57cec5SDimitry Andric size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size); 163*0b57cec5SDimitry Andric if (new_size == 0) 164*0b57cec5SDimitry Andric new_size = __default_alsize; 165*0b57cec5SDimitry Andric char* buf = nullptr; 166*0b57cec5SDimitry Andric if (__palloc_) 167*0b57cec5SDimitry Andric buf = static_cast<char*>(__palloc_(new_size)); 168*0b57cec5SDimitry Andric else 169*0b57cec5SDimitry Andric buf = new char[new_size]; 170*0b57cec5SDimitry Andric if (buf == nullptr) 171*0b57cec5SDimitry Andric return int_type(EOF); 172*0b57cec5SDimitry Andric if (old_size != 0) { 173*0b57cec5SDimitry Andric _LIBCPP_ASSERT(eback(), "overflow copying from NULL"); 174*0b57cec5SDimitry Andric memcpy(buf, eback(), static_cast<size_t>(old_size)); 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric ptrdiff_t ninp = gptr() - eback(); 177*0b57cec5SDimitry Andric ptrdiff_t einp = egptr() - eback(); 178*0b57cec5SDimitry Andric ptrdiff_t nout = pptr() - pbase(); 179*0b57cec5SDimitry Andric if (__strmode_ & __allocated) 180*0b57cec5SDimitry Andric { 181*0b57cec5SDimitry Andric if (__pfree_) 182*0b57cec5SDimitry Andric __pfree_(eback()); 183*0b57cec5SDimitry Andric else 184*0b57cec5SDimitry Andric delete [] eback(); 185*0b57cec5SDimitry Andric } 186*0b57cec5SDimitry Andric setg(buf, buf + ninp, buf + einp); 187*0b57cec5SDimitry Andric setp(buf + einp, buf + new_size); 188*0b57cec5SDimitry Andric __pbump(nout); 189*0b57cec5SDimitry Andric __strmode_ |= __allocated; 190*0b57cec5SDimitry Andric } 191*0b57cec5SDimitry Andric *pptr() = static_cast<char>(__c); 192*0b57cec5SDimitry Andric pbump(1); 193*0b57cec5SDimitry Andric return int_type(static_cast<unsigned char>(__c)); 194*0b57cec5SDimitry Andric } 195*0b57cec5SDimitry Andric 196*0b57cec5SDimitry Andric strstreambuf::int_type 197*0b57cec5SDimitry Andric strstreambuf::pbackfail(int_type __c) 198*0b57cec5SDimitry Andric { 199*0b57cec5SDimitry Andric if (eback() == gptr()) 200*0b57cec5SDimitry Andric return EOF; 201*0b57cec5SDimitry Andric if (__c == EOF) 202*0b57cec5SDimitry Andric { 203*0b57cec5SDimitry Andric gbump(-1); 204*0b57cec5SDimitry Andric return int_type(0); 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric if (__strmode_ & __constant) 207*0b57cec5SDimitry Andric { 208*0b57cec5SDimitry Andric if (gptr()[-1] == static_cast<char>(__c)) 209*0b57cec5SDimitry Andric { 210*0b57cec5SDimitry Andric gbump(-1); 211*0b57cec5SDimitry Andric return __c; 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric return EOF; 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric gbump(-1); 216*0b57cec5SDimitry Andric *gptr() = static_cast<char>(__c); 217*0b57cec5SDimitry Andric return __c; 218*0b57cec5SDimitry Andric } 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric strstreambuf::int_type 221*0b57cec5SDimitry Andric strstreambuf::underflow() 222*0b57cec5SDimitry Andric { 223*0b57cec5SDimitry Andric if (gptr() == egptr()) 224*0b57cec5SDimitry Andric { 225*0b57cec5SDimitry Andric if (egptr() >= pptr()) 226*0b57cec5SDimitry Andric return EOF; 227*0b57cec5SDimitry Andric setg(eback(), gptr(), pptr()); 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric return int_type(static_cast<unsigned char>(*gptr())); 230*0b57cec5SDimitry Andric } 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric strstreambuf::pos_type 233*0b57cec5SDimitry Andric strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) 234*0b57cec5SDimitry Andric { 235*0b57cec5SDimitry Andric off_type __p(-1); 236*0b57cec5SDimitry Andric bool pos_in = (__which & ios::in) != 0; 237*0b57cec5SDimitry Andric bool pos_out = (__which & ios::out) != 0; 238*0b57cec5SDimitry Andric bool legal = false; 239*0b57cec5SDimitry Andric switch (__way) 240*0b57cec5SDimitry Andric { 241*0b57cec5SDimitry Andric case ios::beg: 242*0b57cec5SDimitry Andric case ios::end: 243*0b57cec5SDimitry Andric if (pos_in || pos_out) 244*0b57cec5SDimitry Andric legal = true; 245*0b57cec5SDimitry Andric break; 246*0b57cec5SDimitry Andric case ios::cur: 247*0b57cec5SDimitry Andric if (pos_in != pos_out) 248*0b57cec5SDimitry Andric legal = true; 249*0b57cec5SDimitry Andric break; 250*0b57cec5SDimitry Andric } 251*0b57cec5SDimitry Andric if (pos_in && gptr() == nullptr) 252*0b57cec5SDimitry Andric legal = false; 253*0b57cec5SDimitry Andric if (pos_out && pptr() == nullptr) 254*0b57cec5SDimitry Andric legal = false; 255*0b57cec5SDimitry Andric if (legal) 256*0b57cec5SDimitry Andric { 257*0b57cec5SDimitry Andric off_type newoff; 258*0b57cec5SDimitry Andric char* seekhigh = epptr() ? epptr() : egptr(); 259*0b57cec5SDimitry Andric switch (__way) 260*0b57cec5SDimitry Andric { 261*0b57cec5SDimitry Andric case ios::beg: 262*0b57cec5SDimitry Andric newoff = 0; 263*0b57cec5SDimitry Andric break; 264*0b57cec5SDimitry Andric case ios::cur: 265*0b57cec5SDimitry Andric newoff = (pos_in ? gptr() : pptr()) - eback(); 266*0b57cec5SDimitry Andric break; 267*0b57cec5SDimitry Andric case ios::end: 268*0b57cec5SDimitry Andric newoff = seekhigh - eback(); 269*0b57cec5SDimitry Andric break; 270*0b57cec5SDimitry Andric default: 271*0b57cec5SDimitry Andric _LIBCPP_UNREACHABLE(); 272*0b57cec5SDimitry Andric } 273*0b57cec5SDimitry Andric newoff += __off; 274*0b57cec5SDimitry Andric if (0 <= newoff && newoff <= seekhigh - eback()) 275*0b57cec5SDimitry Andric { 276*0b57cec5SDimitry Andric char* newpos = eback() + newoff; 277*0b57cec5SDimitry Andric if (pos_in) 278*0b57cec5SDimitry Andric setg(eback(), newpos, _VSTD::max(newpos, egptr())); 279*0b57cec5SDimitry Andric if (pos_out) 280*0b57cec5SDimitry Andric { 281*0b57cec5SDimitry Andric // min(pbase, newpos), newpos, epptr() 282*0b57cec5SDimitry Andric __off = epptr() - newpos; 283*0b57cec5SDimitry Andric setp(min(pbase(), newpos), epptr()); 284*0b57cec5SDimitry Andric __pbump((epptr() - pbase()) - __off); 285*0b57cec5SDimitry Andric } 286*0b57cec5SDimitry Andric __p = newoff; 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric return pos_type(__p); 290*0b57cec5SDimitry Andric } 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric strstreambuf::pos_type 293*0b57cec5SDimitry Andric strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) 294*0b57cec5SDimitry Andric { 295*0b57cec5SDimitry Andric off_type __p(-1); 296*0b57cec5SDimitry Andric bool pos_in = (__which & ios::in) != 0; 297*0b57cec5SDimitry Andric bool pos_out = (__which & ios::out) != 0; 298*0b57cec5SDimitry Andric if (pos_in || pos_out) 299*0b57cec5SDimitry Andric { 300*0b57cec5SDimitry Andric if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))) 301*0b57cec5SDimitry Andric { 302*0b57cec5SDimitry Andric off_type newoff = __sp; 303*0b57cec5SDimitry Andric char* seekhigh = epptr() ? epptr() : egptr(); 304*0b57cec5SDimitry Andric if (0 <= newoff && newoff <= seekhigh - eback()) 305*0b57cec5SDimitry Andric { 306*0b57cec5SDimitry Andric char* newpos = eback() + newoff; 307*0b57cec5SDimitry Andric if (pos_in) 308*0b57cec5SDimitry Andric setg(eback(), newpos, _VSTD::max(newpos, egptr())); 309*0b57cec5SDimitry Andric if (pos_out) 310*0b57cec5SDimitry Andric { 311*0b57cec5SDimitry Andric // min(pbase, newpos), newpos, epptr() 312*0b57cec5SDimitry Andric off_type temp = epptr() - newpos; 313*0b57cec5SDimitry Andric setp(min(pbase(), newpos), epptr()); 314*0b57cec5SDimitry Andric __pbump((epptr() - pbase()) - temp); 315*0b57cec5SDimitry Andric } 316*0b57cec5SDimitry Andric __p = newoff; 317*0b57cec5SDimitry Andric } 318*0b57cec5SDimitry Andric } 319*0b57cec5SDimitry Andric } 320*0b57cec5SDimitry Andric return pos_type(__p); 321*0b57cec5SDimitry Andric } 322*0b57cec5SDimitry Andric 323*0b57cec5SDimitry Andric istrstream::~istrstream() 324*0b57cec5SDimitry Andric { 325*0b57cec5SDimitry Andric } 326*0b57cec5SDimitry Andric 327*0b57cec5SDimitry Andric ostrstream::~ostrstream() 328*0b57cec5SDimitry Andric { 329*0b57cec5SDimitry Andric } 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric strstream::~strstream() 332*0b57cec5SDimitry Andric { 333*0b57cec5SDimitry Andric } 334*0b57cec5SDimitry Andric 335*0b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 336