]>
Commit | Line | Data |
---|---|---|
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 | ||
64 | void | |
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 | ||
112 | void | |
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 | ||
122 | int | |
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 | ||
183 | int | |
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 | ||
282 | int | |
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 | ||
292 | void | |
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 |
304 | struct _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 | }; |