strstream.cpp revision 321369
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
20strstreambuf::strstreambuf(streamsize __alsize)
21    : __strmode_(__dynamic),
22      __alsize_(__alsize),
23      __palloc_(nullptr),
24      __pfree_(nullptr)
25{
26}
27
28strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
29    : __strmode_(__dynamic),
30      __alsize_(__default_alsize),
31      __palloc_(__palloc),
32      __pfree_(__pfree)
33{
34}
35
36void
37strstreambuf::__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
52strstreambuf::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
61strstreambuf::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
70strstreambuf::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
79strstreambuf::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
88strstreambuf::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
97strstreambuf::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
106strstreambuf::~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
117void
118strstreambuf::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
127void
128strstreambuf::freeze(bool __freezefl)
129{
130    if (__strmode_ & __dynamic)
131    {
132        if (__freezefl)
133            __strmode_ |= __frozen;
134        else
135            __strmode_ &= ~__frozen;
136    }
137}
138
139char*
140strstreambuf::str()
141{
142    if (__strmode_ & __dynamic)
143        __strmode_ |= __frozen;
144    return eback();
145}
146
147int
148strstreambuf::pcount() const
149{
150    return static_cast<int>(pptr() - pbase());
151}
152
153strstreambuf::int_type
154strstreambuf::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(static_cast<int>(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
197strstreambuf::int_type
198strstreambuf::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
221strstreambuf::int_type
222strstreambuf::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
233strstreambuf::pos_type
234strstreambuf::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(static_cast<int>((epptr() - pbase()) - __off));
286            }
287            __p = newoff;
288        }
289    }
290    return pos_type(__p);
291}
292
293strstreambuf::pos_type
294strstreambuf::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(static_cast<int>((epptr() - pbase()) - temp));
316                }
317                __p = newoff;
318            }
319        }
320    }
321    return pos_type(__p);
322}
323
324istrstream::~istrstream()
325{
326}
327
328ostrstream::~ostrstream()
329{
330}
331
332strstream::~strstream()
333{
334}
335
336_LIBCPP_END_NAMESPACE_STD
337