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