blob: 83702fc72e807ce5a970ad7fa4ed24f1a199a4d2 [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();
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);
Howard Hinnant28b24882011-12-01 20:21:04 +0000188 pbump(static_cast<int>(nout));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000189 __strmode_ |= __allocated;
190 }
191 *pptr() = static_cast<char>(__c);
192 pbump(1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000193 return int_type(static_cast<unsigned char>(__c));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000194}
195
196strstreambuf::int_type
197strstreambuf::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
220strstreambuf::int_type
221strstreambuf::underflow()
222{
223 if (gptr() == egptr())
224 {
225 if (egptr() >= pptr())
226 return EOF;
227 setg(eback(), gptr(), pptr());
228 }
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000229 return int_type(static_cast<unsigned char>(*gptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000230}
231
Howard Hinnantc51e1022010-05-11 19:42:16 +0000232strstreambuf::pos_type
233strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
234{
235 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000236 bool pos_in = (__which & ios::in) != 0;
237 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000238 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)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000276 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000277 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
Howard Hinnantc51e1022010-05-11 19:42:16 +0000290strstreambuf::pos_type
291strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
292{
293 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000294 bool pos_in = (__which & ios::in) != 0;
295 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000296 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)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000306 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000307 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
321istrstream::~istrstream()
322{
323}
324
325ostrstream::~ostrstream()
326{
327}
328
329strstream::~strstream()
330{
331}
332
333_LIBCPP_END_NAMESPACE_STD