strstream.cpp revision 227825
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)
37227825Stheraven        __n = 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);
159227825Stheraven        streamsize old_size = (epptr() ? epptr() : egptr()) - eback();
160227825Stheraven        streamsize new_size = max<streamsize>(__alsize_, 2*old_size);
161227825Stheraven        char* buf = nullptr;
162227825Stheraven        if (__palloc_)
163227825Stheraven            buf = static_cast<char*>(__palloc_(new_size));
164227825Stheraven        else
165227825Stheraven            buf = new char[new_size];
166227825Stheraven        if (buf == nullptr)
167227825Stheraven            return int_type(EOF);
168227825Stheraven        memcpy(buf, eback(), old_size);
169227825Stheraven        ptrdiff_t ninp = gptr()  - eback();
170227825Stheraven        ptrdiff_t einp = egptr() - eback();
171227825Stheraven        ptrdiff_t nout = pptr()  - pbase();
172227825Stheraven        ptrdiff_t eout = epptr() - pbase();
173227825Stheraven        if (__strmode_ & __allocated)
174227825Stheraven        {
175227825Stheraven            if (__pfree_)
176227825Stheraven                __pfree_(eback());
177227825Stheraven            else
178227825Stheraven                delete [] eback();
179227825Stheraven        }
180227825Stheraven        setg(buf, buf + ninp, buf + einp);
181227825Stheraven        setp(buf + einp, buf + einp + eout);
182227825Stheraven        pbump(nout);
183227825Stheraven        __strmode_ |= __allocated;
184227825Stheraven    }
185227825Stheraven    *pptr() = static_cast<char>(__c);
186227825Stheraven    pbump(1);
187227825Stheraven    return int_type((unsigned char)__c);
188227825Stheraven}
189227825Stheraven
190227825Stheravenstrstreambuf::int_type
191227825Stheravenstrstreambuf::pbackfail(int_type __c)
192227825Stheraven{
193227825Stheraven    if (eback() == gptr())
194227825Stheraven        return EOF;
195227825Stheraven    if (__c == EOF)
196227825Stheraven    {
197227825Stheraven        gbump(-1);
198227825Stheraven        return int_type(0);
199227825Stheraven    }
200227825Stheraven    if (__strmode_ & __constant)
201227825Stheraven    {
202227825Stheraven        if (gptr()[-1] == static_cast<char>(__c))
203227825Stheraven        {
204227825Stheraven            gbump(-1);
205227825Stheraven            return __c;
206227825Stheraven        }
207227825Stheraven        return EOF;
208227825Stheraven    }
209227825Stheraven    gbump(-1);
210227825Stheraven    *gptr() = static_cast<char>(__c);
211227825Stheraven    return __c;
212227825Stheraven}
213227825Stheraven
214227825Stheravenstrstreambuf::int_type
215227825Stheravenstrstreambuf::underflow()
216227825Stheraven{
217227825Stheraven    if (gptr() == egptr())
218227825Stheraven    {
219227825Stheraven        if (egptr() >= pptr())
220227825Stheraven            return EOF;
221227825Stheraven        setg(eback(), gptr(), pptr());
222227825Stheraven    }
223227825Stheraven    return int_type((unsigned char)*gptr());
224227825Stheraven}
225227825Stheraven
226227825Stheravenstrstreambuf::pos_type
227227825Stheravenstrstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
228227825Stheraven{
229227825Stheraven    off_type __p(-1);
230227825Stheraven    bool pos_in = __which & ios::in;
231227825Stheraven    bool pos_out = __which & ios::out;
232227825Stheraven    bool legal = false;
233227825Stheraven    switch (__way)
234227825Stheraven    {
235227825Stheraven    case ios::beg:
236227825Stheraven    case ios::end:
237227825Stheraven        if (pos_in || pos_out)
238227825Stheraven            legal = true;
239227825Stheraven        break;
240227825Stheraven    case ios::cur:
241227825Stheraven        if (pos_in != pos_out)
242227825Stheraven            legal = true;
243227825Stheraven        break;
244227825Stheraven    }
245227825Stheraven    if (pos_in && gptr() == nullptr)
246227825Stheraven        legal = false;
247227825Stheraven    if (pos_out && pptr() == nullptr)
248227825Stheraven        legal = false;
249227825Stheraven    if (legal)
250227825Stheraven    {
251227825Stheraven        off_type newoff;
252227825Stheraven        char* seekhigh = epptr() ? epptr() : egptr();
253227825Stheraven        switch (__way)
254227825Stheraven        {
255227825Stheraven        case ios::beg:
256227825Stheraven            newoff = 0;
257227825Stheraven            break;
258227825Stheraven        case ios::cur:
259227825Stheraven            newoff = (pos_in ? gptr() : pptr()) - eback();
260227825Stheraven            break;
261227825Stheraven        case ios::end:
262227825Stheraven            newoff = seekhigh - eback();
263227825Stheraven            break;
264227825Stheraven        }
265227825Stheraven        newoff += __off;
266227825Stheraven        if (0 <= newoff && newoff <= seekhigh - eback())
267227825Stheraven        {
268227825Stheraven            char* newpos = eback() + newoff;
269227825Stheraven            if (pos_in)
270227825Stheraven                setg(eback(), newpos, _VSTD::max(newpos, egptr()));
271227825Stheraven            if (pos_out)
272227825Stheraven            {
273227825Stheraven                // min(pbase, newpos), newpos, epptr()
274227825Stheraven                __off = epptr() - newpos;
275227825Stheraven                setp(min(pbase(), newpos), epptr());
276227825Stheraven                pbump(static_cast<int>((epptr() - pbase()) - __off));
277227825Stheraven            }
278227825Stheraven            __p = newoff;
279227825Stheraven        }
280227825Stheraven    }
281227825Stheraven    return pos_type(__p);
282227825Stheraven}
283227825Stheraven
284227825Stheravenstrstreambuf::pos_type
285227825Stheravenstrstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
286227825Stheraven{
287227825Stheraven    off_type __p(-1);
288227825Stheraven    bool pos_in = __which & ios::in;
289227825Stheraven    bool pos_out = __which & ios::out;
290227825Stheraven    if (pos_in || pos_out)
291227825Stheraven    {
292227825Stheraven        if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
293227825Stheraven        {
294227825Stheraven            off_type newoff = __sp;
295227825Stheraven            char* seekhigh = epptr() ? epptr() : egptr();
296227825Stheraven            if (0 <= newoff && newoff <= seekhigh - eback())
297227825Stheraven            {
298227825Stheraven                char* newpos = eback() + newoff;
299227825Stheraven                if (pos_in)
300227825Stheraven                    setg(eback(), newpos, _VSTD::max(newpos, egptr()));
301227825Stheraven                if (pos_out)
302227825Stheraven                {
303227825Stheraven                    // min(pbase, newpos), newpos, epptr()
304227825Stheraven                    off_type temp = epptr() - newpos;
305227825Stheraven                    setp(min(pbase(), newpos), epptr());
306227825Stheraven                    pbump(static_cast<int>((epptr() - pbase()) - temp));
307227825Stheraven                }
308227825Stheraven                __p = newoff;
309227825Stheraven            }
310227825Stheraven        }
311227825Stheraven    }
312227825Stheraven    return pos_type(__p);
313227825Stheraven}
314227825Stheraven
315227825Stheravenistrstream::~istrstream()
316227825Stheraven{
317227825Stheraven}
318227825Stheraven
319227825Stheravenostrstream::~ostrstream()
320227825Stheraven{
321227825Stheraven}
322227825Stheraven
323227825Stheravenstrstream::~strstream()
324227825Stheraven{
325227825Stheraven}
326227825Stheraven
327227825Stheraven_LIBCPP_END_NAMESPACE_STD
328