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