strstream.cpp revision 227825
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 17strstreambuf::strstreambuf(streamsize __alsize) 18 : __strmode_(__dynamic), 19 __alsize_(__alsize), 20 __palloc_(nullptr), 21 __pfree_(nullptr) 22{ 23} 24 25strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*)) 26 : __strmode_(__dynamic), 27 __alsize_(__default_alsize), 28 __palloc_(__palloc), 29 __pfree_(__pfree) 30{ 31} 32 33void 34strstreambuf::__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 49strstreambuf::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 58strstreambuf::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 67strstreambuf::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 76strstreambuf::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 85strstreambuf::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 94strstreambuf::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 103strstreambuf::~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 114void 115strstreambuf::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 124void 125strstreambuf::freeze(bool __freezefl) 126{ 127 if (__strmode_ & __dynamic) 128 { 129 if (__freezefl) 130 __strmode_ |= __frozen; 131 else 132 __strmode_ &= ~__frozen; 133 } 134} 135 136char* 137strstreambuf::str() 138{ 139 if (__strmode_ & __dynamic) 140 __strmode_ |= __frozen; 141 return eback(); 142} 143 144int 145strstreambuf::pcount() const 146{ 147 return static_cast<int>(pptr() - pbase()); 148} 149 150strstreambuf::int_type 151strstreambuf::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_(new_size)); 164 else 165 buf = new char[new_size]; 166 if (buf == nullptr) 167 return int_type(EOF); 168 memcpy(buf, eback(), 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(nout); 183 __strmode_ |= __allocated; 184 } 185 *pptr() = static_cast<char>(__c); 186 pbump(1); 187 return int_type((unsigned char)__c); 188} 189 190strstreambuf::int_type 191strstreambuf::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 214strstreambuf::int_type 215strstreambuf::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 226strstreambuf::pos_type 227strstreambuf::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 284strstreambuf::pos_type 285strstreambuf::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 315istrstream::~istrstream() 316{ 317} 318 319ostrstream::~ostrstream() 320{ 321} 322 323strstream::~strstream() 324{ 325} 326 327_LIBCPP_END_NAMESPACE_STD 328