]>
Commit | Line | Data |
---|---|---|
42526146 PE |
1 | // strstream definitions -*- C++ -*- |
2 | ||
83ffe9cd | 3 | // Copyright (C) 2001-2023 Free Software Foundation, Inc. |
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 | ||
12ffa228 BK |
51 | namespace std _GLIBCXX_VISIBILITY(default) |
52 | { | |
53 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 54 | |
9a56333e | 55 | strstreambuf::strstreambuf(streamsize initial_capacity) |
f92ab29f | 56 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true), |
9a56333e BK |
57 | _M_frozen(false), _M_constant(false) |
58 | { | |
4977bab6 | 59 | streamsize n = std::max(initial_capacity, streamsize(16)); |
f92ab29f | 60 | |
49bc23b7 | 61 | char* buf = _M_alloc(n); |
f92ab29f | 62 | if (buf) |
9a56333e | 63 | { |
49bc23b7 BK |
64 | setp(buf, buf + n); |
65 | setg(buf, buf, buf); | |
9a56333e BK |
66 | } |
67 | } | |
68 | ||
69 | strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*)) | |
f92ab29f | 70 | : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true), |
9a56333e BK |
71 | _M_frozen(false), _M_constant(false) |
72 | { | |
49bc23b7 BK |
73 | streamsize n = 16; |
74 | ||
75 | char* buf = _M_alloc(n); | |
f92ab29f | 76 | if (buf) |
9a56333e | 77 | { |
49bc23b7 BK |
78 | setp(buf, buf + n); |
79 | setg(buf, buf, buf); | |
9a56333e BK |
80 | } |
81 | } | |
82 | ||
50a681c4 | 83 | strstreambuf::strstreambuf(char* get, streamsize n, char* put) throw () |
f92ab29f | 84 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
9a56333e BK |
85 | _M_frozen(false), _M_constant(false) |
86 | { _M_setup(get, put, n); } | |
87 | ||
50a681c4 | 88 | strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put) throw () |
f92ab29f | 89 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
497e42fd | 90 | _M_frozen(false), _M_constant(false) |
9a56333e BK |
91 | { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } |
92 | ||
f92ab29f | 93 | strstreambuf::strstreambuf(unsigned char* get, streamsize n, |
50a681c4 | 94 | unsigned char* put) throw () |
f92ab29f | 95 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
9a56333e BK |
96 | _M_frozen(false), _M_constant(false) |
97 | { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } | |
98 | ||
50a681c4 | 99 | strstreambuf::strstreambuf(const char* get, streamsize n) throw () |
f92ab29f | 100 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
9a56333e BK |
101 | _M_frozen(false), _M_constant(true) |
102 | { _M_setup(const_cast<char*>(get), 0, n); } | |
103 | ||
50a681c4 | 104 | strstreambuf::strstreambuf(const signed char* get, streamsize n) throw () |
f92ab29f | 105 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
9a56333e BK |
106 | _M_frozen(false), _M_constant(true) |
107 | { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); } | |
108 | ||
50a681c4 | 109 | strstreambuf::strstreambuf(const unsigned char* get, streamsize n) throw () |
f92ab29f | 110 | : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), |
9a56333e BK |
111 | _M_frozen(false), _M_constant(true) |
112 | { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); } | |
113 | ||
114 | strstreambuf::~strstreambuf() | |
115 | { | |
116 | if (_M_dynamic && !_M_frozen) | |
49bc23b7 | 117 | _M_free(eback()); |
9a56333e BK |
118 | } |
119 | ||
f92ab29f | 120 | void |
50a681c4 | 121 | strstreambuf::freeze(bool frozenflag) throw () |
9a56333e BK |
122 | { |
123 | if (_M_dynamic) | |
124 | _M_frozen = frozenflag; | |
125 | } | |
126 | ||
f92ab29f | 127 | char* |
50a681c4 | 128 | strstreambuf::str() throw () |
9a56333e BK |
129 | { |
130 | freeze(true); | |
131 | return eback(); | |
132 | } | |
133 | ||
f92ab29f | 134 | int |
50a681c4 | 135 | strstreambuf::pcount() const throw () |
9a56333e BK |
136 | { return pptr() ? pptr() - pbase() : 0; } |
137 | ||
f92ab29f CG |
138 | strstreambuf::int_type |
139 | strstreambuf::overflow(int_type c) | |
9a56333e BK |
140 | { |
141 | if (c == traits_type::eof()) | |
142 | return traits_type::not_eof(c); | |
f92ab29f | 143 | |
9a56333e | 144 | // Try to expand the buffer. |
f92ab29f | 145 | if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) |
9a56333e BK |
146 | { |
147 | ptrdiff_t old_size = epptr() - pbase(); | |
dd6eaaed | 148 | ptrdiff_t new_size = std::max(ptrdiff_t(2 * old_size), ptrdiff_t(1)); |
f92ab29f | 149 | |
9a56333e | 150 | char* buf = _M_alloc(new_size); |
f92ab29f | 151 | if (buf) |
9a56333e BK |
152 | { |
153 | memcpy(buf, pbase(), old_size); | |
154 | char* old_buffer = pbase(); | |
155 | bool reposition_get = false; | |
156 | ptrdiff_t old_get_offset; | |
f92ab29f | 157 | if (gptr() != 0) |
9a56333e BK |
158 | { |
159 | reposition_get = true; | |
160 | old_get_offset = gptr() - eback(); | |
161 | } | |
f92ab29f | 162 | |
9a56333e | 163 | setp(buf, buf + new_size); |
1139a735 | 164 | __safe_pbump(old_size); |
9a56333e BK |
165 | |
166 | if (reposition_get) | |
f92ab29f | 167 | setg(buf, buf + old_get_offset, buf + |
4977bab6 | 168 | std::max(old_get_offset, old_size)); |
9a56333e BK |
169 | |
170 | _M_free(old_buffer); | |
171 | } | |
172 | } | |
f92ab29f CG |
173 | |
174 | if (pptr() != epptr()) | |
9a56333e BK |
175 | { |
176 | *pptr() = c; | |
177 | pbump(1); | |
178 | return c; | |
179 | } | |
180 | else | |
181 | return traits_type::eof(); | |
182 | } | |
183 | ||
f92ab29f | 184 | strstreambuf::int_type |
9a56333e BK |
185 | strstreambuf::pbackfail(int_type c) |
186 | { | |
f92ab29f | 187 | if (gptr() != eback()) |
9a56333e | 188 | { |
f92ab29f | 189 | if (c == _Traits::eof()) |
497e42fd BK |
190 | { |
191 | gbump(-1); | |
192 | return _Traits::not_eof(c); | |
193 | } | |
f92ab29f | 194 | else if (c == _Traits::to_int_type(gptr()[-1])) |
497e42fd BK |
195 | { // KLUDGE |
196 | gbump(-1); | |
197 | return c; | |
198 | } | |
f92ab29f | 199 | else if (!_M_constant) |
497e42fd BK |
200 | { |
201 | gbump(-1); | |
202 | *gptr() = c; | |
203 | return c; | |
204 | } | |
b2dad0e3 | 205 | } |
eafa1afa | 206 | return _Traits::eof(); |
9a56333e | 207 | } |
eafa1afa | 208 | |
f92ab29f | 209 | strstreambuf::int_type |
9a56333e BK |
210 | strstreambuf::underflow() |
211 | { | |
212 | if (gptr() == egptr() && pptr() && pptr() > egptr()) | |
213 | setg(eback(), gptr(), pptr()); | |
f92ab29f | 214 | |
9a56333e BK |
215 | if (gptr() != egptr()) |
216 | return (unsigned char) *gptr(); | |
217 | else | |
218 | return _Traits::eof(); | |
219 | } | |
220 | ||
221 | basic_streambuf<char, char_traits<char> >* | |
222 | strstreambuf::setbuf(char*, streamsize) | |
223 | { return this; } | |
224 | ||
225 | strstreambuf::pos_type | |
f92ab29f | 226 | strstreambuf::seekoff(off_type off, ios_base::seekdir dir, |
9a56333e BK |
227 | ios_base::openmode mode) |
228 | { | |
229 | bool do_get = false; | |
230 | bool do_put = false; | |
231 | ||
f92ab29f | 232 | if ((mode & (ios_base::in | ios_base::out)) |
9a56333e BK |
233 | == (ios_base::in | ios_base::out) && |
234 | (dir == ios_base::beg || dir == ios_base::end)) | |
46bbeb65 | 235 | do_get = do_put = true; |
9a56333e BK |
236 | else if (mode & ios_base::in) |
237 | do_get = true; | |
238 | else if (mode & ios_base::out) | |
239 | do_put = true; | |
240 | ||
241 | // !gptr() is here because, according to D.7.1 paragraph 4, the seekable | |
242 | // area is undefined if there is no get area. | |
243 | if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr()) | |
244 | return pos_type(off_type(-1)); | |
eafa1afa | 245 | |
9a56333e BK |
246 | char* seeklow = eback(); |
247 | char* seekhigh = epptr() ? epptr() : egptr(); | |
248 | ||
249 | off_type newoff; | |
f92ab29f | 250 | switch (dir) |
9a56333e BK |
251 | { |
252 | case ios_base::beg: | |
253 | newoff = 0; | |
254 | break; | |
255 | case ios_base::end: | |
256 | newoff = seekhigh - seeklow; | |
257 | break; | |
258 | case ios_base::cur: | |
259 | newoff = do_put ? pptr() - seeklow : gptr() - seeklow; | |
260 | break; | |
261 | default: | |
262 | return pos_type(off_type(-1)); | |
263 | } | |
f92ab29f | 264 | |
9a56333e BK |
265 | off += newoff; |
266 | if (off < 0 || off > seekhigh - seeklow) | |
267 | return pos_type(off_type(-1)); | |
eafa1afa | 268 | |
f92ab29f | 269 | if (do_put) |
9a56333e | 270 | { |
f92ab29f | 271 | if (seeklow + off < pbase()) |
9a56333e BK |
272 | { |
273 | setp(seeklow, epptr()); | |
1139a735 | 274 | __safe_pbump(off); |
9a56333e | 275 | } |
f92ab29f | 276 | else |
9a56333e BK |
277 | { |
278 | setp(pbase(), epptr()); | |
1139a735 | 279 | __safe_pbump(off - (pbase() - seeklow)); |
9a56333e BK |
280 | } |
281 | } | |
f92ab29f | 282 | if (do_get) |
9a56333e BK |
283 | { |
284 | if (off <= egptr() - seeklow) | |
285 | setg(seeklow, seeklow + off, egptr()); | |
286 | else if (off <= pptr() - seeklow) | |
287 | setg(seeklow, seeklow + off, pptr()); | |
288 | else | |
289 | setg(seeklow, seeklow + off, epptr()); | |
290 | } | |
291 | return pos_type(newoff); | |
292 | } | |
293 | ||
294 | strstreambuf::pos_type | |
295 | strstreambuf::seekpos(pos_type pos, ios_base::openmode mode) | |
296 | { return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode); } | |
297 | ||
f92ab29f | 298 | char* |
9a56333e BK |
299 | strstreambuf::_M_alloc(size_t n) |
300 | { | |
301 | if (_M_alloc_fun) | |
302 | return static_cast<char*>(_M_alloc_fun(n)); | |
eafa1afa | 303 | else |
9a56333e BK |
304 | return new char[n]; |
305 | } | |
306 | ||
f92ab29f | 307 | void |
9a56333e BK |
308 | strstreambuf::_M_free(char* p) |
309 | { | |
310 | if (p) | |
2a67bec2 ILT |
311 | { |
312 | if (_M_free_fun) | |
313 | _M_free_fun(p); | |
314 | else | |
315 | delete[] p; | |
316 | } | |
9a56333e BK |
317 | } |
318 | ||
f92ab29f | 319 | void |
50a681c4 | 320 | strstreambuf::_M_setup(char* get, char* put, streamsize n) throw () |
9a56333e | 321 | { |
f92ab29f | 322 | if (get) |
9a56333e BK |
323 | { |
324 | size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX); | |
f92ab29f CG |
325 | |
326 | if (put) | |
9a56333e BK |
327 | { |
328 | setg(get, get, put); | |
329 | setp(put, put + N); | |
330 | } | |
f92ab29f | 331 | else |
9a56333e BK |
332 | setg(get, get, get + N); |
333 | } | |
334 | } | |
335 | ||
336 | istrstream::istrstream(char* s) | |
337 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) | |
338 | { basic_ios<char>::init(&_M_buf); } | |
339 | ||
340 | istrstream::istrstream(const char* s) | |
341 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) | |
342 | { basic_ios<char>::init(&_M_buf); } | |
343 | ||
344 | istrstream::istrstream(char* s, streamsize n) | |
345 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) | |
346 | { basic_ios<char>::init(&_M_buf); } | |
347 | ||
348 | istrstream::istrstream(const char* s, streamsize n) | |
349 | : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) | |
350 | { basic_ios<char>::init(&_M_buf); } | |
351 | ||
352 | istrstream::~istrstream() { } | |
353 | ||
f92ab29f | 354 | strstreambuf* |
50a681c4 | 355 | istrstream::rdbuf() const throw () |
9a56333e BK |
356 | { return const_cast<strstreambuf*>(&_M_buf); } |
357 | ||
f92ab29f | 358 | char* |
50a681c4 | 359 | istrstream::str() throw () |
9a56333e BK |
360 | { return _M_buf.str(); } |
361 | ||
362 | ostrstream::ostrstream() | |
363 | : basic_ios<char>(), basic_ostream<char>(0), _M_buf() | |
364 | { basic_ios<char>::init(&_M_buf); } | |
365 | ||
366 | ostrstream::ostrstream(char* s, int n, ios_base::openmode mode) | |
f92ab29f | 367 | : basic_ios<char>(), basic_ostream<char>(0), |
9a56333e BK |
368 | _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) |
369 | { basic_ios<char>::init(&_M_buf); } | |
370 | ||
371 | ostrstream::~ostrstream() {} | |
372 | ||
f92ab29f | 373 | strstreambuf* |
50a681c4 | 374 | ostrstream::rdbuf() const throw () |
9a56333e BK |
375 | { return const_cast<strstreambuf*>(&_M_buf); } |
376 | ||
f92ab29f | 377 | void |
50a681c4 | 378 | ostrstream::freeze(bool freezeflag) throw () |
9a56333e BK |
379 | { _M_buf.freeze(freezeflag); } |
380 | ||
f92ab29f | 381 | char* |
50a681c4 | 382 | ostrstream::str() throw () |
9a56333e BK |
383 | { return _M_buf.str(); } |
384 | ||
f92ab29f | 385 | int |
50a681c4 | 386 | ostrstream::pcount() const throw () |
9a56333e BK |
387 | { return _M_buf.pcount(); } |
388 | ||
389 | strstream::strstream() | |
390 | : basic_ios<char>(), basic_iostream<char>(0), _M_buf() | |
391 | { basic_ios<char>::init(&_M_buf); } | |
392 | ||
393 | strstream::strstream(char* s, int n, ios_base::openmode mode) | |
f92ab29f | 394 | : basic_ios<char>(), basic_iostream<char>(0), |
9a56333e BK |
395 | _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) |
396 | { basic_ios<char>::init(&_M_buf); } | |
397 | ||
398 | strstream::~strstream() { } | |
399 | ||
f92ab29f | 400 | strstreambuf* |
50a681c4 | 401 | strstream::rdbuf() const throw () |
9a56333e BK |
402 | { return const_cast<strstreambuf*>(&_M_buf); } |
403 | ||
f92ab29f | 404 | void |
50a681c4 | 405 | strstream::freeze(bool freezeflag) throw () |
9a56333e BK |
406 | { _M_buf.freeze(freezeflag); } |
407 | ||
f92ab29f | 408 | int |
50a681c4 | 409 | strstream::pcount() const throw () |
9a56333e BK |
410 | { return _M_buf.pcount(); } |
411 | ||
f92ab29f | 412 | char* |
50a681c4 | 413 | strstream::str() throw () |
9a56333e | 414 | { return _M_buf.str(); } |
3cbc7af0 | 415 | |
12ffa228 BK |
416 | _GLIBCXX_END_NAMESPACE_VERSION |
417 | } // namespace |