]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/strops.c
Update to LGPL v2.1.
[thirdparty/glibc.git] / libio / strops.c
CommitLineData
2ca8b1ee 1/* Copyright (C) 1993, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
96aa2d94 3
41bdb6e2
AJ
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.
96aa2d94 8
41bdb6e2
AJ
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
40a55d20 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2
AJ
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. */
96aa2d94
RM
27
28#include "strfile.h"
29#include "libioP.h"
30#include <string.h>
31
8a523922
UD
32#if 0
33/* The following definitions are for exposition only.
6d52618b 34 They map the terminology used in the ANSI/ISO C++ draft standard
8a523922
UD
35 to the implementation. */
36
37/* allocated: set when a dynamic array object has been allocated, and
38 hence should be freed by the destructor for the strstreambuf object. */
39#define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
40
41/* constant: set when the array object has const elements,
42 so the output sequence cannot be written. */
43#define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
44
45/* alsize: the suggested minimum size for a dynamic array object. */
46#define ALSIZE(FP) ??? /* not stored */
47
48/* palloc: points to the function to call to allocate a dynamic array object.*/
49#define PALLOC(FP) \
50 ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
51
52/* pfree: points to the function to call to free a dynamic array object. */
53#define PFREE(FP) \
54 ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
55
56#endif
96aa2d94
RM
57
58#ifdef TODO
59/* An "unbounded buffer" is when a buffer is supplied, but with no
60 specified length. An example is the buffer argument to sprintf.
61 */
62#endif
63
64void
2ca8b1ee
GM
65_IO_str_init_static (sf, ptr, size, pstart)
66 _IO_strfile *sf;
40a55d20
UD
67 char *ptr;
68 int size;
69 char *pstart;
96aa2d94 70{
2ca8b1ee
GM
71 _IO_FILE *fp = &sf->_sbf._f;
72
96aa2d94 73 if (size == 0)
40a55d20 74 size = strlen (ptr);
96aa2d94
RM
75 else if (size < 0)
76 {
77 /* If size is negative 'the characters are assumed to
78 continue indefinitely.' This is kind of messy ... */
96aa2d94
RM
79 int s;
80 size = 512;
8a523922
UD
81 /* Try increasing powers of 2, as long as we don't wrap around. */
82 for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
96aa2d94 83 size = s;
8a523922
UD
84 /* Try increasing size as much as we can without wrapping around. */
85 for (s = size >> 1; s > 0; s >>= 1)
86 {
87 if (ptr + size + s > ptr)
88 size += s;
89 }
96aa2d94 90 }
40a55d20 91 _IO_setb (fp, ptr, ptr + size, 0);
96aa2d94
RM
92
93 fp->_IO_write_base = ptr;
94 fp->_IO_read_base = ptr;
95 fp->_IO_read_ptr = ptr;
96 if (pstart)
97 {
98 fp->_IO_write_ptr = pstart;
f21acc89 99 fp->_IO_write_end = ptr + size;
96aa2d94
RM
100 fp->_IO_read_end = pstart;
101 }
102 else
103 {
104 fp->_IO_write_ptr = ptr;
105 fp->_IO_write_end = ptr;
106 fp->_IO_read_end = ptr+size;
107 }
96aa2d94 108 /* A null _allocate_buffer function flags the strfile as being static. */
2ca8b1ee 109 sf->_s._allocate_buffer = (_IO_alloc_type) 0;
96aa2d94
RM
110}
111
112void
2ca8b1ee
GM
113_IO_str_init_readonly (sf, ptr, size)
114 _IO_strfile *sf;
40a55d20
UD
115 const char *ptr;
116 int size;
96aa2d94 117{
2ca8b1ee
GM
118 _IO_str_init_static (sf, (char *) ptr, size, NULL);
119 sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES;
96aa2d94
RM
120}
121
122int
40a55d20
UD
123_IO_str_overflow (fp, c)
124 _IO_FILE *fp;
125 int c;
96aa2d94
RM
126{
127 int flush_only = c == EOF;
8a523922 128 _IO_size_t pos;
96aa2d94
RM
129 if (fp->_flags & _IO_NO_WRITES)
130 return flush_only ? 0 : EOF;
96aa2d94
RM
131 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
132 {
96aa2d94 133 fp->_flags |= _IO_CURRENTLY_PUTTING;
8a523922
UD
134 fp->_IO_write_ptr = fp->_IO_read_ptr;
135 fp->_IO_read_ptr = fp->_IO_read_end;
96aa2d94 136 }
8a523922 137 pos = fp->_IO_write_ptr - fp->_IO_write_base;
40a55d20 138 if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
96aa2d94
RM
139 {
140 if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
8a523922 141 return EOF;
96aa2d94
RM
142 else
143 {
144 char *new_buf;
8a523922 145 char *old_buf = fp->_IO_buf_base;
40a55d20 146 _IO_size_t new_size = 2 * _IO_blen (fp) + 100;
96aa2d94 147 new_buf
40a55d20 148 = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
96aa2d94
RM
149 if (new_buf == NULL)
150 {
151 /* __ferror(fp) = 1; */
152 return EOF;
153 }
d64b6ad0 154 if (old_buf)
96aa2d94 155 {
40a55d20 156 memcpy (new_buf, old_buf, _IO_blen (fp));
d64b6ad0 157 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
96aa2d94
RM
158 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
159 fp->_IO_buf_base = NULL;
160 }
8a523922
UD
161#if 0
162 if (lenp == &LEN(fp)) /* use '\0'-filling */
40a55d20 163 memset (new_buf + pos, 0, blen() - pos);
8a523922 164#endif
40a55d20 165 _IO_setb (fp, new_buf, new_buf + new_size, 1);
8a523922
UD
166 fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
167 fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
168 fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
169 fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
170
96aa2d94 171 fp->_IO_write_base = new_buf;
f21acc89 172 fp->_IO_write_end = fp->_IO_buf_end;
96aa2d94 173 }
96aa2d94
RM
174 }
175
96aa2d94
RM
176 if (!flush_only)
177 *fp->_IO_write_ptr++ = (unsigned char) c;
8a523922
UD
178 if (fp->_IO_write_ptr > fp->_IO_read_end)
179 fp->_IO_read_end = fp->_IO_write_ptr;
96aa2d94
RM
180 return c;
181}
182
183int
40a55d20
UD
184_IO_str_underflow (fp)
185 _IO_FILE *fp;
96aa2d94 186{
8a523922
UD
187 if (fp->_IO_write_ptr > fp->_IO_read_end)
188 fp->_IO_read_end = fp->_IO_write_ptr;
96aa2d94
RM
189 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
190 {
191 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
8a523922 192 fp->_IO_read_ptr = fp->_IO_write_ptr;
96aa2d94
RM
193 fp->_IO_write_ptr = fp->_IO_write_end;
194 }
96aa2d94 195 if (fp->_IO_read_ptr < fp->_IO_read_end)
195d0dd4 196 return *((unsigned char *) fp->_IO_read_ptr);
96aa2d94
RM
197 else
198 return EOF;
199}
200
8a523922
UD
201/* The size of the valid part of the buffer. */
202
96aa2d94 203_IO_ssize_t
40a55d20
UD
204_IO_str_count (fp)
205 _IO_FILE *fp;
96aa2d94 206{
2604afb1
UD
207 return ((fp->_IO_write_ptr > fp->_IO_read_end
208 ? fp->_IO_write_ptr : fp->_IO_read_end)
40a55d20 209 - fp->_IO_read_base);
a68b0d31 210}
96aa2d94 211
d64b6ad0 212_IO_off64_t
40a55d20
UD
213_IO_str_seekoff (fp, offset, dir, mode)
214 _IO_FILE *fp;
dfd2257a 215 _IO_off64_t offset;
40a55d20
UD
216 int dir;
217 int mode;
96aa2d94 218{
d64b6ad0 219 _IO_off64_t new_pos;
96aa2d94 220
dd7d45e8
UD
221 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
222 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
223
2eb45444 224 if (mode == 0)
96aa2d94 225 {
2eb45444
UD
226 /* Don't move any pointers. But there is no clear indication what
227 mode FP is in. Let's guess. */
228 if (fp->_IO_file_flags & _IO_NO_WRITES)
229 new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
230 else
231 new_pos = fp->_IO_write_ptr - fp->_IO_write_base;
232 }
233 else
234 {
235 _IO_ssize_t cur_size = _IO_str_count(fp);
236 new_pos = EOF;
237
238 /* Move the get pointer, if requested. */
239 if (mode & _IOS_INPUT)
96aa2d94 240 {
2eb45444
UD
241 switch (dir)
242 {
243 case _IO_seek_end:
244 offset += cur_size;
245 break;
246 case _IO_seek_cur:
247 offset += fp->_IO_read_ptr - fp->_IO_read_base;
248 break;
249 default: /* case _IO_seek_set: */
250 break;
251 }
252 if (offset < 0 || (_IO_ssize_t) offset > cur_size)
253 return EOF;
254 fp->_IO_read_ptr = fp->_IO_read_base + offset;
255 fp->_IO_read_end = fp->_IO_read_base + cur_size;
256 new_pos = offset;
96aa2d94 257 }
96aa2d94 258
2eb45444
UD
259 /* Move the put pointer, if requested. */
260 if (mode & _IOS_OUTPUT)
96aa2d94 261 {
2eb45444
UD
262 switch (dir)
263 {
264 case _IO_seek_end:
265 offset += cur_size;
266 break;
267 case _IO_seek_cur:
268 offset += fp->_IO_write_ptr - fp->_IO_write_base;
269 break;
270 default: /* case _IO_seek_set: */
271 break;
272 }
273 if (offset < 0 || (_IO_ssize_t) offset > cur_size)
274 return EOF;
275 fp->_IO_write_ptr = fp->_IO_write_base + offset;
276 new_pos = offset;
96aa2d94 277 }
96aa2d94
RM
278 }
279 return new_pos;
280}
281
282int
40a55d20
UD
283_IO_str_pbackfail (fp, c)
284 _IO_FILE *fp;
285 int c;
96aa2d94
RM
286{
287 if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
288 return EOF;
40a55d20 289 return _IO_default_pbackfail (fp, c);
96aa2d94
RM
290}
291
292void
40a55d20
UD
293_IO_str_finish (fp, dummy)
294 _IO_FILE *fp;
295 int dummy;
96aa2d94
RM
296{
297 if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
40a55d20 298 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
96aa2d94
RM
299 fp->_IO_buf_base = NULL;
300
40a55d20 301 _IO_default_finish (fp, 0);
96aa2d94
RM
302}
303
40a55d20
UD
304struct _IO_jump_t _IO_str_jumps =
305{
96aa2d94
RM
306 JUMP_INIT_DUMMY,
307 JUMP_INIT(finish, _IO_str_finish),
308 JUMP_INIT(overflow, _IO_str_overflow),
309 JUMP_INIT(underflow, _IO_str_underflow),
310 JUMP_INIT(uflow, _IO_default_uflow),
311 JUMP_INIT(pbackfail, _IO_str_pbackfail),
312 JUMP_INIT(xsputn, _IO_default_xsputn),
313 JUMP_INIT(xsgetn, _IO_default_xsgetn),
314 JUMP_INIT(seekoff, _IO_str_seekoff),
315 JUMP_INIT(seekpos, _IO_default_seekpos),
316 JUMP_INIT(setbuf, _IO_default_setbuf),
317 JUMP_INIT(sync, _IO_default_sync),
318 JUMP_INIT(doallocate, _IO_default_doallocate),
319 JUMP_INIT(read, _IO_default_read),
320 JUMP_INIT(write, _IO_default_write),
321 JUMP_INIT(seek, _IO_default_seek),
322 JUMP_INIT(close, _IO_default_close),
dfd2257a
UD
323 JUMP_INIT(stat, _IO_default_stat),
324 JUMP_INIT(showmanyc, _IO_default_showmanyc),
325 JUMP_INIT(imbue, _IO_default_imbue)
96aa2d94 326};