1 //===------------------------ strstream.cpp -------------------------------===// 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 "strstream" 10 #include "algorithm" 11 #include "climits" 12 #include "cstring" 13 #include "cstdlib" 14 #include "__debug" 15 #include "__undef_macros" 16 17 _LIBCPP_BEGIN_NAMESPACE_STD 18 19 strstreambuf::strstreambuf(streamsize __alsize) 20 : __strmode_(__dynamic), 21 __alsize_(__alsize), 22 __palloc_(nullptr), 23 __pfree_(nullptr) 24 { 25 } 26 27 strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*)) 28 : __strmode_(__dynamic), 29 __alsize_(__default_alsize), 30 __palloc_(__palloc), 31 __pfree_(__pfree) 32 { 33 } 34 35 void 36 strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) 37 { 38 if (__n == 0) 39 __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 51 strstreambuf::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 60 strstreambuf::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 69 strstreambuf::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 78 strstreambuf::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 87 strstreambuf::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 96 strstreambuf::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 105 strstreambuf::~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 116 void 117 strstreambuf::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 126 void 127 strstreambuf::freeze(bool __freezefl) 128 { 129 if (__strmode_ & __dynamic) 130 { 131 if (__freezefl) 132 __strmode_ |= __frozen; 133 else 134 __strmode_ &= ~__frozen; 135 } 136 } 137 138 char* 139 strstreambuf::str() 140 { 141 if (__strmode_ & __dynamic) 142 __strmode_ |= __frozen; 143 return eback(); 144 } 145 146 int 147 strstreambuf::pcount() const 148 { 149 return static_cast<int>(pptr() - pbase()); 150 } 151 152 strstreambuf::int_type 153 strstreambuf::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 196 strstreambuf::int_type 197 strstreambuf::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 220 strstreambuf::int_type 221 strstreambuf::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 232 strstreambuf::pos_type 233 strstreambuf::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 292 strstreambuf::pos_type 293 strstreambuf::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 323 istrstream::~istrstream() 324 { 325 } 326 327 ostrstream::~ostrstream() 328 { 329 } 330 331 strstream::~strstream() 332 { 333 } 334 335 _LIBCPP_END_NAMESPACE_STD 336