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