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(const_cast<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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<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(const_cast<char *>(reinterpret_cast<const 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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<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(const_cast<char *>(reinterpret_cast<const 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 size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback()); 160 size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size); 161 if (new_size == 0) 162 new_size = __default_alsize; 163 char* buf = nullptr; 164 if (__palloc_) 165 buf = static_cast<char*>(__palloc_(new_size)); 166 else 167 buf = new char[new_size]; 168 if (buf == nullptr) 169 return int_type(EOF); 170 memcpy(buf, eback(), static_cast<size_t>(old_size)); 171 ptrdiff_t ninp = gptr() - eback(); 172 ptrdiff_t einp = egptr() - eback(); 173 ptrdiff_t nout = pptr() - pbase(); 174 ptrdiff_t eout = epptr() - pbase(); 175 if (__strmode_ & __allocated) 176 { 177 if (__pfree_) 178 __pfree_(eback()); 179 else 180 delete [] eback(); 181 } 182 setg(buf, buf + ninp, buf + einp); 183 setp(buf + einp, buf + einp + eout); 184 pbump(static_cast<int>(nout)); 185 __strmode_ |= __allocated; 186 } 187 *pptr() = static_cast<char>(__c); 188 pbump(1); 189 return int_type(static_cast<unsigned char>(__c)); 190 } 191 192 strstreambuf::int_type 193 strstreambuf::pbackfail(int_type __c) 194 { 195 if (eback() == gptr()) 196 return EOF; 197 if (__c == EOF) 198 { 199 gbump(-1); 200 return int_type(0); 201 } 202 if (__strmode_ & __constant) 203 { 204 if (gptr()[-1] == static_cast<char>(__c)) 205 { 206 gbump(-1); 207 return __c; 208 } 209 return EOF; 210 } 211 gbump(-1); 212 *gptr() = static_cast<char>(__c); 213 return __c; 214 } 215 216 strstreambuf::int_type 217 strstreambuf::underflow() 218 { 219 if (gptr() == egptr()) 220 { 221 if (egptr() >= pptr()) 222 return EOF; 223 setg(eback(), gptr(), pptr()); 224 } 225 return int_type(static_cast<unsigned char>(*gptr())); 226 } 227 228 strstreambuf::pos_type 229 strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) 230 { 231 off_type __p(-1); 232 bool pos_in = (__which & ios::in) != 0; 233 bool pos_out = (__which & ios::out) != 0; 234 bool legal = false; 235 switch (__way) 236 { 237 case ios::beg: 238 case ios::end: 239 if (pos_in || pos_out) 240 legal = true; 241 break; 242 case ios::cur: 243 if (pos_in != pos_out) 244 legal = true; 245 break; 246 } 247 if (pos_in && gptr() == nullptr) 248 legal = false; 249 if (pos_out && pptr() == nullptr) 250 legal = false; 251 if (legal) 252 { 253 off_type newoff; 254 char* seekhigh = epptr() ? epptr() : egptr(); 255 switch (__way) 256 { 257 case ios::beg: 258 newoff = 0; 259 break; 260 case ios::cur: 261 newoff = (pos_in ? gptr() : pptr()) - eback(); 262 break; 263 case ios::end: 264 newoff = seekhigh - eback(); 265 break; 266 } 267 newoff += __off; 268 if (0 <= newoff && newoff <= seekhigh - eback()) 269 { 270 char* newpos = eback() + newoff; 271 if (pos_in) 272 setg(eback(), newpos, _VSTD::max(newpos, egptr())); 273 if (pos_out) 274 { 275 // min(pbase, newpos), newpos, epptr() 276 __off = epptr() - newpos; 277 setp(min(pbase(), newpos), epptr()); 278 pbump(static_cast<int>((epptr() - pbase()) - __off)); 279 } 280 __p = newoff; 281 } 282 } 283 return pos_type(__p); 284 } 285 286 strstreambuf::pos_type 287 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) 288 { 289 off_type __p(-1); 290 bool pos_in = (__which & ios::in) != 0; 291 bool pos_out = (__which & ios::out) != 0; 292 if (pos_in || pos_out) 293 { 294 if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))) 295 { 296 off_type newoff = __sp; 297 char* seekhigh = epptr() ? epptr() : egptr(); 298 if (0 <= newoff && newoff <= seekhigh - eback()) 299 { 300 char* newpos = eback() + newoff; 301 if (pos_in) 302 setg(eback(), newpos, _VSTD::max(newpos, egptr())); 303 if (pos_out) 304 { 305 // min(pbase, newpos), newpos, epptr() 306 off_type temp = epptr() - newpos; 307 setp(min(pbase(), newpos), epptr()); 308 pbump(static_cast<int>((epptr() - pbase()) - temp)); 309 } 310 __p = newoff; 311 } 312 } 313 } 314 return pos_type(__p); 315 } 316 317 istrstream::~istrstream() 318 { 319 } 320 321 ostrstream::~ostrstream() 322 { 323 } 324 325 strstream::~strstream() 326 { 327 } 328 329 _LIBCPP_END_NAMESPACE_STD 330