]>
Commit | Line | Data |
---|---|---|
b2637a22 | 1 | /* Copyright (C) 1993,1997-1999,2001-2003,2004 Free Software Foundation, Inc. |
41bdb6e2 | 2 | This file is part of the GNU C Library. |
d64b6ad0 | 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. | |
d64b6ad0 | 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 | |
d64b6ad0 | 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. */ | |
d64b6ad0 UD |
27 | |
28 | #include "strfile.h" | |
29 | #include "libioP.h" | |
30 | #include <string.h> | |
31 | #include <wchar.h> | |
0d875352 | 32 | #include <stdio_ext.h> |
d64b6ad0 UD |
33 | |
34 | #if 0 | |
35 | /* The following definitions are for exposition only. | |
36 | They map the terminology used in the ANSI/ISO C++ draft standard | |
37 | to the implementation. */ | |
38 | ||
39 | /* allocated: set when a dynamic array object has been allocated, and | |
40 | hence should be freed by the destructor for the strstreambuf object. */ | |
41 | #define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP)) | |
42 | ||
43 | /* constant: set when the array object has const elements, | |
44 | so the output sequence cannot be written. */ | |
45 | #define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES) | |
46 | ||
47 | /* alsize: the suggested minimum size for a dynamic array object. */ | |
48 | #define ALSIZE(FP) ??? /* not stored */ | |
49 | ||
50 | /* palloc: points to the function to call to allocate a dynamic array object.*/ | |
51 | #define PALLOC(FP) \ | |
52 | ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer) | |
53 | ||
54 | /* pfree: points to the function to call to free a dynamic array object. */ | |
55 | #define PFREE(FP) \ | |
56 | ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer) | |
57 | ||
58 | #endif | |
59 | ||
60 | #ifdef TODO | |
61 | /* An "unbounded buffer" is when a buffer is supplied, but with no | |
62 | specified length. An example is the buffer argument to sprintf. | |
63 | */ | |
64 | #endif | |
65 | ||
66 | void | |
67 | _IO_wstr_init_static (fp, ptr, size, pstart) | |
68 | _IO_FILE *fp; | |
69 | wchar_t *ptr; | |
40a54e4d | 70 | _IO_size_t size; |
d64b6ad0 UD |
71 | wchar_t *pstart; |
72 | { | |
40a54e4d | 73 | wchar_t *end; |
b2637a22 | 74 | |
d64b6ad0 | 75 | if (size == 0) |
40a54e4d UD |
76 | end = ptr + __wcslen (ptr); |
77 | else if ((_IO_size_t) ptr + size * sizeof (wchar_t) > (_IO_size_t) ptr) | |
78 | end = ptr + size; | |
79 | else | |
80 | /* Even for misaligned ptr make sure there is integral number of wide | |
81 | characters. */ | |
82 | end = ptr + (-1 - (_IO_size_t) ptr) / sizeof (wchar_t); | |
83 | INTUSE(_IO_wsetb) (fp, ptr, end, 0); | |
d64b6ad0 UD |
84 | |
85 | fp->_wide_data->_IO_write_base = ptr; | |
86 | fp->_wide_data->_IO_read_base = ptr; | |
87 | fp->_wide_data->_IO_read_ptr = ptr; | |
88 | if (pstart) | |
89 | { | |
90 | fp->_wide_data->_IO_write_ptr = pstart; | |
40a54e4d | 91 | fp->_wide_data->_IO_write_end = end; |
d64b6ad0 UD |
92 | fp->_wide_data->_IO_read_end = pstart; |
93 | } | |
94 | else | |
95 | { | |
96 | fp->_wide_data->_IO_write_ptr = ptr; | |
97 | fp->_wide_data->_IO_write_end = ptr; | |
40a54e4d | 98 | fp->_wide_data->_IO_read_end = end; |
d64b6ad0 UD |
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 | ||
d64b6ad0 UD |
104 | _IO_wint_t |
105 | _IO_wstr_overflow (fp, c) | |
106 | _IO_FILE *fp; | |
107 | _IO_wint_t c; | |
108 | { | |
109 | int flush_only = c == WEOF; | |
110 | _IO_size_t pos; | |
111 | if (fp->_flags & _IO_NO_WRITES) | |
112 | return flush_only ? 0 : WEOF; | |
113 | if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) | |
114 | { | |
115 | fp->_flags |= _IO_CURRENTLY_PUTTING; | |
116 | fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr; | |
117 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; | |
118 | } | |
119 | pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base; | |
120 | if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only)) | |
121 | { | |
122 | if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */ | |
123 | return WEOF; | |
124 | else | |
125 | { | |
126 | wchar_t *new_buf; | |
127 | wchar_t *old_buf = fp->_wide_data->_IO_buf_base; | |
128 | _IO_size_t new_size = 2 * _IO_wblen (fp) + 100; | |
129 | new_buf | |
130 | = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size | |
131 | * sizeof (wchar_t)); | |
132 | if (new_buf == NULL) | |
133 | { | |
134 | /* __ferror(fp) = 1; */ | |
135 | return WEOF; | |
136 | } | |
137 | if (old_buf) | |
138 | { | |
139 | __wmemcpy (new_buf, old_buf, _IO_wblen (fp)); | |
140 | (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); | |
141 | /* Make sure _IO_setb won't try to delete _IO_buf_base. */ | |
142 | fp->_wide_data->_IO_buf_base = NULL; | |
143 | } | |
77fe0b9c | 144 | INTUSE(_IO_wsetb) (fp, new_buf, new_buf + new_size, 1); |
d64b6ad0 UD |
145 | fp->_wide_data->_IO_read_base = |
146 | new_buf + (fp->_wide_data->_IO_read_base - old_buf); | |
147 | fp->_wide_data->_IO_read_ptr = | |
148 | new_buf + (fp->_wide_data->_IO_read_ptr - old_buf); | |
149 | fp->_wide_data->_IO_read_end = | |
150 | new_buf + (fp->_wide_data->_IO_read_end - old_buf); | |
151 | fp->_wide_data->_IO_write_ptr = | |
152 | new_buf + (fp->_wide_data->_IO_write_ptr - old_buf); | |
153 | ||
154 | fp->_wide_data->_IO_write_base = new_buf; | |
155 | fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end; | |
156 | } | |
157 | } | |
158 | ||
159 | if (!flush_only) | |
160 | *fp->_wide_data->_IO_write_ptr++ = c; | |
161 | if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) | |
162 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; | |
163 | return c; | |
164 | } | |
165 | ||
166 | _IO_wint_t | |
167 | _IO_wstr_underflow (fp) | |
168 | _IO_FILE *fp; | |
169 | { | |
170 | if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) | |
171 | fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; | |
172 | if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING)) | |
173 | { | |
174 | fp->_flags &= ~_IO_CURRENTLY_PUTTING; | |
175 | fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; | |
176 | fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end; | |
177 | } | |
178 | if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) | |
179 | return *fp->_wide_data->_IO_read_ptr; | |
180 | else | |
181 | return WEOF; | |
182 | } | |
183 | ||
184 | /* The size of the valid part of the buffer. */ | |
185 | ||
186 | _IO_ssize_t | |
187 | _IO_wstr_count (fp) | |
188 | _IO_FILE *fp; | |
189 | { | |
190 | return ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end | |
191 | ? fp->_wide_data->_IO_write_ptr : fp->_wide_data->_IO_read_end) | |
192 | - fp->_wide_data->_IO_read_base); | |
193 | } | |
194 | ||
195 | _IO_off64_t | |
196 | _IO_wstr_seekoff (fp, offset, dir, mode) | |
197 | _IO_FILE *fp; | |
198 | _IO_off64_t offset; | |
199 | int dir; | |
200 | int mode; | |
201 | { | |
202 | _IO_off64_t new_pos; | |
203 | ||
204 | if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET)) | |
205 | mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT); | |
206 | ||
207 | if (mode == 0) | |
208 | { | |
209 | /* Don't move any pointers. But there is no clear indication what | |
210 | mode FP is in. Let's guess. */ | |
211 | if (fp->_IO_file_flags & _IO_NO_WRITES) | |
212 | new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base; | |
213 | else | |
214 | new_pos = (fp->_wide_data->_IO_write_ptr | |
215 | - fp->_wide_data->_IO_write_base); | |
216 | } | |
217 | else | |
218 | { | |
219 | _IO_ssize_t cur_size = _IO_wstr_count (fp); | |
220 | new_pos = EOF; | |
221 | ||
222 | /* Move the get pointer, if requested. */ | |
223 | if (mode & _IOS_INPUT) | |
224 | { | |
225 | switch (dir) | |
226 | { | |
227 | case _IO_seek_end: | |
228 | offset += cur_size; | |
229 | break; | |
230 | case _IO_seek_cur: | |
231 | offset += (fp->_wide_data->_IO_read_ptr | |
232 | - fp->_wide_data->_IO_read_base); | |
233 | break; | |
234 | default: /* case _IO_seek_set: */ | |
235 | break; | |
236 | } | |
237 | if (offset < 0 || (_IO_ssize_t) offset > cur_size) | |
238 | return EOF; | |
239 | fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base | |
240 | + offset); | |
241 | fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base | |
242 | + cur_size); | |
243 | new_pos = offset; | |
244 | } | |
245 | ||
246 | /* Move the put pointer, if requested. */ | |
247 | if (mode & _IOS_OUTPUT) | |
248 | { | |
249 | switch (dir) | |
250 | { | |
251 | case _IO_seek_end: | |
252 | offset += cur_size; | |
253 | break; | |
254 | case _IO_seek_cur: | |
255 | offset += (fp->_wide_data->_IO_write_ptr | |
256 | - fp->_wide_data->_IO_write_base); | |
257 | break; | |
258 | default: /* case _IO_seek_set: */ | |
259 | break; | |
260 | } | |
261 | if (offset < 0 || (_IO_ssize_t) offset > cur_size) | |
262 | return EOF; | |
263 | fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base | |
264 | + offset); | |
265 | new_pos = offset; | |
266 | } | |
267 | } | |
268 | return new_pos; | |
269 | } | |
270 | ||
271 | _IO_wint_t | |
272 | _IO_wstr_pbackfail (fp, c) | |
273 | _IO_FILE *fp; | |
274 | _IO_wint_t c; | |
275 | { | |
6dd67bd5 | 276 | if ((fp->_flags & _IO_NO_WRITES) && c != WEOF) |
d64b6ad0 | 277 | return WEOF; |
77fe0b9c | 278 | return INTUSE(_IO_wdefault_pbackfail) (fp, c); |
d64b6ad0 UD |
279 | } |
280 | ||
281 | void | |
282 | _IO_wstr_finish (fp, dummy) | |
283 | _IO_FILE *fp; | |
284 | int dummy; | |
285 | { | |
286 | if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) | |
287 | (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base); | |
288 | fp->_wide_data->_IO_buf_base = NULL; | |
289 | ||
77fe0b9c | 290 | INTUSE(_IO_wdefault_finish) (fp, 0); |
d64b6ad0 UD |
291 | } |
292 | ||
b2637a22 | 293 | const struct _IO_jump_t _IO_wstr_jumps = |
d64b6ad0 UD |
294 | { |
295 | JUMP_INIT_DUMMY, | |
296 | JUMP_INIT(finish, _IO_wstr_finish), | |
297 | JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow), | |
298 | JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow), | |
77fe0b9c | 299 | JUMP_INIT(uflow, (_IO_underflow_t) INTUSE(_IO_wdefault_uflow)), |
d64b6ad0 | 300 | JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail), |
77fe0b9c UD |
301 | JUMP_INIT(xsputn, INTUSE(_IO_wdefault_xsputn)), |
302 | JUMP_INIT(xsgetn, INTUSE(_IO_wdefault_xsgetn)), | |
d64b6ad0 UD |
303 | JUMP_INIT(seekoff, _IO_wstr_seekoff), |
304 | JUMP_INIT(seekpos, _IO_default_seekpos), | |
bff334e0 | 305 | JUMP_INIT(setbuf, _IO_default_setbuf), |
d64b6ad0 | 306 | JUMP_INIT(sync, _IO_default_sync), |
77fe0b9c | 307 | JUMP_INIT(doallocate, INTUSE(_IO_wdefault_doallocate)), |
d64b6ad0 UD |
308 | JUMP_INIT(read, _IO_default_read), |
309 | JUMP_INIT(write, _IO_default_write), | |
310 | JUMP_INIT(seek, _IO_default_seek), | |
311 | JUMP_INIT(close, _IO_default_close), | |
312 | JUMP_INIT(stat, _IO_default_stat), | |
313 | JUMP_INIT(showmanyc, _IO_default_showmanyc), | |
314 | JUMP_INIT(imbue, _IO_default_imbue) | |
315 | }; |