blob: 0e2d7ff21bb97f0cf0d9751f3cb0b1ef858dcb24 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------ strstream.cpp -------------------------------===//
2//
Howard Hinnantc566dc32010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00004//
Howard Hinnantee11c312010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantc51e1022010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "strstream"
11#include "algorithm"
12#include "climits"
13#include "cstring"
Eric Fiseliercebabc02016-06-19 07:08:27 +000014#include "__debug"
Howard Hinnantc51e1022010-05-11 19:42:16 +000015
16_LIBCPP_BEGIN_NAMESPACE_STD
17
18strstreambuf::strstreambuf(streamsize __alsize)
19 : __strmode_(__dynamic),
20 __alsize_(__alsize),
21 __palloc_(nullptr),
22 __pfree_(nullptr)
23{
24}
25
26strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
27 : __strmode_(__dynamic),
28 __alsize_(__default_alsize),
29 __palloc_(__palloc),
30 __pfree_(__pfree)
31{
32}
33
34void
35strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
36{
37 if (__n == 0)
Howard Hinnant28b24882011-12-01 20:21:04 +000038 __n = static_cast<streamsize>(strlen(__gnext));
Howard Hinnantc51e1022010-05-11 19:42:16 +000039 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
50strstreambuf::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
59strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
60 : __strmode_(__constant),
61 __alsize_(__default_alsize),
62 __palloc_(nullptr),
63 __pfree_(nullptr)
64{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000065 __init(const_cast<char *>(__gnext), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +000066}
67
68strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
69 : __strmode_(),
70 __alsize_(__default_alsize),
71 __palloc_(nullptr),
72 __pfree_(nullptr)
73{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000074 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
Howard Hinnantc51e1022010-05-11 19:42:16 +000075}
76
77strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
78 : __strmode_(__constant),
79 __alsize_(__default_alsize),
80 __palloc_(nullptr),
81 __pfree_(nullptr)
82{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000083 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +000084}
85
86strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
87 : __strmode_(),
88 __alsize_(__default_alsize),
89 __palloc_(nullptr),
90 __pfree_(nullptr)
91{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000092 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
Howard Hinnantc51e1022010-05-11 19:42:16 +000093}
94
95strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
96 : __strmode_(__constant),
97 __alsize_(__default_alsize),
98 __palloc_(nullptr),
99 __pfree_(nullptr)
100{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000101 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000102}
103
Howard Hinnantc51e1022010-05-11 19:42:16 +0000104strstreambuf::~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
115void
116strstreambuf::swap(strstreambuf& __rhs)
117{
118 streambuf::swap(__rhs);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000119 _VSTD::swap(__strmode_, __rhs.__strmode_);
120 _VSTD::swap(__alsize_, __rhs.__alsize_);
121 _VSTD::swap(__palloc_, __rhs.__palloc_);
122 _VSTD::swap(__pfree_, __rhs.__pfree_);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000123}
124
125void
126strstreambuf::freeze(bool __freezefl)
127{
128 if (__strmode_ & __dynamic)
129 {
130 if (__freezefl)
131 __strmode_ |= __frozen;
132 else
133 __strmode_ &= ~__frozen;
134 }
135}
136
137char*
138strstreambuf::str()
139{
140 if (__strmode_ & __dynamic)
141 __strmode_ |= __frozen;
142 return eback();
143}
144
145int
146strstreambuf::pcount() const
147{
148 return static_cast<int>(pptr() - pbase());
149}
150
151strstreambuf::int_type
152strstreambuf::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);
Marshall Cloweeb11f92013-08-14 17:53:31 +0000160 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);
Howard Hinnant25c50642013-03-19 22:16:57 +0000162 if (new_size == 0)
163 new_size = __default_alsize;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000164 char* buf = nullptr;
165 if (__palloc_)
Marshall Cloweeb11f92013-08-14 17:53:31 +0000166 buf = static_cast<char*>(__palloc_(new_size));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000167 else
168 buf = new char[new_size];
169 if (buf == nullptr)
170 return int_type(EOF);
Eric Fiseliercebabc02016-06-19 07:08:27 +0000171 if (old_size != 0) {
172 _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
173 memcpy(buf, eback(), static_cast<size_t>(old_size));
174 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000175 ptrdiff_t ninp = gptr() - eback();
176 ptrdiff_t einp = egptr() - eback();
177 ptrdiff_t nout = pptr() - pbase();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000178 if (__strmode_ & __allocated)
179 {
180 if (__pfree_)
181 __pfree_(eback());
182 else
183 delete [] eback();
184 }
185 setg(buf, buf + ninp, buf + einp);
Akira Hatanaka5c06eb52016-06-29 15:26:13 +0000186 setp(buf + einp, buf + new_size);
Howard Hinnant28b24882011-12-01 20:21:04 +0000187 pbump(static_cast<int>(nout));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000188 __strmode_ |= __allocated;
189 }
190 *pptr() = static_cast<char>(__c);
191 pbump(1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000192 return int_type(static_cast<unsigned char>(__c));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000193}
194
195strstreambuf::int_type
196strstreambuf::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
219strstreambuf::int_type
220strstreambuf::underflow()
221{
222 if (gptr() == egptr())
223 {
224 if (egptr() >= pptr())
225 return EOF;
226 setg(eback(), gptr(), pptr());
227 }
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000228 return int_type(static_cast<unsigned char>(*gptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000229}
230
Howard Hinnantc51e1022010-05-11 19:42:16 +0000231strstreambuf::pos_type
232strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
233{
234 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000235 bool pos_in = (__which & ios::in) != 0;
236 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000237 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)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000275 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276 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
Howard Hinnantc51e1022010-05-11 19:42:16 +0000289strstreambuf::pos_type
290strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
291{
292 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000293 bool pos_in = (__which & ios::in) != 0;
294 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000295 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)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000305 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000306 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
320istrstream::~istrstream()
321{
322}
323
324ostrstream::~ostrstream()
325{
326}
327
328strstream::~strstream()
329{
330}
331
332_LIBCPP_END_NAMESPACE_STD