diff options
author | tjr <tjr@FreeBSD.org> | 2004-04-06 13:14:03 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2004-04-06 13:14:03 +0000 |
commit | 4212f9711ffee179c943b9f40b788b759a1ad9e6 (patch) | |
tree | 6779dc19a3df61ca545f851748ebd5f5de3a255e /lib | |
parent | fcc4fa555ff7fcd7b9e4327aa717b090a18361b5 (diff) | |
download | FreeBSD-src-4212f9711ffee179c943b9f40b788b759a1ad9e6.zip FreeBSD-src-4212f9711ffee179c943b9f40b788b759a1ad9e6.tar.gz |
Prepare to handle state-dependent encodings. This mainly involves not
taking shortcuts when it comes to storing and passing around conversion
states.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/locale/btowc.c | 11 | ||||
-rw-r--r-- | lib/libc/locale/mblen.c | 26 | ||||
-rw-r--r-- | lib/libc/locale/mbrlen.c | 9 | ||||
-rw-r--r-- | lib/libc/locale/mbrtowc.c | 3 | ||||
-rw-r--r-- | lib/libc/locale/mbsrtowcs.c | 11 | ||||
-rw-r--r-- | lib/libc/locale/mbstowcs.c | 11 | ||||
-rw-r--r-- | lib/libc/locale/mbtowc.c | 15 | ||||
-rw-r--r-- | lib/libc/locale/wcrtomb.c | 3 | ||||
-rw-r--r-- | lib/libc/locale/wcsrtombs.c | 28 | ||||
-rw-r--r-- | lib/libc/locale/wcstombs.c | 11 | ||||
-rw-r--r-- | lib/libc/locale/wctob.c | 12 | ||||
-rw-r--r-- | lib/libc/locale/wctomb.c | 18 |
12 files changed, 87 insertions, 71 deletions
diff --git a/lib/libc/locale/btowc.c b/lib/libc/locale/btowc.c index b0b24f2..34439b8 100644 --- a/lib/libc/locale/btowc.c +++ b/lib/libc/locale/btowc.c @@ -28,28 +28,25 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> -#include <string.h> #include <wchar.h> wint_t btowc(int c) { + static const mbstate_t initial; + mbstate_t mbs = initial; char cc; wchar_t wc; if (c == EOF) return (WEOF); - cc = (char)c; /* * We expect mbrtowc() to return 0 or 1, hence the check for n > 1 * which detects error return values as well as "impossible" byte * counts. - * - * We pass NULL as the state pointer to mbrtowc() because we don't - * support state-dependent encodings and don't want to waste time - * creating a zeroed mbstate_t that will not be used. */ - if (mbrtowc(&wc, &cc, 1, NULL) > 1) + cc = (char)c; + if (mbrtowc(&wc, &cc, 1, &mbs) > 1) return (WEOF); return (wc); } diff --git a/lib/libc/locale/mblen.c b/lib/libc/locale/mblen.c index 5025115..8db5335 100644 --- a/lib/libc/locale/mblen.c +++ b/lib/libc/locale/mblen.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002, 2003 Tim J. Robbins. + * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,15 +27,29 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <errno.h> +#include <limits.h> #include <stdlib.h> +#include <wchar.h> int mblen(const char *s, size_t n) { + static const mbstate_t initial; + static mbstate_t mbs; + size_t rval; - /* - * Calling mbtowc() is only legal because we don't support - * state-dependent encodings. - */ - return (mbtowc(NULL, s, n)); + if (s == NULL) { + /* No support for state dependent encodings. */ + mbs = initial; + return (0); + } + rval = mbrtowc(NULL, s, n, &mbs); + if (rval == (size_t)-1 || rval == (size_t)-2) + return (-1); + if (rval > INT_MAX) { + errno = ERANGE; + return (-1); + } + return ((int)rval); } diff --git a/lib/libc/locale/mbrlen.c b/lib/libc/locale/mbrlen.c index a2ab65b..edad289 100644 --- a/lib/libc/locale/mbrlen.c +++ b/lib/libc/locale/mbrlen.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 @@ -30,8 +30,11 @@ __FBSDID("$FreeBSD$"); #include <wchar.h> size_t -mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps __unused) +mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps) { + static mbstate_t mbs; - return (mbrtowc(NULL, s, n, NULL)); + if (ps == NULL) + ps = &mbs; + return (mbrtowc(NULL, s, n, ps)); } diff --git a/lib/libc/locale/mbrtowc.c b/lib/libc/locale/mbrtowc.c index f3b12b4..22a9041 100644 --- a/lib/libc/locale/mbrtowc.c +++ b/lib/libc/locale/mbrtowc.c @@ -36,6 +36,9 @@ size_t mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, mbstate_t * __restrict ps) { + static mbstate_t mbs; + if (ps == NULL) + ps = &mbs; return (__mbrtowc(pwc, s, n, ps)); } diff --git a/lib/libc/locale/mbsrtowcs.c b/lib/libc/locale/mbsrtowcs.c index 3e7b3b8..8b3de2f 100644 --- a/lib/libc/locale/mbsrtowcs.c +++ b/lib/libc/locale/mbsrtowcs.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 @@ -34,8 +34,9 @@ __FBSDID("$FreeBSD$"); size_t mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, - mbstate_t * __restrict ps __unused) + mbstate_t * __restrict ps) { + static mbstate_t mbs; const char *s; size_t nchr; wchar_t wc; @@ -44,9 +45,11 @@ mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, s = *src; nchr = 0; + if (ps == NULL) + ps = &mbs; if (dst == NULL) { for (;;) { - if ((nb = (int)mbrtowc(&wc, s, MB_CUR_MAX, NULL)) < 0) + if ((nb = (int)mbrtowc(&wc, s, MB_CUR_MAX, ps)) < 0) /* Invalid sequence - mbrtowc() sets errno. */ return ((size_t)-1); else if (nb == 0) @@ -58,7 +61,7 @@ mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len, } while (len-- > 0) { - if ((nb = (int)mbrtowc(dst, s, MB_CUR_MAX, NULL)) < 0) { + if ((nb = (int)mbrtowc(dst, s, MB_CUR_MAX, ps)) < 0) { *src = s; return ((size_t)-1); } else if (nb == 0) { diff --git a/lib/libc/locale/mbstowcs.c b/lib/libc/locale/mbstowcs.c index 419c1d3..b63f1f2 100644 --- a/lib/libc/locale/mbstowcs.c +++ b/lib/libc/locale/mbstowcs.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002, 2003 Tim J. Robbins. + * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,17 +28,12 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> -#include <string.h> #include <wchar.h> size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) { + static mbstate_t mbs; - /* - * We pass NULL as the state pointer to mbsrtowcs() because we don't - * support state-dependent encodings and don't want to waste time - * creating a zeroed mbstate_t that will not be used. - */ - return (mbsrtowcs(pwcs, &s, n, NULL)); + return (mbsrtowcs(pwcs, &s, n, &mbs)); } diff --git a/lib/libc/locale/mbtowc.c b/lib/libc/locale/mbtowc.c index cc88566..465f45a 100644 --- a/lib/libc/locale/mbtowc.c +++ b/lib/libc/locale/mbtowc.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002, 2003 Tim J. Robbins. + * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,17 +36,16 @@ __FBSDID("$FreeBSD$"); int mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n) { + static const mbstate_t initial; + static mbstate_t mbs; size_t rval; - if (s == NULL) + if (s == NULL) { /* No support for state dependent encodings. */ + mbs = initial; return (0); - /* - * We pass NULL as the state pointer to mbrtowc() because we don't - * support state-dependent encodings and don't want to waste time - * creating a zeroed mbstate_t that will not be used. - */ - rval = mbrtowc(pwc, s, n, NULL); + } + rval = mbrtowc(pwc, s, n, &mbs); if (rval == (size_t)-1 || rval == (size_t)-2) return (-1); if (rval > INT_MAX) { diff --git a/lib/libc/locale/wcrtomb.c b/lib/libc/locale/wcrtomb.c index 722e5c1..5f79949 100644 --- a/lib/libc/locale/wcrtomb.c +++ b/lib/libc/locale/wcrtomb.c @@ -34,6 +34,9 @@ extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); size_t wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) { + static mbstate_t mbs; + if (ps == NULL) + ps = &mbs; return (__wcrtomb(s, wc, ps)); } diff --git a/lib/libc/locale/wcsrtombs.c b/lib/libc/locale/wcsrtombs.c index ea3354b..4fa5ff8 100644 --- a/lib/libc/locale/wcsrtombs.c +++ b/lib/libc/locale/wcsrtombs.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 @@ -27,7 +27,6 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <errno.h> #include <limits.h> #include <stdlib.h> #include <string.h> @@ -35,8 +34,10 @@ __FBSDID("$FreeBSD$"); size_t wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, - mbstate_t * __restrict ps __unused) + mbstate_t * __restrict ps) { + static mbstate_t mbs; + mbstate_t mbsbak; char buf[MB_LEN_MAX]; const wchar_t *s; size_t nbytes; @@ -45,9 +46,11 @@ wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, s = *src; nbytes = 0; + if (ps == NULL) + ps = &mbs; if (dst == NULL) { for (;;) { - if ((nb = (int)wcrtomb(buf, *s, NULL)) < 0) + if ((nb = (int)wcrtomb(buf, *s, ps)) < 0) /* Invalid character - wcrtomb() sets errno. */ return ((size_t)-1); else if (*s == L'\0') @@ -61,19 +64,28 @@ wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len, while (len > 0) { if (len > (size_t)MB_CUR_MAX) { /* Enough space to translate in-place. */ - if ((nb = (int)wcrtomb(dst, *s, NULL)) < 0) { + if ((nb = (int)wcrtomb(dst, *s, ps)) < 0) { *src = s; return ((size_t)-1); } } else { - /* May not be enough space; use temp. buffer. */ - if ((nb = (int)wcrtomb(buf, *s, NULL)) < 0) { + /* + * May not be enough space; use temp. buffer. + * + * We need to save a copy of the conversion state + * here so we can restore it if the multibyte + * character is too long for the buffer. + */ + mbsbak = *ps; + if ((nb = (int)wcrtomb(buf, *s, ps)) < 0) { *src = s; return ((size_t)-1); } - if (nb > (int)len) + if (nb > (int)len) { /* MB sequence for character won't fit. */ + *ps = mbsbak; break; + } memcpy(dst, buf, nb); } if (*s == L'\0') { diff --git a/lib/libc/locale/wcstombs.c b/lib/libc/locale/wcstombs.c index f415aed..cc5fab4 100644 --- a/lib/libc/locale/wcstombs.c +++ b/lib/libc/locale/wcstombs.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002, 2003 Tim J. Robbins. + * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,17 +28,12 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> -#include <string.h> #include <wchar.h> size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) { + static mbstate_t mbs; - /* - * We pass NULL as the state pointer to wcsrtombs() because we don't - * support state-dependent encodings and don't want to waste time - * creating a zeroed mbstate_t that will not be used. - */ - return (wcsrtombs(s, &pwcs, n, NULL)); + return (wcsrtombs(s, &pwcs, n, &mbs)); } diff --git a/lib/libc/locale/wctob.c b/lib/libc/locale/wctob.c index da7afcf..4f4d295 100644 --- a/lib/libc/locale/wctob.c +++ b/lib/libc/locale/wctob.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002, 2003 Tim J. Robbins. + * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,20 +29,16 @@ __FBSDID("$FreeBSD$"); #include <limits.h> #include <stdio.h> -#include <string.h> #include <wchar.h> int wctob(wint_t c) { + static const mbstate_t initial; + mbstate_t mbs = initial; char buf[MB_LEN_MAX]; - /* - * We pass NULL as the state pointer to wcrtomb() because we don't - * support state-dependent encodings and don't want to waste time - * creating a zeroed mbstate_t that will not be used. - */ - if (c == WEOF || wcrtomb(buf, c, NULL) != 1) + if (c == WEOF || wcrtomb(buf, c, &mbs) != 1) return (EOF); return ((unsigned char)*buf); } diff --git a/lib/libc/locale/wctomb.c b/lib/libc/locale/wctomb.c index e212b96..9e6f183 100644 --- a/lib/libc/locale/wctomb.c +++ b/lib/libc/locale/wctomb.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002, 2003 Tim J. Robbins. + * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,20 +36,16 @@ __FBSDID("$FreeBSD$"); int wctomb(char *s, wchar_t wchar) { - char buf[MB_LEN_MAX]; + static const mbstate_t initial; + static mbstate_t mbs; size_t rval; - if (s == NULL) + if (s == NULL) { /* No support for state dependent encodings. */ + mbs = initial; return (0); - if (s == NULL) - s = buf; - /* - * We pass NULL as the state pointer to wcrtomb() because we don't - * support state-dependent encodings and don't want to waste time - * creating a zeroed mbstate_t that will not be used. - */ - if ((rval = wcrtomb(s, wchar, NULL)) == (size_t)-1) + } + if ((rval = wcrtomb(s, wchar, &mbs)) == (size_t)-1) return (-1); if (rval > INT_MAX) { errno = ERANGE; |