1 //===------------------------ strstream.cpp -------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "strstream"
11 #include "algorithm"
12 #include "climits"
13 #include "cstring"
14 
15 _LIBCPP_BEGIN_NAMESPACE_STD
16 
17 strstreambuf::strstreambuf(streamsize __alsize)
18     : __strmode_(__dynamic),
19       __alsize_(__alsize),
20       __palloc_(nullptr),
21       __pfree_(nullptr)
22 {
23 }
24 
25 strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
26     : __strmode_(__dynamic),
27       __alsize_(__default_alsize),
28       __palloc_(__palloc),
29       __pfree_(__pfree)
30 {
31 }
32 
33 void
34 strstreambuf::__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 
49 strstreambuf::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 
58 strstreambuf::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 
67 strstreambuf::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 
76 strstreambuf::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 
85 strstreambuf::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 
94 strstreambuf::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 
103 #ifdef _LIBCPP_MOVE
104 
105 strstreambuf::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 
116 strstreambuf&
117 strstreambuf::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);
133 }
134 
135 #endif
136 
137 strstreambuf::~strstreambuf()
138 {
139     if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
140     {
141         if (__pfree_)
142             __pfree_(eback());
143         else
144             delete [] eback();
145     }
146 }
147 
148 void
149 strstreambuf::swap(strstreambuf& __rhs)
150 {
151     streambuf::swap(__rhs);
152     _STD::swap(__strmode_, __rhs.__strmode_);
153     _STD::swap(__alsize_, __rhs.__alsize_);
154     _STD::swap(__palloc_, __rhs.__palloc_);
155     _STD::swap(__pfree_, __rhs.__pfree_);
156 }
157 
158 void
159 strstreambuf::freeze(bool __freezefl)
160 {
161     if (__strmode_ & __dynamic)
162     {
163         if (__freezefl)
164             __strmode_ |= __frozen;
165         else
166             __strmode_ &= ~__frozen;
167     }
168 }
169 
170 char*
171 strstreambuf::str()
172 {
173     if (__strmode_ & __dynamic)
174         __strmode_ |= __frozen;
175     return eback();
176 }
177 
178 int
179 strstreambuf::pcount() const
180 {
181     return static_cast<int>(pptr() - pbase());
182 }
183 
184 strstreambuf::int_type
185 strstreambuf::overflow(int_type __c)
186 {
187     if (__c == EOF)
188         return int_type(0);
189     if (pptr() == epptr())
190     {
191         if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
192             return int_type(EOF);
193         streamsize old_size = (epptr() ? epptr() : egptr()) - eback();
194         streamsize new_size = max<streamsize>(__alsize_, 2*old_size);
195         char* buf = nullptr;
196         if (__palloc_)
197             buf = static_cast<char*>(__palloc_(new_size));
198         else
199             buf = new char[new_size];
200         if (buf == nullptr)
201             return int_type(EOF);
202         memcpy(buf, eback(), old_size);
203         ptrdiff_t ninp = gptr()  - eback();
204         ptrdiff_t einp = egptr() - eback();
205         ptrdiff_t nout = pptr()  - pbase();
206         ptrdiff_t eout = epptr() - pbase();
207         if (__strmode_ & __allocated)
208         {
209             if (__pfree_)
210                 __pfree_(eback());
211             else
212                 delete [] eback();
213         }
214         setg(buf, buf + ninp, buf + einp);
215         setp(buf + einp, buf + einp + eout);
216         pbump(nout);
217         __strmode_ |= __allocated;
218     }
219     *pptr() = static_cast<char>(__c);
220     pbump(1);
221     return int_type((unsigned char)__c);
222 }
223 
224 strstreambuf::int_type
225 strstreambuf::pbackfail(int_type __c)
226 {
227     if (eback() == gptr())
228         return EOF;
229     if (__c == EOF)
230     {
231         gbump(-1);
232         return int_type(0);
233     }
234     if (__strmode_ & __constant)
235     {
236         if (gptr()[-1] == static_cast<char>(__c))
237         {
238             gbump(-1);
239             return __c;
240         }
241         return EOF;
242     }
243     gbump(-1);
244     *gptr() = static_cast<char>(__c);
245     return __c;
246 }
247 
248 strstreambuf::int_type
249 strstreambuf::underflow()
250 {
251     if (gptr() == egptr())
252     {
253         if (egptr() >= pptr())
254             return EOF;
255         setg(eback(), gptr(), pptr());
256     }
257     return int_type((unsigned char)*gptr());
258 }
259 
260 
261 strstreambuf::pos_type
262 strstreambuf::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)
305                 setg(eback(), newpos, max(newpos, egptr()));
306             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 
319 
320 strstreambuf::pos_type
321 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
322 {
323     off_type __p(-1);
324     bool pos_in = __which & ios::in;
325     bool pos_out = __which & ios::out;
326     if (pos_in || pos_out)
327     {
328         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
329         {
330             off_type newoff = __sp;
331             char* seekhigh = epptr() ? epptr() : egptr();
332             if (0 <= newoff && newoff <= seekhigh - eback())
333             {
334                 char* newpos = eback() + newoff;
335                 if (pos_in)
336                     setg(eback(), newpos, max(newpos, egptr()));
337                 if (pos_out)
338                 {
339                     // min(pbase, newpos), newpos, epptr()
340                     off_type temp = epptr() - newpos;
341                     setp(min(pbase(), newpos), epptr());
342                     pbump(static_cast<int>((epptr() - pbase()) - temp));
343                 }
344                 __p = newoff;
345             }
346         }
347     }
348     return pos_type(__p);
349 }
350 
351 istrstream::~istrstream()
352 {
353 }
354 
355 ostrstream::~ostrstream()
356 {
357 }
358 
359 strstream::~strstream()
360 {
361 }
362 
363 _LIBCPP_END_NAMESPACE_STD
364