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