update from main archive 961009
[glibc.git] / libio / strops.c
blob464063322d3ae643abd0861f1759ddf5510e195f
1 /*
2 Copyright (C) 1993 Free Software Foundation
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.
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.
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.
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. */
25 #include "strfile.h"
26 #include "libioP.h"
27 #include <string.h>
29 #define LEN(fp) (((_IO_strfile*)(fp))->_s._len)
31 #ifdef TODO
32 /* An "unbounded buffer" is when a buffer is supplied, but with no
33 specified length. An example is the buffer argument to sprintf.
35 #endif
37 void
38 DEFUN(_IO_str_init_static, (fp, ptr, size, pstart),
39 _IO_FILE *fp AND char *ptr AND int size AND char *pstart)
41 if (size == 0)
42 size = strlen(ptr);
43 else if (size < 0)
45 /* If size is negative 'the characters are assumed to
46 continue indefinitely.' This is kind of messy ... */
47 #if 1
48 int s;
49 size = 512;
50 /* Try increasing powers of 2, as long as we don't wrap around.
51 This can lose in pathological cases (ptr near the end
52 of the address space). A better solution might be to
53 adjust the size on underflow/overflow. FIXME. */
54 for ( ; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
55 size = s;
56 size = s;
57 #else
58 /* The following semi-portable kludge assumes that
59 sizeof(unsigned long) == sizeof(char*). Hence,
60 (unsigned long)(-1) should be the largest possible address. */
61 unsigned long highest = (unsigned long)(-1);
62 /* Pointers are signed on some brain-damaged systems, in
63 which case we divide by two to get the maximum signed address. */
64 if ((char*)highest < ptr)
65 highest >>= 1;
66 size = (char*)highest - ptr;
67 #endif
69 _IO_setb(fp, ptr, ptr+size, 0);
71 fp->_IO_write_base = ptr;
72 fp->_IO_read_base = ptr;
73 fp->_IO_read_ptr = ptr;
74 if (pstart)
76 fp->_IO_write_ptr = pstart;
77 fp->_IO_write_end = ptr+size;
78 fp->_IO_read_end = pstart;
80 else
82 fp->_IO_write_ptr = ptr;
83 fp->_IO_write_end = ptr;
84 fp->_IO_read_end = ptr+size;
86 LEN(fp) = size;
87 /* A null _allocate_buffer function flags the strfile as being static. */
88 (((_IO_strfile*)(fp))->_s._allocate_buffer) = (_IO_alloc_type)0;
91 void
92 DEFUN(_IO_str_init_readonly, (fp, ptr, size),
93 _IO_FILE *fp AND const char *ptr AND int size)
95 _IO_str_init_static (fp, (char*)ptr, size, NULL);
96 fp->_IO_file_flags |= _IO_NO_WRITES;
99 int
100 DEFUN(_IO_str_overflow, (fp, c),
101 register _IO_FILE* fp AND int c)
103 int flush_only = c == EOF;
104 _IO_size_t pos = fp->_IO_write_ptr - fp->_IO_write_base;
105 _IO_size_t get_pos = fp->_IO_read_ptr - fp->_IO_read_base;
106 if (fp->_flags & _IO_NO_WRITES)
107 return flush_only ? 0 : EOF;
108 if (pos > LEN(fp)) LEN(fp) = pos;
109 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
111 pos = get_pos;
112 fp->_flags |= _IO_CURRENTLY_PUTTING;
113 get_pos = LEN(fp);
115 if (pos >= (_IO_size_t) (_IO_blen(fp) + flush_only))
117 if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
119 #ifdef TODO
120 if (indefinite size)
122 fp->_IO_buf_end += 512;
124 else
125 #endif
126 return EOF;
128 else
130 char *new_buf;
131 _IO_size_t new_size = 2 * _IO_blen(fp);
132 new_buf
133 = (char*)(*((_IO_strfile*)fp)->_s._allocate_buffer)(new_size);
134 if (new_buf == NULL)
136 /* __ferror(fp) = 1; */
137 return EOF;
139 memcpy(new_buf, fp->_IO_buf_base, _IO_blen(fp));
140 #if 0
141 if (lenp == &LEN(fp)) /* use '\0'-filling */
142 memset(new_buf + pos, 0, blen() - pos);
143 #endif
144 if (fp->_IO_buf_base)
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;
150 _IO_setb(fp, new_buf, new_buf + new_size, 1);
151 fp->_IO_write_base = new_buf;
153 fp->_IO_write_end = fp->_IO_buf_end;
156 fp->_IO_write_ptr = fp->_IO_buf_base + pos;
158 fp->_IO_read_base = fp->_IO_buf_base;
159 fp->_IO_read_ptr = fp->_IO_buf_base + get_pos;
160 fp->_IO_read_end = fp->_IO_buf_base + LEN(fp);
162 if (!flush_only)
163 *fp->_IO_write_ptr++ = (unsigned char) c;
164 return c;
168 DEFUN(_IO_str_underflow, (fp),
169 register _IO_FILE* fp)
171 _IO_size_t ppos = fp->_IO_write_ptr - fp->_IO_write_base;
172 if (ppos > LEN(fp)) LEN(fp) = ppos;
173 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
175 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
176 fp->_IO_write_ptr = fp->_IO_write_end;
178 fp->_IO_read_end = fp->_IO_read_base + LEN(fp);
179 if (fp->_IO_read_ptr < fp->_IO_read_end)
180 return *fp->_IO_read_ptr;
181 else
182 return EOF;
185 _IO_ssize_t
186 DEFUN(_IO_str_count, (fp),
187 register _IO_FILE *fp)
189 _IO_ssize_t put_len = fp->_IO_write_ptr - fp->_IO_write_base;
190 if (put_len < (_IO_ssize_t) LEN(fp))
191 put_len = LEN(fp);
192 return put_len;
195 _IO_pos_t
196 DEFUN(_IO_str_seekoff, (fp, offset, dir, mode),
197 register _IO_FILE *fp AND _IO_off_t offset AND int dir AND int mode)
199 _IO_ssize_t cur_size = _IO_str_count(fp);
200 _IO_pos_t new_pos = EOF;
202 /* Move the get pointer, if requested. */
203 if (mode & _IOS_INPUT)
205 switch (dir)
207 case _IO_seek_end:
208 offset += cur_size;
209 break;
210 case _IO_seek_cur:
211 offset += fp->_IO_read_ptr - fp->_IO_read_base;
212 break;
213 default: /* case _IO_seek_set: */
214 break;
216 if (offset < 0 || (_IO_ssize_t)offset > cur_size)
217 return EOF;
218 fp->_IO_read_ptr = fp->_IO_read_base + offset;
219 fp->_IO_read_end = fp->_IO_read_base + cur_size;
220 new_pos = offset;
223 /* Move the put pointer, if requested. */
224 if (mode & _IOS_OUTPUT)
226 switch (dir)
228 case _IO_seek_end:
229 offset += cur_size;
230 break;
231 case _IO_seek_cur:
232 offset += fp->_IO_write_ptr - fp->_IO_write_base;
233 break;
234 default: /* case _IO_seek_set: */
235 break;
237 if (offset < 0 || (_IO_ssize_t)offset > cur_size)
238 return EOF;
239 LEN(fp) = cur_size;
240 fp->_IO_write_ptr = fp->_IO_write_base + offset;
241 new_pos = offset;
243 return new_pos;
247 DEFUN(_IO_str_pbackfail, (fp, c),
248 register _IO_FILE *fp AND int c)
250 if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
251 return EOF;
252 return _IO_default_pbackfail(fp, c);
255 void
256 DEFUN (_IO_str_finish, (fp),
257 register _IO_FILE* fp)
259 if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
260 (((_IO_strfile*)fp)->_s._free_buffer)(fp->_IO_buf_base);
261 fp->_IO_buf_base = NULL;
263 _IO_default_finish(fp);
266 struct _IO_jump_t _IO_str_jumps = {
267 JUMP_INIT_DUMMY,
268 JUMP_INIT(finish, _IO_str_finish),
269 JUMP_INIT(overflow, _IO_str_overflow),
270 JUMP_INIT(underflow, _IO_str_underflow),
271 JUMP_INIT(uflow, _IO_default_uflow),
272 JUMP_INIT(pbackfail, _IO_str_pbackfail),
273 JUMP_INIT(xsputn, _IO_default_xsputn),
274 JUMP_INIT(xsgetn, _IO_default_xsgetn),
275 JUMP_INIT(seekoff, _IO_str_seekoff),
276 JUMP_INIT(seekpos, _IO_default_seekpos),
277 JUMP_INIT(setbuf, _IO_default_setbuf),
278 JUMP_INIT(sync, _IO_default_sync),
279 JUMP_INIT(doallocate, _IO_default_doallocate),
280 JUMP_INIT(read, _IO_default_read),
281 JUMP_INIT(write, _IO_default_write),
282 JUMP_INIT(seek, _IO_default_seek),
283 JUMP_INIT(close, _IO_default_close),
284 JUMP_INIT(stat, _IO_default_stat)