crt: new implementation for btowc and wctob Replacementes for C95 functions btowc and wctob now use mbrtowc and wcrtomb respectively to perform conversion. This ensures that their behavior is consistent with mbrtowc and wcrtomb functions. Signed-off-by: Kirill Makurin <maiddaisuki@outlook.com>
diff --git a/mingw-w64-crt/misc/btowc.c b/mingw-w64-crt/misc/btowc.c index c8fbd8e..caf2d95 100644 --- a/mingw-w64-crt/misc/btowc.c +++ b/mingw-w64-crt/misc/btowc.c
@@ -7,6 +7,7 @@ #define WIN32_LEAN_AND_MEAN #endif #include "mb_wc_common.h" +#include <limits.h> #include <wchar.h> #include <stdio.h> #include <windows.h> @@ -15,14 +16,16 @@ { if (c == EOF) return (WEOF); - else - { - unsigned char ch = c; - wchar_t wc = WEOF; - if (!MultiByteToWideChar (___lc_codepage_func(), MB_ERR_INVALID_CHARS, - (char*)&ch, 1, &wc, 1)) - return WEOF; - return wc; - } + /* Use dummy string so that mbrtowc will never return (size_t)-2 */ + char str[MB_LEN_MAX] = {(unsigned char) c, 0, 0, 0, 0}; + + wint_t wc = WEOF; + mbstate_t state = {0}; + + if (mbrtowc (&wc, (char *) str, MB_CUR_MAX, &state) == (size_t) -1) { + return WEOF; + } + + return wc; }
diff --git a/mingw-w64-crt/misc/wctob.c b/mingw-w64-crt/misc/wctob.c index 995f6db..2fe6661 100644 --- a/mingw-w64-crt/misc/wctob.c +++ b/mingw-w64-crt/misc/wctob.c
@@ -7,23 +7,28 @@ #define WIN32_LEAN_AND_MEAN #endif #include "mb_wc_common.h" +#include <limits.h> #include <wchar.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <windows.h> -/* Return just the first byte after translating to multibyte. */ -int wctob (wint_t wc ) +int wctob (wint_t wc) { - wchar_t w = wc; - char c; - int invalid_char = 0; - if (!WideCharToMultiByte (___lc_codepage_func(), - 0 /* Is this correct flag? */, - &w, 1, &c, 1, NULL, &invalid_char) - || invalid_char) - return EOF; + /* Return early */ + if (IS_LOW_SURROGATE (wc) || IS_HIGH_SURROGATE (wc) || wc == WEOF) { + return EOF; + } - return (unsigned char) c; + mbstate_t state = {0}; + /* Buffer large enough to hold any multibyte character */ + char mbc[MB_LEN_MAX]; + + size_t length = wcrtomb (mbc, wc, &state); + if (length > 1) { + return EOF; + } + + return (unsigned char) mbc[0]; }