OSDN Git Service

2001-06-22 Phil Edwards <pme@sources.redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / strstream.cc
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 <strstream.h>
21 #include <algorithm>
22 #include <new>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <limits.h>
26
27 namespace std
28 {
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     }
179     else if (c == static_cast<int_type>(gptr()[-1])) {  // KLUDGE
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
424 } // namespace std
425
426 // Local Variables:
427 // mode:C++
428 // End: