blob: c3a7eb9a8c66dba8b6605f2315f8464799924e3f [file] [log] [blame]
Louis Dionne9bd93882021-11-17 16:25:01 -05001//===----------------------------------------------------------------------===//
Howard Hinnantc51e1022010-05-11 19:42:16 +00002//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantc51e1022010-05-11 19:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
Nikolas Klausercfe21472022-02-14 18:26:02 +01009#include <__utility/unreachable.h>
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -050010#include <__debug>
11#include <algorithm>
12#include <climits>
13#include <cstdlib>
14#include <cstring>
15#include <strstream>
16
17_LIBCPP_PUSH_MACROS
18#include <__undef_macros>
Howard Hinnantc51e1022010-05-11 19:42:16 +000019
20_LIBCPP_BEGIN_NAMESPACE_STD
21
22strstreambuf::strstreambuf(streamsize __alsize)
23 : __strmode_(__dynamic),
24 __alsize_(__alsize),
25 __palloc_(nullptr),
26 __pfree_(nullptr)
27{
28}
29
30strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
31 : __strmode_(__dynamic),
32 __alsize_(__default_alsize),
33 __palloc_(__palloc),
34 __pfree_(__pfree)
35{
36}
37
38void
39strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
40{
41 if (__n == 0)
Howard Hinnant28b24882011-12-01 20:21:04 +000042 __n = static_cast<streamsize>(strlen(__gnext));
Howard Hinnantc51e1022010-05-11 19:42:16 +000043 else if (__n < 0)
44 __n = INT_MAX;
45 if (__pbeg == nullptr)
46 setg(__gnext, __gnext, __gnext + __n);
47 else
48 {
49 setg(__gnext, __gnext, __pbeg);
50 setp(__pbeg, __pbeg + __n);
51 }
52}
53
54strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
55 : __strmode_(),
56 __alsize_(__default_alsize),
57 __palloc_(nullptr),
58 __pfree_(nullptr)
59{
60 __init(__gnext, __n, __pbeg);
61}
62
63strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
64 : __strmode_(__constant),
65 __alsize_(__default_alsize),
66 __palloc_(nullptr),
67 __pfree_(nullptr)
68{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000069 __init(const_cast<char *>(__gnext), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +000070}
71
72strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
73 : __strmode_(),
74 __alsize_(__default_alsize),
75 __palloc_(nullptr),
76 __pfree_(nullptr)
77{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000078 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
Howard Hinnantc51e1022010-05-11 19:42:16 +000079}
80
81strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
82 : __strmode_(__constant),
83 __alsize_(__default_alsize),
84 __palloc_(nullptr),
85 __pfree_(nullptr)
86{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000087 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +000088}
89
90strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
91 : __strmode_(),
92 __alsize_(__default_alsize),
93 __palloc_(nullptr),
94 __pfree_(nullptr)
95{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000096 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
Howard Hinnantc51e1022010-05-11 19:42:16 +000097}
98
99strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
100 : __strmode_(__constant),
101 __alsize_(__default_alsize),
102 __palloc_(nullptr),
103 __pfree_(nullptr)
104{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000105 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000106}
107
Howard Hinnantc51e1022010-05-11 19:42:16 +0000108strstreambuf::~strstreambuf()
109{
110 if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
111 {
112 if (__pfree_)
113 __pfree_(eback());
114 else
115 delete [] eback();
116 }
117}
118
119void
120strstreambuf::swap(strstreambuf& __rhs)
121{
122 streambuf::swap(__rhs);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000123 _VSTD::swap(__strmode_, __rhs.__strmode_);
124 _VSTD::swap(__alsize_, __rhs.__alsize_);
125 _VSTD::swap(__palloc_, __rhs.__palloc_);
126 _VSTD::swap(__pfree_, __rhs.__pfree_);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000127}
128
129void
130strstreambuf::freeze(bool __freezefl)
131{
132 if (__strmode_ & __dynamic)
133 {
134 if (__freezefl)
135 __strmode_ |= __frozen;
136 else
137 __strmode_ &= ~__frozen;
138 }
139}
140
141char*
142strstreambuf::str()
143{
144 if (__strmode_ & __dynamic)
145 __strmode_ |= __frozen;
146 return eback();
147}
148
149int
150strstreambuf::pcount() const
151{
152 return static_cast<int>(pptr() - pbase());
153}
154
155strstreambuf::int_type
156strstreambuf::overflow(int_type __c)
157{
158 if (__c == EOF)
159 return int_type(0);
160 if (pptr() == epptr())
161 {
162 if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
163 return int_type(EOF);
Marshall Cloweeb11f92013-08-14 17:53:31 +0000164 size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
165 size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
Howard Hinnant25c50642013-03-19 22:16:57 +0000166 if (new_size == 0)
167 new_size = __default_alsize;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000168 char* buf = nullptr;
169 if (__palloc_)
Marshall Cloweeb11f92013-08-14 17:53:31 +0000170 buf = static_cast<char*>(__palloc_(new_size));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000171 else
172 buf = new char[new_size];
173 if (buf == nullptr)
174 return int_type(EOF);
Eric Fiseliercebabc02016-06-19 07:08:27 +0000175 if (old_size != 0) {
176 _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
177 memcpy(buf, eback(), static_cast<size_t>(old_size));
178 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000179 ptrdiff_t ninp = gptr() - eback();
180 ptrdiff_t einp = egptr() - eback();
181 ptrdiff_t nout = pptr() - pbase();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000182 if (__strmode_ & __allocated)
183 {
184 if (__pfree_)
185 __pfree_(eback());
186 else
187 delete [] eback();
188 }
189 setg(buf, buf + ninp, buf + einp);
Akira Hatanaka5c06eb52016-06-29 15:26:13 +0000190 setp(buf + einp, buf + new_size);
Marshall Clow33932622017-09-12 15:00:43 +0000191 __pbump(nout);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000192 __strmode_ |= __allocated;
193 }
194 *pptr() = static_cast<char>(__c);
195 pbump(1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000196 return int_type(static_cast<unsigned char>(__c));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000197}
198
199strstreambuf::int_type
200strstreambuf::pbackfail(int_type __c)
201{
202 if (eback() == gptr())
203 return EOF;
204 if (__c == EOF)
205 {
206 gbump(-1);
207 return int_type(0);
208 }
209 if (__strmode_ & __constant)
210 {
211 if (gptr()[-1] == static_cast<char>(__c))
212 {
213 gbump(-1);
214 return __c;
215 }
216 return EOF;
217 }
218 gbump(-1);
219 *gptr() = static_cast<char>(__c);
220 return __c;
221}
222
223strstreambuf::int_type
224strstreambuf::underflow()
225{
226 if (gptr() == egptr())
227 {
228 if (egptr() >= pptr())
229 return EOF;
230 setg(eback(), gptr(), pptr());
231 }
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000232 return int_type(static_cast<unsigned char>(*gptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233}
234
Howard Hinnantc51e1022010-05-11 19:42:16 +0000235strstreambuf::pos_type
236strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
237{
238 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000239 bool pos_in = (__which & ios::in) != 0;
240 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000241 bool legal = false;
242 switch (__way)
243 {
244 case ios::beg:
245 case ios::end:
246 if (pos_in || pos_out)
247 legal = true;
248 break;
249 case ios::cur:
250 if (pos_in != pos_out)
251 legal = true;
252 break;
253 }
254 if (pos_in && gptr() == nullptr)
255 legal = false;
256 if (pos_out && pptr() == nullptr)
257 legal = false;
258 if (legal)
259 {
260 off_type newoff;
261 char* seekhigh = epptr() ? epptr() : egptr();
262 switch (__way)
263 {
264 case ios::beg:
265 newoff = 0;
266 break;
267 case ios::cur:
268 newoff = (pos_in ? gptr() : pptr()) - eback();
269 break;
270 case ios::end:
271 newoff = seekhigh - eback();
272 break;
Eric Fiselierf0d9d5d2016-08-29 20:43:38 +0000273 default:
Nikolas Klausercfe21472022-02-14 18:26:02 +0100274 __libcpp_unreachable();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000275 }
276 newoff += __off;
277 if (0 <= newoff && newoff <= seekhigh - eback())
278 {
279 char* newpos = eback() + newoff;
280 if (pos_in)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000281 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000282 if (pos_out)
283 {
284 // min(pbase, newpos), newpos, epptr()
285 __off = epptr() - newpos;
286 setp(min(pbase(), newpos), epptr());
Marshall Clow33932622017-09-12 15:00:43 +0000287 __pbump((epptr() - pbase()) - __off);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288 }
289 __p = newoff;
290 }
291 }
292 return pos_type(__p);
293}
294
Howard Hinnantc51e1022010-05-11 19:42:16 +0000295strstreambuf::pos_type
296strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
297{
298 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000299 bool pos_in = (__which & ios::in) != 0;
300 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000301 if (pos_in || pos_out)
302 {
303 if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
304 {
305 off_type newoff = __sp;
306 char* seekhigh = epptr() ? epptr() : egptr();
307 if (0 <= newoff && newoff <= seekhigh - eback())
308 {
309 char* newpos = eback() + newoff;
310 if (pos_in)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000311 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000312 if (pos_out)
313 {
314 // min(pbase, newpos), newpos, epptr()
315 off_type temp = epptr() - newpos;
316 setp(min(pbase(), newpos), epptr());
Marshall Clow33932622017-09-12 15:00:43 +0000317 __pbump((epptr() - pbase()) - temp);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000318 }
319 __p = newoff;
320 }
321 }
322 }
323 return pos_type(__p);
324}
325
326istrstream::~istrstream()
327{
328}
329
330ostrstream::~ostrstream()
331{
332}
333
334strstream::~strstream()
335{
336}
337
338_LIBCPP_END_NAMESPACE_STD
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -0500339
340_LIBCPP_POP_MACROS