diff options
author | das <das@FreeBSD.org> | 2012-04-29 16:28:39 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2012-04-29 16:28:39 +0000 |
commit | 99428404bed28d421872e61f367292954ab61dc2 (patch) | |
tree | 90305c02b6140f111de9eb5ca26f308a7e9ed0d9 /lib/libc/stdio/fgetwc.c | |
parent | bfedf1ea421f9d5cf143cd7304bbcc03525462db (diff) | |
download | FreeBSD-src-99428404bed28d421872e61f367292954ab61dc2.zip FreeBSD-src-99428404bed28d421872e61f367292954ab61dc2.tar.gz |
Previously, vfscanf()'s wide character processing functions were
reading wide characters manually. With this change, they now use
fgetwc(). To make this work, we use an internal version of fgetwc()
with a few extensions: it takes an mbstate * because non-wide streams
don't have a built-in mbstate, and it indicates the number of bytes
read.
vfscanf() now resembles vfwscanf() more closely. Minor functional
improvements include working xlocale support in vfscanf(), setting the
stream error indicator on encoding errors, and proper handling of
shift-based encodings. (Actually, making shift-based encodings work
with non-wide streams is hopeless, but the implementation now matches
the broken specification.)
Diffstat (limited to 'lib/libc/stdio/fgetwc.c')
-rw-r--r-- | lib/libc/stdio/fgetwc.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/lib/libc/stdio/fgetwc.c b/lib/libc/stdio/fgetwc.c index 0e87753..52bc988 100644 --- a/lib/libc/stdio/fgetwc.c +++ b/lib/libc/stdio/fgetwc.c @@ -59,6 +59,7 @@ fgetwc_l(FILE *fp, locale_t locale) return (r); } + wint_t fgetwc(FILE *fp) { @@ -66,40 +67,45 @@ fgetwc(FILE *fp) } /* - * Non-MT-safe version. + * Internal (non-MPSAFE) version of fgetwc(). This version takes an + * mbstate_t argument specifying the initial conversion state. For + * wide streams, this should always be fp->_mbstate. On return, *nread + * is set to the number of bytes read. */ -wint_t -__fgetwc(FILE *fp, locale_t locale) +wint_t +__fgetwc_mbs(FILE *fp, mbstate_t *mbs, int *nread, locale_t locale) { wchar_t wc; size_t nconv; struct xlocale_ctype *l = XLOCALE_CTYPE(locale); - if (fp->_r <= 0 && __srefill(fp)) + if (fp->_r <= 0 && __srefill(fp)) { + *nread = 0; return (WEOF); + } if (MB_CUR_MAX == 1) { /* Fast path for single-byte encodings. */ wc = *fp->_p++; fp->_r--; + *nread = 1; return (wc); } + *nread = 0; do { - nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); + nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, mbs); if (nconv == (size_t)-1) break; else if (nconv == (size_t)-2) continue; else if (nconv == 0) { - /* - * Assume that the only valid representation of - * the null wide character is a single null byte. - */ fp->_p++; fp->_r--; + (*nread)++; return (L'\0'); } else { fp->_p += nconv; fp->_r -= nconv; + *nread += nconv; return (wc); } } while (__srefill(fp) == 0); |