1 /* Copyright (C) 1993-2024 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 <https://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 (FILE *fp
, wchar_t *ptr
, size_t size
,
41 end
= ptr
+ __wcslen (ptr
);
42 else if ((size_t) ptr
+ size
* sizeof (wchar_t) > (size_t) ptr
)
45 /* Even for misaligned ptr make sure there is integral number of wide
47 end
= ptr
+ (-1 - (size_t) ptr
) / sizeof (wchar_t);
48 _IO_wsetb (fp
, ptr
, end
, 0);
50 fp
->_wide_data
->_IO_write_base
= ptr
;
51 fp
->_wide_data
->_IO_read_base
= ptr
;
52 fp
->_wide_data
->_IO_read_ptr
= ptr
;
55 fp
->_wide_data
->_IO_write_ptr
= pstart
;
56 fp
->_wide_data
->_IO_write_end
= end
;
57 fp
->_wide_data
->_IO_read_end
= pstart
;
61 fp
->_wide_data
->_IO_write_ptr
= ptr
;
62 fp
->_wide_data
->_IO_write_end
= ptr
;
63 fp
->_wide_data
->_IO_read_end
= end
;
65 /* A null _allocate_buffer function flags the strfile as being static. */
66 (((_IO_strfile
*) fp
)->_s
._allocate_buffer_unused
) = (_IO_alloc_type
)0;
70 _IO_wstr_overflow (FILE *fp
, wint_t c
)
72 int flush_only
= c
== WEOF
;
74 if (fp
->_flags
& _IO_NO_WRITES
)
75 return flush_only
? 0 : WEOF
;
76 if ((fp
->_flags
& _IO_TIED_PUT_GET
) && !(fp
->_flags
& _IO_CURRENTLY_PUTTING
))
78 fp
->_flags
|= _IO_CURRENTLY_PUTTING
;
79 fp
->_wide_data
->_IO_write_ptr
= fp
->_wide_data
->_IO_read_ptr
;
80 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
82 pos
= fp
->_wide_data
->_IO_write_ptr
- fp
->_wide_data
->_IO_write_base
;
83 if (pos
>= (size_t) (_IO_wblen (fp
) + flush_only
))
85 if (fp
->_flags2
& _IO_FLAGS2_USER_WBUF
) /* not allowed to enlarge */
90 wchar_t *old_buf
= fp
->_wide_data
->_IO_buf_base
;
91 size_t old_wblen
= _IO_wblen (fp
);
92 size_t new_size
= 2 * old_wblen
+ 100;
94 if (__glibc_unlikely (new_size
< old_wblen
)
95 || __glibc_unlikely (new_size
> SIZE_MAX
/ sizeof (wchar_t)))
98 new_buf
= malloc (new_size
* sizeof (wchar_t));
101 /* __ferror(fp) = 1; */
106 __wmemcpy (new_buf
, old_buf
, old_wblen
);
108 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
109 fp
->_wide_data
->_IO_buf_base
= NULL
;
112 __wmemset (new_buf
+ old_wblen
, L
'\0', new_size
- old_wblen
);
114 _IO_wsetb (fp
, new_buf
, new_buf
+ new_size
, 1);
115 fp
->_wide_data
->_IO_read_base
=
116 new_buf
+ (fp
->_wide_data
->_IO_read_base
- old_buf
);
117 fp
->_wide_data
->_IO_read_ptr
=
118 new_buf
+ (fp
->_wide_data
->_IO_read_ptr
- old_buf
);
119 fp
->_wide_data
->_IO_read_end
=
120 new_buf
+ (fp
->_wide_data
->_IO_read_end
- old_buf
);
121 fp
->_wide_data
->_IO_write_ptr
=
122 new_buf
+ (fp
->_wide_data
->_IO_write_ptr
- old_buf
);
124 fp
->_wide_data
->_IO_write_base
= new_buf
;
125 fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_buf_end
;
130 *fp
->_wide_data
->_IO_write_ptr
++ = c
;
131 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
132 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
141 _IO_wstr_underflow (FILE *fp
)
143 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
144 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
145 if ((fp
->_flags
& _IO_TIED_PUT_GET
) && (fp
->_flags
& _IO_CURRENTLY_PUTTING
))
147 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
148 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_write_ptr
;
149 fp
->_wide_data
->_IO_write_ptr
= fp
->_wide_data
->_IO_write_end
;
151 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
152 return *fp
->_wide_data
->_IO_read_ptr
;
158 /* The size of the valid part of the buffer. */
160 _IO_wstr_count (FILE *fp
)
162 struct _IO_wide_data
*wd
= fp
->_wide_data
;
164 return ((wd
->_IO_write_ptr
> wd
->_IO_read_end
165 ? wd
->_IO_write_ptr
: wd
->_IO_read_end
)
166 - wd
->_IO_read_base
);
171 enlarge_userbuf (FILE *fp
, off64_t offset
, int reading
)
173 if ((ssize_t
) offset
<= _IO_wblen (fp
))
176 struct _IO_wide_data
*wd
= fp
->_wide_data
;
178 ssize_t oldend
= wd
->_IO_write_end
- wd
->_IO_write_base
;
180 /* Try to enlarge the buffer. */
181 if (fp
->_flags2
& _IO_FLAGS2_USER_WBUF
)
182 /* User-provided buffer. */
185 size_t newsize
= offset
+ 100;
186 if (__glibc_unlikely (newsize
> SIZE_MAX
/ sizeof (wchar_t)))
189 wchar_t *oldbuf
= wd
->_IO_buf_base
;
190 wchar_t *newbuf
= malloc (newsize
* sizeof (wchar_t));
196 __wmemcpy (newbuf
, oldbuf
, _IO_wblen (fp
));
198 /* Make sure _IO_setb won't try to delete
200 wd
->_IO_buf_base
= NULL
;
203 _IO_wsetb (fp
, newbuf
, newbuf
+ newsize
, 1);
207 wd
->_IO_write_base
= newbuf
+ (wd
->_IO_write_base
- oldbuf
);
208 wd
->_IO_write_ptr
= newbuf
+ (wd
->_IO_write_ptr
- oldbuf
);
209 wd
->_IO_write_end
= newbuf
+ (wd
->_IO_write_end
- oldbuf
);
210 wd
->_IO_read_ptr
= newbuf
+ (wd
->_IO_read_ptr
- oldbuf
);
212 wd
->_IO_read_base
= newbuf
;
213 wd
->_IO_read_end
= wd
->_IO_buf_end
;
217 wd
->_IO_read_base
= newbuf
+ (wd
->_IO_read_base
- oldbuf
);
218 wd
->_IO_read_ptr
= newbuf
+ (wd
->_IO_read_ptr
- oldbuf
);
219 wd
->_IO_read_end
= newbuf
+ (wd
->_IO_read_end
- oldbuf
);
220 wd
->_IO_write_ptr
= newbuf
+ (wd
->_IO_write_ptr
- oldbuf
);
222 wd
->_IO_write_base
= newbuf
;
223 wd
->_IO_write_end
= wd
->_IO_buf_end
;
226 /* Clear the area between the last write position and th
228 assert (offset
>= oldend
);
230 __wmemset (wd
->_IO_read_base
+ oldend
, L
'\0', offset
- oldend
);
232 __wmemset (wd
->_IO_write_base
+ oldend
, L
'\0', offset
- oldend
);
238 _IO_wstr_switch_to_get_mode (FILE *fp
)
240 if (_IO_in_backup (fp
))
241 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_backup_base
;
244 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_buf_base
;
245 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
246 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
248 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_write_ptr
;
249 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
251 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
255 _IO_wstr_seekoff (FILE *fp
, off64_t offset
, int dir
, int mode
)
259 if (mode
== 0 && (fp
->_flags
& _IO_TIED_PUT_GET
))
260 mode
= (fp
->_flags
& _IO_CURRENTLY_PUTTING
? _IOS_OUTPUT
: _IOS_INPUT
);
262 bool was_writing
= ((fp
->_wide_data
->_IO_write_ptr
263 > fp
->_wide_data
->_IO_write_base
)
264 || _IO_in_put_mode (fp
));
266 _IO_wstr_switch_to_get_mode (fp
);
270 new_pos
= (fp
->_wide_data
->_IO_write_ptr
271 - fp
->_wide_data
->_IO_write_base
);
275 ssize_t cur_size
= _IO_wstr_count (fp
);
278 /* Move the get pointer, if requested. */
279 if (mode
& _IOS_INPUT
)
288 base
= (fp
->_wide_data
->_IO_read_ptr
289 - fp
->_wide_data
->_IO_read_base
);
291 default: /* case _IO_seek_end: */
295 ssize_t maxval
= SSIZE_MAX
/sizeof (wchar_t) - base
;
296 if (offset
< -base
|| offset
> maxval
)
298 __set_errno (EINVAL
);
303 && enlarge_userbuf (fp
, base
, 1) != 0)
305 fp
->_wide_data
->_IO_read_ptr
= (fp
->_wide_data
->_IO_read_base
307 fp
->_wide_data
->_IO_read_end
= (fp
->_wide_data
->_IO_read_base
312 /* Move the put pointer, if requested. */
313 if (mode
& _IOS_OUTPUT
)
322 base
= (fp
->_wide_data
->_IO_write_ptr
323 - fp
->_wide_data
->_IO_write_base
);
325 default: /* case _IO_seek_end: */
329 ssize_t maxval
= SSIZE_MAX
/sizeof (wchar_t) - base
;
330 if (offset
< -base
|| offset
> maxval
)
332 __set_errno (EINVAL
);
337 && enlarge_userbuf (fp
, base
, 0) != 0)
339 fp
->_wide_data
->_IO_write_ptr
= (fp
->_wide_data
->_IO_write_base
348 _IO_wstr_pbackfail (FILE *fp
, wint_t c
)
350 if ((fp
->_flags
& _IO_NO_WRITES
) && c
!= WEOF
)
352 return _IO_wdefault_pbackfail (fp
, c
);
356 _IO_wstr_finish (FILE *fp
, int dummy
)
358 if (fp
->_wide_data
->_IO_buf_base
&& !(fp
->_flags2
& _IO_FLAGS2_USER_WBUF
))
359 free (fp
->_wide_data
->_IO_buf_base
);
360 fp
->_wide_data
->_IO_buf_base
= NULL
;
362 _IO_wdefault_finish (fp
, 0);