]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/wstrops.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / libio / wstrops.c
CommitLineData
b168057a 1/* Copyright (C) 1993-2015 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
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>.
41bdb6e2
AJ
17
18 As a special exception, if you link the code in this file with
19 files compiled with a GNU compiler to produce an executable,
20 that does not cause the resulting executable to be covered by
21 the GNU Lesser General Public License. This exception does not
22 however invalidate any other reasons why the executable file
23 might be covered by the GNU Lesser General Public License.
24 This exception applies to code released by its copyright holders
25 in files containing the exception. */
d64b6ad0 26
107b8a92 27#include <assert.h>
d64b6ad0
UD
28#include "strfile.h"
29#include "libioP.h"
30#include <string.h>
31#include <wchar.h>
0d875352 32#include <stdio_ext.h>
d64b6ad0 33
d64b6ad0
UD
34void
35_IO_wstr_init_static (fp, ptr, size, pstart)
36 _IO_FILE *fp;
37 wchar_t *ptr;
40a54e4d 38 _IO_size_t size;
d64b6ad0
UD
39 wchar_t *pstart;
40{
40a54e4d 41 wchar_t *end;
b2637a22 42
d64b6ad0 43 if (size == 0)
40a54e4d
UD
44 end = ptr + __wcslen (ptr);
45 else if ((_IO_size_t) ptr + size * sizeof (wchar_t) > (_IO_size_t) ptr)
46 end = ptr + size;
47 else
48 /* Even for misaligned ptr make sure there is integral number of wide
49 characters. */
50 end = ptr + (-1 - (_IO_size_t) ptr) / sizeof (wchar_t);
d18ea0c5 51 _IO_wsetb (fp, ptr, end, 0);
d64b6ad0
UD
52
53 fp->_wide_data->_IO_write_base = ptr;
54 fp->_wide_data->_IO_read_base = ptr;
55 fp->_wide_data->_IO_read_ptr = ptr;
56 if (pstart)
57 {
58 fp->_wide_data->_IO_write_ptr = pstart;
40a54e4d 59 fp->_wide_data->_IO_write_end = end;
d64b6ad0
UD
60 fp->_wide_data->_IO_read_end = pstart;
61 }
62 else
63 {
64 fp->_wide_data->_IO_write_ptr = ptr;
65 fp->_wide_data->_IO_write_end = ptr;
40a54e4d 66 fp->_wide_data->_IO_read_end = end;
d64b6ad0
UD
67 }
68 /* A null _allocate_buffer function flags the strfile as being static. */
107b8a92 69 (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
d64b6ad0
UD
70}
71
d64b6ad0
UD
72_IO_wint_t
73_IO_wstr_overflow (fp, c)
74 _IO_FILE *fp;
75 _IO_wint_t c;
76{
77 int flush_only = c == WEOF;
78 _IO_size_t pos;
79 if (fp->_flags & _IO_NO_WRITES)
80 return flush_only ? 0 : WEOF;
81 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
82 {
83 fp->_flags |= _IO_CURRENTLY_PUTTING;
84 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
85 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
86 }
107b8a92 87 pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
d64b6ad0
UD
88 if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
89 {
1e88bd0f 90 if (fp->_flags2 & _IO_FLAGS2_USER_WBUF) /* not allowed to enlarge */
d64b6ad0
UD
91 return WEOF;
92 else
93 {
94 wchar_t *new_buf;
95 wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
107b8a92
UD
96 size_t old_wblen = _IO_wblen (fp);
97 _IO_size_t new_size = 2 * old_wblen + 100;
98 if (new_size < old_wblen)
99 return EOF;
d64b6ad0
UD
100 new_buf
101 = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
102 * sizeof (wchar_t));
103 if (new_buf == NULL)
104 {
105 /* __ferror(fp) = 1; */
106 return WEOF;
107 }
108 if (old_buf)
109 {
107b8a92 110 __wmemcpy (new_buf, old_buf, old_wblen);
d64b6ad0
UD
111 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
112 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
113 fp->_wide_data->_IO_buf_base = NULL;
114 }
107b8a92
UD
115
116 wmemset (new_buf + old_wblen, L'\0', new_size - old_wblen);
117
d18ea0c5 118 _IO_wsetb (fp, new_buf, new_buf + new_size, 1);
d64b6ad0
UD
119 fp->_wide_data->_IO_read_base =
120 new_buf + (fp->_wide_data->_IO_read_base - old_buf);
121 fp->_wide_data->_IO_read_ptr =
122 new_buf + (fp->_wide_data->_IO_read_ptr - old_buf);
123 fp->_wide_data->_IO_read_end =
124 new_buf + (fp->_wide_data->_IO_read_end - old_buf);
125 fp->_wide_data->_IO_write_ptr =
126 new_buf + (fp->_wide_data->_IO_write_ptr - old_buf);
127
128 fp->_wide_data->_IO_write_base = new_buf;
129 fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end;
130 }
131 }
132
133 if (!flush_only)
134 *fp->_wide_data->_IO_write_ptr++ = c;
135 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
136 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
137 return c;
138}
139
107b8a92 140
d64b6ad0
UD
141_IO_wint_t
142_IO_wstr_underflow (fp)
143 _IO_FILE *fp;
144{
145 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
146 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
147 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
148 {
149 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
150 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
151 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end;
152 }
153 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
154 return *fp->_wide_data->_IO_read_ptr;
155 else
0923a2c8 156 return WEOF;
d64b6ad0
UD
157}
158
a334319f 159
107b8a92 160/* The size of the valid part of the buffer. */
d64b6ad0
UD
161_IO_ssize_t
162_IO_wstr_count (fp)
163 _IO_FILE *fp;
164{
107b8a92
UD
165 struct _IO_wide_data *wd = fp->_wide_data;
166
167 return ((wd->_IO_write_ptr > wd->_IO_read_end
168 ? wd->_IO_write_ptr : wd->_IO_read_end)
169 - wd->_IO_read_base);
d64b6ad0
UD
170}
171
107b8a92
UD
172
173static int
174enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
175{
176 if ((_IO_ssize_t) offset <= _IO_blen (fp))
177 return 0;
178
179 struct _IO_wide_data *wd = fp->_wide_data;
180
181 _IO_ssize_t oldend = wd->_IO_write_end - wd->_IO_write_base;
182
183 /* Try to enlarge the buffer. */
1e88bd0f 184 if (fp->_flags2 & _IO_FLAGS2_USER_WBUF)
107b8a92
UD
185 /* User-provided buffer. */
186 return 1;
187
188 _IO_size_t newsize = offset + 100;
189 wchar_t *oldbuf = wd->_IO_buf_base;
190 wchar_t *newbuf
191 = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
192 * sizeof (wchar_t));
193 if (newbuf == NULL)
194 return 1;
195
196 if (oldbuf != NULL)
197 {
198 __wmemcpy (newbuf, oldbuf, _IO_wblen (fp));
199 (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
200 /* Make sure _IO_setb won't try to delete
201 _IO_buf_base. */
202 wd->_IO_buf_base = NULL;
203 }
204
d18ea0c5 205 _IO_wsetb (fp, newbuf, newbuf + newsize, 1);
107b8a92
UD
206
207 if (reading)
208 {
209 wd->_IO_write_base = newbuf + (wd->_IO_write_base - oldbuf);
210 wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
211 wd->_IO_write_end = newbuf + (wd->_IO_write_end - oldbuf);
212 wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
213
214 wd->_IO_read_base = newbuf;
215 wd->_IO_read_end = wd->_IO_buf_end;
216 }
217 else
218 {
219 wd->_IO_read_base = newbuf + (wd->_IO_read_base - oldbuf);
220 wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
221 wd->_IO_read_end = newbuf + (wd->_IO_read_end - oldbuf);
222 wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
223
224 wd->_IO_write_base = newbuf;
225 wd->_IO_write_end = wd->_IO_buf_end;
226 }
227
228 /* Clear the area between the last write position and th
229 new position. */
230 assert (offset >= oldend);
231 if (reading)
232 wmemset (wd->_IO_read_base + oldend, L'\0', offset - oldend);
233 else
234 wmemset (wd->_IO_write_base + oldend, L'\0', offset - oldend);
235
236 return 0;
237}
238
239
d64b6ad0
UD
240_IO_off64_t
241_IO_wstr_seekoff (fp, offset, dir, mode)
242 _IO_FILE *fp;
243 _IO_off64_t offset;
244 int dir;
245 int mode;
246{
247 _IO_off64_t new_pos;
248
249 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
250 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
251
252 if (mode == 0)
253 {
254 /* Don't move any pointers. But there is no clear indication what
255 mode FP is in. Let's guess. */
256 if (fp->_IO_file_flags & _IO_NO_WRITES)
257 new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
258 else
259 new_pos = (fp->_wide_data->_IO_write_ptr
260 - fp->_wide_data->_IO_write_base);
261 }
262 else
263 {
264 _IO_ssize_t cur_size = _IO_wstr_count (fp);
265 new_pos = EOF;
266
267 /* Move the get pointer, if requested. */
268 if (mode & _IOS_INPUT)
269 {
270 switch (dir)
271 {
272 case _IO_seek_end:
273 offset += cur_size;
274 break;
275 case _IO_seek_cur:
276 offset += (fp->_wide_data->_IO_read_ptr
277 - fp->_wide_data->_IO_read_base);
278 break;
279 default: /* case _IO_seek_set: */
280 break;
281 }
107b8a92
UD
282 if (offset < 0)
283 return EOF;
284 if ((_IO_ssize_t) offset > cur_size
285 && enlarge_userbuf (fp, offset, 1) != 0)
d64b6ad0
UD
286 return EOF;
287 fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
288 + offset);
289 fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
290 + cur_size);
291 new_pos = offset;
292 }
293
294 /* Move the put pointer, if requested. */
295 if (mode & _IOS_OUTPUT)
296 {
297 switch (dir)
298 {
299 case _IO_seek_end:
300 offset += cur_size;
301 break;
302 case _IO_seek_cur:
303 offset += (fp->_wide_data->_IO_write_ptr
304 - fp->_wide_data->_IO_write_base);
305 break;
306 default: /* case _IO_seek_set: */
307 break;
308 }
107b8a92
UD
309 if (offset < 0)
310 return EOF;
311 if ((_IO_ssize_t) offset > cur_size
312 && enlarge_userbuf (fp, offset, 0) != 0)
d64b6ad0
UD
313 return EOF;
314 fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
315 + offset);
316 new_pos = offset;
317 }
318 }
319 return new_pos;
320}
321
322_IO_wint_t
323_IO_wstr_pbackfail (fp, c)
324 _IO_FILE *fp;
325 _IO_wint_t c;
326{
6dd67bd5 327 if ((fp->_flags & _IO_NO_WRITES) && c != WEOF)
d64b6ad0 328 return WEOF;
d18ea0c5 329 return _IO_wdefault_pbackfail (fp, c);
d64b6ad0
UD
330}
331
332void
333_IO_wstr_finish (fp, dummy)
334 _IO_FILE *fp;
335 int dummy;
336{
1e88bd0f 337 if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
d64b6ad0
UD
338 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
339 fp->_wide_data->_IO_buf_base = NULL;
340
d18ea0c5 341 _IO_wdefault_finish (fp, 0);
d64b6ad0
UD
342}
343
b2637a22 344const struct _IO_jump_t _IO_wstr_jumps =
d64b6ad0
UD
345{
346 JUMP_INIT_DUMMY,
347 JUMP_INIT(finish, _IO_wstr_finish),
348 JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
349 JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
d18ea0c5 350 JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
d64b6ad0 351 JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
d18ea0c5
AS
352 JUMP_INIT(xsputn, _IO_wdefault_xsputn),
353 JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
d64b6ad0
UD
354 JUMP_INIT(seekoff, _IO_wstr_seekoff),
355 JUMP_INIT(seekpos, _IO_default_seekpos),
bff334e0 356 JUMP_INIT(setbuf, _IO_default_setbuf),
d64b6ad0 357 JUMP_INIT(sync, _IO_default_sync),
d18ea0c5 358 JUMP_INIT(doallocate, _IO_wdefault_doallocate),
d64b6ad0
UD
359 JUMP_INIT(read, _IO_default_read),
360 JUMP_INIT(write, _IO_default_write),
361 JUMP_INIT(seek, _IO_default_seek),
362 JUMP_INIT(close, _IO_default_close),
363 JUMP_INIT(stat, _IO_default_stat),
364 JUMP_INIT(showmanyc, _IO_default_showmanyc),
365 JUMP_INIT(imbue, _IO_default_imbue)
366};