1 //===------------------------ strstream.cpp -------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "strstream"
11 #include "algorithm"
12 #include "climits"
13 #include "cstring"
14 #include "cstdlib"
15 #include "__debug"
16
17 _LIBCPP_BEGIN_NAMESPACE_STD
18
strstreambuf(streamsize __alsize)19 strstreambuf::strstreambuf(streamsize __alsize)
20 : __strmode_(__dynamic),
21 __alsize_(__alsize),
22 __palloc_(nullptr),
23 __pfree_(nullptr)
24 {
25 }
26
strstreambuf(void * (* __palloc)(size_t),void (* __pfree)(void *))27 strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
28 : __strmode_(__dynamic),
29 __alsize_(__default_alsize),
30 __palloc_(__palloc),
31 __pfree_(__pfree)
32 {
33 }
34
35 void
__init(char * __gnext,streamsize __n,char * __pbeg)36 strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
37 {
38 if (__n == 0)
39 __n = static_cast<streamsize>(strlen(__gnext));
40 else if (__n < 0)
41 __n = INT_MAX;
42 if (__pbeg == nullptr)
43 setg(__gnext, __gnext, __gnext + __n);
44 else
45 {
46 setg(__gnext, __gnext, __pbeg);
47 setp(__pbeg, __pbeg + __n);
48 }
49 }
50
strstreambuf(char * __gnext,streamsize __n,char * __pbeg)51 strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
52 : __strmode_(),
53 __alsize_(__default_alsize),
54 __palloc_(nullptr),
55 __pfree_(nullptr)
56 {
57 __init(__gnext, __n, __pbeg);
58 }
59
strstreambuf(const char * __gnext,streamsize __n)60 strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
61 : __strmode_(__constant),
62 __alsize_(__default_alsize),
63 __palloc_(nullptr),
64 __pfree_(nullptr)
65 {
66 __init(const_cast<char *>(__gnext), __n, nullptr);
67 }
68
strstreambuf(signed char * __gnext,streamsize __n,signed char * __pbeg)69 strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
70 : __strmode_(),
71 __alsize_(__default_alsize),
72 __palloc_(nullptr),
73 __pfree_(nullptr)
74 {
75 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
76 }
77
strstreambuf(const signed char * __gnext,streamsize __n)78 strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
79 : __strmode_(__constant),
80 __alsize_(__default_alsize),
81 __palloc_(nullptr),
82 __pfree_(nullptr)
83 {
84 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
85 }
86
strstreambuf(unsigned char * __gnext,streamsize __n,unsigned char * __pbeg)87 strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
88 : __strmode_(),
89 __alsize_(__default_alsize),
90 __palloc_(nullptr),
91 __pfree_(nullptr)
92 {
93 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
94 }
95
strstreambuf(const unsigned char * __gnext,streamsize __n)96 strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
97 : __strmode_(__constant),
98 __alsize_(__default_alsize),
99 __palloc_(nullptr),
100 __pfree_(nullptr)
101 {
102 __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
103 }
104
~strstreambuf()105 strstreambuf::~strstreambuf()
106 {
107 if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
108 {
109 if (__pfree_)
110 __pfree_(eback());
111 else
112 delete [] eback();
113 }
114 }
115
116 void
swap(strstreambuf & __rhs)117 strstreambuf::swap(strstreambuf& __rhs)
118 {
119 streambuf::swap(__rhs);
120 _VSTD::swap(__strmode_, __rhs.__strmode_);
121 _VSTD::swap(__alsize_, __rhs.__alsize_);
122 _VSTD::swap(__palloc_, __rhs.__palloc_);
123 _VSTD::swap(__pfree_, __rhs.__pfree_);
124 }
125
126 void
freeze(bool __freezefl)127 strstreambuf::freeze(bool __freezefl)
128 {
129 if (__strmode_ & __dynamic)
130 {
131 if (__freezefl)
132 __strmode_ |= __frozen;
133 else
134 __strmode_ &= ~__frozen;
135 }
136 }
137
138 char*
str()139 strstreambuf::str()
140 {
141 if (__strmode_ & __dynamic)
142 __strmode_ |= __frozen;
143 return eback();
144 }
145
146 int
pcount() const147 strstreambuf::pcount() const
148 {
149 return static_cast<int>(pptr() - pbase());
150 }
151
152 strstreambuf::int_type
overflow(int_type __c)153 strstreambuf::overflow(int_type __c)
154 {
155 if (__c == EOF)
156 return int_type(0);
157 if (pptr() == epptr())
158 {
159 if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
160 return int_type(EOF);
161 size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
162 size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
163 if (new_size == 0)
164 new_size = __default_alsize;
165 char* buf = nullptr;
166 if (__palloc_)
167 buf = static_cast<char*>(__palloc_(new_size));
168 else
169 buf = new char[new_size];
170 if (buf == nullptr)
171 return int_type(EOF);
172 if (old_size != 0) {
173 _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
174 memcpy(buf, eback(), static_cast<size_t>(old_size));
175 }
176 ptrdiff_t ninp = gptr() - eback();
177 ptrdiff_t einp = egptr() - eback();
178 ptrdiff_t nout = pptr() - pbase();
179 if (__strmode_ & __allocated)
180 {
181 if (__pfree_)
182 __pfree_(eback());
183 else
184 delete [] eback();
185 }
186 setg(buf, buf + ninp, buf + einp);
187 setp(buf + einp, buf + new_size);
188 pbump(static_cast<int>(nout));
189 __strmode_ |= __allocated;
190 }
191 *pptr() = static_cast<char>(__c);
192 pbump(1);
193 return int_type(static_cast<unsigned char>(__c));
194 }
195
196 strstreambuf::int_type
pbackfail(int_type __c)197 strstreambuf::pbackfail(int_type __c)
198 {
199 if (eback() == gptr())
200 return EOF;
201 if (__c == EOF)
202 {
203 gbump(-1);
204 return int_type(0);
205 }
206 if (__strmode_ & __constant)
207 {
208 if (gptr()[-1] == static_cast<char>(__c))
209 {
210 gbump(-1);
211 return __c;
212 }
213 return EOF;
214 }
215 gbump(-1);
216 *gptr() = static_cast<char>(__c);
217 return __c;
218 }
219
220 strstreambuf::int_type
underflow()221 strstreambuf::underflow()
222 {
223 if (gptr() == egptr())
224 {
225 if (egptr() >= pptr())
226 return EOF;
227 setg(eback(), gptr(), pptr());
228 }
229 return int_type(static_cast<unsigned char>(*gptr()));
230 }
231
232 strstreambuf::pos_type
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __which)233 strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
234 {
235 off_type __p(-1);
236 bool pos_in = (__which & ios::in) != 0;
237 bool pos_out = (__which & ios::out) != 0;
238 bool legal = false;
239 switch (__way)
240 {
241 case ios::beg:
242 case ios::end:
243 if (pos_in || pos_out)
244 legal = true;
245 break;
246 case ios::cur:
247 if (pos_in != pos_out)
248 legal = true;
249 break;
250 }
251 if (pos_in && gptr() == nullptr)
252 legal = false;
253 if (pos_out && pptr() == nullptr)
254 legal = false;
255 if (legal)
256 {
257 off_type newoff;
258 char* seekhigh = epptr() ? epptr() : egptr();
259 switch (__way)
260 {
261 case ios::beg:
262 newoff = 0;
263 break;
264 case ios::cur:
265 newoff = (pos_in ? gptr() : pptr()) - eback();
266 break;
267 case ios::end:
268 newoff = seekhigh - eback();
269 break;
270 default:
271 _LIBCPP_UNREACHABLE();
272 }
273 newoff += __off;
274 if (0 <= newoff && newoff <= seekhigh - eback())
275 {
276 char* newpos = eback() + newoff;
277 if (pos_in)
278 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
279 if (pos_out)
280 {
281 // min(pbase, newpos), newpos, epptr()
282 __off = epptr() - newpos;
283 setp(min(pbase(), newpos), epptr());
284 pbump(static_cast<int>((epptr() - pbase()) - __off));
285 }
286 __p = newoff;
287 }
288 }
289 return pos_type(__p);
290 }
291
292 strstreambuf::pos_type
seekpos(pos_type __sp,ios_base::openmode __which)293 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
294 {
295 off_type __p(-1);
296 bool pos_in = (__which & ios::in) != 0;
297 bool pos_out = (__which & ios::out) != 0;
298 if (pos_in || pos_out)
299 {
300 if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
301 {
302 off_type newoff = __sp;
303 char* seekhigh = epptr() ? epptr() : egptr();
304 if (0 <= newoff && newoff <= seekhigh - eback())
305 {
306 char* newpos = eback() + newoff;
307 if (pos_in)
308 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
309 if (pos_out)
310 {
311 // min(pbase, newpos), newpos, epptr()
312 off_type temp = epptr() - newpos;
313 setp(min(pbase(), newpos), epptr());
314 pbump(static_cast<int>((epptr() - pbase()) - temp));
315 }
316 __p = newoff;
317 }
318 }
319 }
320 return pos_type(__p);
321 }
322
~istrstream()323 istrstream::~istrstream()
324 {
325 }
326
~ostrstream()327 ostrstream::~ostrstream()
328 {
329 }
330
~strstream()331 strstream::~strstream()
332 {
333 }
334
335 _LIBCPP_END_NAMESPACE_STD
336