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