xref: /haiku/src/system/libroot/posix/glibc/libio/strops.c (revision 24159a0c7d6d6dcba9f2a0c1a7c08d2c8167f21b)
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 
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 };
333