]>
Commit | Line | Data |
---|---|---|
a68b0d31 | 1 | /* |
96aa2d94 RM |
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 | ||
8a523922 UD |
29 | #if 0 |
30 | /* The following definitions are for exposition only. | |
6d52618b | 31 | They map the terminology used in the ANSI/ISO C++ draft standard |
8a523922 UD |
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 | |
96aa2d94 RM |
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 ... */ | |
96aa2d94 RM |
71 | int s; |
72 | size = 512; | |
8a523922 UD |
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; ) | |
96aa2d94 | 75 | size = s; |
8a523922 UD |
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 | } | |
96aa2d94 RM |
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; | |
9c2322bc | 91 | fp->_IO_write_end = pstart; |
96aa2d94 RM |
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 | } | |
96aa2d94 RM |
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; | |
8a523922 | 117 | _IO_size_t pos; |
96aa2d94 RM |
118 | if (fp->_flags & _IO_NO_WRITES) |
119 | return flush_only ? 0 : EOF; | |
96aa2d94 RM |
120 | if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) |
121 | { | |
96aa2d94 | 122 | fp->_flags |= _IO_CURRENTLY_PUTTING; |
8a523922 UD |
123 | fp->_IO_write_ptr = fp->_IO_read_ptr; |
124 | fp->_IO_read_ptr = fp->_IO_read_end; | |
96aa2d94 | 125 | } |
8a523922 | 126 | pos = fp->_IO_write_ptr - fp->_IO_write_base; |
f8b87ef0 | 127 | if (pos >= (_IO_size_t) (_IO_blen(fp) + flush_only)) |
96aa2d94 RM |
128 | { |
129 | if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */ | |
8a523922 | 130 | return EOF; |
96aa2d94 RM |
131 | else |
132 | { | |
133 | char *new_buf; | |
8a523922 UD |
134 | char *old_buf = fp->_IO_buf_base; |
135 | _IO_size_t new_size = 2 * _IO_blen(fp) + 100; | |
96aa2d94 RM |
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 | } | |
96aa2d94 RM |
143 | if (fp->_IO_buf_base) |
144 | { | |
8a523922 | 145 | memcpy(new_buf, old_buf, _IO_blen(fp)); |
96aa2d94 RM |
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 | } | |
8a523922 UD |
150 | #if 0 |
151 | if (lenp == &LEN(fp)) /* use '\0'-filling */ | |
152 | memset(new_buf + pos, 0, blen() - pos); | |
153 | #endif | |
96aa2d94 | 154 | _IO_setb(fp, new_buf, new_buf + new_size, 1); |
8a523922 UD |
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 | ||
96aa2d94 | 160 | fp->_IO_write_base = new_buf; |
9c2322bc | 161 | fp->_IO_write_end = new_buf + (fp->_IO_write_end - old_buf); |
96aa2d94 | 162 | } |
96aa2d94 RM |
163 | } |
164 | ||
96aa2d94 RM |
165 | if (!flush_only) |
166 | *fp->_IO_write_ptr++ = (unsigned char) c; | |
8a523922 UD |
167 | if (fp->_IO_write_ptr > fp->_IO_read_end) |
168 | fp->_IO_read_end = fp->_IO_write_ptr; | |
96aa2d94 RM |
169 | return c; |
170 | } | |
171 | ||
172 | int | |
173 | DEFUN(_IO_str_underflow, (fp), | |
174 | register _IO_FILE* fp) | |
175 | { | |
8a523922 UD |
176 | if (fp->_IO_write_ptr > fp->_IO_read_end) |
177 | fp->_IO_read_end = fp->_IO_write_ptr; | |
96aa2d94 RM |
178 | if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING)) |
179 | { | |
180 | fp->_flags &= ~_IO_CURRENTLY_PUTTING; | |
8a523922 | 181 | fp->_IO_read_ptr = fp->_IO_write_ptr; |
96aa2d94 RM |
182 | fp->_IO_write_ptr = fp->_IO_write_end; |
183 | } | |
96aa2d94 RM |
184 | if (fp->_IO_read_ptr < fp->_IO_read_end) |
185 | return *fp->_IO_read_ptr; | |
186 | else | |
187 | return EOF; | |
188 | } | |
189 | ||
8a523922 UD |
190 | /* The size of the valid part of the buffer. */ |
191 | ||
96aa2d94 RM |
192 | _IO_ssize_t |
193 | DEFUN(_IO_str_count, (fp), | |
194 | register _IO_FILE *fp) | |
195 | { | |
478b92f0 | 196 | return (fp->_IO_write_end > fp->_IO_read_end ? fp->_IO_write_end |
8a523922 UD |
197 | : fp->_IO_read_end) |
198 | - fp->_IO_read_base; | |
a68b0d31 | 199 | } |
96aa2d94 RM |
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 | } | |
a68b0d31 | 222 | if (offset < 0 || (_IO_ssize_t)offset > cur_size) |
96aa2d94 RM |
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 | } | |
a68b0d31 | 243 | if (offset < 0 || (_IO_ssize_t)offset > cur_size) |
96aa2d94 | 244 | return EOF; |
96aa2d94 RM |
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 | |
ceb2d9aa UD |
261 | DEFUN (_IO_str_finish, (fp, dummy), |
262 | register _IO_FILE* fp AND int dummy) | |
96aa2d94 RM |
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 | ||
ceb2d9aa | 268 | _IO_default_finish(fp, 0); |
96aa2d94 RM |
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 | }; |