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"
14227825Stheraven
15227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
16227825Stheraven
17227825Stheravenstrstreambuf::strstreambuf(streamsize __alsize)
18227825Stheraven    : __strmode_(__dynamic),
19227825Stheraven      __alsize_(__alsize),
20227825Stheraven      __palloc_(nullptr),
21227825Stheraven      __pfree_(nullptr)
22227825Stheraven{
23227825Stheraven}
24227825Stheraven
25227825Stheravenstrstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
26227825Stheraven    : __strmode_(__dynamic),
27227825Stheraven      __alsize_(__default_alsize),
28227825Stheraven      __palloc_(__palloc),
29227825Stheraven      __pfree_(__pfree)
30227825Stheraven{
31227825Stheraven}
32227825Stheraven
33227825Stheravenvoid
34227825Stheravenstrstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
35227825Stheraven{
36227825Stheraven    if (__n == 0)
37232950Stheraven        __n = static_cast<streamsize>(strlen(__gnext));
38227825Stheraven    else if (__n < 0)
39227825Stheraven        __n = INT_MAX;
40227825Stheraven    if (__pbeg == nullptr)
41227825Stheraven        setg(__gnext, __gnext, __gnext + __n);
42227825Stheraven    else
43227825Stheraven    {
44227825Stheraven        setg(__gnext, __gnext, __pbeg);
45227825Stheraven        setp(__pbeg, __pbeg + __n);
46227825Stheraven    }
47227825Stheraven}
48227825Stheraven
49227825Stheravenstrstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
50227825Stheraven    : __strmode_(),
51227825Stheraven      __alsize_(__default_alsize),
52227825Stheraven      __palloc_(nullptr),
53227825Stheraven      __pfree_(nullptr)
54227825Stheraven{
55227825Stheraven    __init(__gnext, __n, __pbeg);
56227825Stheraven}
57227825Stheraven
58227825Stheravenstrstreambuf::strstreambuf(const char* __gnext, streamsize __n)
59227825Stheraven    : __strmode_(__constant),
60227825Stheraven      __alsize_(__default_alsize),
61227825Stheraven      __palloc_(nullptr),
62227825Stheraven      __pfree_(nullptr)
63227825Stheraven{
64227825Stheraven    __init((char*)__gnext, __n, nullptr);
65227825Stheraven}
66227825Stheraven
67227825Stheravenstrstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
68227825Stheraven    : __strmode_(),
69227825Stheraven      __alsize_(__default_alsize),
70227825Stheraven      __palloc_(nullptr),
71227825Stheraven      __pfree_(nullptr)
72227825Stheraven{
73227825Stheraven    __init((char*)__gnext, __n, (char*)__pbeg);
74227825Stheraven}
75227825Stheraven
76227825Stheravenstrstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
77227825Stheraven    : __strmode_(__constant),
78227825Stheraven      __alsize_(__default_alsize),
79227825Stheraven      __palloc_(nullptr),
80227825Stheraven      __pfree_(nullptr)
81227825Stheraven{
82227825Stheraven    __init((char*)__gnext, __n, nullptr);
83227825Stheraven}
84227825Stheraven
85227825Stheravenstrstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
86227825Stheraven    : __strmode_(),
87227825Stheraven      __alsize_(__default_alsize),
88227825Stheraven      __palloc_(nullptr),
89227825Stheraven      __pfree_(nullptr)
90227825Stheraven{
91227825Stheraven    __init((char*)__gnext, __n, (char*)__pbeg);
92227825Stheraven}
93227825Stheraven
94227825Stheravenstrstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
95227825Stheraven    : __strmode_(__constant),
96227825Stheraven      __alsize_(__default_alsize),
97227825Stheraven      __palloc_(nullptr),
98227825Stheraven      __pfree_(nullptr)
99227825Stheraven{
100227825Stheraven    __init((char*)__gnext, __n, nullptr);
101227825Stheraven}
102227825Stheraven
103227825Stheravenstrstreambuf::~strstreambuf()
104227825Stheraven{
105227825Stheraven    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
106227825Stheraven    {
107227825Stheraven        if (__pfree_)
108227825Stheraven            __pfree_(eback());
109227825Stheraven        else
110227825Stheraven            delete [] eback();
111227825Stheraven    }
112227825Stheraven}
113227825Stheraven
114227825Stheravenvoid
115227825Stheravenstrstreambuf::swap(strstreambuf& __rhs)
116227825Stheraven{
117227825Stheraven    streambuf::swap(__rhs);
118227825Stheraven    _VSTD::swap(__strmode_, __rhs.__strmode_);
119227825Stheraven    _VSTD::swap(__alsize_, __rhs.__alsize_);
120227825Stheraven    _VSTD::swap(__palloc_, __rhs.__palloc_);
121227825Stheraven    _VSTD::swap(__pfree_, __rhs.__pfree_);
122227825Stheraven}
123227825Stheraven
124227825Stheravenvoid
125227825Stheravenstrstreambuf::freeze(bool __freezefl)
126227825Stheraven{
127227825Stheraven    if (__strmode_ & __dynamic)
128227825Stheraven    {
129227825Stheraven        if (__freezefl)
130227825Stheraven            __strmode_ |= __frozen;
131227825Stheraven        else
132227825Stheraven            __strmode_ &= ~__frozen;
133227825Stheraven    }
134227825Stheraven}
135227825Stheraven
136227825Stheravenchar*
137227825Stheravenstrstreambuf::str()
138227825Stheraven{
139227825Stheraven    if (__strmode_ & __dynamic)
140227825Stheraven        __strmode_ |= __frozen;
141227825Stheraven    return eback();
142227825Stheraven}
143227825Stheraven
144227825Stheravenint
145227825Stheravenstrstreambuf::pcount() const
146227825Stheraven{
147227825Stheraven    return static_cast<int>(pptr() - pbase());
148227825Stheraven}
149227825Stheraven
150227825Stheravenstrstreambuf::int_type
151227825Stheravenstrstreambuf::overflow(int_type __c)
152227825Stheraven{
153227825Stheraven    if (__c == EOF)
154227825Stheraven        return int_type(0);
155227825Stheraven    if (pptr() == epptr())
156227825Stheraven    {
157227825Stheraven        if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
158227825Stheraven            return int_type(EOF);
159262801Sdim        size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
160262801Sdim        size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
161250514Sdim        if (new_size == 0)
162250514Sdim            new_size = __default_alsize;
163227825Stheraven        char* buf = nullptr;
164227825Stheraven        if (__palloc_)
165262801Sdim            buf = static_cast<char*>(__palloc_(new_size));
166227825Stheraven        else
167227825Stheraven            buf = new char[new_size];
168227825Stheraven        if (buf == nullptr)
169227825Stheraven            return int_type(EOF);
170232950Stheraven        memcpy(buf, eback(), static_cast<size_t>(old_size));
171227825Stheraven        ptrdiff_t ninp = gptr()  - eback();
172227825Stheraven        ptrdiff_t einp = egptr() - eback();
173227825Stheraven        ptrdiff_t nout = pptr()  - pbase();
174227825Stheraven        ptrdiff_t eout = epptr() - pbase();
175227825Stheraven        if (__strmode_ & __allocated)
176227825Stheraven        {
177227825Stheraven            if (__pfree_)
178227825Stheraven                __pfree_(eback());
179227825Stheraven            else
180227825Stheraven                delete [] eback();
181227825Stheraven        }
182227825Stheraven        setg(buf, buf + ninp, buf + einp);
183227825Stheraven        setp(buf + einp, buf + einp + eout);
184232950Stheraven        pbump(static_cast<int>(nout));
185227825Stheraven        __strmode_ |= __allocated;
186227825Stheraven    }
187227825Stheraven    *pptr() = static_cast<char>(__c);
188227825Stheraven    pbump(1);
189227825Stheraven    return int_type((unsigned char)__c);
190227825Stheraven}
191227825Stheraven
192227825Stheravenstrstreambuf::int_type
193227825Stheravenstrstreambuf::pbackfail(int_type __c)
194227825Stheraven{
195227825Stheraven    if (eback() == gptr())
196227825Stheraven        return EOF;
197227825Stheraven    if (__c == EOF)
198227825Stheraven    {
199227825Stheraven        gbump(-1);
200227825Stheraven        return int_type(0);
201227825Stheraven    }
202227825Stheraven    if (__strmode_ & __constant)
203227825Stheraven    {
204227825Stheraven        if (gptr()[-1] == static_cast<char>(__c))
205227825Stheraven        {
206227825Stheraven            gbump(-1);
207227825Stheraven            return __c;
208227825Stheraven        }
209227825Stheraven        return EOF;
210227825Stheraven    }
211227825Stheraven    gbump(-1);
212227825Stheraven    *gptr() = static_cast<char>(__c);
213227825Stheraven    return __c;
214227825Stheraven}
215227825Stheraven
216227825Stheravenstrstreambuf::int_type
217227825Stheravenstrstreambuf::underflow()
218227825Stheraven{
219227825Stheraven    if (gptr() == egptr())
220227825Stheraven    {
221227825Stheraven        if (egptr() >= pptr())
222227825Stheraven            return EOF;
223227825Stheraven        setg(eback(), gptr(), pptr());
224227825Stheraven    }
225227825Stheraven    return int_type((unsigned char)*gptr());
226227825Stheraven}
227227825Stheraven
228227825Stheravenstrstreambuf::pos_type
229227825Stheravenstrstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
230227825Stheraven{
231227825Stheraven    off_type __p(-1);
232262801Sdim    bool pos_in = (__which & ios::in) != 0;
233262801Sdim    bool pos_out = (__which & ios::out) != 0;
234227825Stheraven    bool legal = false;
235227825Stheraven    switch (__way)
236227825Stheraven    {
237227825Stheraven    case ios::beg:
238227825Stheraven    case ios::end:
239227825Stheraven        if (pos_in || pos_out)
240227825Stheraven            legal = true;
241227825Stheraven        break;
242227825Stheraven    case ios::cur:
243227825Stheraven        if (pos_in != pos_out)
244227825Stheraven            legal = true;
245227825Stheraven        break;
246227825Stheraven    }
247227825Stheraven    if (pos_in && gptr() == nullptr)
248227825Stheraven        legal = false;
249227825Stheraven    if (pos_out && pptr() == nullptr)
250227825Stheraven        legal = false;
251227825Stheraven    if (legal)
252227825Stheraven    {
253227825Stheraven        off_type newoff;
254227825Stheraven        char* seekhigh = epptr() ? epptr() : egptr();
255227825Stheraven        switch (__way)
256227825Stheraven        {
257227825Stheraven        case ios::beg:
258227825Stheraven            newoff = 0;
259227825Stheraven            break;
260227825Stheraven        case ios::cur:
261227825Stheraven            newoff = (pos_in ? gptr() : pptr()) - eback();
262227825Stheraven            break;
263227825Stheraven        case ios::end:
264227825Stheraven            newoff = seekhigh - eback();
265227825Stheraven            break;
266227825Stheraven        }
267227825Stheraven        newoff += __off;
268227825Stheraven        if (0 <= newoff && newoff <= seekhigh - eback())
269227825Stheraven        {
270227825Stheraven            char* newpos = eback() + newoff;
271227825Stheraven            if (pos_in)
272227825Stheraven                setg(eback(), newpos, _VSTD::max(newpos, egptr()));
273227825Stheraven            if (pos_out)
274227825Stheraven            {
275227825Stheraven                // min(pbase, newpos), newpos, epptr()
276227825Stheraven                __off = epptr() - newpos;
277227825Stheraven                setp(min(pbase(), newpos), epptr());
278227825Stheraven                pbump(static_cast<int>((epptr() - pbase()) - __off));
279227825Stheraven            }
280227825Stheraven            __p = newoff;
281227825Stheraven        }
282227825Stheraven    }
283227825Stheraven    return pos_type(__p);
284227825Stheraven}
285227825Stheraven
286227825Stheravenstrstreambuf::pos_type
287227825Stheravenstrstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
288227825Stheraven{
289227825Stheraven    off_type __p(-1);
290262801Sdim    bool pos_in = (__which & ios::in) != 0;
291262801Sdim    bool pos_out = (__which & ios::out) != 0;
292227825Stheraven    if (pos_in || pos_out)
293227825Stheraven    {
294227825Stheraven        if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
295227825Stheraven        {
296227825Stheraven            off_type newoff = __sp;
297227825Stheraven            char* seekhigh = epptr() ? epptr() : egptr();
298227825Stheraven            if (0 <= newoff && newoff <= seekhigh - eback())
299227825Stheraven            {
300227825Stheraven                char* newpos = eback() + newoff;
301227825Stheraven                if (pos_in)
302227825Stheraven                    setg(eback(), newpos, _VSTD::max(newpos, egptr()));
303227825Stheraven                if (pos_out)
304227825Stheraven                {
305227825Stheraven                    // min(pbase, newpos), newpos, epptr()
306227825Stheraven                    off_type temp = epptr() - newpos;
307227825Stheraven                    setp(min(pbase(), newpos), epptr());
308227825Stheraven                    pbump(static_cast<int>((epptr() - pbase()) - temp));
309227825Stheraven                }
310227825Stheraven                __p = newoff;
311227825Stheraven            }
312227825Stheraven        }
313227825Stheraven    }
314227825Stheraven    return pos_type(__p);
315227825Stheraven}
316227825Stheraven
317227825Stheravenistrstream::~istrstream()
318227825Stheraven{
319227825Stheraven}
320227825Stheraven
321227825Stheravenostrstream::~ostrstream()
322227825Stheraven{
323227825Stheraven}
324227825Stheraven
325227825Stheravenstrstream::~strstream()
326227825Stheraven{
327227825Stheraven}
328227825Stheraven
329227825Stheraven_LIBCPP_END_NAMESPACE_STD
330