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