236
|
1 //===----------------------------------------------------------------------===//
|
150
|
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
|
236
|
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>
|
150
|
19
|
|
20 _LIBCPP_BEGIN_NAMESPACE_STD
|
|
21
|
|
22 strstreambuf::strstreambuf(streamsize __alsize)
|
|
23 : __strmode_(__dynamic),
|
|
24 __alsize_(__alsize),
|
|
25 __palloc_(nullptr),
|
|
26 __pfree_(nullptr)
|
|
27 {
|
|
28 }
|
|
29
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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*
|
|
142 strstreambuf::str()
|
|
143 {
|
|
144 if (__strmode_ & __dynamic)
|
|
145 __strmode_ |= __frozen;
|
|
146 return eback();
|
|
147 }
|
|
148
|
|
149 int
|
|
150 strstreambuf::pcount() const
|
|
151 {
|
|
152 return static_cast<int>(pptr() - pbase());
|
|
153 }
|
|
154
|
|
155 strstreambuf::int_type
|
|
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
|
|
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
|
|
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
|
|
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:
|
236
|
274 __libcpp_unreachable();
|
150
|
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
|
|
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
|
|
326 istrstream::~istrstream()
|
|
327 {
|
|
328 }
|
|
329
|
|
330 ostrstream::~ostrstream()
|
|
331 {
|
|
332 }
|
|
333
|
|
334 strstream::~strstream()
|
|
335 {
|
|
336 }
|
|
337
|
|
338 _LIBCPP_END_NAMESPACE_STD
|
236
|
339
|
|
340 _LIBCPP_POP_MACROS
|