d679a0de63be56bc2d43e05abe76e28de556de42
[kopensolaris-gnu/glibc.git] / libio / strops.c
1 /* Copyright (C) 1993, 1997-2000, 2001 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 "strfile.h"
29 #include "libioP.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
65 void
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   _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 }
112
113 void
114 _IO_str_init_readonly (sf, ptr, size)
115      _IO_strfile *sf;
116      const char *ptr;
117      int size;
118 {
119   _IO_str_init_static (sf, (char *) ptr, size, NULL);
120   sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES;
121 }
122
123 int
124 _IO_str_overflow (fp, c)
125      _IO_FILE *fp;
126      int c;
127 {
128   int flush_only = c == EOF;
129   _IO_size_t pos;
130   if (fp->_flags & _IO_NO_WRITES)
131       return flush_only ? 0 : EOF;
132   if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
133     {
134       fp->_flags |= _IO_CURRENTLY_PUTTING;
135       fp->_IO_write_ptr = fp->_IO_read_ptr;
136       fp->_IO_read_ptr = fp->_IO_read_end;
137     }
138   pos =  fp->_IO_write_ptr - fp->_IO_write_base;
139   if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
140     {
141       if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
142         return EOF;
143       else
144         {
145           char *new_buf;
146           char *old_buf = fp->_IO_buf_base;
147           _IO_size_t new_size = 2 * _IO_blen (fp) + 100;
148           new_buf
149             = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
150           if (new_buf == NULL)
151             {
152               /*          __ferror(fp) = 1; */
153               return EOF;
154             }
155           if (old_buf)
156             {
157               memcpy (new_buf, old_buf, _IO_blen (fp));
158               (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
159               /* Make sure _IO_setb won't try to delete _IO_buf_base. */
160               fp->_IO_buf_base = NULL;
161             }
162 #if 0
163           if (lenp == &LEN(fp)) /* use '\0'-filling */
164               memset (new_buf + pos, 0, blen() - pos);
165 #endif
166           _IO_setb (fp, new_buf, new_buf + new_size, 1);
167           fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
168           fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
169           fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
170           fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
171
172           fp->_IO_write_base = new_buf;
173           fp->_IO_write_end = fp->_IO_buf_end;
174         }
175     }
176
177   if (!flush_only)
178     *fp->_IO_write_ptr++ = (unsigned char) c;
179   if (fp->_IO_write_ptr > fp->_IO_read_end)
180     fp->_IO_read_end = fp->_IO_write_ptr;
181   return c;
182 }
183
184 int
185 _IO_str_underflow (fp)
186      _IO_FILE *fp;
187 {
188   if (fp->_IO_write_ptr > fp->_IO_read_end)
189     fp->_IO_read_end = fp->_IO_write_ptr;
190   if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
191     {
192       fp->_flags &= ~_IO_CURRENTLY_PUTTING;
193       fp->_IO_read_ptr = fp->_IO_write_ptr;
194       fp->_IO_write_ptr = fp->_IO_write_end;
195     }
196   if (fp->_IO_read_ptr < fp->_IO_read_end)
197     return *((unsigned char *) fp->_IO_read_ptr);
198   else
199     return EOF;
200 }
201
202 /* The size of the valid part of the buffer.  */
203
204 _IO_ssize_t
205 _IO_str_count (fp)
206      _IO_FILE *fp;
207 {
208   return ((fp->_IO_write_ptr > fp->_IO_read_end
209            ? fp->_IO_write_ptr : fp->_IO_read_end)
210           - fp->_IO_read_base);
211 }
212
213 _IO_off64_t
214 _IO_str_seekoff (fp, offset, dir, mode)
215      _IO_FILE *fp;
216      _IO_off64_t offset;
217      int dir;
218      int mode;
219 {
220   _IO_off64_t new_pos;
221
222   if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
223     mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
224
225   if (mode == 0)
226     {
227       /* Don't move any pointers. But there is no clear indication what
228          mode FP is in. Let's guess. */
229       if (fp->_IO_file_flags & _IO_NO_WRITES)
230         new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
231       else
232         new_pos = fp->_IO_write_ptr - fp->_IO_write_base;
233     }
234   else
235     {
236       _IO_ssize_t cur_size = _IO_str_count(fp);
237       new_pos = EOF;
238
239       /* Move the get pointer, if requested. */
240       if (mode & _IOS_INPUT)
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_read_ptr - fp->_IO_read_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_read_ptr = fp->_IO_read_base + offset;
256           fp->_IO_read_end = fp->_IO_read_base + cur_size;
257           new_pos = offset;
258         }
259
260       /* Move the put pointer, if requested. */
261       if (mode & _IOS_OUTPUT)
262         {
263           switch (dir)
264             {
265             case _IO_seek_end:
266               offset += cur_size;
267               break;
268             case _IO_seek_cur:
269               offset += fp->_IO_write_ptr - fp->_IO_write_base;
270               break;
271             default: /* case _IO_seek_set: */
272               break;
273             }
274           if (offset < 0 || (_IO_ssize_t) offset > cur_size)
275             return EOF;
276           fp->_IO_write_ptr = fp->_IO_write_base + offset;
277           new_pos = offset;
278         }
279     }
280   return new_pos;
281 }
282
283 int
284 _IO_str_pbackfail (fp, c)
285      _IO_FILE *fp;
286      int c;
287 {
288   if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
289     return EOF;
290   return _IO_default_pbackfail (fp, c);
291 }
292
293 void
294 _IO_str_finish (fp, dummy)
295      _IO_FILE *fp;
296      int dummy;
297 {
298   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
299     (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
300   fp->_IO_buf_base = NULL;
301
302   _IO_default_finish (fp, 0);
303 }
304
305 struct _IO_jump_t _IO_str_jumps =
306 {
307   JUMP_INIT_DUMMY,
308   JUMP_INIT(finish, _IO_str_finish),
309   JUMP_INIT(overflow, _IO_str_overflow),
310   JUMP_INIT(underflow, _IO_str_underflow),
311   JUMP_INIT(uflow, _IO_default_uflow),
312   JUMP_INIT(pbackfail, _IO_str_pbackfail),
313   JUMP_INIT(xsputn, _IO_default_xsputn),
314   JUMP_INIT(xsgetn, _IO_default_xsgetn),
315   JUMP_INIT(seekoff, _IO_str_seekoff),
316   JUMP_INIT(seekpos, _IO_default_seekpos),
317   JUMP_INIT(setbuf, _IO_default_setbuf),
318   JUMP_INIT(sync, _IO_default_sync),
319   JUMP_INIT(doallocate, _IO_default_doallocate),
320   JUMP_INIT(read, _IO_default_read),
321   JUMP_INIT(write, _IO_default_write),
322   JUMP_INIT(seek, _IO_default_seek),
323   JUMP_INIT(close, _IO_default_close),
324   JUMP_INIT(stat, _IO_default_stat),
325   JUMP_INIT(showmanyc, _IO_default_showmanyc),
326   JUMP_INIT(imbue, _IO_default_imbue)
327 };