]>
Commit | Line | Data |
---|---|---|
42526146 PE |
1 | // strstream definitions -*- C++ -*- |
2 | ||
748086b7 | 3 | // Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation |
42526146 | 4 | // |
38cca750 BK |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
42526146 | 9 | // any later version. |
38cca750 BK |
10 | |
11 | // This library is distributed in the hope that it will be useful, | |
42526146 PE |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
38cca750 | 15 | |
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
42526146 | 19 | |
748086b7 JJ |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
42526146 | 24 | |
b2dad0e3 BK |
25 | /* |
26 | * Copyright (c) 1998 | |
27 | * Silicon Graphics Computer Systems, Inc. | |
28 | * | |
29 | * Permission to use, copy, modify, distribute and sell this software | |
30 | * and its documentation for any purpose is hereby granted without fee, | |
31 | * provided that the above copyright notice appear in all copies and | |
32 | * that both that copyright notice and this permission notice appear | |
33 | * in supporting documentation. Silicon Graphics makes no | |
34 | * representations about the suitability of this software for any | |
35 | * purpose. It is provided "as is" without express or implied warranty. | |
36 | */ | |
37 | ||
38 | // Implementation of the classes in header <strstream>. | |
39 | // WARNING: The classes defined in <strstream> are DEPRECATED. This | |
40 | // header is defined in section D.7.1 of the C++ standard, and it | |
41 | // MAY BE REMOVED in a future standard revision. You should use the | |
42 | // header <sstream> instead. | |
43 | ||
9a56333e | 44 | #include <strstream> |
5feb272b | 45 | #include <algorithm> |
b2dad0e3 BK |
46 | #include <new> |
47 | #include <stdlib.h> | |
48 | #include <string.h> | |
49 | #include <limits.h> | |
50 | ||
3cbc7af0 BK |
51 | _GLIBCXX_BEGIN_NAMESPACE(std) |
52 | ||
9a56333e BK |
53 | strstreambuf::strstreambuf(streamsize initial_capacity) |
54 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true), | |
55 | _M_frozen(false), _M_constant(false) | |
56 | { | |
4977bab6 | 57 | streamsize n = std::max(initial_capacity, streamsize(16)); |
49bc23b7 BK |
58 | |
59 | char* buf = _M_alloc(n); | |
60 | if (buf) | |
9a56333e | 61 | { |
49bc23b7 BK |
62 | setp(buf, buf + n); |
63 | setg(buf, buf, buf); | |
9a56333e BK |
64 | } |
65 | } | |
66 | ||
67 | strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*)) | |
68 | : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true), | |
69 | _M_frozen(false), _M_constant(false) | |
70 | { | |
49bc23b7 BK |
71 | streamsize n = 16; |
72 | ||
73 | char* buf = _M_alloc(n); | |
74 | if (buf) | |
9a56333e | 75 | { |
49bc23b7 BK |
76 | setp(buf, buf + n); |
77 | setg(buf, buf, buf); | |
9a56333e BK |
78 | } |
79 | } | |
80 | ||
50a681c4 | 81 | strstreambuf::strstreambuf(char* get, streamsize n, char* put) throw () |
9a56333e BK |
82 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
83 | _M_frozen(false), _M_constant(false) | |
84 | { _M_setup(get, put, n); } | |
85 | ||
50a681c4 | 86 | strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put) throw () |
9a56333e | 87 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
497e42fd | 88 | _M_frozen(false), _M_constant(false) |
9a56333e BK |
89 | { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } |
90 | ||
91 | strstreambuf::strstreambuf(unsigned char* get, streamsize n, | |
50a681c4 | 92 | unsigned char* put) throw () |
9a56333e BK |
93 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
94 | _M_frozen(false), _M_constant(false) | |
95 | { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } | |
96 | ||
50a681c4 | 97 | strstreambuf::strstreambuf(const char* get, streamsize n) throw () |
9a56333e BK |
98 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
99 | _M_frozen(false), _M_constant(true) | |
100 | { _M_setup(const_cast<char*>(get), 0, n); } | |
101 | ||
50a681c4 | 102 | strstreambuf::strstreambuf(const signed char* get, streamsize n) throw () |
9a56333e BK |
103 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
104 | _M_frozen(false), _M_constant(true) | |
105 | { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); } | |
106 | ||
50a681c4 | 107 | strstreambuf::strstreambuf(const unsigned char* get, streamsize n) throw () |
9a56333e BK |
108 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
109 | _M_frozen(false), _M_constant(true) | |
110 | { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); } | |
111 | ||
112 | strstreambuf::~strstreambuf() | |
113 | { | |
114 | if (_M_dynamic && !_M_frozen) | |
49bc23b7 | 115 | _M_free(eback()); |
9a56333e BK |
116 | } |
117 | ||
118 | void | |
50a681c4 | 119 | strstreambuf::freeze(bool frozenflag) throw () |
9a56333e BK |
120 | { |
121 | if (_M_dynamic) | |
122 | _M_frozen = frozenflag; | |
123 | } | |
124 | ||
125 | char* | |
50a681c4 | 126 | strstreambuf::str() throw () |
9a56333e BK |
127 | { |
128 | freeze(true); | |
129 | return eback(); | |
130 | } | |
131 | ||
132 | int | |
50a681c4 | 133 | strstreambuf::pcount() const throw () |
9a56333e BK |
134 | { return pptr() ? pptr() - pbase() : 0; } |
135 | ||
136 | strstreambuf::int_type | |
137 | strstreambuf::overflow(int_type c) | |
138 | { | |
139 | if (c == traits_type::eof()) | |
140 | return traits_type::not_eof(c); | |
497e42fd | 141 | |
9a56333e BK |
142 | // Try to expand the buffer. |
143 | if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) | |
144 | { | |
145 | ptrdiff_t old_size = epptr() - pbase(); | |
dd6eaaed | 146 | ptrdiff_t new_size = std::max(ptrdiff_t(2 * old_size), ptrdiff_t(1)); |
497e42fd | 147 | |
9a56333e BK |
148 | char* buf = _M_alloc(new_size); |
149 | if (buf) | |
150 | { | |
151 | memcpy(buf, pbase(), old_size); | |
152 | char* old_buffer = pbase(); | |
153 | bool reposition_get = false; | |
154 | ptrdiff_t old_get_offset; | |
155 | if (gptr() != 0) | |
156 | { | |
157 | reposition_get = true; | |
158 | old_get_offset = gptr() - eback(); | |
159 | } | |
497e42fd | 160 | |
9a56333e BK |
161 | setp(buf, buf + new_size); |
162 | pbump(old_size); | |
163 | ||
164 | if (reposition_get) | |
165 | setg(buf, buf + old_get_offset, buf + | |
4977bab6 | 166 | std::max(old_get_offset, old_size)); |
9a56333e BK |
167 | |
168 | _M_free(old_buffer); | |
169 | } | |
170 | } | |
497e42fd | 171 | |
9a56333e BK |
172 | if (pptr() != epptr()) |
173 | { | |
174 | *pptr() = c; | |
175 | pbump(1); | |
176 | return c; | |
177 | } | |
178 | else | |
179 | return traits_type::eof(); | |
180 | } | |
181 | ||
182 | strstreambuf::int_type | |
183 | strstreambuf::pbackfail(int_type c) | |
184 | { | |
185 | if (gptr() != eback()) | |
186 | { | |
497e42fd BK |
187 | if (c == _Traits::eof()) |
188 | { | |
189 | gbump(-1); | |
190 | return _Traits::not_eof(c); | |
191 | } | |
a62e7311 | 192 | else if (c == _Traits::to_int_type(gptr()[-1])) |
497e42fd BK |
193 | { // KLUDGE |
194 | gbump(-1); | |
195 | return c; | |
196 | } | |
197 | else if (!_M_constant) | |
198 | { | |
199 | gbump(-1); | |
200 | *gptr() = c; | |
201 | return c; | |
202 | } | |
b2dad0e3 | 203 | } |
eafa1afa | 204 | return _Traits::eof(); |
9a56333e | 205 | } |
eafa1afa | 206 | |
9a56333e BK |
207 | strstreambuf::int_type |
208 | strstreambuf::underflow() | |
209 | { | |
210 | if (gptr() == egptr() && pptr() && pptr() > egptr()) | |
211 | setg(eback(), gptr(), pptr()); | |
eafa1afa | 212 | |
9a56333e BK |
213 | if (gptr() != egptr()) |
214 | return (unsigned char) *gptr(); | |
215 | else | |
216 | return _Traits::eof(); | |
217 | } | |
218 | ||
219 | basic_streambuf<char, char_traits<char> >* | |
220 | strstreambuf::setbuf(char*, streamsize) | |
221 | { return this; } | |
222 | ||
223 | strstreambuf::pos_type | |
224 | strstreambuf::seekoff(off_type off, ios_base::seekdir dir, | |
225 | ios_base::openmode mode) | |
226 | { | |
227 | bool do_get = false; | |
228 | bool do_put = false; | |
229 | ||
230 | if ((mode & (ios_base::in | ios_base::out)) | |
231 | == (ios_base::in | ios_base::out) && | |
232 | (dir == ios_base::beg || dir == ios_base::end)) | |
46bbeb65 | 233 | do_get = do_put = true; |
9a56333e BK |
234 | else if (mode & ios_base::in) |
235 | do_get = true; | |
236 | else if (mode & ios_base::out) | |
237 | do_put = true; | |
238 | ||
239 | // !gptr() is here because, according to D.7.1 paragraph 4, the seekable | |
240 | // area is undefined if there is no get area. | |
241 | if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr()) | |
242 | return pos_type(off_type(-1)); | |
eafa1afa | 243 | |
9a56333e BK |
244 | char* seeklow = eback(); |
245 | char* seekhigh = epptr() ? epptr() : egptr(); | |
246 | ||
247 | off_type newoff; | |
248 | switch (dir) | |
249 | { | |
250 | case ios_base::beg: | |
251 | newoff = 0; | |
252 | break; | |
253 | case ios_base::end: | |
254 | newoff = seekhigh - seeklow; | |
255 | break; | |
256 | case ios_base::cur: | |
257 | newoff = do_put ? pptr() - seeklow : gptr() - seeklow; | |
258 | break; | |
259 | default: | |
260 | return pos_type(off_type(-1)); | |
261 | } | |
262 | ||
263 | off += newoff; | |
264 | if (off < 0 || off > seekhigh - seeklow) | |
265 | return pos_type(off_type(-1)); | |
eafa1afa | 266 | |
9a56333e BK |
267 | if (do_put) |
268 | { | |
269 | if (seeklow + off < pbase()) | |
270 | { | |
271 | setp(seeklow, epptr()); | |
272 | pbump(off); | |
273 | } | |
274 | else | |
275 | { | |
276 | setp(pbase(), epptr()); | |
277 | pbump(off - (pbase() - seeklow)); | |
278 | } | |
279 | } | |
280 | if (do_get) | |
281 | { | |
282 | if (off <= egptr() - seeklow) | |
283 | setg(seeklow, seeklow + off, egptr()); | |
284 | else if (off <= pptr() - seeklow) | |
285 | setg(seeklow, seeklow + off, pptr()); | |
286 | else | |
287 | setg(seeklow, seeklow + off, epptr()); | |
288 | } | |
289 | return pos_type(newoff); | |
290 | } | |
291 | ||
292 | strstreambuf::pos_type | |
293 | strstreambuf::seekpos(pos_type pos, ios_base::openmode mode) | |
294 | { return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode); } | |
295 | ||
296 | char* | |
297 | strstreambuf::_M_alloc(size_t n) | |
298 | { | |
299 | if (_M_alloc_fun) | |
300 | return static_cast<char*>(_M_alloc_fun(n)); | |
eafa1afa | 301 | else |
9a56333e BK |
302 | return new char[n]; |
303 | } | |
304 | ||
305 | void | |
306 | strstreambuf::_M_free(char* p) | |
307 | { | |
308 | if (p) | |
2a67bec2 ILT |
309 | { |
310 | if (_M_free_fun) | |
311 | _M_free_fun(p); | |
312 | else | |
313 | delete[] p; | |
314 | } | |
9a56333e BK |
315 | } |
316 | ||
317 | void | |
50a681c4 | 318 | strstreambuf::_M_setup(char* get, char* put, streamsize n) throw () |
9a56333e BK |
319 | { |
320 | if (get) | |
321 | { | |
322 | size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX); | |
497e42fd | 323 | |
9a56333e BK |
324 | if (put) |
325 | { | |
326 | setg(get, get, put); | |
327 | setp(put, put + N); | |
328 | } | |
329 | else | |
330 | setg(get, get, get + N); | |
331 | } | |
332 | } | |
333 | ||
334 | istrstream::istrstream(char* s) | |
335 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) | |
336 | { basic_ios<char>::init(&_M_buf); } | |
337 | ||
338 | istrstream::istrstream(const char* s) | |
339 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) | |
340 | { basic_ios<char>::init(&_M_buf); } | |
341 | ||
342 | istrstream::istrstream(char* s, streamsize n) | |
343 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) | |
344 | { basic_ios<char>::init(&_M_buf); } | |
345 | ||
346 | istrstream::istrstream(const char* s, streamsize n) | |
347 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) | |
348 | { basic_ios<char>::init(&_M_buf); } | |
349 | ||
350 | istrstream::~istrstream() { } | |
351 | ||
352 | strstreambuf* | |
50a681c4 | 353 | istrstream::rdbuf() const throw () |
9a56333e BK |
354 | { return const_cast<strstreambuf*>(&_M_buf); } |
355 | ||
356 | char* | |
50a681c4 | 357 | istrstream::str() throw () |
9a56333e BK |
358 | { return _M_buf.str(); } |
359 | ||
360 | ostrstream::ostrstream() | |
361 | : basic_ios<char>(), basic_ostream<char>(0), _M_buf() | |
362 | { basic_ios<char>::init(&_M_buf); } | |
363 | ||
364 | ostrstream::ostrstream(char* s, int n, ios_base::openmode mode) | |
365 | : basic_ios<char>(), basic_ostream<char>(0), | |
366 | _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) | |
367 | { basic_ios<char>::init(&_M_buf); } | |
368 | ||
369 | ostrstream::~ostrstream() {} | |
370 | ||
371 | strstreambuf* | |
50a681c4 | 372 | ostrstream::rdbuf() const throw () |
9a56333e BK |
373 | { return const_cast<strstreambuf*>(&_M_buf); } |
374 | ||
375 | void | |
50a681c4 | 376 | ostrstream::freeze(bool freezeflag) throw () |
9a56333e BK |
377 | { _M_buf.freeze(freezeflag); } |
378 | ||
379 | char* | |
50a681c4 | 380 | ostrstream::str() throw () |
9a56333e BK |
381 | { return _M_buf.str(); } |
382 | ||
383 | int | |
50a681c4 | 384 | ostrstream::pcount() const throw () |
9a56333e BK |
385 | { return _M_buf.pcount(); } |
386 | ||
387 | strstream::strstream() | |
388 | : basic_ios<char>(), basic_iostream<char>(0), _M_buf() | |
389 | { basic_ios<char>::init(&_M_buf); } | |
390 | ||
391 | strstream::strstream(char* s, int n, ios_base::openmode mode) | |
392 | : basic_ios<char>(), basic_iostream<char>(0), | |
393 | _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) | |
394 | { basic_ios<char>::init(&_M_buf); } | |
395 | ||
396 | strstream::~strstream() { } | |
397 | ||
398 | strstreambuf* | |
50a681c4 | 399 | strstream::rdbuf() const throw () |
9a56333e BK |
400 | { return const_cast<strstreambuf*>(&_M_buf); } |
401 | ||
402 | void | |
50a681c4 | 403 | strstream::freeze(bool freezeflag) throw () |
9a56333e BK |
404 | { _M_buf.freeze(freezeflag); } |
405 | ||
406 | int | |
50a681c4 | 407 | strstream::pcount() const throw () |
9a56333e BK |
408 | { return _M_buf.pcount(); } |
409 | ||
410 | char* | |
50a681c4 | 411 | strstream::str() throw () |
9a56333e | 412 | { return _M_buf.str(); } |
3cbc7af0 BK |
413 | |
414 | _GLIBCXX_END_NAMESPACE |