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