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. */
32 #include <stdio_ext.h>
35 _IO_wstr_init_static (fp
, ptr
, size
, pstart
)
44 end
= ptr
+ __wcslen (ptr
);
45 else if ((_IO_size_t
) ptr
+ size
* sizeof (wchar_t) > (_IO_size_t
) ptr
)
48 /* Even for misaligned ptr make sure there is integral number of wide
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
;
58 fp
->_wide_data
->_IO_write_ptr
= pstart
;
59 fp
->_wide_data
->_IO_write_end
= end
;
60 fp
->_wide_data
->_IO_read_end
= pstart
;
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;
73 _IO_wstr_overflow (fp
, c
)
77 int flush_only
= c
== WEOF
;
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 */
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)))
104 = (wchar_t *) (*((_IO_strfile
*) fp
)->_s
._allocate_buffer
) (new_size
108 /* __ferror(fp) = 1; */
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
;
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
;
145 _IO_wstr_underflow (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
;
163 /* The size of the valid part of the buffer. */
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
);
177 enlarge_userbuf (_IO_FILE
*fp
, _IO_off64_t offset
, int reading
)
179 if ((_IO_ssize_t
) offset
<= _IO_blen (fp
))
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. */
191 _IO_size_t newsize
= offset
+ 100;
192 if (__glibc_unlikely (newsize
> SIZE_MAX
/ sizeof (wchar_t)))
195 wchar_t *oldbuf
= wd
->_IO_buf_base
;
197 = (wchar_t *) (*((_IO_strfile
*) fp
)->_s
._allocate_buffer
) (newsize
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
208 wd
->_IO_buf_base
= NULL
;
211 _IO_wsetb (fp
, newbuf
, newbuf
+ newsize
, 1);
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
;
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
236 assert (offset
>= oldend
);
238 wmemset (wd
->_IO_read_base
+ oldend
, L
'\0', offset
- oldend
);
240 wmemset (wd
->_IO_write_base
+ oldend
, L
'\0', offset
- oldend
);
247 _IO_wstr_seekoff (fp
, offset
, dir
, mode
)
255 if (mode
== 0 && (fp
->_flags
& _IO_TIED_PUT_GET
))
256 mode
= (fp
->_flags
& _IO_CURRENTLY_PUTTING
? _IOS_OUTPUT
: _IOS_INPUT
);
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
;
265 new_pos
= (fp
->_wide_data
->_IO_write_ptr
266 - fp
->_wide_data
->_IO_write_base
);
270 _IO_ssize_t cur_size
= _IO_wstr_count (fp
);
273 /* Move the get pointer, if requested. */
274 if (mode
& _IOS_INPUT
)
282 offset
+= (fp
->_wide_data
->_IO_read_ptr
283 - fp
->_wide_data
->_IO_read_base
);
285 default: /* case _IO_seek_set: */
290 if ((_IO_ssize_t
) offset
> cur_size
291 && enlarge_userbuf (fp
, offset
, 1) != 0)
293 fp
->_wide_data
->_IO_read_ptr
= (fp
->_wide_data
->_IO_read_base
295 fp
->_wide_data
->_IO_read_end
= (fp
->_wide_data
->_IO_read_base
300 /* Move the put pointer, if requested. */
301 if (mode
& _IOS_OUTPUT
)
309 offset
+= (fp
->_wide_data
->_IO_write_ptr
310 - fp
->_wide_data
->_IO_write_base
);
312 default: /* case _IO_seek_set: */
317 if ((_IO_ssize_t
) offset
> cur_size
318 && enlarge_userbuf (fp
, offset
, 0) != 0)
320 fp
->_wide_data
->_IO_write_ptr
= (fp
->_wide_data
->_IO_write_base
329 _IO_wstr_pbackfail (fp
, c
)
333 if ((fp
->_flags
& _IO_NO_WRITES
) && c
!= WEOF
)
335 return _IO_wdefault_pbackfail (fp
, c
);
339 _IO_wstr_finish (fp
, 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
=
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
)