blob: fe7e2d412065e7e58ee32d30cbf5968b8ecfefa7 [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>
Howard Hinnantc51e1022010-05-11 19:42:16 +000010#include "strstream"
11#include "algorithm"
12#include "climits"
13#include "cstring"
Eric Fiselierf0d9d5d2016-08-29 20:43:38 +000014#include "cstdlib"
Eric Fiseliercebabc02016-06-19 07:08:27 +000015#include "__debug"
Eric Fiselierf4433a32017-05-31 22:07:49 +000016#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000017
18_LIBCPP_BEGIN_NAMESPACE_STD
19
20strstreambuf::strstreambuf(streamsize __alsize)
21 : __strmode_(__dynamic),
22 __alsize_(__alsize),
23 __palloc_(nullptr),
24 __pfree_(nullptr)
25{
26}
27
28strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
29 : __strmode_(__dynamic),
30 __alsize_(__default_alsize),
31 __palloc_(__palloc),
32 __pfree_(__pfree)
33{
34}
35
36void
37strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
38{
39 if (__n == 0)
Howard Hinnant28b24882011-12-01 20:21:04 +000040 __n = static_cast<streamsize>(strlen(__gnext));
Howard Hinnantc51e1022010-05-11 19:42:16 +000041 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
52strstreambuf::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
61strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
62 : __strmode_(__constant),
63 __alsize_(__default_alsize),
64 __palloc_(nullptr),
65 __pfree_(nullptr)
66{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000067 __init(const_cast<char *>(__gnext), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +000068}
69
70strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
71 : __strmode_(),
72 __alsize_(__default_alsize),
73 __palloc_(nullptr),
74 __pfree_(nullptr)
75{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000076 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
Howard Hinnantc51e1022010-05-11 19:42:16 +000077}
78
79strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
80 : __strmode_(__constant),
81 __alsize_(__default_alsize),
82 __palloc_(nullptr),
83 __pfree_(nullptr)
84{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000085 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +000086}
87
88strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
89 : __strmode_(),
90 __alsize_(__default_alsize),
91 __palloc_(nullptr),
92 __pfree_(nullptr)
93{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000094 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
Howard Hinnantc51e1022010-05-11 19:42:16 +000095}
96
97strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
98 : __strmode_(__constant),
99 __alsize_(__default_alsize),
100 __palloc_(nullptr),
101 __pfree_(nullptr)
102{
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000103 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000104}
105
Howard Hinnantc51e1022010-05-11 19:42:16 +0000106strstreambuf::~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
117void
118strstreambuf::swap(strstreambuf& __rhs)
119{
120 streambuf::swap(__rhs);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000121 _VSTD::swap(__strmode_, __rhs.__strmode_);
122 _VSTD::swap(__alsize_, __rhs.__alsize_);
123 _VSTD::swap(__palloc_, __rhs.__palloc_);
124 _VSTD::swap(__pfree_, __rhs.__pfree_);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000125}
126
127void
128strstreambuf::freeze(bool __freezefl)
129{
130 if (__strmode_ & __dynamic)
131 {
132 if (__freezefl)
133 __strmode_ |= __frozen;
134 else
135 __strmode_ &= ~__frozen;
136 }
137}
138
139char*
140strstreambuf::str()
141{
142 if (__strmode_ & __dynamic)
143 __strmode_ |= __frozen;
144 return eback();
145}
146
147int
148strstreambuf::pcount() const
149{
150 return static_cast<int>(pptr() - pbase());
151}
152
153strstreambuf::int_type
154strstreambuf::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);
Marshall Cloweeb11f92013-08-14 17:53:31 +0000162 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);
Howard Hinnant25c50642013-03-19 22:16:57 +0000164 if (new_size == 0)
165 new_size = __default_alsize;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000166 char* buf = nullptr;
167 if (__palloc_)
Marshall Cloweeb11f92013-08-14 17:53:31 +0000168 buf = static_cast<char*>(__palloc_(new_size));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000169 else
170 buf = new char[new_size];
171 if (buf == nullptr)
172 return int_type(EOF);
Eric Fiseliercebabc02016-06-19 07:08:27 +0000173 if (old_size != 0) {
174 _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
175 memcpy(buf, eback(), static_cast<size_t>(old_size));
176 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000177 ptrdiff_t ninp = gptr() - eback();
178 ptrdiff_t einp = egptr() - eback();
179 ptrdiff_t nout = pptr() - pbase();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000180 if (__strmode_ & __allocated)
181 {
182 if (__pfree_)
183 __pfree_(eback());
184 else
185 delete [] eback();
186 }
187 setg(buf, buf + ninp, buf + einp);
Akira Hatanaka5c06eb52016-06-29 15:26:13 +0000188 setp(buf + einp, buf + new_size);
Marshall Clow33932622017-09-12 15:00:43 +0000189 __pbump(nout);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000190 __strmode_ |= __allocated;
191 }
192 *pptr() = static_cast<char>(__c);
193 pbump(1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000194 return int_type(static_cast<unsigned char>(__c));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000195}
196
197strstreambuf::int_type
198strstreambuf::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
221strstreambuf::int_type
222strstreambuf::underflow()
223{
224 if (gptr() == egptr())
225 {
226 if (egptr() >= pptr())
227 return EOF;
228 setg(eback(), gptr(), pptr());
229 }
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000230 return int_type(static_cast<unsigned char>(*gptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000231}
232
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233strstreambuf::pos_type
234strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
235{
236 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000237 bool pos_in = (__which & ios::in) != 0;
238 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000239 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;
Eric Fiselierf0d9d5d2016-08-29 20:43:38 +0000271 default:
Nikolas Klausercfe21472022-02-14 18:26:02 +0100272 __libcpp_unreachable();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000273 }
274 newoff += __off;
275 if (0 <= newoff && newoff <= seekhigh - eback())
276 {
277 char* newpos = eback() + newoff;
278 if (pos_in)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000279 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000280 if (pos_out)
281 {
282 // min(pbase, newpos), newpos, epptr()
283 __off = epptr() - newpos;
284 setp(min(pbase(), newpos), epptr());
Marshall Clow33932622017-09-12 15:00:43 +0000285 __pbump((epptr() - pbase()) - __off);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000286 }
287 __p = newoff;
288 }
289 }
290 return pos_type(__p);
291}
292
Howard Hinnantc51e1022010-05-11 19:42:16 +0000293strstreambuf::pos_type
294strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
295{
296 off_type __p(-1);
Marshall Clowdfcbb432013-10-13 01:02:45 +0000297 bool pos_in = (__which & ios::in) != 0;
298 bool pos_out = (__which & ios::out) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000299 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)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000309 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000310 if (pos_out)
311 {
312 // min(pbase, newpos), newpos, epptr()
313 off_type temp = epptr() - newpos;
314 setp(min(pbase(), newpos), epptr());
Marshall Clow33932622017-09-12 15:00:43 +0000315 __pbump((epptr() - pbase()) - temp);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000316 }
317 __p = newoff;
318 }
319 }
320 }
321 return pos_type(__p);
322}
323
324istrstream::~istrstream()
325{
326}
327
328ostrstream::~ostrstream()
329{
330}
331
332strstream::~strstream()
333{
334}
335
336_LIBCPP_END_NAMESPACE_STD