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