Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
glibc/libio/wgenops.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
698 lines (628 sloc)
18.5 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright (C) 1993-2016 Free Software Foundation, Inc. | |
This file is part of the GNU C Library. | |
Written by Ulrich Drepper <drepper@cygnus.com>. | |
Based on the single byte version by Per Bothner <bothner@cygnus.com>. | |
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. */ | |
/* Generic or default I/O operations. */ | |
#include "libioP.h" | |
#include <stdlib.h> | |
#include <string.h> | |
#include <wchar.h> | |
#ifndef _LIBC | |
# define __wmemcpy(dst, src, n) wmemcpy (dst, src, n) | |
#endif | |
static int save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) __THROW | |
#ifdef _LIBC | |
internal_function | |
#endif | |
; | |
/* Return minimum _pos markers | |
Assumes the current get area is the main get area. */ | |
_IO_ssize_t | |
_IO_least_wmarker (_IO_FILE *fp, wchar_t *end_p) | |
{ | |
_IO_ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base; | |
struct _IO_marker *mark; | |
for (mark = fp->_markers; mark != NULL; mark = mark->_next) | |
if (mark->_pos < least_so_far) | |
least_so_far = mark->_pos; | |
return least_so_far; | |
} | |
libc_hidden_def (_IO_least_wmarker) | |
/* Switch current get area from backup buffer to (start of) main get area. */ | |
void | |
_IO_switch_to_main_wget_area (_IO_FILE *fp) | |
{ | |
wchar_t *tmp; | |
fp->_flags &= ~_IO_IN_BACKUP; | |
/* Swap _IO_read_end and _IO_save_end. */ | |
tmp = fp->_wide_data->_IO_read_end; | |
fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; | |
fp->_wide_data->_IO_save_end= tmp; | |
/* Swap _IO_read_base and _IO_save_base. */ | |
tmp = fp->_wide_data->_IO_read_base; | |
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; | |
fp->_wide_data->_IO_save_base = tmp; | |
/* Set _IO_read_ptr. */ | |
fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base; | |
} | |
libc_hidden_def (_IO_switch_to_main_wget_area) | |
/* Switch current get area from main get area to (end of) backup area. */ | |
void | |
_IO_switch_to_wbackup_area (_IO_FILE *fp) | |
{ | |
wchar_t *tmp; | |
fp->_flags |= _IO_IN_BACKUP; | |
/* Swap _IO_read_end and _IO_save_end. */ | |
tmp = fp->_wide_data->_IO_read_end; | |
fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; | |
fp->_wide_data->_IO_save_end = tmp; | |
/* Swap _IO_read_base and _IO_save_base. */ | |
tmp = fp->_wide_data->_IO_read_base; | |
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; | |
fp->_wide_data->_IO_save_base = tmp; | |
/* Set _IO_read_ptr. */ | |
fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; | |
} | |
libc_hidden_def (_IO_switch_to_wbackup_area) | |
void | |
_IO_wsetb (_IO_FILE *f, wchar_t *b, wchar_t *eb, int a) | |
{ | |
if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF)) | |
free (f->_wide_data->_IO_buf_base); | |
f->_wide_data->_IO_buf_base = b; | |
f->_wide_data->_IO_buf_end = eb; | |
if (a) | |
f->_flags2 &= ~_IO_FLAGS2_USER_WBUF; | |
else | |
f->_flags2 |= _IO_FLAGS2_USER_WBUF; | |
} | |
libc_hidden_def (_IO_wsetb) | |
wint_t | |
_IO_wdefault_pbackfail (_IO_FILE *fp, wint_t c) | |
{ | |
if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base | |
&& !_IO_in_backup (fp) | |
&& (wint_t) fp->_IO_read_ptr[-1] == c) | |
--fp->_IO_read_ptr; | |
else | |
{ | |
/* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/ | |
if (!_IO_in_backup (fp)) | |
{ | |
/* We need to keep the invariant that the main get area | |
logically follows the backup area. */ | |
if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base | |
&& _IO_have_wbackup (fp)) | |
{ | |
if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr)) | |
return WEOF; | |
} | |
else if (!_IO_have_wbackup (fp)) | |
{ | |
/* No backup buffer: allocate one. */ | |
/* Use nshort buffer, if unused? (probably not) FIXME */ | |
int backup_size = 128; | |
wchar_t *bbuf = (wchar_t *) malloc (backup_size | |
* sizeof (wchar_t)); | |
if (bbuf == NULL) | |
return WEOF; | |
fp->_wide_data->_IO_save_base = bbuf; | |
fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base | |
+ backup_size); | |
fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end; | |
} | |
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr; | |
_IO_switch_to_wbackup_area (fp); | |
} | |
else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base) | |
{ | |
/* Increase size of existing backup buffer. */ | |
_IO_size_t new_size; | |
_IO_size_t old_size = (fp->_wide_data->_IO_read_end | |
- fp->_wide_data->_IO_read_base); | |
wchar_t *new_buf; | |
new_size = 2 * old_size; | |
new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t)); | |
if (new_buf == NULL) | |
return WEOF; | |
__wmemcpy (new_buf + (new_size - old_size), | |
fp->_wide_data->_IO_read_base, old_size); | |
free (fp->_wide_data->_IO_read_base); | |
_IO_wsetg (fp, new_buf, new_buf + (new_size - old_size), | |
new_buf + new_size); | |
fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr; | |
} | |
*--fp->_wide_data->_IO_read_ptr = c; | |
} | |
return c; | |
} | |
libc_hidden_def (_IO_wdefault_pbackfail) | |
void | |
_IO_wdefault_finish (_IO_FILE *fp, int dummy) | |
{ | |
struct _IO_marker *mark; | |
if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) | |
{ | |
free (fp->_wide_data->_IO_buf_base); | |
fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL; | |
} | |
for (mark = fp->_markers; mark != NULL; mark = mark->_next) | |
mark->_sbuf = NULL; | |
if (fp->_IO_save_base) | |
{ | |
free (fp->_wide_data->_IO_save_base); | |
fp->_IO_save_base = NULL; | |
} | |
#ifdef _IO_MTSAFE_IO | |
if (fp->_lock != NULL) | |
_IO_lock_fini (*fp->_lock); | |
#endif | |
_IO_un_link ((struct _IO_FILE_plus *) fp); | |
} | |
libc_hidden_def (_IO_wdefault_finish) | |
wint_t | |
_IO_wdefault_uflow (_IO_FILE *fp) | |
{ | |
wint_t wch; | |
wch = _IO_UNDERFLOW (fp); | |
if (wch == WEOF) | |
return WEOF; | |
return *fp->_wide_data->_IO_read_ptr++; | |
} | |
libc_hidden_def (_IO_wdefault_uflow) | |
wint_t | |
__woverflow (_IO_FILE *f, wint_t wch) | |
{ | |
if (f->_mode == 0) | |
_IO_fwide (f, 1); | |
return _IO_OVERFLOW (f, wch); | |
} | |
libc_hidden_def (__woverflow) | |
wint_t | |
__wuflow (_IO_FILE *fp) | |
{ | |
if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) | |
return WEOF; | |
if (fp->_mode == 0) | |
_IO_fwide (fp, 1); | |
if (_IO_in_put_mode (fp)) | |
if (_IO_switch_to_wget_mode (fp) == EOF) | |
return WEOF; | |
if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) | |
return *fp->_wide_data->_IO_read_ptr++; | |
if (_IO_in_backup (fp)) | |
{ | |
_IO_switch_to_main_wget_area (fp); | |
if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) | |
return *fp->_wide_data->_IO_read_ptr++; | |
} | |
if (_IO_have_markers (fp)) | |
{ | |
if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) | |
return WEOF; | |
} | |
else if (_IO_have_wbackup (fp)) | |
_IO_free_wbackup_area (fp); | |
return _IO_UFLOW (fp); | |
} | |
libc_hidden_def (__wuflow) | |
wint_t | |
__wunderflow (_IO_FILE *fp) | |
{ | |
if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) | |
return WEOF; | |
if (fp->_mode == 0) | |
_IO_fwide (fp, 1); | |
if (_IO_in_put_mode (fp)) | |
if (_IO_switch_to_wget_mode (fp) == EOF) | |
return WEOF; | |
if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) | |
return *fp->_wide_data->_IO_read_ptr; | |
if (_IO_in_backup (fp)) | |
{ | |
_IO_switch_to_main_wget_area (fp); | |
if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) | |
return *fp->_wide_data->_IO_read_ptr; | |
} | |
if (_IO_have_markers (fp)) | |
{ | |
if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) | |
return WEOF; | |
} | |
else if (_IO_have_backup (fp)) | |
_IO_free_wbackup_area (fp); | |
return _IO_UNDERFLOW (fp); | |
} | |
libc_hidden_def (__wunderflow) | |
_IO_size_t | |
_IO_wdefault_xsputn (_IO_FILE *f, const void *data, _IO_size_t n) | |
{ | |
const wchar_t *s = (const wchar_t *) data; | |
_IO_size_t more = n; | |
if (more <= 0) | |
return 0; | |
for (;;) | |
{ | |
/* Space available. */ | |
_IO_ssize_t count = (f->_wide_data->_IO_write_end | |
- f->_wide_data->_IO_write_ptr); | |
if (count > 0) | |
{ | |
if ((_IO_size_t) count > more) | |
count = more; | |
if (count > 20) | |
{ | |
#ifdef _LIBC | |
f->_wide_data->_IO_write_ptr = | |
__wmempcpy (f->_wide_data->_IO_write_ptr, s, count); | |
#else | |
memcpy (f->_wide_data->_IO_write_ptr, s, count); | |
f->_wide_data->_IO_write_ptr += count; | |
#endif | |
s += count; | |
} | |
else if (count <= 0) | |
count = 0; | |
else | |
{ | |
wchar_t *p = f->_wide_data->_IO_write_ptr; | |
_IO_ssize_t i; | |
for (i = count; --i >= 0; ) | |
*p++ = *s++; | |
f->_wide_data->_IO_write_ptr = p; | |
} | |
more -= count; | |
} | |
if (more == 0 || __woverflow (f, *s++) == WEOF) | |
break; | |
more--; | |
} | |
return n - more; | |
} | |
libc_hidden_def (_IO_wdefault_xsputn) | |
_IO_size_t | |
_IO_wdefault_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n) | |
{ | |
_IO_size_t more = n; | |
wchar_t *s = (wchar_t*) data; | |
for (;;) | |
{ | |
/* Data available. */ | |
_IO_ssize_t count = (fp->_wide_data->_IO_read_end | |
- fp->_wide_data->_IO_read_ptr); | |
if (count > 0) | |
{ | |
if ((_IO_size_t) count > more) | |
count = more; | |
if (count > 20) | |
{ | |
#ifdef _LIBC | |
s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count); | |
#else | |
memcpy (s, fp->_wide_data->_IO_read_ptr, count); | |
s += count; | |
#endif | |
fp->_wide_data->_IO_read_ptr += count; | |
} | |
else if (count <= 0) | |
count = 0; | |
else | |
{ | |
wchar_t *p = fp->_wide_data->_IO_read_ptr; | |
int i = (int) count; | |
while (--i >= 0) | |
*s++ = *p++; | |
fp->_wide_data->_IO_read_ptr = p; | |
} | |
more -= count; | |
} | |
if (more == 0 || __wunderflow (fp) == WEOF) | |
break; | |
} | |
return n - more; | |
} | |
libc_hidden_def (_IO_wdefault_xsgetn) | |
void | |
_IO_wdoallocbuf (_IO_FILE *fp) | |
{ | |
if (fp->_wide_data->_IO_buf_base) | |
return; | |
if (!(fp->_flags & _IO_UNBUFFERED)) | |
if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF) | |
return; | |
_IO_wsetb (fp, fp->_wide_data->_shortbuf, | |
fp->_wide_data->_shortbuf + 1, 0); | |
} | |
libc_hidden_def (_IO_wdoallocbuf) | |
int | |
_IO_wdefault_doallocate (_IO_FILE *fp) | |
{ | |
wchar_t *buf; | |
buf = malloc (_IO_BUFSIZ); | |
if (__glibc_unlikely (buf == NULL)) | |
return EOF; | |
_IO_wsetb (fp, buf, buf + _IO_BUFSIZ, 1); | |
return 1; | |
} | |
libc_hidden_def (_IO_wdefault_doallocate) | |
int | |
_IO_switch_to_wget_mode (_IO_FILE *fp) | |
{ | |
if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base) | |
if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF) | |
return EOF; | |
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_write_base = fp->_wide_data->_IO_write_ptr | |
= fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr; | |
fp->_flags &= ~_IO_CURRENTLY_PUTTING; | |
return 0; | |
} | |
libc_hidden_def (_IO_switch_to_wget_mode) | |
void | |
_IO_free_wbackup_area (_IO_FILE *fp) | |
{ | |
if (_IO_in_backup (fp)) | |
_IO_switch_to_main_wget_area (fp); /* Just in case. */ | |
free (fp->_wide_data->_IO_save_base); | |
fp->_wide_data->_IO_save_base = NULL; | |
fp->_wide_data->_IO_save_end = NULL; | |
fp->_wide_data->_IO_backup_base = NULL; | |
} | |
libc_hidden_def (_IO_free_wbackup_area) | |
#if 0 | |
int | |
_IO_switch_to_wput_mode (_IO_FILE *fp) | |
{ | |
fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_read_ptr; | |
fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr; | |
/* Following is wrong if line- or un-buffered? */ | |
fp->_wide_data->_IO_write_end = (fp->_flags & _IO_IN_BACKUP | |
? fp->_wide_data->_IO_read_end | |
: fp->_wide_data->_IO_buf_end); | |
fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; | |
fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_end; | |
fp->_flags |= _IO_CURRENTLY_PUTTING; | |
return 0; | |
} | |
#endif | |
static int | |
#ifdef _LIBC | |
internal_function | |
#endif | |
save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) | |
{ | |
/* Append [_IO_read_base..end_p] to backup area. */ | |
_IO_ssize_t least_mark = _IO_least_wmarker (fp, end_p); | |
/* needed_size is how much space we need in the backup area. */ | |
_IO_size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base) | |
- least_mark); | |
/* FIXME: Dubious arithmetic if pointers are NULL */ | |
_IO_size_t current_Bsize = (fp->_wide_data->_IO_save_end | |
- fp->_wide_data->_IO_save_base); | |
_IO_size_t avail; /* Extra space available for future expansion. */ | |
_IO_ssize_t delta; | |
struct _IO_marker *mark; | |
if (needed_size > current_Bsize) | |
{ | |
wchar_t *new_buffer; | |
avail = 100; | |
new_buffer = (wchar_t *) malloc ((avail + needed_size) | |
* sizeof (wchar_t)); | |
if (new_buffer == NULL) | |
return EOF; /* FIXME */ | |
if (least_mark < 0) | |
{ | |
#ifdef _LIBC | |
__wmempcpy (__wmempcpy (new_buffer + avail, | |
fp->_wide_data->_IO_save_end + least_mark, | |
-least_mark), | |
fp->_wide_data->_IO_read_base, | |
end_p - fp->_wide_data->_IO_read_base); | |
#else | |
memcpy (new_buffer + avail, | |
fp->_wide_data->_IO_save_end + least_mark, | |
-least_mark * sizeof (wchar_t)); | |
memcpy (new_buffer + avail - least_mark, | |
fp->_wide_data->_IO_read_base, | |
(end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t)); | |
#endif | |
} | |
else | |
{ | |
#ifdef _LIBC | |
__wmemcpy (new_buffer + avail, | |
fp->_wide_data->_IO_read_base + least_mark, | |
needed_size); | |
#else | |
memcpy (new_buffer + avail, | |
fp->_wide_data->_IO_read_base + least_mark, | |
needed_size * sizeof (wchar_t)); | |
#endif | |
} | |
free (fp->_wide_data->_IO_save_base); | |
fp->_wide_data->_IO_save_base = new_buffer; | |
fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size; | |
} | |
else | |
{ | |
avail = current_Bsize - needed_size; | |
if (least_mark < 0) | |
{ | |
#ifdef _LIBC | |
__wmemmove (fp->_wide_data->_IO_save_base + avail, | |
fp->_wide_data->_IO_save_end + least_mark, | |
-least_mark); | |
__wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark, | |
fp->_wide_data->_IO_read_base, | |
end_p - fp->_wide_data->_IO_read_base); | |
#else | |
memmove (fp->_wide_data->_IO_save_base + avail, | |
fp->_wide_data->_IO_save_end + least_mark, | |
-least_mark * sizeof (wchar_t)); | |
memcpy (fp->_wide_data->_IO_save_base + avail - least_mark, | |
fp->_wide_data->_IO_read_base, | |
(end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t)); | |
#endif | |
} | |
else if (needed_size > 0) | |
#ifdef _LIBC | |
__wmemcpy (fp->_wide_data->_IO_save_base + avail, | |
fp->_wide_data->_IO_read_base + least_mark, | |
needed_size); | |
#else | |
memcpy (fp->_wide_data->_IO_save_base + avail, | |
fp->_wide_data->_IO_read_base + least_mark, | |
needed_size * sizeof (wchar_t)); | |
#endif | |
} | |
fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail; | |
/* Adjust all the streammarkers. */ | |
delta = end_p - fp->_wide_data->_IO_read_base; | |
for (mark = fp->_markers; mark != NULL; mark = mark->_next) | |
mark->_pos -= delta; | |
return 0; | |
} | |
wint_t | |
_IO_sputbackwc (_IO_FILE *fp, wint_t c) | |
{ | |
wint_t result; | |
if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base | |
&& (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c) | |
{ | |
fp->_wide_data->_IO_read_ptr--; | |
result = c; | |
} | |
else | |
result = _IO_PBACKFAIL (fp, c); | |
if (result != WEOF) | |
fp->_flags &= ~_IO_EOF_SEEN; | |
return result; | |
} | |
libc_hidden_def (_IO_sputbackwc) | |
wint_t | |
_IO_sungetwc (_IO_FILE *fp) | |
{ | |
wint_t result; | |
if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base) | |
{ | |
fp->_wide_data->_IO_read_ptr--; | |
result = *fp->_wide_data->_IO_read_ptr; | |
} | |
else | |
result = _IO_PBACKFAIL (fp, EOF); | |
if (result != WEOF) | |
fp->_flags &= ~_IO_EOF_SEEN; | |
return result; | |
} | |
unsigned | |
_IO_adjust_wcolumn (unsigned start, const wchar_t *line, int count) | |
{ | |
const wchar_t *ptr = line + count; | |
while (ptr > line) | |
if (*--ptr == L'\n') | |
return line + count - ptr - 1; | |
return start + count; | |
} | |
void | |
_IO_init_wmarker (struct _IO_marker *marker, _IO_FILE *fp) | |
{ | |
marker->_sbuf = fp; | |
if (_IO_in_put_mode (fp)) | |
_IO_switch_to_wget_mode (fp); | |
if (_IO_in_backup (fp)) | |
marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end; | |
else | |
marker->_pos = (fp->_wide_data->_IO_read_ptr | |
- fp->_wide_data->_IO_read_base); | |
/* Should perhaps sort the chain? */ | |
marker->_next = fp->_markers; | |
fp->_markers = marker; | |
} | |
#define BAD_DELTA EOF | |
/* Return difference between MARK and current position of MARK's stream. */ | |
int | |
_IO_wmarker_delta (struct _IO_marker *mark) | |
{ | |
int cur_pos; | |
if (mark->_sbuf == NULL) | |
return BAD_DELTA; | |
if (_IO_in_backup (mark->_sbuf)) | |
cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr | |
- mark->_sbuf->_wide_data->_IO_read_end); | |
else | |
cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr | |
- mark->_sbuf->_wide_data->_IO_read_base); | |
return mark->_pos - cur_pos; | |
} | |
int | |
_IO_seekwmark (_IO_FILE *fp, struct _IO_marker *mark, int delta) | |
{ | |
if (mark->_sbuf != fp) | |
return EOF; | |
if (mark->_pos >= 0) | |
{ | |
if (_IO_in_backup (fp)) | |
_IO_switch_to_main_wget_area (fp); | |
fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base | |
+ mark->_pos); | |
} | |
else | |
{ | |
if (!_IO_in_backup (fp)) | |
_IO_switch_to_wbackup_area (fp); | |
fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos; | |
} | |
return 0; | |
} | |
void | |
_IO_unsave_wmarkers (_IO_FILE *fp) | |
{ | |
struct _IO_marker *mark = fp->_markers; | |
if (mark) | |
{ | |
#ifdef TODO | |
streampos offset = seekoff (0, ios::cur, ios::in); | |
if (offset != EOF) | |
{ | |
offset += eGptr () - Gbase (); | |
for ( ; mark != NULL; mark = mark->_next) | |
mark->set_streampos (mark->_pos + offset); | |
} | |
else | |
{ | |
for ( ; mark != NULL; mark = mark->_next) | |
mark->set_streampos (EOF); | |
} | |
#endif | |
fp->_markers = 0; | |
} | |
if (_IO_have_backup (fp)) | |
_IO_free_wbackup_area (fp); | |
} |