| /** |
| * This file has no copyright assigned and is placed in the Public Domain. |
| * This file is part of the mingw-w64 runtime package. |
| * No warranty is given; refer to the file DISCLAIMER.PD within this package. |
| */ |
| #ifndef WIN32_LEAN_AND_MEAN |
| #define WIN32_LEAN_AND_MEAN |
| #endif |
| #include <locale.h> |
| #include <wchar.h> |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <limits.h> |
| #include <windows.h> |
| |
| size_t wcrtomb ( |
| char *__restrict__ mbc, |
| wchar_t wc, |
| mbstate_t *__restrict__ state |
| ) { |
| /* Set `state` to initial state */ |
| if (mbc == NULL) { |
| if (state != NULL) { |
| *state = 0; |
| } |
| return 1; |
| } |
| |
| /* Detect invalid conversion state */ |
| if (state != NULL && *state) { |
| _set_errno (EINVAL); |
| return (size_t) -1; |
| } |
| |
| /* Store terminating L'\0' */ |
| if (wc == L'\0') { |
| if (mbc != NULL) { |
| mbc[0] = '\0'; |
| } |
| return 1; |
| } |
| |
| /* Code page used by current locale */ |
| unsigned cp = ___lc_codepage_func (); |
| |
| /* Maximum character length in `cp` */ |
| int mb_cur_max = ___mb_cur_max_func (); |
| |
| /* Handle "C" locale */ |
| if (cp == 0) { |
| if (wc > 0xFF) { |
| goto eilseq; |
| } |
| if (mbc != NULL) { |
| mbc[0] = (char) wc; |
| } |
| return 1; |
| } |
| |
| BOOL defaultCharacterUsed = FALSE; |
| char buffer[2] = {0, 0}; |
| |
| /* For consistency with CRT, we do not use WC_NO_BEST_FIT_CHARS */ |
| int ret = WideCharToMultiByte ( |
| cp, 0, &wc, 1, buffer, mb_cur_max, NULL, &defaultCharacterUsed |
| ); |
| |
| if (ret == 0 || ret > mb_cur_max || defaultCharacterUsed) { |
| goto eilseq; |
| } |
| |
| memcpy (mbc, buffer, ret); |
| return ret; |
| |
| eilseq: |
| _set_errno (EILSEQ); |
| return (size_t) -1; |
| } |
| |
| size_t wcsrtombs ( |
| char *__restrict__ mbs, |
| const wchar_t **__restrict__ wcs, |
| size_t count, |
| mbstate_t *__restrict__ state |
| ) { |
| /* Buffer to store single converted character */ |
| char mbc[2]; |
| /* Total number of bytes stored in `mbs` */ |
| size_t mbcConverted = 0; |
| |
| /* Next wide character to convert */ |
| const wchar_t *wc = *wcs; |
| |
| while (1) { |
| const size_t length = wcrtomb (mbc, *wc, state); |
| |
| /* Conversion failed */ |
| if (length == (size_t) -1) { |
| if (mbs != NULL) { |
| *wcs = wc; |
| } |
| return (size_t) -1; |
| } |
| |
| /* POSIX and ISO C are silent about this */ |
| if (mbs != NULL && count == 0) { |
| return 0; |
| } |
| |
| /* Terminating '\0' has been converted, stop */ |
| if (mbc[0] == '\0') { |
| if (mbs != NULL) { |
| *mbs = '\0'; |
| *wcs = NULL; |
| } |
| break; |
| } |
| |
| /* Storing `mbc` in `mbs` would exceed `count` */ |
| if (mbs != NULL && mbcConverted + length > count) { |
| *wcs = wc; |
| break; |
| } |
| |
| /* Write `mbc` to `mbs` */ |
| if (mbs != NULL) { |
| memcpy (mbs, mbc, length); |
| mbs += length; |
| } |
| |
| mbcConverted += length; |
| wc += 1; |
| |
| /* `count` bytes have been written to `mbs`, stop */ |
| if (mbs != NULL && mbcConverted == count) { |
| *wcs = wc; |
| break; |
| } |
| } |
| |
| return mbcConverted; |
| } |