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