1 //===------------------------ strstream.cpp -------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. 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 #ifdef _LIBCPP_MOVE 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 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 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, 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 320 strstreambuf::pos_type 321 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) 322 { 323 off_type __p(-1); 324 bool pos_in = __which & ios::in; 325 bool pos_out = __which & ios::out; 326 if (pos_in || pos_out) 327 { 328 if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))) 329 { 330 off_type newoff = __sp; 331 char* seekhigh = epptr() ? epptr() : egptr(); 332 if (0 <= newoff && newoff <= seekhigh - eback()) 333 { 334 char* newpos = eback() + newoff; 335 if (pos_in) 336 setg(eback(), newpos, max(newpos, egptr())); 337 if (pos_out) 338 { 339 // min(pbase, newpos), newpos, epptr() 340 off_type temp = epptr() - newpos; 341 setp(min(pbase(), newpos), epptr()); 342 pbump(static_cast<int>((epptr() - pbase()) - temp)); 343 } 344 __p = newoff; 345 } 346 } 347 } 348 return pos_type(__p); 349 } 350 351 istrstream::~istrstream() 352 { 353 } 354 355 ostrstream::~ostrstream() 356 { 357 } 358 359 strstream::~strstream() 360 { 361 } 362 363 _LIBCPP_END_NAMESPACE_STD 364