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