diff options
Diffstat (limited to 'REORG.TODO/libio/wstrops.c')
-rw-r--r-- | REORG.TODO/libio/wstrops.c | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/REORG.TODO/libio/wstrops.c b/REORG.TODO/libio/wstrops.c new file mode 100644 index 0000000000..bb62fd6702 --- /dev/null +++ b/REORG.TODO/libio/wstrops.c @@ -0,0 +1,388 @@ +/* Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. + + As a special exception, if you link the code in this file with + files compiled with a GNU compiler to produce an executable, + that does not cause the resulting executable to be covered by + the GNU Lesser General Public License. This exception does not + however invalidate any other reasons why the executable file + might be covered by the GNU Lesser General Public License. + This exception applies to code released by its copyright holders + in files containing the exception. */ + +#include <assert.h> +#include "strfile.h" +#include "libioP.h" +#include <string.h> +#include <wchar.h> +#include <stdio_ext.h> + +void +_IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size, + wchar_t *pstart) +{ + wchar_t *end; + + if (size == 0) + end = ptr + __wcslen (ptr); + else if ((_IO_size_t) ptr + size * sizeof (wchar_t) > (_IO_size_t) ptr) + end = ptr + size; + else + /* Even for misaligned ptr make sure there is integral number of wide + characters. */ + end = ptr + (-1 - (_IO_size_t) ptr) / sizeof (wchar_t); + _IO_wsetb (fp, ptr, end, 0); + + fp->_wide_data->_IO_write_base = ptr; + fp->_wide_data->_IO_read_base = ptr; + fp->_wide_data->_IO_read_ptr = ptr; + if (pstart) + { + fp->_wide_data->_IO_write_ptr = pstart; + fp->_wide_data->_IO_write_end = end; + fp->_wide_data->_IO_read_end = pstart; + } + else + { + fp->_wide_data->_IO_write_ptr = ptr; + fp->_wide_data->_IO_write_end = ptr; + fp->_wide_data->_IO_read_end = end; + } + /* A null _allocate_buffer function flags the strfile as being static. */ + (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0; +} + +_IO_wint_t +_IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) +{ + int flush_only = c == WEOF; + _IO_size_t pos; + if (fp->_flags & _IO_NO_WRITES) + return flush_only ? 0 : WEOF; + if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) + { + fp->_flags |= _IO_CURRENTLY_PUTTING; + fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr; + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; + } + pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base; + if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only)) + { + if (fp->_flags2 & _IO_FLAGS2_USER_WBUF) /* not allowed to enlarge */ + return WEOF; + else + { + wchar_t *new_buf; + wchar_t *old_buf = fp->_wide_data->_IO_buf_base; + size_t old_wblen = _IO_wblen (fp); + _IO_size_t new_size = 2 * old_wblen + 100; + + if (__glibc_unlikely (new_size < old_wblen) + || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t))) + return EOF; + + new_buf + = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size + * sizeof (wchar_t)); + if (new_buf == NULL) + { + /* __ferror(fp) = 1; */ + return WEOF; + } + if (old_buf) + { + __wmemcpy (new_buf, old_buf, old_wblen); + (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); + /* Make sure _IO_setb won't try to delete _IO_buf_base. */ + fp->_wide_data->_IO_buf_base = NULL; + } + + __wmemset (new_buf + old_wblen, L'\0', new_size - old_wblen); + + _IO_wsetb (fp, new_buf, new_buf + new_size, 1); + fp->_wide_data->_IO_read_base = + new_buf + (fp->_wide_data->_IO_read_base - old_buf); + fp->_wide_data->_IO_read_ptr = + new_buf + (fp->_wide_data->_IO_read_ptr - old_buf); + fp->_wide_data->_IO_read_end = + new_buf + (fp->_wide_data->_IO_read_end - old_buf); + fp->_wide_data->_IO_write_ptr = + new_buf + (fp->_wide_data->_IO_write_ptr - old_buf); + + fp->_wide_data->_IO_write_base = new_buf; + fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end; + } + } + + if (!flush_only) + *fp->_wide_data->_IO_write_ptr++ = c; + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + return c; +} + + +_IO_wint_t +_IO_wstr_underflow (_IO_FILE *fp) +{ + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING)) + { + fp->_flags &= ~_IO_CURRENTLY_PUTTING; + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; + fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end; + } + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; + else + return WEOF; +} + + +/* The size of the valid part of the buffer. */ +_IO_ssize_t +_IO_wstr_count (_IO_FILE *fp) +{ + struct _IO_wide_data *wd = fp->_wide_data; + + return ((wd->_IO_write_ptr > wd->_IO_read_end + ? wd->_IO_write_ptr : wd->_IO_read_end) + - wd->_IO_read_base); +} + + +static int +enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) +{ + if ((_IO_ssize_t) offset <= _IO_wblen (fp)) + return 0; + + struct _IO_wide_data *wd = fp->_wide_data; + + _IO_ssize_t oldend = wd->_IO_write_end - wd->_IO_write_base; + + /* Try to enlarge the buffer. */ + if (fp->_flags2 & _IO_FLAGS2_USER_WBUF) + /* User-provided buffer. */ + return 1; + + _IO_size_t newsize = offset + 100; + if (__glibc_unlikely (newsize > SIZE_MAX / sizeof (wchar_t))) + return 1; + + wchar_t *oldbuf = wd->_IO_buf_base; + wchar_t *newbuf + = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize + * sizeof (wchar_t)); + if (newbuf == NULL) + return 1; + + if (oldbuf != NULL) + { + __wmemcpy (newbuf, oldbuf, _IO_wblen (fp)); + (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); + /* Make sure _IO_setb won't try to delete + _IO_buf_base. */ + wd->_IO_buf_base = NULL; + } + + _IO_wsetb (fp, newbuf, newbuf + newsize, 1); + + if (reading) + { + wd->_IO_write_base = newbuf + (wd->_IO_write_base - oldbuf); + wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf); + wd->_IO_write_end = newbuf + (wd->_IO_write_end - oldbuf); + wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf); + + wd->_IO_read_base = newbuf; + wd->_IO_read_end = wd->_IO_buf_end; + } + else + { + wd->_IO_read_base = newbuf + (wd->_IO_read_base - oldbuf); + wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf); + wd->_IO_read_end = newbuf + (wd->_IO_read_end - oldbuf); + wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf); + + wd->_IO_write_base = newbuf; + wd->_IO_write_end = wd->_IO_buf_end; + } + + /* Clear the area between the last write position and th + new position. */ + assert (offset >= oldend); + if (reading) + __wmemset (wd->_IO_read_base + oldend, L'\0', offset - oldend); + else + __wmemset (wd->_IO_write_base + oldend, L'\0', offset - oldend); + + return 0; +} + +static void +_IO_wstr_switch_to_get_mode (_IO_FILE *fp) +{ + if (_IO_in_backup (fp)) + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base; + else + { + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base; + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + } + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + + fp->_flags &= ~_IO_CURRENTLY_PUTTING; +} + +_IO_off64_t +_IO_wstr_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode) +{ + _IO_off64_t new_pos; + + if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET)) + mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT); + + bool was_writing = (fp->_wide_data->_IO_write_ptr > + fp->_wide_data->_IO_write_base + || _IO_in_put_mode (fp)); + if (was_writing) + _IO_wstr_switch_to_get_mode (fp); + + if (mode == 0) + { + new_pos = (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); + } + else + { + _IO_ssize_t cur_size = _IO_wstr_count (fp); + new_pos = EOF; + + /* Move the get pointer, if requested. */ + if (mode & _IOS_INPUT) + { + _IO_ssize_t base; + switch (dir) + { + case _IO_seek_set: + base = 0; + break; + case _IO_seek_cur: + base = (fp->_wide_data->_IO_read_ptr + - fp->_wide_data->_IO_read_base); + break; + default: /* case _IO_seek_end: */ + base = cur_size; + break; + } + _IO_ssize_t maxval = SSIZE_MAX/sizeof (wchar_t) - base; + if (offset < -base || offset > maxval) + { + __set_errno (EINVAL); + return EOF; + } + base += offset; + if (base > cur_size + && enlarge_userbuf (fp, base, 1) != 0) + return EOF; + fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base + + base); + fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base + + cur_size); + new_pos = offset; + } + + /* Move the put pointer, if requested. */ + if (mode & _IOS_OUTPUT) + { + _IO_ssize_t base; + switch (dir) + { + case _IO_seek_set: + base = 0; + break; + case _IO_seek_cur: + base = (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); + break; + default: /* case _IO_seek_end: */ + base = cur_size; + break; + } + _IO_ssize_t maxval = SSIZE_MAX/sizeof (wchar_t) - base; + if (offset < -base || offset > maxval) + { + __set_errno (EINVAL); + return EOF; + } + base += offset; + if (base > cur_size + && enlarge_userbuf (fp, base, 0) != 0) + return EOF; + fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base + + base); + new_pos = base; + } + } + return new_pos; +} + +_IO_wint_t +_IO_wstr_pbackfail (_IO_FILE *fp, _IO_wint_t c) +{ + if ((fp->_flags & _IO_NO_WRITES) && c != WEOF) + return WEOF; + return _IO_wdefault_pbackfail (fp, c); +} + +void +_IO_wstr_finish (_IO_FILE *fp, int dummy) +{ + if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) + (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base); + fp->_wide_data->_IO_buf_base = NULL; + + _IO_wdefault_finish (fp, 0); +} + +const struct _IO_jump_t _IO_wstr_jumps libio_vtable = +{ + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_wstr_finish), + JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow), + JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow), + JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow), + JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail), + JUMP_INIT(xsputn, _IO_wdefault_xsputn), + JUMP_INIT(xsgetn, _IO_wdefault_xsgetn), + JUMP_INIT(seekoff, _IO_wstr_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, _IO_default_setbuf), + JUMP_INIT(sync, _IO_default_sync), + JUMP_INIT(doallocate, _IO_wdefault_doallocate), + JUMP_INIT(read, _IO_default_read), + JUMP_INIT(write, _IO_default_write), + JUMP_INIT(seek, _IO_default_seek), + JUMP_INIT(close, _IO_default_close), + JUMP_INIT(stat, _IO_default_stat), + JUMP_INIT(showmanyc, _IO_default_showmanyc), + JUMP_INIT(imbue, _IO_default_imbue) +}; |