X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/9385eb3d10ebe5eb398c52040ec3dbfba9b0cdcf..507116e319a1470bb0a5040d4d23e5c76955ef97:/stdio/FreeBSD/fgetws.c?ds=sidebyside diff --git a/stdio/FreeBSD/fgetws.c b/stdio/FreeBSD/fgetws.c index d818f62..278e809 100644 --- a/stdio/FreeBSD/fgetws.c +++ b/stdio/FreeBSD/fgetws.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002 Tim J. Robbins. + * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,22 +25,33 @@ */ #include -__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.4 2002/09/20 13:25:40 tjr Exp $"); +__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetws.c,v 1.8 2009/11/25 04:45:45 wollman Exp $"); + +#include "xlocale_private.h" #include "namespace.h" #include #include +#include #include #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "mblocal.h" wchar_t * -fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t loc) { wchar_t *wsp; - wint_t wc; + size_t nconv; + const char *src; + unsigned char *nl; + struct __xlocale_st_runelocale *rl; + size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict, size_t, size_t, __darwin_mbstate_t * __restrict, locale_t); + NORMALIZE_LOCALE(loc); + rl = loc->__lc_ctype; + __mbsnrtowcs = rl->__mbsnrtowcs; FLOCKFILE(fp); ORIENT(fp, 1); @@ -49,22 +60,43 @@ fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) goto error; } + if (fp->_r <= 0 && __srefill(fp)) + /* EOF */ + goto error; wsp = ws; - while (n-- > 1) { - /* XXX Inefficient */ - if ((wc = __fgetwc(fp)) == WEOF && errno == EILSEQ) + do { + src = (const char *)fp->_p; + nl = memchr(fp->_p, '\n', fp->_r); + nconv = __mbsnrtowcs(wsp, &src, + nl != NULL ? (nl - fp->_p + 1) : fp->_r, + n - 1, &fp->_mbstate, loc); + if (nconv == (size_t)-1) + /* Conversion error */ goto error; - if (wc == WEOF) { - if (wsp == ws) - /* EOF/error, no characters read yet. */ - goto error; - break; + if (src == NULL) { + /* + * We hit a null byte. Increment the character count, + * since mbsnrtowcs()'s return value doesn't include + * the terminating null, then resume conversion + * after the null. + */ + nconv++; + src = memchr(fp->_p, '\0', fp->_r); + src++; } - *wsp++ = (wchar_t)wc; - if (wc == L'\n') - break; - } - *wsp++ = L'\0'; + fp->_r -= (unsigned char *)src - fp->_p; + fp->_p = (unsigned char *)src; + n -= nconv; + wsp += nconv; + } while (wsp[-1] != L'\n' && n > 1 && (fp->_r > 0 || + __srefill(fp) == 0)); + if (wsp == ws) + /* EOF */ + goto error; + if (!rl->__mbsinit(&fp->_mbstate, loc)) + /* Incomplete character */ + goto error; + *wsp = L'\0'; FUNLOCKFILE(fp); return (ws); @@ -73,3 +105,9 @@ error: FUNLOCKFILE(fp); return (NULL); } + +wchar_t * +fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +{ + return fgetws_l(ws, n, fp, __current_locale()); +}