S390: Optimize wmemset.
[glibc.git] / libio / wstrops.c
blob3993579bd144bc1a0dff50ca65469a9f1f29aa8c
1 /* Copyright (C) 1993-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>.
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. */
27 #include <assert.h>
28 #include "strfile.h"
29 #include "libioP.h"
30 #include <string.h>
31 #include <wchar.h>
32 #include <stdio_ext.h>
34 void
35 _IO_wstr_init_static (fp, ptr, size, pstart)
36 _IO_FILE *fp;
37 wchar_t *ptr;
38 _IO_size_t size;
39 wchar_t *pstart;
41 wchar_t *end;
43 if (size == 0)
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);
51 _IO_wsetb (fp, ptr, end, 0);
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)
58 fp->_wide_data->_IO_write_ptr = pstart;
59 fp->_wide_data->_IO_write_end = end;
60 fp->_wide_data->_IO_read_end = pstart;
62 else
64 fp->_wide_data->_IO_write_ptr = ptr;
65 fp->_wide_data->_IO_write_end = ptr;
66 fp->_wide_data->_IO_read_end = end;
68 /* A null _allocate_buffer function flags the strfile as being static. */
69 (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
72 _IO_wint_t
73 _IO_wstr_overflow (fp, c)
74 _IO_FILE *fp;
75 _IO_wint_t c;
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))
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;
87 pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
88 if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
90 if (fp->_flags2 & _IO_FLAGS2_USER_WBUF) /* not allowed to enlarge */
91 return WEOF;
92 else
94 wchar_t *new_buf;
95 wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
96 size_t old_wblen = _IO_wblen (fp);
97 _IO_size_t new_size = 2 * old_wblen + 100;
99 if (__glibc_unlikely (new_size < old_wblen)
100 || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t)))
101 return EOF;
103 new_buf
104 = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
105 * sizeof (wchar_t));
106 if (new_buf == NULL)
108 /* __ferror(fp) = 1; */
109 return WEOF;
111 if (old_buf)
113 __wmemcpy (new_buf, old_buf, old_wblen);
114 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
115 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
116 fp->_wide_data->_IO_buf_base = NULL;
119 wmemset (new_buf + old_wblen, L'\0', new_size - old_wblen);
121 _IO_wsetb (fp, new_buf, new_buf + new_size, 1);
122 fp->_wide_data->_IO_read_base =
123 new_buf + (fp->_wide_data->_IO_read_base - old_buf);
124 fp->_wide_data->_IO_read_ptr =
125 new_buf + (fp->_wide_data->_IO_read_ptr - old_buf);
126 fp->_wide_data->_IO_read_end =
127 new_buf + (fp->_wide_data->_IO_read_end - old_buf);
128 fp->_wide_data->_IO_write_ptr =
129 new_buf + (fp->_wide_data->_IO_write_ptr - old_buf);
131 fp->_wide_data->_IO_write_base = new_buf;
132 fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end;
136 if (!flush_only)
137 *fp->_wide_data->_IO_write_ptr++ = c;
138 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
139 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
140 return c;
144 _IO_wint_t
145 _IO_wstr_underflow (fp)
146 _IO_FILE *fp;
148 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
149 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
150 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
152 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
153 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
154 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end;
156 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
157 return *fp->_wide_data->_IO_read_ptr;
158 else
159 return WEOF;
163 /* The size of the valid part of the buffer. */
164 _IO_ssize_t
165 _IO_wstr_count (fp)
166 _IO_FILE *fp;
168 struct _IO_wide_data *wd = fp->_wide_data;
170 return ((wd->_IO_write_ptr > wd->_IO_read_end
171 ? wd->_IO_write_ptr : wd->_IO_read_end)
172 - wd->_IO_read_base);
176 static int
177 enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
179 if ((_IO_ssize_t) offset <= _IO_blen (fp))
180 return 0;
182 struct _IO_wide_data *wd = fp->_wide_data;
184 _IO_ssize_t oldend = wd->_IO_write_end - wd->_IO_write_base;
186 /* Try to enlarge the buffer. */
187 if (fp->_flags2 & _IO_FLAGS2_USER_WBUF)
188 /* User-provided buffer. */
189 return 1;
191 _IO_size_t newsize = offset + 100;
192 if (__glibc_unlikely (newsize > SIZE_MAX / sizeof (wchar_t)))
193 return 1;
195 wchar_t *oldbuf = wd->_IO_buf_base;
196 wchar_t *newbuf
197 = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
198 * sizeof (wchar_t));
199 if (newbuf == NULL)
200 return 1;
202 if (oldbuf != NULL)
204 __wmemcpy (newbuf, oldbuf, _IO_wblen (fp));
205 (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
206 /* Make sure _IO_setb won't try to delete
207 _IO_buf_base. */
208 wd->_IO_buf_base = NULL;
211 _IO_wsetb (fp, newbuf, newbuf + newsize, 1);
213 if (reading)
215 wd->_IO_write_base = newbuf + (wd->_IO_write_base - oldbuf);
216 wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
217 wd->_IO_write_end = newbuf + (wd->_IO_write_end - oldbuf);
218 wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
220 wd->_IO_read_base = newbuf;
221 wd->_IO_read_end = wd->_IO_buf_end;
223 else
225 wd->_IO_read_base = newbuf + (wd->_IO_read_base - oldbuf);
226 wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
227 wd->_IO_read_end = newbuf + (wd->_IO_read_end - oldbuf);
228 wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
230 wd->_IO_write_base = newbuf;
231 wd->_IO_write_end = wd->_IO_buf_end;
234 /* Clear the area between the last write position and th
235 new position. */
236 assert (offset >= oldend);
237 if (reading)
238 wmemset (wd->_IO_read_base + oldend, L'\0', offset - oldend);
239 else
240 wmemset (wd->_IO_write_base + oldend, L'\0', offset - oldend);
242 return 0;
246 _IO_off64_t
247 _IO_wstr_seekoff (fp, offset, dir, mode)
248 _IO_FILE *fp;
249 _IO_off64_t offset;
250 int dir;
251 int mode;
253 _IO_off64_t new_pos;
255 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
256 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
258 if (mode == 0)
260 /* Don't move any pointers. But there is no clear indication what
261 mode FP is in. Let's guess. */
262 if (fp->_IO_file_flags & _IO_NO_WRITES)
263 new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
264 else
265 new_pos = (fp->_wide_data->_IO_write_ptr
266 - fp->_wide_data->_IO_write_base);
268 else
270 _IO_ssize_t cur_size = _IO_wstr_count (fp);
271 new_pos = EOF;
273 /* Move the get pointer, if requested. */
274 if (mode & _IOS_INPUT)
276 switch (dir)
278 case _IO_seek_end:
279 offset += cur_size;
280 break;
281 case _IO_seek_cur:
282 offset += (fp->_wide_data->_IO_read_ptr
283 - fp->_wide_data->_IO_read_base);
284 break;
285 default: /* case _IO_seek_set: */
286 break;
288 if (offset < 0)
289 return EOF;
290 if ((_IO_ssize_t) offset > cur_size
291 && enlarge_userbuf (fp, offset, 1) != 0)
292 return EOF;
293 fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
294 + offset);
295 fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base
296 + cur_size);
297 new_pos = offset;
300 /* Move the put pointer, if requested. */
301 if (mode & _IOS_OUTPUT)
303 switch (dir)
305 case _IO_seek_end:
306 offset += cur_size;
307 break;
308 case _IO_seek_cur:
309 offset += (fp->_wide_data->_IO_write_ptr
310 - fp->_wide_data->_IO_write_base);
311 break;
312 default: /* case _IO_seek_set: */
313 break;
315 if (offset < 0)
316 return EOF;
317 if ((_IO_ssize_t) offset > cur_size
318 && enlarge_userbuf (fp, offset, 0) != 0)
319 return EOF;
320 fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
321 + offset);
322 new_pos = offset;
325 return new_pos;
328 _IO_wint_t
329 _IO_wstr_pbackfail (fp, c)
330 _IO_FILE *fp;
331 _IO_wint_t c;
333 if ((fp->_flags & _IO_NO_WRITES) && c != WEOF)
334 return WEOF;
335 return _IO_wdefault_pbackfail (fp, c);
338 void
339 _IO_wstr_finish (fp, dummy)
340 _IO_FILE *fp;
341 int dummy;
343 if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
344 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
345 fp->_wide_data->_IO_buf_base = NULL;
347 _IO_wdefault_finish (fp, 0);
350 const struct _IO_jump_t _IO_wstr_jumps =
352 JUMP_INIT_DUMMY,
353 JUMP_INIT(finish, _IO_wstr_finish),
354 JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow),
355 JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),
356 JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
357 JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),
358 JUMP_INIT(xsputn, _IO_wdefault_xsputn),
359 JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),
360 JUMP_INIT(seekoff, _IO_wstr_seekoff),
361 JUMP_INIT(seekpos, _IO_default_seekpos),
362 JUMP_INIT(setbuf, _IO_default_setbuf),
363 JUMP_INIT(sync, _IO_default_sync),
364 JUMP_INIT(doallocate, _IO_wdefault_doallocate),
365 JUMP_INIT(read, _IO_default_read),
366 JUMP_INIT(write, _IO_default_write),
367 JUMP_INIT(seek, _IO_default_seek),
368 JUMP_INIT(close, _IO_default_close),
369 JUMP_INIT(stat, _IO_default_stat),
370 JUMP_INIT(showmanyc, _IO_default_showmanyc),
371 JUMP_INIT(imbue, _IO_default_imbue)