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