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