Update.
[platform/upstream/glibc.git] / libio / strops.c
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 "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   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 }
112 INTDEF(_IO_str_init_static)
113
114 void
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
124 int
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 }
184 INTDEF(_IO_str_overflow)
185
186 int
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 }
203 INTDEF(_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 }
285 INTDEF(_IO_str_seekoff)
286
287 int
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 }
296 INTDEF(_IO_str_pbackfail)
297
298 void
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
310 struct _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 };