blob: ef12f982fe7c6933a320c955ecc07a25ff1d36d9 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------ strstream.cpp -------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-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 Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "strstream"
11#include "algorithm"
12#include "climits"
13#include "cstring"
14
15_LIBCPP_BEGIN_NAMESPACE_STD
16
17strstreambuf::strstreambuf(streamsize __alsize)
18 : __strmode_(__dynamic),
19 __alsize_(__alsize),
20 __palloc_(nullptr),
21 __pfree_(nullptr)
22{
23}
24
25strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
26 : __strmode_(__dynamic),
27 __alsize_(__default_alsize),
28 __palloc_(__palloc),
29 __pfree_(__pfree)
30{
31}
32
33void
34strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
35{
36 if (__n == 0)
37 __n = strlen(__gnext);
38 else if (__n < 0)
39 __n = INT_MAX;
40 if (__pbeg == nullptr)
41 setg(__gnext, __gnext, __gnext + __n);
42 else
43 {
44 setg(__gnext, __gnext, __pbeg);
45 setp(__pbeg, __pbeg + __n);
46 }
47}
48
49strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
50 : __strmode_(),
51 __alsize_(__default_alsize),
52 __palloc_(nullptr),
53 __pfree_(nullptr)
54{
55 __init(__gnext, __n, __pbeg);
56}
57
58strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
59 : __strmode_(__constant),
60 __alsize_(__default_alsize),
61 __palloc_(nullptr),
62 __pfree_(nullptr)
63{
64 __init((char*)__gnext, __n, nullptr);
65}
66
67strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
68 : __strmode_(),
69 __alsize_(__default_alsize),
70 __palloc_(nullptr),
71 __pfree_(nullptr)
72{
73 __init((char*)__gnext, __n, (char*)__pbeg);
74}
75
76strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
77 : __strmode_(__constant),
78 __alsize_(__default_alsize),
79 __palloc_(nullptr),
80 __pfree_(nullptr)
81{
82 __init((char*)__gnext, __n, nullptr);
83}
84
85strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
86 : __strmode_(),
87 __alsize_(__default_alsize),
88 __palloc_(nullptr),
89 __pfree_(nullptr)
90{
91 __init((char*)__gnext, __n, (char*)__pbeg);
92}
93
94strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
95 : __strmode_(__constant),
96 __alsize_(__default_alsize),
97 __palloc_(nullptr),
98 __pfree_(nullptr)
99{
100 __init((char*)__gnext, __n, nullptr);
101}
102
Howard Hinnant73d21a42010-09-04 23:28:19 +0000103#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000104
105strstreambuf::strstreambuf(strstreambuf&& __rhs)
106 : streambuf(__rhs),
107 __strmode_(__rhs.__strmode_),
108 __alsize_(__rhs.__alsize_),
109 __palloc_(__rhs.__palloc_),
110 __pfree_(__rhs.__pfree_)
111{
112 __rhs.setg(nullptr, nullptr, nullptr);
113 __rhs.setp(nullptr, nullptr);
114}
115
116strstreambuf&
117strstreambuf::operator=(strstreambuf&& __rhs)
118{
119 if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
120 {
121 if (__pfree_)
122 __pfree_(eback());
123 else
124 delete [] eback();
125 }
126 streambuf::operator=(__rhs);
127 __strmode_ = __rhs.__strmode_;
128 __alsize_ = __rhs.__alsize_;
129 __palloc_ = __rhs.__palloc_;
130 __pfree_ = __rhs.__pfree_;
131 __rhs.setg(nullptr, nullptr, nullptr);
132 __rhs.setp(nullptr, nullptr);
Howard Hinnant9a21a012011-01-27 21:01:11 +0000133 return *this;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000134}
135
Howard Hinnant73d21a42010-09-04 23:28:19 +0000136#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000137
138strstreambuf::~strstreambuf()
139{
140 if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
141 {
142 if (__pfree_)
143 __pfree_(eback());
144 else
145 delete [] eback();
146 }
147}
148
149void
150strstreambuf::swap(strstreambuf& __rhs)
151{
152 streambuf::swap(__rhs);
153 _STD::swap(__strmode_, __rhs.__strmode_);
154 _STD::swap(__alsize_, __rhs.__alsize_);
155 _STD::swap(__palloc_, __rhs.__palloc_);
156 _STD::swap(__pfree_, __rhs.__pfree_);
157}
158
159void
160strstreambuf::freeze(bool __freezefl)
161{
162 if (__strmode_ & __dynamic)
163 {
164 if (__freezefl)
165 __strmode_ |= __frozen;
166 else
167 __strmode_ &= ~__frozen;
168 }
169}
170
171char*
172strstreambuf::str()
173{
174 if (__strmode_ & __dynamic)
175 __strmode_ |= __frozen;
176 return eback();
177}
178
179int
180strstreambuf::pcount() const
181{
182 return static_cast<int>(pptr() - pbase());
183}
184
185strstreambuf::int_type
186strstreambuf::overflow(int_type __c)
187{
188 if (__c == EOF)
189 return int_type(0);
190 if (pptr() == epptr())
191 {
192 if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
193 return int_type(EOF);
194 streamsize old_size = (epptr() ? epptr() : egptr()) - eback();
195 streamsize new_size = max<streamsize>(__alsize_, 2*old_size);
196 char* buf = nullptr;
197 if (__palloc_)
198 buf = static_cast<char*>(__palloc_(new_size));
199 else
200 buf = new char[new_size];
201 if (buf == nullptr)
202 return int_type(EOF);
203 memcpy(buf, eback(), old_size);
204 ptrdiff_t ninp = gptr() - eback();
205 ptrdiff_t einp = egptr() - eback();
206 ptrdiff_t nout = pptr() - pbase();
207 ptrdiff_t eout = epptr() - pbase();
208 if (__strmode_ & __allocated)
209 {
210 if (__pfree_)
211 __pfree_(eback());
212 else
213 delete [] eback();
214 }
215 setg(buf, buf + ninp, buf + einp);
216 setp(buf + einp, buf + einp + eout);
217 pbump(nout);
218 __strmode_ |= __allocated;
219 }
220 *pptr() = static_cast<char>(__c);
221 pbump(1);
222 return int_type((unsigned char)__c);
223}
224
225strstreambuf::int_type
226strstreambuf::pbackfail(int_type __c)
227{
228 if (eback() == gptr())
229 return EOF;
230 if (__c == EOF)
231 {
232 gbump(-1);
233 return int_type(0);
234 }
235 if (__strmode_ & __constant)
236 {
237 if (gptr()[-1] == static_cast<char>(__c))
238 {
239 gbump(-1);
240 return __c;
241 }
242 return EOF;
243 }
244 gbump(-1);
245 *gptr() = static_cast<char>(__c);
246 return __c;
247}
248
249strstreambuf::int_type
250strstreambuf::underflow()
251{
252 if (gptr() == egptr())
253 {
254 if (egptr() >= pptr())
255 return EOF;
256 setg(eback(), gptr(), pptr());
257 }
258 return int_type((unsigned char)*gptr());
259}
260
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261strstreambuf::pos_type
262strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
263{
264 off_type __p(-1);
265 bool pos_in = __which & ios::in;
266 bool pos_out = __which & ios::out;
267 bool legal = false;
268 switch (__way)
269 {
270 case ios::beg:
271 case ios::end:
272 if (pos_in || pos_out)
273 legal = true;
274 break;
275 case ios::cur:
276 if (pos_in != pos_out)
277 legal = true;
278 break;
279 }
280 if (pos_in && gptr() == nullptr)
281 legal = false;
282 if (pos_out && pptr() == nullptr)
283 legal = false;
284 if (legal)
285 {
286 off_type newoff;
287 char* seekhigh = epptr() ? epptr() : egptr();
288 switch (__way)
289 {
290 case ios::beg:
291 newoff = 0;
292 break;
293 case ios::cur:
294 newoff = (pos_in ? gptr() : pptr()) - eback();
295 break;
296 case ios::end:
297 newoff = seekhigh - eback();
298 break;
299 }
300 newoff += __off;
301 if (0 <= newoff && newoff <= seekhigh - eback())
302 {
303 char* newpos = eback() + newoff;
304 if (pos_in)
Howard Hinnant6cf5d8c2011-02-14 19:12:38 +0000305 setg(eback(), newpos, _STD::max(newpos, egptr()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000306 if (pos_out)
307 {
308 // min(pbase, newpos), newpos, epptr()
309 __off = epptr() - newpos;
310 setp(min(pbase(), newpos), epptr());
311 pbump(static_cast<int>((epptr() - pbase()) - __off));
312 }
313 __p = newoff;
314 }
315 }
316 return pos_type(__p);
317}
318
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000319strstreambuf::pos_type
320strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
321{
322 off_type __p(-1);
323 bool pos_in = __which & ios::in;
324 bool pos_out = __which & ios::out;
325 if (pos_in || pos_out)
326 {
327 if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
328 {
329 off_type newoff = __sp;
330 char* seekhigh = epptr() ? epptr() : egptr();
331 if (0 <= newoff && newoff <= seekhigh - eback())
332 {
333 char* newpos = eback() + newoff;
334 if (pos_in)
Howard Hinnant6cf5d8c2011-02-14 19:12:38 +0000335 setg(eback(), newpos, _STD::max(newpos, egptr()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000336 if (pos_out)
337 {
338 // min(pbase, newpos), newpos, epptr()
339 off_type temp = epptr() - newpos;
340 setp(min(pbase(), newpos), epptr());
341 pbump(static_cast<int>((epptr() - pbase()) - temp));
342 }
343 __p = newoff;
344 }
345 }
346 }
347 return pos_type(__p);
348}
349
350istrstream::~istrstream()
351{
352}
353
354ostrstream::~ostrstream()
355{
356}
357
358strstream::~strstream()
359{
360}
361
362_LIBCPP_END_NAMESPACE_STD