1/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
2   This file is part of the GNU IO Library.
3
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU General Public License as
6   published by the Free Software Foundation; either version 2, or (at
7   your option) any later version.
8
9   This library is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this library; see the file COPYING.  If not, write to
16   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
17   MA 02111-1307, USA.
18
19   As a special exception, if you link this library with files
20   compiled with a GNU compiler to produce an executable, this does
21   not cause the resulting executable to be covered by the GNU General
22   Public License.  This exception does not however invalidate any
23   other reasons why the executable file might be covered by the GNU
24   General Public License.  */
25
26#include "strfile.h"
27#include "libioP.h"
28#include <string.h>
29
30#if 0
31/* The following definitions are for exposition only.
32   They map the terminology used in the ANSI/ISO C++ draft standard
33   to the implementation. */
34
35/* allocated:  set  when a dynamic array object has been allocated, and
36   hence should be freed by the destructor for the strstreambuf object. */
37#define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
38
39/* constant:  set when the array object has const elements,
40   so the output sequence cannot be written. */
41#define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
42
43/* alsize:  the suggested minimum size for a dynamic array object. */
44#define ALSIZE(FP) ??? /* not stored */
45
46/* palloc: points to the function to call to allocate a dynamic array object.*/
47#define PALLOC(FP) \
48  ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
49
50/* pfree: points  to  the  function  to call to free a dynamic array object. */
51#define PFREE(FP) \
52  ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
53
54#endif
55
56#ifdef TODO
57/* An "unbounded buffer" is when a buffer is supplied, but with no
58   specified length.  An example is the buffer argument to sprintf.
59   */
60#endif
61
62void
63_IO_str_init_static (fp, ptr, size, pstart)
64     _IO_FILE *fp;
65     char *ptr;
66     int size;
67     char *pstart;
68{
69  if (size == 0)
70    size = strlen (ptr);
71  else if (size < 0)
72    {
73      /* If size is negative 'the characters are assumed to
74	 continue indefinitely.'  This is kind of messy ... */
75      int s;
76      size = 512;
77      /* Try increasing powers of 2, as long as we don't wrap around. */
78      for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
79	size = s;
80      /* Try increasing size as much as we can without wrapping around. */
81      for (s = size >> 1; s > 0; s >>= 1)
82	{
83	  if (ptr + size + s > ptr)
84	    size += s;
85	}
86    }
87  _IO_setb (fp, ptr, ptr + size, 0);
88
89  fp->_IO_write_base = ptr;
90  fp->_IO_read_base = ptr;
91  fp->_IO_read_ptr = ptr;
92  if (pstart)
93    {
94      fp->_IO_write_ptr = pstart;
95      fp->_IO_write_end = ptr + size;
96      fp->_IO_read_end = pstart;
97    }
98  else
99    {
100      fp->_IO_write_ptr = ptr;
101      fp->_IO_write_end = ptr;
102      fp->_IO_read_end = ptr+size;
103    }
104  /* A null _allocate_buffer function flags the strfile as being static. */
105  (((_IO_strfile *) fp)->_s._allocate_buffer) =  (_IO_alloc_type)0;
106}
107
108void
109_IO_str_init_readonly (fp, ptr, size)
110     _IO_FILE *fp;
111     const char *ptr;
112     int size;
113{
114  _IO_str_init_static (fp, (char *) ptr, size, NULL);
115  fp->_IO_file_flags |= _IO_NO_WRITES;
116}
117
118int
119_IO_str_overflow (fp, c)
120     _IO_FILE *fp;
121     int c;
122{
123  int flush_only = c == EOF;
124  _IO_size_t pos;
125  if (fp->_flags & _IO_NO_WRITES)
126      return flush_only ? 0 : EOF;
127  if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
128    {
129      fp->_flags |= _IO_CURRENTLY_PUTTING;
130      fp->_IO_write_ptr = fp->_IO_read_ptr;
131      fp->_IO_read_ptr = fp->_IO_read_end;
132    }
133  pos =  fp->_IO_write_ptr - fp->_IO_write_base;
134  if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
135    {
136      if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
137	return EOF;
138      else
139	{
140	  char *new_buf;
141	  char *old_buf = fp->_IO_buf_base;
142	  _IO_size_t new_size = 2 * _IO_blen (fp) + 100;
143	  new_buf
144	    = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
145	  if (new_buf == NULL)
146	    {
147	      /*	  __ferror(fp) = 1; */
148	      return EOF;
149	    }
150	  if (fp->_IO_buf_base)
151	    {
152	      memcpy (new_buf, old_buf, _IO_blen (fp));
153	      (*((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
154	      /* Make sure _IO_setb won't try to delete _IO_buf_base. */
155	      fp->_IO_buf_base = NULL;
156	    }
157#if 0
158	  if (lenp == &LEN(fp)) /* use '\0'-filling */
159	      memset (new_buf + pos, 0, blen() - pos);
160#endif
161	  _IO_setb (fp, new_buf, new_buf + new_size, 1);
162	  fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
163	  fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
164	  fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
165	  fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
166
167	  fp->_IO_write_base = new_buf;
168	  fp->_IO_write_end = fp->_IO_buf_end;
169	}
170    }
171
172  if (!flush_only)
173    *fp->_IO_write_ptr++ = (unsigned char) c;
174  if (fp->_IO_write_ptr > fp->_IO_read_end)
175    fp->_IO_read_end = fp->_IO_write_ptr;
176  return c;
177}
178
179int
180_IO_str_underflow (fp)
181     _IO_FILE *fp;
182{
183  if (fp->_IO_write_ptr > fp->_IO_read_end)
184    fp->_IO_read_end = fp->_IO_write_ptr;
185  if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
186    {
187      fp->_flags &= ~_IO_CURRENTLY_PUTTING;
188      fp->_IO_read_ptr = fp->_IO_write_ptr;
189      fp->_IO_write_ptr = fp->_IO_write_end;
190    }
191  if (fp->_IO_read_ptr < fp->_IO_read_end)
192    return *((unsigned char *) fp->_IO_read_ptr);
193  else
194    return EOF;
195}
196
197/* The size of the valid part of the buffer.  */
198
199_IO_ssize_t
200_IO_str_count (fp)
201     _IO_FILE *fp;
202{
203  return ((fp->_IO_write_ptr > fp->_IO_read_end
204	   ? fp->_IO_write_ptr : fp->_IO_read_end)
205	  - fp->_IO_read_base);
206}
207
208_IO_pos_t
209_IO_str_seekoff (fp, offset, dir, mode)
210     _IO_FILE *fp;
211     _IO_off_t offset;
212     int dir;
213     int mode;
214{
215  _IO_ssize_t cur_size = _IO_str_count (fp);
216  _IO_pos_t new_pos = EOF;
217
218  /* Move the get pointer, if requested. */
219  if (mode & _IOS_INPUT)
220    {
221      switch (dir)
222	{
223	case _IO_seek_end:
224	  offset += cur_size;
225	  break;
226	case _IO_seek_cur:
227	  offset += fp->_IO_read_ptr - fp->_IO_read_base;
228	  break;
229	default: /* case _IO_seek_set: */
230	  break;
231	}
232      if (offset < 0 || (_IO_ssize_t) offset > cur_size)
233	return EOF;
234      fp->_IO_read_ptr = fp->_IO_read_base + offset;
235      fp->_IO_read_end = fp->_IO_read_base + cur_size;
236      new_pos = offset;
237    }
238
239  /* Move the put pointer, if requested. */
240  if (mode & _IOS_OUTPUT)
241    {
242      switch (dir)
243	{
244	case _IO_seek_end:
245	  offset += cur_size;
246	  break;
247	case _IO_seek_cur:
248	  offset += fp->_IO_write_ptr - fp->_IO_write_base;
249	  break;
250	default: /* case _IO_seek_set: */
251	  break;
252	}
253      if (offset < 0 || (_IO_ssize_t) offset > cur_size)
254	return EOF;
255      fp->_IO_write_ptr = fp->_IO_write_base + offset;
256      new_pos = offset;
257    }
258  return new_pos;
259}
260
261int
262_IO_str_pbackfail (fp, c)
263     _IO_FILE *fp;
264     int c;
265{
266  if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
267    return EOF;
268  return _IO_default_pbackfail (fp, c);
269}
270
271void
272_IO_str_finish (fp, dummy)
273     _IO_FILE *fp;
274     int dummy;
275{
276  if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
277    (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
278  fp->_IO_buf_base = NULL;
279
280  _IO_default_finish (fp, 0);
281}
282
283struct _IO_jump_t _IO_str_jumps =
284{
285  JUMP_INIT_DUMMY,
286  JUMP_INIT(finish, _IO_str_finish),
287  JUMP_INIT(overflow, _IO_str_overflow),
288  JUMP_INIT(underflow, _IO_str_underflow),
289  JUMP_INIT(uflow, _IO_default_uflow),
290  JUMP_INIT(pbackfail, _IO_str_pbackfail),
291  JUMP_INIT(xsputn, _IO_default_xsputn),
292  JUMP_INIT(xsgetn, _IO_default_xsgetn),
293  JUMP_INIT(seekoff, _IO_str_seekoff),
294  JUMP_INIT(seekpos, _IO_default_seekpos),
295  JUMP_INIT(setbuf, _IO_default_setbuf),
296  JUMP_INIT(sync, _IO_default_sync),
297  JUMP_INIT(doallocate, _IO_default_doallocate),
298  JUMP_INIT(read, _IO_default_read),
299  JUMP_INIT(write, _IO_default_write),
300  JUMP_INIT(seek, _IO_default_seek),
301  JUMP_INIT(close, _IO_default_close),
302  JUMP_INIT(stat, _IO_default_stat)
303};
304