1227825Stheraven//===------------------------ strstream.cpp -------------------------------===// 2227825Stheraven// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6227825Stheraven// 7227825Stheraven//===----------------------------------------------------------------------===// 8227825Stheraven 9227825Stheraven#include "strstream" 10227825Stheraven#include "algorithm" 11227825Stheraven#include "climits" 12227825Stheraven#include "cstring" 13314564Sdim#include "cstdlib" 14309124Sdim#include "__debug" 15321369Sdim#include "__undef_macros" 16227825Stheraven 17227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 18227825Stheraven 19227825Stheravenstrstreambuf::strstreambuf(streamsize __alsize) 20227825Stheraven : __strmode_(__dynamic), 21227825Stheraven __alsize_(__alsize), 22227825Stheraven __palloc_(nullptr), 23227825Stheraven __pfree_(nullptr) 24227825Stheraven{ 25227825Stheraven} 26227825Stheraven 27227825Stheravenstrstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*)) 28227825Stheraven : __strmode_(__dynamic), 29227825Stheraven __alsize_(__default_alsize), 30227825Stheraven __palloc_(__palloc), 31227825Stheraven __pfree_(__pfree) 32227825Stheraven{ 33227825Stheraven} 34227825Stheraven 35227825Stheravenvoid 36227825Stheravenstrstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) 37227825Stheraven{ 38227825Stheraven if (__n == 0) 39232924Stheraven __n = static_cast<streamsize>(strlen(__gnext)); 40227825Stheraven else if (__n < 0) 41227825Stheraven __n = INT_MAX; 42227825Stheraven if (__pbeg == nullptr) 43227825Stheraven setg(__gnext, __gnext, __gnext + __n); 44227825Stheraven else 45227825Stheraven { 46227825Stheraven setg(__gnext, __gnext, __pbeg); 47227825Stheraven setp(__pbeg, __pbeg + __n); 48227825Stheraven } 49227825Stheraven} 50227825Stheraven 51227825Stheravenstrstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg) 52227825Stheraven : __strmode_(), 53227825Stheraven __alsize_(__default_alsize), 54227825Stheraven __palloc_(nullptr), 55227825Stheraven __pfree_(nullptr) 56227825Stheraven{ 57227825Stheraven __init(__gnext, __n, __pbeg); 58227825Stheraven} 59227825Stheraven 60227825Stheravenstrstreambuf::strstreambuf(const char* __gnext, streamsize __n) 61227825Stheraven : __strmode_(__constant), 62227825Stheraven __alsize_(__default_alsize), 63227825Stheraven __palloc_(nullptr), 64227825Stheraven __pfree_(nullptr) 65227825Stheraven{ 66276792Sdim __init(const_cast<char *>(__gnext), __n, nullptr); 67227825Stheraven} 68227825Stheraven 69227825Stheravenstrstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg) 70227825Stheraven : __strmode_(), 71227825Stheraven __alsize_(__default_alsize), 72227825Stheraven __palloc_(nullptr), 73227825Stheraven __pfree_(nullptr) 74227825Stheraven{ 75276792Sdim __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); 76227825Stheraven} 77227825Stheraven 78227825Stheravenstrstreambuf::strstreambuf(const signed char* __gnext, streamsize __n) 79227825Stheraven : __strmode_(__constant), 80227825Stheraven __alsize_(__default_alsize), 81227825Stheraven __palloc_(nullptr), 82227825Stheraven __pfree_(nullptr) 83227825Stheraven{ 84276792Sdim __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); 85227825Stheraven} 86227825Stheraven 87227825Stheravenstrstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg) 88227825Stheraven : __strmode_(), 89227825Stheraven __alsize_(__default_alsize), 90227825Stheraven __palloc_(nullptr), 91227825Stheraven __pfree_(nullptr) 92227825Stheraven{ 93276792Sdim __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); 94227825Stheraven} 95227825Stheraven 96227825Stheravenstrstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n) 97227825Stheraven : __strmode_(__constant), 98227825Stheraven __alsize_(__default_alsize), 99227825Stheraven __palloc_(nullptr), 100227825Stheraven __pfree_(nullptr) 101227825Stheraven{ 102276792Sdim __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); 103227825Stheraven} 104227825Stheraven 105227825Stheravenstrstreambuf::~strstreambuf() 106227825Stheraven{ 107227825Stheraven if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) 108227825Stheraven { 109227825Stheraven if (__pfree_) 110227825Stheraven __pfree_(eback()); 111227825Stheraven else 112227825Stheraven delete [] eback(); 113227825Stheraven } 114227825Stheraven} 115227825Stheraven 116227825Stheravenvoid 117227825Stheravenstrstreambuf::swap(strstreambuf& __rhs) 118227825Stheraven{ 119227825Stheraven streambuf::swap(__rhs); 120227825Stheraven _VSTD::swap(__strmode_, __rhs.__strmode_); 121227825Stheraven _VSTD::swap(__alsize_, __rhs.__alsize_); 122227825Stheraven _VSTD::swap(__palloc_, __rhs.__palloc_); 123227825Stheraven _VSTD::swap(__pfree_, __rhs.__pfree_); 124227825Stheraven} 125227825Stheraven 126227825Stheravenvoid 127227825Stheravenstrstreambuf::freeze(bool __freezefl) 128227825Stheraven{ 129227825Stheraven if (__strmode_ & __dynamic) 130227825Stheraven { 131227825Stheraven if (__freezefl) 132227825Stheraven __strmode_ |= __frozen; 133227825Stheraven else 134227825Stheraven __strmode_ &= ~__frozen; 135227825Stheraven } 136227825Stheraven} 137227825Stheraven 138227825Stheravenchar* 139227825Stheravenstrstreambuf::str() 140227825Stheraven{ 141227825Stheraven if (__strmode_ & __dynamic) 142227825Stheraven __strmode_ |= __frozen; 143227825Stheraven return eback(); 144227825Stheraven} 145227825Stheraven 146227825Stheravenint 147227825Stheravenstrstreambuf::pcount() const 148227825Stheraven{ 149227825Stheraven return static_cast<int>(pptr() - pbase()); 150227825Stheraven} 151227825Stheraven 152227825Stheravenstrstreambuf::int_type 153227825Stheravenstrstreambuf::overflow(int_type __c) 154227825Stheraven{ 155227825Stheraven if (__c == EOF) 156227825Stheraven return int_type(0); 157227825Stheraven if (pptr() == epptr()) 158227825Stheraven { 159227825Stheraven if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0) 160227825Stheraven return int_type(EOF); 161261272Sdim size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback()); 162261272Sdim size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size); 163249989Sdim if (new_size == 0) 164249989Sdim new_size = __default_alsize; 165227825Stheraven char* buf = nullptr; 166227825Stheraven if (__palloc_) 167261272Sdim buf = static_cast<char*>(__palloc_(new_size)); 168227825Stheraven else 169227825Stheraven buf = new char[new_size]; 170227825Stheraven if (buf == nullptr) 171227825Stheraven return int_type(EOF); 172309124Sdim if (old_size != 0) { 173309124Sdim _LIBCPP_ASSERT(eback(), "overflow copying from NULL"); 174309124Sdim memcpy(buf, eback(), static_cast<size_t>(old_size)); 175309124Sdim } 176227825Stheraven ptrdiff_t ninp = gptr() - eback(); 177227825Stheraven ptrdiff_t einp = egptr() - eback(); 178227825Stheraven ptrdiff_t nout = pptr() - pbase(); 179227825Stheraven if (__strmode_ & __allocated) 180227825Stheraven { 181227825Stheraven if (__pfree_) 182227825Stheraven __pfree_(eback()); 183227825Stheraven else 184227825Stheraven delete [] eback(); 185227825Stheraven } 186227825Stheraven setg(buf, buf + ninp, buf + einp); 187309124Sdim setp(buf + einp, buf + new_size); 188327952Sdim __pbump(nout); 189227825Stheraven __strmode_ |= __allocated; 190227825Stheraven } 191227825Stheraven *pptr() = static_cast<char>(__c); 192227825Stheraven pbump(1); 193276792Sdim return int_type(static_cast<unsigned char>(__c)); 194227825Stheraven} 195227825Stheraven 196227825Stheravenstrstreambuf::int_type 197227825Stheravenstrstreambuf::pbackfail(int_type __c) 198227825Stheraven{ 199227825Stheraven if (eback() == gptr()) 200227825Stheraven return EOF; 201227825Stheraven if (__c == EOF) 202227825Stheraven { 203227825Stheraven gbump(-1); 204227825Stheraven return int_type(0); 205227825Stheraven } 206227825Stheraven if (__strmode_ & __constant) 207227825Stheraven { 208227825Stheraven if (gptr()[-1] == static_cast<char>(__c)) 209227825Stheraven { 210227825Stheraven gbump(-1); 211227825Stheraven return __c; 212227825Stheraven } 213227825Stheraven return EOF; 214227825Stheraven } 215227825Stheraven gbump(-1); 216227825Stheraven *gptr() = static_cast<char>(__c); 217227825Stheraven return __c; 218227825Stheraven} 219227825Stheraven 220227825Stheravenstrstreambuf::int_type 221227825Stheravenstrstreambuf::underflow() 222227825Stheraven{ 223227825Stheraven if (gptr() == egptr()) 224227825Stheraven { 225227825Stheraven if (egptr() >= pptr()) 226227825Stheraven return EOF; 227227825Stheraven setg(eback(), gptr(), pptr()); 228227825Stheraven } 229276792Sdim return int_type(static_cast<unsigned char>(*gptr())); 230227825Stheraven} 231227825Stheraven 232227825Stheravenstrstreambuf::pos_type 233227825Stheravenstrstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) 234227825Stheraven{ 235227825Stheraven off_type __p(-1); 236261272Sdim bool pos_in = (__which & ios::in) != 0; 237261272Sdim bool pos_out = (__which & ios::out) != 0; 238227825Stheraven bool legal = false; 239227825Stheraven switch (__way) 240227825Stheraven { 241227825Stheraven case ios::beg: 242227825Stheraven case ios::end: 243227825Stheraven if (pos_in || pos_out) 244227825Stheraven legal = true; 245227825Stheraven break; 246227825Stheraven case ios::cur: 247227825Stheraven if (pos_in != pos_out) 248227825Stheraven legal = true; 249227825Stheraven break; 250227825Stheraven } 251227825Stheraven if (pos_in && gptr() == nullptr) 252227825Stheraven legal = false; 253227825Stheraven if (pos_out && pptr() == nullptr) 254227825Stheraven legal = false; 255227825Stheraven if (legal) 256227825Stheraven { 257227825Stheraven off_type newoff; 258227825Stheraven char* seekhigh = epptr() ? epptr() : egptr(); 259227825Stheraven switch (__way) 260227825Stheraven { 261227825Stheraven case ios::beg: 262227825Stheraven newoff = 0; 263227825Stheraven break; 264227825Stheraven case ios::cur: 265227825Stheraven newoff = (pos_in ? gptr() : pptr()) - eback(); 266227825Stheraven break; 267227825Stheraven case ios::end: 268227825Stheraven newoff = seekhigh - eback(); 269227825Stheraven break; 270314564Sdim default: 271314564Sdim _LIBCPP_UNREACHABLE(); 272227825Stheraven } 273227825Stheraven newoff += __off; 274227825Stheraven if (0 <= newoff && newoff <= seekhigh - eback()) 275227825Stheraven { 276227825Stheraven char* newpos = eback() + newoff; 277227825Stheraven if (pos_in) 278227825Stheraven setg(eback(), newpos, _VSTD::max(newpos, egptr())); 279227825Stheraven if (pos_out) 280227825Stheraven { 281227825Stheraven // min(pbase, newpos), newpos, epptr() 282227825Stheraven __off = epptr() - newpos; 283227825Stheraven setp(min(pbase(), newpos), epptr()); 284327952Sdim __pbump((epptr() - pbase()) - __off); 285227825Stheraven } 286227825Stheraven __p = newoff; 287227825Stheraven } 288227825Stheraven } 289227825Stheraven return pos_type(__p); 290227825Stheraven} 291227825Stheraven 292227825Stheravenstrstreambuf::pos_type 293227825Stheravenstrstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) 294227825Stheraven{ 295227825Stheraven off_type __p(-1); 296261272Sdim bool pos_in = (__which & ios::in) != 0; 297261272Sdim bool pos_out = (__which & ios::out) != 0; 298227825Stheraven if (pos_in || pos_out) 299227825Stheraven { 300227825Stheraven if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))) 301227825Stheraven { 302227825Stheraven off_type newoff = __sp; 303227825Stheraven char* seekhigh = epptr() ? epptr() : egptr(); 304227825Stheraven if (0 <= newoff && newoff <= seekhigh - eback()) 305227825Stheraven { 306227825Stheraven char* newpos = eback() + newoff; 307227825Stheraven if (pos_in) 308227825Stheraven setg(eback(), newpos, _VSTD::max(newpos, egptr())); 309227825Stheraven if (pos_out) 310227825Stheraven { 311227825Stheraven // min(pbase, newpos), newpos, epptr() 312227825Stheraven off_type temp = epptr() - newpos; 313227825Stheraven setp(min(pbase(), newpos), epptr()); 314327952Sdim __pbump((epptr() - pbase()) - temp); 315227825Stheraven } 316227825Stheraven __p = newoff; 317227825Stheraven } 318227825Stheraven } 319227825Stheraven } 320227825Stheraven return pos_type(__p); 321227825Stheraven} 322227825Stheraven 323227825Stheravenistrstream::~istrstream() 324227825Stheraven{ 325227825Stheraven} 326227825Stheraven 327227825Stheravenostrstream::~ostrstream() 328227825Stheraven{ 329227825Stheraven} 330227825Stheraven 331227825Stheravenstrstream::~strstream() 332227825Stheraven{ 333227825Stheraven} 334227825Stheraven 335227825Stheraven_LIBCPP_END_NAMESPACE_STD 336