1 //===----------------------------------------------------------------------===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include <__assert>
10 #include <__utility/unreachable.h>
11 #include <algorithm>
12 #include <climits>
13 #include <cstdlib>
14 #include <cstring>
15 #include <strstream>
16
17 _LIBCPP_PUSH_MACROS
18 #include <__undef_macros>
19
20 _LIBCPP_BEGIN_NAMESPACE_STD
21
strstreambuf(streamsize __alsize)22 strstreambuf::strstreambuf(streamsize __alsize)
23 : __strmode_(__dynamic),
24 __alsize_(__alsize),
25 __palloc_(nullptr),
26 __pfree_(nullptr)
27 {
28 }
29
strstreambuf(void * (* __palloc)(size_t),void (* __pfree)(void *))30 strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
31 : __strmode_(__dynamic),
32 __alsize_(__default_alsize),
33 __palloc_(__palloc),
34 __pfree_(__pfree)
35 {
36 }
37
38 void
__init(char * __gnext,streamsize __n,char * __pbeg)39 strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
40 {
41 if (__n == 0)
42 __n = static_cast<streamsize>(strlen(__gnext));
43 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
strstreambuf(char * __gnext,streamsize __n,char * __pbeg)54 strstreambuf::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
strstreambuf(const char * __gnext,streamsize __n)63 strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
64 : __strmode_(__constant),
65 __alsize_(__default_alsize),
66 __palloc_(nullptr),
67 __pfree_(nullptr)
68 {
69 __init(const_cast<char *>(__gnext), __n, nullptr);
70 }
71
strstreambuf(signed char * __gnext,streamsize __n,signed char * __pbeg)72 strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
73 : __strmode_(),
74 __alsize_(__default_alsize),
75 __palloc_(nullptr),
76 __pfree_(nullptr)
77 {
78 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
79 }
80
strstreambuf(const signed char * __gnext,streamsize __n)81 strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
82 : __strmode_(__constant),
83 __alsize_(__default_alsize),
84 __palloc_(nullptr),
85 __pfree_(nullptr)
86 {
87 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
88 }
89
strstreambuf(unsigned char * __gnext,streamsize __n,unsigned char * __pbeg)90 strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
91 : __strmode_(),
92 __alsize_(__default_alsize),
93 __palloc_(nullptr),
94 __pfree_(nullptr)
95 {
96 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
97 }
98
strstreambuf(const unsigned char * __gnext,streamsize __n)99 strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
100 : __strmode_(__constant),
101 __alsize_(__default_alsize),
102 __palloc_(nullptr),
103 __pfree_(nullptr)
104 {
105 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
106 }
107
~strstreambuf()108 strstreambuf::~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
119 void
swap(strstreambuf & __rhs)120 strstreambuf::swap(strstreambuf& __rhs)
121 {
122 streambuf::swap(__rhs);
123 _VSTD::swap(__strmode_, __rhs.__strmode_);
124 _VSTD::swap(__alsize_, __rhs.__alsize_);
125 _VSTD::swap(__palloc_, __rhs.__palloc_);
126 _VSTD::swap(__pfree_, __rhs.__pfree_);
127 }
128
129 void
freeze(bool __freezefl)130 strstreambuf::freeze(bool __freezefl)
131 {
132 if (__strmode_ & __dynamic)
133 {
134 if (__freezefl)
135 __strmode_ |= __frozen;
136 else
137 __strmode_ &= ~__frozen;
138 }
139 }
140
141 char*
str()142 strstreambuf::str()
143 {
144 if (__strmode_ & __dynamic)
145 __strmode_ |= __frozen;
146 return eback();
147 }
148
149 int
pcount() const150 strstreambuf::pcount() const
151 {
152 return static_cast<int>(pptr() - pbase());
153 }
154
155 strstreambuf::int_type
overflow(int_type __c)156 strstreambuf::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);
164 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);
166 if (new_size == 0)
167 new_size = __default_alsize;
168 char* buf = nullptr;
169 if (__palloc_)
170 buf = static_cast<char*>(__palloc_(new_size));
171 else
172 buf = new char[new_size];
173 if (buf == nullptr)
174 return int_type(EOF);
175 if (old_size != 0) {
176 _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
177 memcpy(buf, eback(), static_cast<size_t>(old_size));
178 }
179 ptrdiff_t ninp = gptr() - eback();
180 ptrdiff_t einp = egptr() - eback();
181 ptrdiff_t nout = pptr() - pbase();
182 if (__strmode_ & __allocated)
183 {
184 if (__pfree_)
185 __pfree_(eback());
186 else
187 delete [] eback();
188 }
189 setg(buf, buf + ninp, buf + einp);
190 setp(buf + einp, buf + new_size);
191 __pbump(nout);
192 __strmode_ |= __allocated;
193 }
194 *pptr() = static_cast<char>(__c);
195 pbump(1);
196 return int_type(static_cast<unsigned char>(__c));
197 }
198
199 strstreambuf::int_type
pbackfail(int_type __c)200 strstreambuf::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
223 strstreambuf::int_type
underflow()224 strstreambuf::underflow()
225 {
226 if (gptr() == egptr())
227 {
228 if (egptr() >= pptr())
229 return EOF;
230 setg(eback(), gptr(), pptr());
231 }
232 return int_type(static_cast<unsigned char>(*gptr()));
233 }
234
235 strstreambuf::pos_type
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __which)236 strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
237 {
238 off_type __p(-1);
239 bool pos_in = (__which & ios::in) != 0;
240 bool pos_out = (__which & ios::out) != 0;
241 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;
273 default:
274 __libcpp_unreachable();
275 }
276 newoff += __off;
277 if (0 <= newoff && newoff <= seekhigh - eback())
278 {
279 char* newpos = eback() + newoff;
280 if (pos_in)
281 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
282 if (pos_out)
283 {
284 // min(pbase, newpos), newpos, epptr()
285 __off = epptr() - newpos;
286 setp(min(pbase(), newpos), epptr());
287 __pbump((epptr() - pbase()) - __off);
288 }
289 __p = newoff;
290 }
291 }
292 return pos_type(__p);
293 }
294
295 strstreambuf::pos_type
seekpos(pos_type __sp,ios_base::openmode __which)296 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
297 {
298 off_type __p(-1);
299 bool pos_in = (__which & ios::in) != 0;
300 bool pos_out = (__which & ios::out) != 0;
301 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)
311 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
312 if (pos_out)
313 {
314 // min(pbase, newpos), newpos, epptr()
315 off_type temp = epptr() - newpos;
316 setp(min(pbase(), newpos), epptr());
317 __pbump((epptr() - pbase()) - temp);
318 }
319 __p = newoff;
320 }
321 }
322 }
323 return pos_type(__p);
324 }
325
~istrstream()326 istrstream::~istrstream()
327 {
328 }
329
~ostrstream()330 ostrstream::~ostrstream()
331 {
332 }
333
~strstream()334 strstream::~strstream()
335 {
336 }
337
338 _LIBCPP_END_NAMESPACE_STD
339
340 _LIBCPP_POP_MACROS
341