xref: /freebsd/contrib/llvm-project/libcxx/src/strstream.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===------------------------ strstream.cpp -------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "strstream"
10*0b57cec5SDimitry Andric #include "algorithm"
11*0b57cec5SDimitry Andric #include "climits"
12*0b57cec5SDimitry Andric #include "cstring"
13*0b57cec5SDimitry Andric #include "cstdlib"
14*0b57cec5SDimitry Andric #include "__debug"
15*0b57cec5SDimitry Andric #include "__undef_macros"
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric strstreambuf::strstreambuf(streamsize __alsize)
20*0b57cec5SDimitry Andric     : __strmode_(__dynamic),
21*0b57cec5SDimitry Andric       __alsize_(__alsize),
22*0b57cec5SDimitry Andric       __palloc_(nullptr),
23*0b57cec5SDimitry Andric       __pfree_(nullptr)
24*0b57cec5SDimitry Andric {
25*0b57cec5SDimitry Andric }
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
28*0b57cec5SDimitry Andric     : __strmode_(__dynamic),
29*0b57cec5SDimitry Andric       __alsize_(__default_alsize),
30*0b57cec5SDimitry Andric       __palloc_(__palloc),
31*0b57cec5SDimitry Andric       __pfree_(__pfree)
32*0b57cec5SDimitry Andric {
33*0b57cec5SDimitry Andric }
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric void
36*0b57cec5SDimitry Andric strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
37*0b57cec5SDimitry Andric {
38*0b57cec5SDimitry Andric     if (__n == 0)
39*0b57cec5SDimitry Andric         __n = static_cast<streamsize>(strlen(__gnext));
40*0b57cec5SDimitry Andric     else if (__n < 0)
41*0b57cec5SDimitry Andric         __n = INT_MAX;
42*0b57cec5SDimitry Andric     if (__pbeg == nullptr)
43*0b57cec5SDimitry Andric         setg(__gnext, __gnext, __gnext + __n);
44*0b57cec5SDimitry Andric     else
45*0b57cec5SDimitry Andric     {
46*0b57cec5SDimitry Andric         setg(__gnext, __gnext, __pbeg);
47*0b57cec5SDimitry Andric         setp(__pbeg, __pbeg + __n);
48*0b57cec5SDimitry Andric     }
49*0b57cec5SDimitry Andric }
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
52*0b57cec5SDimitry Andric     : __strmode_(),
53*0b57cec5SDimitry Andric       __alsize_(__default_alsize),
54*0b57cec5SDimitry Andric       __palloc_(nullptr),
55*0b57cec5SDimitry Andric       __pfree_(nullptr)
56*0b57cec5SDimitry Andric {
57*0b57cec5SDimitry Andric     __init(__gnext, __n, __pbeg);
58*0b57cec5SDimitry Andric }
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
61*0b57cec5SDimitry Andric     : __strmode_(__constant),
62*0b57cec5SDimitry Andric       __alsize_(__default_alsize),
63*0b57cec5SDimitry Andric       __palloc_(nullptr),
64*0b57cec5SDimitry Andric       __pfree_(nullptr)
65*0b57cec5SDimitry Andric {
66*0b57cec5SDimitry Andric     __init(const_cast<char *>(__gnext), __n, nullptr);
67*0b57cec5SDimitry Andric }
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
70*0b57cec5SDimitry Andric     : __strmode_(),
71*0b57cec5SDimitry Andric       __alsize_(__default_alsize),
72*0b57cec5SDimitry Andric       __palloc_(nullptr),
73*0b57cec5SDimitry Andric       __pfree_(nullptr)
74*0b57cec5SDimitry Andric {
75*0b57cec5SDimitry Andric     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
76*0b57cec5SDimitry Andric }
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
79*0b57cec5SDimitry Andric     : __strmode_(__constant),
80*0b57cec5SDimitry Andric       __alsize_(__default_alsize),
81*0b57cec5SDimitry Andric       __palloc_(nullptr),
82*0b57cec5SDimitry Andric       __pfree_(nullptr)
83*0b57cec5SDimitry Andric {
84*0b57cec5SDimitry Andric     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
85*0b57cec5SDimitry Andric }
86*0b57cec5SDimitry Andric 
87*0b57cec5SDimitry Andric strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
88*0b57cec5SDimitry Andric     : __strmode_(),
89*0b57cec5SDimitry Andric       __alsize_(__default_alsize),
90*0b57cec5SDimitry Andric       __palloc_(nullptr),
91*0b57cec5SDimitry Andric       __pfree_(nullptr)
92*0b57cec5SDimitry Andric {
93*0b57cec5SDimitry Andric     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
94*0b57cec5SDimitry Andric }
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
97*0b57cec5SDimitry Andric     : __strmode_(__constant),
98*0b57cec5SDimitry Andric       __alsize_(__default_alsize),
99*0b57cec5SDimitry Andric       __palloc_(nullptr),
100*0b57cec5SDimitry Andric       __pfree_(nullptr)
101*0b57cec5SDimitry Andric {
102*0b57cec5SDimitry Andric     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
103*0b57cec5SDimitry Andric }
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric strstreambuf::~strstreambuf()
106*0b57cec5SDimitry Andric {
107*0b57cec5SDimitry Andric     if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
108*0b57cec5SDimitry Andric     {
109*0b57cec5SDimitry Andric         if (__pfree_)
110*0b57cec5SDimitry Andric             __pfree_(eback());
111*0b57cec5SDimitry Andric         else
112*0b57cec5SDimitry Andric             delete [] eback();
113*0b57cec5SDimitry Andric     }
114*0b57cec5SDimitry Andric }
115*0b57cec5SDimitry Andric 
116*0b57cec5SDimitry Andric void
117*0b57cec5SDimitry Andric strstreambuf::swap(strstreambuf& __rhs)
118*0b57cec5SDimitry Andric {
119*0b57cec5SDimitry Andric     streambuf::swap(__rhs);
120*0b57cec5SDimitry Andric     _VSTD::swap(__strmode_, __rhs.__strmode_);
121*0b57cec5SDimitry Andric     _VSTD::swap(__alsize_, __rhs.__alsize_);
122*0b57cec5SDimitry Andric     _VSTD::swap(__palloc_, __rhs.__palloc_);
123*0b57cec5SDimitry Andric     _VSTD::swap(__pfree_, __rhs.__pfree_);
124*0b57cec5SDimitry Andric }
125*0b57cec5SDimitry Andric 
126*0b57cec5SDimitry Andric void
127*0b57cec5SDimitry Andric strstreambuf::freeze(bool __freezefl)
128*0b57cec5SDimitry Andric {
129*0b57cec5SDimitry Andric     if (__strmode_ & __dynamic)
130*0b57cec5SDimitry Andric     {
131*0b57cec5SDimitry Andric         if (__freezefl)
132*0b57cec5SDimitry Andric             __strmode_ |= __frozen;
133*0b57cec5SDimitry Andric         else
134*0b57cec5SDimitry Andric             __strmode_ &= ~__frozen;
135*0b57cec5SDimitry Andric     }
136*0b57cec5SDimitry Andric }
137*0b57cec5SDimitry Andric 
138*0b57cec5SDimitry Andric char*
139*0b57cec5SDimitry Andric strstreambuf::str()
140*0b57cec5SDimitry Andric {
141*0b57cec5SDimitry Andric     if (__strmode_ & __dynamic)
142*0b57cec5SDimitry Andric         __strmode_ |= __frozen;
143*0b57cec5SDimitry Andric     return eback();
144*0b57cec5SDimitry Andric }
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric int
147*0b57cec5SDimitry Andric strstreambuf::pcount() const
148*0b57cec5SDimitry Andric {
149*0b57cec5SDimitry Andric     return static_cast<int>(pptr() - pbase());
150*0b57cec5SDimitry Andric }
151*0b57cec5SDimitry Andric 
152*0b57cec5SDimitry Andric strstreambuf::int_type
153*0b57cec5SDimitry Andric strstreambuf::overflow(int_type __c)
154*0b57cec5SDimitry Andric {
155*0b57cec5SDimitry Andric     if (__c == EOF)
156*0b57cec5SDimitry Andric         return int_type(0);
157*0b57cec5SDimitry Andric     if (pptr() == epptr())
158*0b57cec5SDimitry Andric     {
159*0b57cec5SDimitry Andric         if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
160*0b57cec5SDimitry Andric             return int_type(EOF);
161*0b57cec5SDimitry Andric         size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
162*0b57cec5SDimitry Andric         size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
163*0b57cec5SDimitry Andric         if (new_size == 0)
164*0b57cec5SDimitry Andric             new_size = __default_alsize;
165*0b57cec5SDimitry Andric         char* buf = nullptr;
166*0b57cec5SDimitry Andric         if (__palloc_)
167*0b57cec5SDimitry Andric             buf = static_cast<char*>(__palloc_(new_size));
168*0b57cec5SDimitry Andric         else
169*0b57cec5SDimitry Andric             buf = new char[new_size];
170*0b57cec5SDimitry Andric         if (buf == nullptr)
171*0b57cec5SDimitry Andric             return int_type(EOF);
172*0b57cec5SDimitry Andric         if (old_size != 0) {
173*0b57cec5SDimitry Andric             _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
174*0b57cec5SDimitry Andric             memcpy(buf, eback(), static_cast<size_t>(old_size));
175*0b57cec5SDimitry Andric         }
176*0b57cec5SDimitry Andric         ptrdiff_t ninp = gptr()  - eback();
177*0b57cec5SDimitry Andric         ptrdiff_t einp = egptr() - eback();
178*0b57cec5SDimitry Andric         ptrdiff_t nout = pptr()  - pbase();
179*0b57cec5SDimitry Andric         if (__strmode_ & __allocated)
180*0b57cec5SDimitry Andric         {
181*0b57cec5SDimitry Andric             if (__pfree_)
182*0b57cec5SDimitry Andric                 __pfree_(eback());
183*0b57cec5SDimitry Andric             else
184*0b57cec5SDimitry Andric                 delete [] eback();
185*0b57cec5SDimitry Andric         }
186*0b57cec5SDimitry Andric         setg(buf, buf + ninp, buf + einp);
187*0b57cec5SDimitry Andric         setp(buf + einp, buf + new_size);
188*0b57cec5SDimitry Andric         __pbump(nout);
189*0b57cec5SDimitry Andric         __strmode_ |= __allocated;
190*0b57cec5SDimitry Andric     }
191*0b57cec5SDimitry Andric     *pptr() = static_cast<char>(__c);
192*0b57cec5SDimitry Andric     pbump(1);
193*0b57cec5SDimitry Andric     return int_type(static_cast<unsigned char>(__c));
194*0b57cec5SDimitry Andric }
195*0b57cec5SDimitry Andric 
196*0b57cec5SDimitry Andric strstreambuf::int_type
197*0b57cec5SDimitry Andric strstreambuf::pbackfail(int_type __c)
198*0b57cec5SDimitry Andric {
199*0b57cec5SDimitry Andric     if (eback() == gptr())
200*0b57cec5SDimitry Andric         return EOF;
201*0b57cec5SDimitry Andric     if (__c == EOF)
202*0b57cec5SDimitry Andric     {
203*0b57cec5SDimitry Andric         gbump(-1);
204*0b57cec5SDimitry Andric         return int_type(0);
205*0b57cec5SDimitry Andric     }
206*0b57cec5SDimitry Andric     if (__strmode_ & __constant)
207*0b57cec5SDimitry Andric     {
208*0b57cec5SDimitry Andric         if (gptr()[-1] == static_cast<char>(__c))
209*0b57cec5SDimitry Andric         {
210*0b57cec5SDimitry Andric             gbump(-1);
211*0b57cec5SDimitry Andric             return __c;
212*0b57cec5SDimitry Andric         }
213*0b57cec5SDimitry Andric         return EOF;
214*0b57cec5SDimitry Andric     }
215*0b57cec5SDimitry Andric     gbump(-1);
216*0b57cec5SDimitry Andric     *gptr() = static_cast<char>(__c);
217*0b57cec5SDimitry Andric     return __c;
218*0b57cec5SDimitry Andric }
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric strstreambuf::int_type
221*0b57cec5SDimitry Andric strstreambuf::underflow()
222*0b57cec5SDimitry Andric {
223*0b57cec5SDimitry Andric     if (gptr() == egptr())
224*0b57cec5SDimitry Andric     {
225*0b57cec5SDimitry Andric         if (egptr() >= pptr())
226*0b57cec5SDimitry Andric             return EOF;
227*0b57cec5SDimitry Andric         setg(eback(), gptr(), pptr());
228*0b57cec5SDimitry Andric     }
229*0b57cec5SDimitry Andric     return int_type(static_cast<unsigned char>(*gptr()));
230*0b57cec5SDimitry Andric }
231*0b57cec5SDimitry Andric 
232*0b57cec5SDimitry Andric strstreambuf::pos_type
233*0b57cec5SDimitry Andric strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
234*0b57cec5SDimitry Andric {
235*0b57cec5SDimitry Andric     off_type __p(-1);
236*0b57cec5SDimitry Andric     bool pos_in = (__which & ios::in) != 0;
237*0b57cec5SDimitry Andric     bool pos_out = (__which & ios::out) != 0;
238*0b57cec5SDimitry Andric     bool legal = false;
239*0b57cec5SDimitry Andric     switch (__way)
240*0b57cec5SDimitry Andric     {
241*0b57cec5SDimitry Andric     case ios::beg:
242*0b57cec5SDimitry Andric     case ios::end:
243*0b57cec5SDimitry Andric         if (pos_in || pos_out)
244*0b57cec5SDimitry Andric             legal = true;
245*0b57cec5SDimitry Andric         break;
246*0b57cec5SDimitry Andric     case ios::cur:
247*0b57cec5SDimitry Andric         if (pos_in != pos_out)
248*0b57cec5SDimitry Andric             legal = true;
249*0b57cec5SDimitry Andric         break;
250*0b57cec5SDimitry Andric     }
251*0b57cec5SDimitry Andric     if (pos_in && gptr() == nullptr)
252*0b57cec5SDimitry Andric         legal = false;
253*0b57cec5SDimitry Andric     if (pos_out && pptr() == nullptr)
254*0b57cec5SDimitry Andric         legal = false;
255*0b57cec5SDimitry Andric     if (legal)
256*0b57cec5SDimitry Andric     {
257*0b57cec5SDimitry Andric         off_type newoff;
258*0b57cec5SDimitry Andric         char* seekhigh = epptr() ? epptr() : egptr();
259*0b57cec5SDimitry Andric         switch (__way)
260*0b57cec5SDimitry Andric         {
261*0b57cec5SDimitry Andric         case ios::beg:
262*0b57cec5SDimitry Andric             newoff = 0;
263*0b57cec5SDimitry Andric             break;
264*0b57cec5SDimitry Andric         case ios::cur:
265*0b57cec5SDimitry Andric             newoff = (pos_in ? gptr() : pptr()) - eback();
266*0b57cec5SDimitry Andric             break;
267*0b57cec5SDimitry Andric         case ios::end:
268*0b57cec5SDimitry Andric             newoff = seekhigh - eback();
269*0b57cec5SDimitry Andric             break;
270*0b57cec5SDimitry Andric         default:
271*0b57cec5SDimitry Andric             _LIBCPP_UNREACHABLE();
272*0b57cec5SDimitry Andric         }
273*0b57cec5SDimitry Andric         newoff += __off;
274*0b57cec5SDimitry Andric         if (0 <= newoff && newoff <= seekhigh - eback())
275*0b57cec5SDimitry Andric         {
276*0b57cec5SDimitry Andric             char* newpos = eback() + newoff;
277*0b57cec5SDimitry Andric             if (pos_in)
278*0b57cec5SDimitry Andric                 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
279*0b57cec5SDimitry Andric             if (pos_out)
280*0b57cec5SDimitry Andric             {
281*0b57cec5SDimitry Andric                 // min(pbase, newpos), newpos, epptr()
282*0b57cec5SDimitry Andric                 __off = epptr() - newpos;
283*0b57cec5SDimitry Andric                 setp(min(pbase(), newpos), epptr());
284*0b57cec5SDimitry Andric                 __pbump((epptr() - pbase()) - __off);
285*0b57cec5SDimitry Andric             }
286*0b57cec5SDimitry Andric             __p = newoff;
287*0b57cec5SDimitry Andric         }
288*0b57cec5SDimitry Andric     }
289*0b57cec5SDimitry Andric     return pos_type(__p);
290*0b57cec5SDimitry Andric }
291*0b57cec5SDimitry Andric 
292*0b57cec5SDimitry Andric strstreambuf::pos_type
293*0b57cec5SDimitry Andric strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
294*0b57cec5SDimitry Andric {
295*0b57cec5SDimitry Andric     off_type __p(-1);
296*0b57cec5SDimitry Andric     bool pos_in = (__which & ios::in) != 0;
297*0b57cec5SDimitry Andric     bool pos_out = (__which & ios::out) != 0;
298*0b57cec5SDimitry Andric     if (pos_in || pos_out)
299*0b57cec5SDimitry Andric     {
300*0b57cec5SDimitry Andric         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
301*0b57cec5SDimitry Andric         {
302*0b57cec5SDimitry Andric             off_type newoff = __sp;
303*0b57cec5SDimitry Andric             char* seekhigh = epptr() ? epptr() : egptr();
304*0b57cec5SDimitry Andric             if (0 <= newoff && newoff <= seekhigh - eback())
305*0b57cec5SDimitry Andric             {
306*0b57cec5SDimitry Andric                 char* newpos = eback() + newoff;
307*0b57cec5SDimitry Andric                 if (pos_in)
308*0b57cec5SDimitry Andric                     setg(eback(), newpos, _VSTD::max(newpos, egptr()));
309*0b57cec5SDimitry Andric                 if (pos_out)
310*0b57cec5SDimitry Andric                 {
311*0b57cec5SDimitry Andric                     // min(pbase, newpos), newpos, epptr()
312*0b57cec5SDimitry Andric                     off_type temp = epptr() - newpos;
313*0b57cec5SDimitry Andric                     setp(min(pbase(), newpos), epptr());
314*0b57cec5SDimitry Andric                     __pbump((epptr() - pbase()) - temp);
315*0b57cec5SDimitry Andric                 }
316*0b57cec5SDimitry Andric                 __p = newoff;
317*0b57cec5SDimitry Andric             }
318*0b57cec5SDimitry Andric         }
319*0b57cec5SDimitry Andric     }
320*0b57cec5SDimitry Andric     return pos_type(__p);
321*0b57cec5SDimitry Andric }
322*0b57cec5SDimitry Andric 
323*0b57cec5SDimitry Andric istrstream::~istrstream()
324*0b57cec5SDimitry Andric {
325*0b57cec5SDimitry Andric }
326*0b57cec5SDimitry Andric 
327*0b57cec5SDimitry Andric ostrstream::~ostrstream()
328*0b57cec5SDimitry Andric {
329*0b57cec5SDimitry Andric }
330*0b57cec5SDimitry Andric 
331*0b57cec5SDimitry Andric strstream::~strstream()
332*0b57cec5SDimitry Andric {
333*0b57cec5SDimitry Andric }
334*0b57cec5SDimitry Andric 
335*0b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
336