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