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