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 
15 _LIBCPP_BEGIN_NAMESPACE_STD
16 
strstreambuf(streamsize __alsize)17 strstreambuf::strstreambuf(streamsize __alsize)
18     : __strmode_(__dynamic),
19       __alsize_(__alsize),
20       __palloc_(nullptr),
21       __pfree_(nullptr)
22 {
23 }
24 
strstreambuf(void * (* __palloc)(size_t),void (* __pfree)(void *))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
__init(char * __gnext,streamsize __n,char * __pbeg)34 strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
35 {
36     if (__n == 0)
37         __n = static_cast<streamsize>(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 
strstreambuf(char * __gnext,streamsize __n,char * __pbeg)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 
strstreambuf(const char * __gnext,streamsize __n)58 strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
59     : __strmode_(__constant),
60       __alsize_(__default_alsize),
61       __palloc_(nullptr),
62       __pfree_(nullptr)
63 {
64     __init(const_cast<char *>(__gnext), __n, nullptr);
65 }
66 
strstreambuf(signed char * __gnext,streamsize __n,signed char * __pbeg)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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
74 }
75 
strstreambuf(const signed char * __gnext,streamsize __n)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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
83 }
84 
strstreambuf(unsigned char * __gnext,streamsize __n,unsigned char * __pbeg)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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
92 }
93 
strstreambuf(const unsigned char * __gnext,streamsize __n)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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
101 }
102 
~strstreambuf()103 strstreambuf::~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 
114 void
swap(strstreambuf & __rhs)115 strstreambuf::swap(strstreambuf& __rhs)
116 {
117     streambuf::swap(__rhs);
118     _VSTD::swap(__strmode_, __rhs.__strmode_);
119     _VSTD::swap(__alsize_, __rhs.__alsize_);
120     _VSTD::swap(__palloc_, __rhs.__palloc_);
121     _VSTD::swap(__pfree_, __rhs.__pfree_);
122 }
123 
124 void
freeze(bool __freezefl)125 strstreambuf::freeze(bool __freezefl)
126 {
127     if (__strmode_ & __dynamic)
128     {
129         if (__freezefl)
130             __strmode_ |= __frozen;
131         else
132             __strmode_ &= ~__frozen;
133     }
134 }
135 
136 char*
str()137 strstreambuf::str()
138 {
139     if (__strmode_ & __dynamic)
140         __strmode_ |= __frozen;
141     return eback();
142 }
143 
144 int
pcount() const145 strstreambuf::pcount() const
146 {
147     return static_cast<int>(pptr() - pbase());
148 }
149 
150 strstreambuf::int_type
overflow(int_type __c)151 strstreambuf::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         size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
160         size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
161         if (new_size == 0)
162             new_size = __default_alsize;
163         char* buf = nullptr;
164         if (__palloc_)
165             buf = static_cast<char*>(__palloc_(new_size));
166         else
167             buf = new char[new_size];
168         if (buf == nullptr)
169             return int_type(EOF);
170         memcpy(buf, eback(), static_cast<size_t>(old_size));
171         ptrdiff_t ninp = gptr()  - eback();
172         ptrdiff_t einp = egptr() - eback();
173         ptrdiff_t nout = pptr()  - pbase();
174         ptrdiff_t eout = epptr() - pbase();
175         if (__strmode_ & __allocated)
176         {
177             if (__pfree_)
178                 __pfree_(eback());
179             else
180                 delete [] eback();
181         }
182         setg(buf, buf + ninp, buf + einp);
183         setp(buf + einp, buf + einp + eout);
184         pbump(static_cast<int>(nout));
185         __strmode_ |= __allocated;
186     }
187     *pptr() = static_cast<char>(__c);
188     pbump(1);
189     return int_type(static_cast<unsigned char>(__c));
190 }
191 
192 strstreambuf::int_type
pbackfail(int_type __c)193 strstreambuf::pbackfail(int_type __c)
194 {
195     if (eback() == gptr())
196         return EOF;
197     if (__c == EOF)
198     {
199         gbump(-1);
200         return int_type(0);
201     }
202     if (__strmode_ & __constant)
203     {
204         if (gptr()[-1] == static_cast<char>(__c))
205         {
206             gbump(-1);
207             return __c;
208         }
209         return EOF;
210     }
211     gbump(-1);
212     *gptr() = static_cast<char>(__c);
213     return __c;
214 }
215 
216 strstreambuf::int_type
underflow()217 strstreambuf::underflow()
218 {
219     if (gptr() == egptr())
220     {
221         if (egptr() >= pptr())
222             return EOF;
223         setg(eback(), gptr(), pptr());
224     }
225     return int_type(static_cast<unsigned char>(*gptr()));
226 }
227 
228 strstreambuf::pos_type
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __which)229 strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
230 {
231     off_type __p(-1);
232     bool pos_in = (__which & ios::in) != 0;
233     bool pos_out = (__which & ios::out) != 0;
234     bool legal = false;
235     switch (__way)
236     {
237     case ios::beg:
238     case ios::end:
239         if (pos_in || pos_out)
240             legal = true;
241         break;
242     case ios::cur:
243         if (pos_in != pos_out)
244             legal = true;
245         break;
246     }
247     if (pos_in && gptr() == nullptr)
248         legal = false;
249     if (pos_out && pptr() == nullptr)
250         legal = false;
251     if (legal)
252     {
253         off_type newoff;
254         char* seekhigh = epptr() ? epptr() : egptr();
255         switch (__way)
256         {
257         case ios::beg:
258             newoff = 0;
259             break;
260         case ios::cur:
261             newoff = (pos_in ? gptr() : pptr()) - eback();
262             break;
263         case ios::end:
264             newoff = seekhigh - eback();
265             break;
266         }
267         newoff += __off;
268         if (0 <= newoff && newoff <= seekhigh - eback())
269         {
270             char* newpos = eback() + newoff;
271             if (pos_in)
272                 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
273             if (pos_out)
274             {
275                 // min(pbase, newpos), newpos, epptr()
276                 __off = epptr() - newpos;
277                 setp(min(pbase(), newpos), epptr());
278                 pbump(static_cast<int>((epptr() - pbase()) - __off));
279             }
280             __p = newoff;
281         }
282     }
283     return pos_type(__p);
284 }
285 
286 strstreambuf::pos_type
seekpos(pos_type __sp,ios_base::openmode __which)287 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
288 {
289     off_type __p(-1);
290     bool pos_in = (__which & ios::in) != 0;
291     bool pos_out = (__which & ios::out) != 0;
292     if (pos_in || pos_out)
293     {
294         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
295         {
296             off_type newoff = __sp;
297             char* seekhigh = epptr() ? epptr() : egptr();
298             if (0 <= newoff && newoff <= seekhigh - eback())
299             {
300                 char* newpos = eback() + newoff;
301                 if (pos_in)
302                     setg(eback(), newpos, _VSTD::max(newpos, egptr()));
303                 if (pos_out)
304                 {
305                     // min(pbase, newpos), newpos, epptr()
306                     off_type temp = epptr() - newpos;
307                     setp(min(pbase(), newpos), epptr());
308                     pbump(static_cast<int>((epptr() - pbase()) - temp));
309                 }
310                 __p = newoff;
311             }
312         }
313     }
314     return pos_type(__p);
315 }
316 
~istrstream()317 istrstream::~istrstream()
318 {
319 }
320 
~ostrstream()321 ostrstream::~ostrstream()
322 {
323 }
324 
~strstream()325 strstream::~strstream()
326 {
327 }
328 
329 _LIBCPP_END_NAMESPACE_STD
330