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