strstream.cpp revision 327952
1227825Stheraven//===------------------------ strstream.cpp -------------------------------===//
2227825Stheraven//
3227825Stheraven//                     The LLVM Compiler Infrastructure
4227825Stheraven//
5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
6227825Stheraven// Source Licenses. See LICENSE.TXT for details.
7227825Stheraven//
8227825Stheraven//===----------------------------------------------------------------------===//
9227825Stheraven
10227825Stheraven#include "strstream"
11227825Stheraven#include "algorithm"
12227825Stheraven#include "climits"
13227825Stheraven#include "cstring"
14314564Sdim#include "cstdlib"
15309124Sdim#include "__debug"
16321369Sdim#include "__undef_macros"
17227825Stheraven
18227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
19227825Stheraven
20227825Stheravenstrstreambuf::strstreambuf(streamsize __alsize)
21227825Stheraven    : __strmode_(__dynamic),
22227825Stheraven      __alsize_(__alsize),
23227825Stheraven      __palloc_(nullptr),
24227825Stheraven      __pfree_(nullptr)
25227825Stheraven{
26227825Stheraven}
27227825Stheraven
28227825Stheravenstrstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
29227825Stheraven    : __strmode_(__dynamic),
30227825Stheraven      __alsize_(__default_alsize),
31227825Stheraven      __palloc_(__palloc),
32227825Stheraven      __pfree_(__pfree)
33227825Stheraven{
34227825Stheraven}
35227825Stheraven
36227825Stheravenvoid
37227825Stheravenstrstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
38227825Stheraven{
39227825Stheraven    if (__n == 0)
40232924Stheraven        __n = static_cast<streamsize>(strlen(__gnext));
41227825Stheraven    else if (__n < 0)
42227825Stheraven        __n = INT_MAX;
43227825Stheraven    if (__pbeg == nullptr)
44227825Stheraven        setg(__gnext, __gnext, __gnext + __n);
45227825Stheraven    else
46227825Stheraven    {
47227825Stheraven        setg(__gnext, __gnext, __pbeg);
48227825Stheraven        setp(__pbeg, __pbeg + __n);
49227825Stheraven    }
50227825Stheraven}
51227825Stheraven
52227825Stheravenstrstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
53227825Stheraven    : __strmode_(),
54227825Stheraven      __alsize_(__default_alsize),
55227825Stheraven      __palloc_(nullptr),
56227825Stheraven      __pfree_(nullptr)
57227825Stheraven{
58227825Stheraven    __init(__gnext, __n, __pbeg);
59227825Stheraven}
60227825Stheraven
61227825Stheravenstrstreambuf::strstreambuf(const char* __gnext, streamsize __n)
62227825Stheraven    : __strmode_(__constant),
63227825Stheraven      __alsize_(__default_alsize),
64227825Stheraven      __palloc_(nullptr),
65227825Stheraven      __pfree_(nullptr)
66227825Stheraven{
67276792Sdim    __init(const_cast<char *>(__gnext), __n, nullptr);
68227825Stheraven}
69227825Stheraven
70227825Stheravenstrstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
71227825Stheraven    : __strmode_(),
72227825Stheraven      __alsize_(__default_alsize),
73227825Stheraven      __palloc_(nullptr),
74227825Stheraven      __pfree_(nullptr)
75227825Stheraven{
76276792Sdim    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
77227825Stheraven}
78227825Stheraven
79227825Stheravenstrstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
80227825Stheraven    : __strmode_(__constant),
81227825Stheraven      __alsize_(__default_alsize),
82227825Stheraven      __palloc_(nullptr),
83227825Stheraven      __pfree_(nullptr)
84227825Stheraven{
85276792Sdim    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
86227825Stheraven}
87227825Stheraven
88227825Stheravenstrstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
89227825Stheraven    : __strmode_(),
90227825Stheraven      __alsize_(__default_alsize),
91227825Stheraven      __palloc_(nullptr),
92227825Stheraven      __pfree_(nullptr)
93227825Stheraven{
94276792Sdim    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
95227825Stheraven}
96227825Stheraven
97227825Stheravenstrstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
98227825Stheraven    : __strmode_(__constant),
99227825Stheraven      __alsize_(__default_alsize),
100227825Stheraven      __palloc_(nullptr),
101227825Stheraven      __pfree_(nullptr)
102227825Stheraven{
103276792Sdim    __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
104227825Stheraven}
105227825Stheraven
106227825Stheravenstrstreambuf::~strstreambuf()
107227825Stheraven{
108227825Stheraven    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
109227825Stheraven    {
110227825Stheraven        if (__pfree_)
111227825Stheraven            __pfree_(eback());
112227825Stheraven        else
113227825Stheraven            delete [] eback();
114227825Stheraven    }
115227825Stheraven}
116227825Stheraven
117227825Stheravenvoid
118227825Stheravenstrstreambuf::swap(strstreambuf& __rhs)
119227825Stheraven{
120227825Stheraven    streambuf::swap(__rhs);
121227825Stheraven    _VSTD::swap(__strmode_, __rhs.__strmode_);
122227825Stheraven    _VSTD::swap(__alsize_, __rhs.__alsize_);
123227825Stheraven    _VSTD::swap(__palloc_, __rhs.__palloc_);
124227825Stheraven    _VSTD::swap(__pfree_, __rhs.__pfree_);
125227825Stheraven}
126227825Stheraven
127227825Stheravenvoid
128227825Stheravenstrstreambuf::freeze(bool __freezefl)
129227825Stheraven{
130227825Stheraven    if (__strmode_ & __dynamic)
131227825Stheraven    {
132227825Stheraven        if (__freezefl)
133227825Stheraven            __strmode_ |= __frozen;
134227825Stheraven        else
135227825Stheraven            __strmode_ &= ~__frozen;
136227825Stheraven    }
137227825Stheraven}
138227825Stheraven
139227825Stheravenchar*
140227825Stheravenstrstreambuf::str()
141227825Stheraven{
142227825Stheraven    if (__strmode_ & __dynamic)
143227825Stheraven        __strmode_ |= __frozen;
144227825Stheraven    return eback();
145227825Stheraven}
146227825Stheraven
147227825Stheravenint
148227825Stheravenstrstreambuf::pcount() const
149227825Stheraven{
150227825Stheraven    return static_cast<int>(pptr() - pbase());
151227825Stheraven}
152227825Stheraven
153227825Stheravenstrstreambuf::int_type
154227825Stheravenstrstreambuf::overflow(int_type __c)
155227825Stheraven{
156227825Stheraven    if (__c == EOF)
157227825Stheraven        return int_type(0);
158227825Stheraven    if (pptr() == epptr())
159227825Stheraven    {
160227825Stheraven        if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
161227825Stheraven            return int_type(EOF);
162261272Sdim        size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
163261272Sdim        size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
164249989Sdim        if (new_size == 0)
165249989Sdim            new_size = __default_alsize;
166227825Stheraven        char* buf = nullptr;
167227825Stheraven        if (__palloc_)
168261272Sdim            buf = static_cast<char*>(__palloc_(new_size));
169227825Stheraven        else
170227825Stheraven            buf = new char[new_size];
171227825Stheraven        if (buf == nullptr)
172227825Stheraven            return int_type(EOF);
173309124Sdim        if (old_size != 0) {
174309124Sdim            _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
175309124Sdim            memcpy(buf, eback(), static_cast<size_t>(old_size));
176309124Sdim        }
177227825Stheraven        ptrdiff_t ninp = gptr()  - eback();
178227825Stheraven        ptrdiff_t einp = egptr() - eback();
179227825Stheraven        ptrdiff_t nout = pptr()  - pbase();
180227825Stheraven        if (__strmode_ & __allocated)
181227825Stheraven        {
182227825Stheraven            if (__pfree_)
183227825Stheraven                __pfree_(eback());
184227825Stheraven            else
185227825Stheraven                delete [] eback();
186227825Stheraven        }
187227825Stheraven        setg(buf, buf + ninp, buf + einp);
188309124Sdim        setp(buf + einp, buf + new_size);
189327952Sdim        __pbump(nout);
190227825Stheraven        __strmode_ |= __allocated;
191227825Stheraven    }
192227825Stheraven    *pptr() = static_cast<char>(__c);
193227825Stheraven    pbump(1);
194276792Sdim    return int_type(static_cast<unsigned char>(__c));
195227825Stheraven}
196227825Stheraven
197227825Stheravenstrstreambuf::int_type
198227825Stheravenstrstreambuf::pbackfail(int_type __c)
199227825Stheraven{
200227825Stheraven    if (eback() == gptr())
201227825Stheraven        return EOF;
202227825Stheraven    if (__c == EOF)
203227825Stheraven    {
204227825Stheraven        gbump(-1);
205227825Stheraven        return int_type(0);
206227825Stheraven    }
207227825Stheraven    if (__strmode_ & __constant)
208227825Stheraven    {
209227825Stheraven        if (gptr()[-1] == static_cast<char>(__c))
210227825Stheraven        {
211227825Stheraven            gbump(-1);
212227825Stheraven            return __c;
213227825Stheraven        }
214227825Stheraven        return EOF;
215227825Stheraven    }
216227825Stheraven    gbump(-1);
217227825Stheraven    *gptr() = static_cast<char>(__c);
218227825Stheraven    return __c;
219227825Stheraven}
220227825Stheraven
221227825Stheravenstrstreambuf::int_type
222227825Stheravenstrstreambuf::underflow()
223227825Stheraven{
224227825Stheraven    if (gptr() == egptr())
225227825Stheraven    {
226227825Stheraven        if (egptr() >= pptr())
227227825Stheraven            return EOF;
228227825Stheraven        setg(eback(), gptr(), pptr());
229227825Stheraven    }
230276792Sdim    return int_type(static_cast<unsigned char>(*gptr()));
231227825Stheraven}
232227825Stheraven
233227825Stheravenstrstreambuf::pos_type
234227825Stheravenstrstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
235227825Stheraven{
236227825Stheraven    off_type __p(-1);
237261272Sdim    bool pos_in = (__which & ios::in) != 0;
238261272Sdim    bool pos_out = (__which & ios::out) != 0;
239227825Stheraven    bool legal = false;
240227825Stheraven    switch (__way)
241227825Stheraven    {
242227825Stheraven    case ios::beg:
243227825Stheraven    case ios::end:
244227825Stheraven        if (pos_in || pos_out)
245227825Stheraven            legal = true;
246227825Stheraven        break;
247227825Stheraven    case ios::cur:
248227825Stheraven        if (pos_in != pos_out)
249227825Stheraven            legal = true;
250227825Stheraven        break;
251227825Stheraven    }
252227825Stheraven    if (pos_in && gptr() == nullptr)
253227825Stheraven        legal = false;
254227825Stheraven    if (pos_out && pptr() == nullptr)
255227825Stheraven        legal = false;
256227825Stheraven    if (legal)
257227825Stheraven    {
258227825Stheraven        off_type newoff;
259227825Stheraven        char* seekhigh = epptr() ? epptr() : egptr();
260227825Stheraven        switch (__way)
261227825Stheraven        {
262227825Stheraven        case ios::beg:
263227825Stheraven            newoff = 0;
264227825Stheraven            break;
265227825Stheraven        case ios::cur:
266227825Stheraven            newoff = (pos_in ? gptr() : pptr()) - eback();
267227825Stheraven            break;
268227825Stheraven        case ios::end:
269227825Stheraven            newoff = seekhigh - eback();
270227825Stheraven            break;
271314564Sdim        default:
272314564Sdim            _LIBCPP_UNREACHABLE();
273227825Stheraven        }
274227825Stheraven        newoff += __off;
275227825Stheraven        if (0 <= newoff && newoff <= seekhigh - eback())
276227825Stheraven        {
277227825Stheraven            char* newpos = eback() + newoff;
278227825Stheraven            if (pos_in)
279227825Stheraven                setg(eback(), newpos, _VSTD::max(newpos, egptr()));
280227825Stheraven            if (pos_out)
281227825Stheraven            {
282227825Stheraven                // min(pbase, newpos), newpos, epptr()
283227825Stheraven                __off = epptr() - newpos;
284227825Stheraven                setp(min(pbase(), newpos), epptr());
285327952Sdim                __pbump((epptr() - pbase()) - __off);
286227825Stheraven            }
287227825Stheraven            __p = newoff;
288227825Stheraven        }
289227825Stheraven    }
290227825Stheraven    return pos_type(__p);
291227825Stheraven}
292227825Stheraven
293227825Stheravenstrstreambuf::pos_type
294227825Stheravenstrstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
295227825Stheraven{
296227825Stheraven    off_type __p(-1);
297261272Sdim    bool pos_in = (__which & ios::in) != 0;
298261272Sdim    bool pos_out = (__which & ios::out) != 0;
299227825Stheraven    if (pos_in || pos_out)
300227825Stheraven    {
301227825Stheraven        if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
302227825Stheraven        {
303227825Stheraven            off_type newoff = __sp;
304227825Stheraven            char* seekhigh = epptr() ? epptr() : egptr();
305227825Stheraven            if (0 <= newoff && newoff <= seekhigh - eback())
306227825Stheraven            {
307227825Stheraven                char* newpos = eback() + newoff;
308227825Stheraven                if (pos_in)
309227825Stheraven                    setg(eback(), newpos, _VSTD::max(newpos, egptr()));
310227825Stheraven                if (pos_out)
311227825Stheraven                {
312227825Stheraven                    // min(pbase, newpos), newpos, epptr()
313227825Stheraven                    off_type temp = epptr() - newpos;
314227825Stheraven                    setp(min(pbase(), newpos), epptr());
315327952Sdim                    __pbump((epptr() - pbase()) - temp);
316227825Stheraven                }
317227825Stheraven                __p = newoff;
318227825Stheraven            }
319227825Stheraven        }
320227825Stheraven    }
321227825Stheraven    return pos_type(__p);
322227825Stheraven}
323227825Stheraven
324227825Stheravenistrstream::~istrstream()
325227825Stheraven{
326227825Stheraven}
327227825Stheraven
328227825Stheravenostrstream::~ostrstream()
329227825Stheraven{
330227825Stheraven}
331227825Stheraven
332227825Stheravenstrstream::~strstream()
333227825Stheraven{
334227825Stheraven}
335227825Stheraven
336227825Stheraven_LIBCPP_END_NAMESPACE_STD
337