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