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