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 } 134 135 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 136 137 strstreambuf::~strstreambuf() 138 { 139 if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) 140 { 141 if (__pfree_) 142 __pfree_(eback()); 143 else 144 delete [] eback(); 145 } 146 } 147 148 void 149 strstreambuf::swap(strstreambuf& __rhs) 150 { 151 streambuf::swap(__rhs); 152 _STD::swap(__strmode_, __rhs.__strmode_); 153 _STD::swap(__alsize_, __rhs.__alsize_); 154 _STD::swap(__palloc_, __rhs.__palloc_); 155 _STD::swap(__pfree_, __rhs.__pfree_); 156 } 157 158 void 159 strstreambuf::freeze(bool __freezefl) 160 { 161 if (__strmode_ & __dynamic) 162 { 163 if (__freezefl) 164 __strmode_ |= __frozen; 165 else 166 __strmode_ &= ~__frozen; 167 } 168 } 169 170 char* 171 strstreambuf::str() 172 { 173 if (__strmode_ & __dynamic) 174 __strmode_ |= __frozen; 175 return eback(); 176 } 177 178 int 179 strstreambuf::pcount() const 180 { 181 return static_cast<int>(pptr() - pbase()); 182 } 183 184 strstreambuf::int_type 185 strstreambuf::overflow(int_type __c) 186 { 187 if (__c == EOF) 188 return int_type(0); 189 if (pptr() == epptr()) 190 { 191 if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0) 192 return int_type(EOF); 193 streamsize old_size = (epptr() ? epptr() : egptr()) - eback(); 194 streamsize new_size = max<streamsize>(__alsize_, 2*old_size); 195 char* buf = nullptr; 196 if (__palloc_) 197 buf = static_cast<char*>(__palloc_(new_size)); 198 else 199 buf = new char[new_size]; 200 if (buf == nullptr) 201 return int_type(EOF); 202 memcpy(buf, eback(), old_size); 203 ptrdiff_t ninp = gptr() - eback(); 204 ptrdiff_t einp = egptr() - eback(); 205 ptrdiff_t nout = pptr() - pbase(); 206 ptrdiff_t eout = epptr() - pbase(); 207 if (__strmode_ & __allocated) 208 { 209 if (__pfree_) 210 __pfree_(eback()); 211 else 212 delete [] eback(); 213 } 214 setg(buf, buf + ninp, buf + einp); 215 setp(buf + einp, buf + einp + eout); 216 pbump(nout); 217 __strmode_ |= __allocated; 218 } 219 *pptr() = static_cast<char>(__c); 220 pbump(1); 221 return int_type((unsigned char)__c); 222 } 223 224 strstreambuf::int_type 225 strstreambuf::pbackfail(int_type __c) 226 { 227 if (eback() == gptr()) 228 return EOF; 229 if (__c == EOF) 230 { 231 gbump(-1); 232 return int_type(0); 233 } 234 if (__strmode_ & __constant) 235 { 236 if (gptr()[-1] == static_cast<char>(__c)) 237 { 238 gbump(-1); 239 return __c; 240 } 241 return EOF; 242 } 243 gbump(-1); 244 *gptr() = static_cast<char>(__c); 245 return __c; 246 } 247 248 strstreambuf::int_type 249 strstreambuf::underflow() 250 { 251 if (gptr() == egptr()) 252 { 253 if (egptr() >= pptr()) 254 return EOF; 255 setg(eback(), gptr(), pptr()); 256 } 257 return int_type((unsigned char)*gptr()); 258 } 259 260 strstreambuf::pos_type 261 strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) 262 { 263 off_type __p(-1); 264 bool pos_in = __which & ios::in; 265 bool pos_out = __which & ios::out; 266 bool legal = false; 267 switch (__way) 268 { 269 case ios::beg: 270 case ios::end: 271 if (pos_in || pos_out) 272 legal = true; 273 break; 274 case ios::cur: 275 if (pos_in != pos_out) 276 legal = true; 277 break; 278 } 279 if (pos_in && gptr() == nullptr) 280 legal = false; 281 if (pos_out && pptr() == nullptr) 282 legal = false; 283 if (legal) 284 { 285 off_type newoff; 286 char* seekhigh = epptr() ? epptr() : egptr(); 287 switch (__way) 288 { 289 case ios::beg: 290 newoff = 0; 291 break; 292 case ios::cur: 293 newoff = (pos_in ? gptr() : pptr()) - eback(); 294 break; 295 case ios::end: 296 newoff = seekhigh - eback(); 297 break; 298 } 299 newoff += __off; 300 if (0 <= newoff && newoff <= seekhigh - eback()) 301 { 302 char* newpos = eback() + newoff; 303 if (pos_in) 304 setg(eback(), newpos, max(newpos, egptr())); 305 if (pos_out) 306 { 307 // min(pbase, newpos), newpos, epptr() 308 __off = epptr() - newpos; 309 setp(min(pbase(), newpos), epptr()); 310 pbump(static_cast<int>((epptr() - pbase()) - __off)); 311 } 312 __p = newoff; 313 } 314 } 315 return pos_type(__p); 316 } 317 318 strstreambuf::pos_type 319 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) 320 { 321 off_type __p(-1); 322 bool pos_in = __which & ios::in; 323 bool pos_out = __which & ios::out; 324 if (pos_in || pos_out) 325 { 326 if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))) 327 { 328 off_type newoff = __sp; 329 char* seekhigh = epptr() ? epptr() : egptr(); 330 if (0 <= newoff && newoff <= seekhigh - eback()) 331 { 332 char* newpos = eback() + newoff; 333 if (pos_in) 334 setg(eback(), newpos, max(newpos, egptr())); 335 if (pos_out) 336 { 337 // min(pbase, newpos), newpos, epptr() 338 off_type temp = epptr() - newpos; 339 setp(min(pbase(), newpos), epptr()); 340 pbump(static_cast<int>((epptr() - pbase()) - temp)); 341 } 342 __p = newoff; 343 } 344 } 345 } 346 return pos_type(__p); 347 } 348 349 istrstream::~istrstream() 350 { 351 } 352 353 ostrstream::~ostrstream() 354 { 355 } 356 357 strstream::~strstream() 358 { 359 } 360 361 _LIBCPP_END_NAMESPACE_STD 362