blob: 8cd19e6a353cd743e52a950aadb6077c1e2c6ca0 [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)
Howard Hinnantec3773c2011-12-01 20:21:04 +000037 __n = static_cast<streamsize>(strlen(__gnext));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038 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 Hinnantbc8d3f92010-05-11 19:42:16 +0000103strstreambuf::~strstreambuf()
104{
105 if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
106 {
107 if (__pfree_)
108 __pfree_(eback());
109 else
110 delete [] eback();
111 }
112}
113
114void
115strstreambuf::swap(strstreambuf& __rhs)
116{
117 streambuf::swap(__rhs);
Howard Hinnant0949eed2011-06-30 21:18:19 +0000118 _VSTD::swap(__strmode_, __rhs.__strmode_);
119 _VSTD::swap(__alsize_, __rhs.__alsize_);
120 _VSTD::swap(__palloc_, __rhs.__palloc_);
121 _VSTD::swap(__pfree_, __rhs.__pfree_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000122}
123
124void
125strstreambuf::freeze(bool __freezefl)
126{
127 if (__strmode_ & __dynamic)
128 {
129 if (__freezefl)
130 __strmode_ |= __frozen;
131 else
132 __strmode_ &= ~__frozen;
133 }
134}
135
136char*
137strstreambuf::str()
138{
139 if (__strmode_ & __dynamic)
140 __strmode_ |= __frozen;
141 return eback();
142}
143
144int
145strstreambuf::pcount() const
146{
147 return static_cast<int>(pptr() - pbase());
148}
149
150strstreambuf::int_type
151strstreambuf::overflow(int_type __c)
152{
153 if (__c == EOF)
154 return int_type(0);
155 if (pptr() == epptr())
156 {
157 if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
158 return int_type(EOF);
159 streamsize old_size = (epptr() ? epptr() : egptr()) - eback();
160 streamsize new_size = max<streamsize>(__alsize_, 2*old_size);
161 char* buf = nullptr;
162 if (__palloc_)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000163 buf = static_cast<char*>(__palloc_(static_cast<size_t>(new_size)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000164 else
165 buf = new char[new_size];
166 if (buf == nullptr)
167 return int_type(EOF);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000168 memcpy(buf, eback(), static_cast<size_t>(old_size));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000169 ptrdiff_t ninp = gptr() - eback();
170 ptrdiff_t einp = egptr() - eback();
171 ptrdiff_t nout = pptr() - pbase();
172 ptrdiff_t eout = epptr() - pbase();
173 if (__strmode_ & __allocated)
174 {
175 if (__pfree_)
176 __pfree_(eback());
177 else
178 delete [] eback();
179 }
180 setg(buf, buf + ninp, buf + einp);
181 setp(buf + einp, buf + einp + eout);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000182 pbump(static_cast<int>(nout));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000183 __strmode_ |= __allocated;
184 }
185 *pptr() = static_cast<char>(__c);
186 pbump(1);
187 return int_type((unsigned char)__c);
188}
189
190strstreambuf::int_type
191strstreambuf::pbackfail(int_type __c)
192{
193 if (eback() == gptr())
194 return EOF;
195 if (__c == EOF)
196 {
197 gbump(-1);
198 return int_type(0);
199 }
200 if (__strmode_ & __constant)
201 {
202 if (gptr()[-1] == static_cast<char>(__c))
203 {
204 gbump(-1);
205 return __c;
206 }
207 return EOF;
208 }
209 gbump(-1);
210 *gptr() = static_cast<char>(__c);
211 return __c;
212}
213
214strstreambuf::int_type
215strstreambuf::underflow()
216{
217 if (gptr() == egptr())
218 {
219 if (egptr() >= pptr())
220 return EOF;
221 setg(eback(), gptr(), pptr());
222 }
223 return int_type((unsigned char)*gptr());
224}
225
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000226strstreambuf::pos_type
227strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
228{
229 off_type __p(-1);
230 bool pos_in = __which & ios::in;
231 bool pos_out = __which & ios::out;
232 bool legal = false;
233 switch (__way)
234 {
235 case ios::beg:
236 case ios::end:
237 if (pos_in || pos_out)
238 legal = true;
239 break;
240 case ios::cur:
241 if (pos_in != pos_out)
242 legal = true;
243 break;
244 }
245 if (pos_in && gptr() == nullptr)
246 legal = false;
247 if (pos_out && pptr() == nullptr)
248 legal = false;
249 if (legal)
250 {
251 off_type newoff;
252 char* seekhigh = epptr() ? epptr() : egptr();
253 switch (__way)
254 {
255 case ios::beg:
256 newoff = 0;
257 break;
258 case ios::cur:
259 newoff = (pos_in ? gptr() : pptr()) - eback();
260 break;
261 case ios::end:
262 newoff = seekhigh - eback();
263 break;
264 }
265 newoff += __off;
266 if (0 <= newoff && newoff <= seekhigh - eback())
267 {
268 char* newpos = eback() + newoff;
269 if (pos_in)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000270 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000271 if (pos_out)
272 {
273 // min(pbase, newpos), newpos, epptr()
274 __off = epptr() - newpos;
275 setp(min(pbase(), newpos), epptr());
276 pbump(static_cast<int>((epptr() - pbase()) - __off));
277 }
278 __p = newoff;
279 }
280 }
281 return pos_type(__p);
282}
283
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000284strstreambuf::pos_type
285strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
286{
287 off_type __p(-1);
288 bool pos_in = __which & ios::in;
289 bool pos_out = __which & ios::out;
290 if (pos_in || pos_out)
291 {
292 if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
293 {
294 off_type newoff = __sp;
295 char* seekhigh = epptr() ? epptr() : egptr();
296 if (0 <= newoff && newoff <= seekhigh - eback())
297 {
298 char* newpos = eback() + newoff;
299 if (pos_in)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000300 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000301 if (pos_out)
302 {
303 // min(pbase, newpos), newpos, epptr()
304 off_type temp = epptr() - newpos;
305 setp(min(pbase(), newpos), epptr());
306 pbump(static_cast<int>((epptr() - pbase()) - temp));
307 }
308 __p = newoff;
309 }
310 }
311 }
312 return pos_type(__p);
313}
314
315istrstream::~istrstream()
316{
317}
318
319ostrstream::~ostrstream()
320{
321}
322
323strstream::~strstream()
324{
325}
326
327_LIBCPP_END_NAMESPACE_STD