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 "__debug"
15 
16 _LIBCPP_BEGIN_NAMESPACE_STD
17 
18 strstreambuf::strstreambuf(streamsize __alsize)
19     : __strmode_(__dynamic),
20       __alsize_(__alsize),
21       __palloc_(nullptr),
22       __pfree_(nullptr)
23 {
24 }
25 
26 strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
27     : __strmode_(__dynamic),
28       __alsize_(__default_alsize),
29       __palloc_(__palloc),
30       __pfree_(__pfree)
31 {
32 }
33 
34 void
35 strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
36 {
37     if (__n == 0)
38         __n = static_cast<streamsize>(strlen(__gnext));
39     else if (__n < 0)
40         __n = INT_MAX;
41     if (__pbeg == nullptr)
42         setg(__gnext, __gnext, __gnext + __n);
43     else
44     {
45         setg(__gnext, __gnext, __pbeg);
46         setp(__pbeg, __pbeg + __n);
47     }
48 }
49 
50 strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
51     : __strmode_(),
52       __alsize_(__default_alsize),
53       __palloc_(nullptr),
54       __pfree_(nullptr)
55 {
56     __init(__gnext, __n, __pbeg);
57 }
58 
59 strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
60     : __strmode_(__constant),
61       __alsize_(__default_alsize),
62       __palloc_(nullptr),
63       __pfree_(nullptr)
64 {
65     __init(const_cast<char *>(__gnext), __n, nullptr);
66 }
67 
68 strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
69     : __strmode_(),
70       __alsize_(__default_alsize),
71       __palloc_(nullptr),
72       __pfree_(nullptr)
73 {
74     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
75 }
76 
77 strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
78     : __strmode_(__constant),
79       __alsize_(__default_alsize),
80       __palloc_(nullptr),
81       __pfree_(nullptr)
82 {
83     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
84 }
85 
86 strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
87     : __strmode_(),
88       __alsize_(__default_alsize),
89       __palloc_(nullptr),
90       __pfree_(nullptr)
91 {
92     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
93 }
94 
95 strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
96     : __strmode_(__constant),
97       __alsize_(__default_alsize),
98       __palloc_(nullptr),
99       __pfree_(nullptr)
100 {
101     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
102 }
103 
104 strstreambuf::~strstreambuf()
105 {
106     if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
107     {
108         if (__pfree_)
109             __pfree_(eback());
110         else
111             delete [] eback();
112     }
113 }
114 
115 void
116 strstreambuf::swap(strstreambuf& __rhs)
117 {
118     streambuf::swap(__rhs);
119     _VSTD::swap(__strmode_, __rhs.__strmode_);
120     _VSTD::swap(__alsize_, __rhs.__alsize_);
121     _VSTD::swap(__palloc_, __rhs.__palloc_);
122     _VSTD::swap(__pfree_, __rhs.__pfree_);
123 }
124 
125 void
126 strstreambuf::freeze(bool __freezefl)
127 {
128     if (__strmode_ & __dynamic)
129     {
130         if (__freezefl)
131             __strmode_ |= __frozen;
132         else
133             __strmode_ &= ~__frozen;
134     }
135 }
136 
137 char*
138 strstreambuf::str()
139 {
140     if (__strmode_ & __dynamic)
141         __strmode_ |= __frozen;
142     return eback();
143 }
144 
145 int
146 strstreambuf::pcount() const
147 {
148     return static_cast<int>(pptr() - pbase());
149 }
150 
151 strstreambuf::int_type
152 strstreambuf::overflow(int_type __c)
153 {
154     if (__c == EOF)
155         return int_type(0);
156     if (pptr() == epptr())
157     {
158         if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
159             return int_type(EOF);
160         size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
161         size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
162         if (new_size == 0)
163             new_size = __default_alsize;
164         char* buf = nullptr;
165         if (__palloc_)
166             buf = static_cast<char*>(__palloc_(new_size));
167         else
168             buf = new char[new_size];
169         if (buf == nullptr)
170             return int_type(EOF);
171         if (old_size != 0) {
172             _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
173             memcpy(buf, eback(), static_cast<size_t>(old_size));
174         }
175         ptrdiff_t ninp = gptr()  - eback();
176         ptrdiff_t einp = egptr() - eback();
177         ptrdiff_t nout = pptr()  - pbase();
178         ptrdiff_t eout = epptr() - 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 + einp + eout);
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
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
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
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         }
271         newoff += __off;
272         if (0 <= newoff && newoff <= seekhigh - eback())
273         {
274             char* newpos = eback() + newoff;
275             if (pos_in)
276                 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
277             if (pos_out)
278             {
279                 // min(pbase, newpos), newpos, epptr()
280                 __off = epptr() - newpos;
281                 setp(min(pbase(), newpos), epptr());
282                 pbump(static_cast<int>((epptr() - pbase()) - __off));
283             }
284             __p = newoff;
285         }
286     }
287     return pos_type(__p);
288 }
289 
290 strstreambuf::pos_type
291 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
292 {
293     off_type __p(-1);
294     bool pos_in = (__which & ios::in) != 0;
295     bool pos_out = (__which & ios::out) != 0;
296     if (pos_in || pos_out)
297     {
298         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
299         {
300             off_type newoff = __sp;
301             char* seekhigh = epptr() ? epptr() : egptr();
302             if (0 <= newoff && newoff <= seekhigh - eback())
303             {
304                 char* newpos = eback() + newoff;
305                 if (pos_in)
306                     setg(eback(), newpos, _VSTD::max(newpos, egptr()));
307                 if (pos_out)
308                 {
309                     // min(pbase, newpos), newpos, epptr()
310                     off_type temp = epptr() - newpos;
311                     setp(min(pbase(), newpos), epptr());
312                     pbump(static_cast<int>((epptr() - pbase()) - temp));
313                 }
314                 __p = newoff;
315             }
316         }
317     }
318     return pos_type(__p);
319 }
320 
321 istrstream::~istrstream()
322 {
323 }
324 
325 ostrstream::~ostrstream()
326 {
327 }
328 
329 strstream::~strstream()
330 {
331 }
332 
333 _LIBCPP_END_NAMESPACE_STD
334