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