strstream.cpp revision 353358
1307070Simp//===------------------------ strstream.cpp -------------------------------===//
2307070Simp//
3307070Simp// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4307070Simp// See https://llvm.org/LICENSE.txt for license information.
5307070Simp// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6307070Simp//
7307070Simp//===----------------------------------------------------------------------===//
8307070Simp
9307070Simp#include "strstream"
10307070Simp#include "algorithm"
11307070Simp#include "climits"
12307070Simp#include "cstring"
13307070Simp#include "cstdlib"
14307070Simp#include "__debug"
15307070Simp#include "__undef_macros"
16307070Simp
17307070Simp_LIBCPP_BEGIN_NAMESPACE_STD
18307070Simp
19307070Simpstrstreambuf::strstreambuf(streamsize __alsize)
20307070Simp    : __strmode_(__dynamic),
21307070Simp      __alsize_(__alsize),
22307070Simp      __palloc_(nullptr),
23307070Simp      __pfree_(nullptr)
24307070Simp{
25307070Simp}
26307070Simp
27307070Simpstrstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
28307070Simp    : __strmode_(__dynamic),
29307070Simp      __alsize_(__default_alsize),
30307070Simp      __palloc_(__palloc),
31307070Simp      __pfree_(__pfree)
32307070Simp{
33307070Simp}
34307070Simp
35307070Simpvoid
36307070Simpstrstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
37307070Simp{
38307070Simp    if (__n == 0)
39307070Simp        __n = static_cast<streamsize>(strlen(__gnext));
40    else if (__n < 0)
41        __n = INT_MAX;
42    if (__pbeg == nullptr)
43        setg(__gnext, __gnext, __gnext + __n);
44    else
45    {
46        setg(__gnext, __gnext, __pbeg);
47        setp(__pbeg, __pbeg + __n);
48    }
49}
50
51strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
52    : __strmode_(),
53      __alsize_(__default_alsize),
54      __palloc_(nullptr),
55      __pfree_(nullptr)
56{
57    __init(__gnext, __n, __pbeg);
58}
59
60strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
61    : __strmode_(__constant),
62      __alsize_(__default_alsize),
63      __palloc_(nullptr),
64      __pfree_(nullptr)
65{
66    __init(const_cast<char *>(__gnext), __n, nullptr);
67}
68
69strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
70    : __strmode_(),
71      __alsize_(__default_alsize),
72      __palloc_(nullptr),
73      __pfree_(nullptr)
74{
75    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
76}
77
78strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
79    : __strmode_(__constant),
80      __alsize_(__default_alsize),
81      __palloc_(nullptr),
82      __pfree_(nullptr)
83{
84    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
85}
86
87strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
88    : __strmode_(),
89      __alsize_(__default_alsize),
90      __palloc_(nullptr),
91      __pfree_(nullptr)
92{
93    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
94}
95
96strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
97    : __strmode_(__constant),
98      __alsize_(__default_alsize),
99      __palloc_(nullptr),
100      __pfree_(nullptr)
101{
102    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
103}
104
105strstreambuf::~strstreambuf()
106{
107    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
108    {
109        if (__pfree_)
110            __pfree_(eback());
111        else
112            delete [] eback();
113    }
114}
115
116void
117strstreambuf::swap(strstreambuf& __rhs)
118{
119    streambuf::swap(__rhs);
120    _VSTD::swap(__strmode_, __rhs.__strmode_);
121    _VSTD::swap(__alsize_, __rhs.__alsize_);
122    _VSTD::swap(__palloc_, __rhs.__palloc_);
123    _VSTD::swap(__pfree_, __rhs.__pfree_);
124}
125
126void
127strstreambuf::freeze(bool __freezefl)
128{
129    if (__strmode_ & __dynamic)
130    {
131        if (__freezefl)
132            __strmode_ |= __frozen;
133        else
134            __strmode_ &= ~__frozen;
135    }
136}
137
138char*
139strstreambuf::str()
140{
141    if (__strmode_ & __dynamic)
142        __strmode_ |= __frozen;
143    return eback();
144}
145
146int
147strstreambuf::pcount() const
148{
149    return static_cast<int>(pptr() - pbase());
150}
151
152strstreambuf::int_type
153strstreambuf::overflow(int_type __c)
154{
155    if (__c == EOF)
156        return int_type(0);
157    if (pptr() == epptr())
158    {
159        if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
160            return int_type(EOF);
161        size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
162        size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
163        if (new_size == 0)
164            new_size = __default_alsize;
165        char* buf = nullptr;
166        if (__palloc_)
167            buf = static_cast<char*>(__palloc_(new_size));
168        else
169            buf = new char[new_size];
170        if (buf == nullptr)
171            return int_type(EOF);
172        if (old_size != 0) {
173            _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
174            memcpy(buf, eback(), static_cast<size_t>(old_size));
175        }
176        ptrdiff_t ninp = gptr()  - eback();
177        ptrdiff_t einp = egptr() - eback();
178        ptrdiff_t nout = pptr()  - 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 + new_size);
188        __pbump(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
196strstreambuf::int_type
197strstreambuf::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
220strstreambuf::int_type
221strstreambuf::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
232strstreambuf::pos_type
233strstreambuf::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        default:
271            _LIBCPP_UNREACHABLE();
272        }
273        newoff += __off;
274        if (0 <= newoff && newoff <= seekhigh - eback())
275        {
276            char* newpos = eback() + newoff;
277            if (pos_in)
278                setg(eback(), newpos, _VSTD::max(newpos, egptr()));
279            if (pos_out)
280            {
281                // min(pbase, newpos), newpos, epptr()
282                __off = epptr() - newpos;
283                setp(min(pbase(), newpos), epptr());
284                __pbump((epptr() - pbase()) - __off);
285            }
286            __p = newoff;
287        }
288    }
289    return pos_type(__p);
290}
291
292strstreambuf::pos_type
293strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
294{
295    off_type __p(-1);
296    bool pos_in = (__which & ios::in) != 0;
297    bool pos_out = (__which & ios::out) != 0;
298    if (pos_in || pos_out)
299    {
300        if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
301        {
302            off_type newoff = __sp;
303            char* seekhigh = epptr() ? epptr() : egptr();
304            if (0 <= newoff && newoff <= seekhigh - eback())
305            {
306                char* newpos = eback() + newoff;
307                if (pos_in)
308                    setg(eback(), newpos, _VSTD::max(newpos, egptr()));
309                if (pos_out)
310                {
311                    // min(pbase, newpos), newpos, epptr()
312                    off_type temp = epptr() - newpos;
313                    setp(min(pbase(), newpos), epptr());
314                    __pbump((epptr() - pbase()) - temp);
315                }
316                __p = newoff;
317            }
318        }
319    }
320    return pos_type(__p);
321}
322
323istrstream::~istrstream()
324{
325}
326
327ostrstream::~ostrstream()
328{
329}
330
331strstream::~strstream()
332{
333}
334
335_LIBCPP_END_NAMESPACE_STD
336