| #include <uchar.h> |
| #include <errno.h> |
| #include <wchar.h> |
| |
| size_t c16rtomb(char* restrict s, char16_t c16, mbstate_t* restrict ps) { |
| static unsigned internal_state; |
| if (!ps) |
| ps = (void*)&internal_state; |
| unsigned* x = (unsigned*)ps; |
| wchar_t wc; |
| |
| if (!s) { |
| if (*x) |
| goto ilseq; |
| return 1; |
| } |
| |
| if (!*x && c16 - 0xd800u < 0x400) { |
| *x = (c16 - 0xd7c0) << 10; |
| return 0; |
| } |
| |
| if (*x) { |
| if (c16 - 0xdc00u >= 0x400) |
| goto ilseq; |
| else |
| wc = *x + c16 - 0xdc00; |
| *x = 0; |
| } else { |
| wc = c16; |
| } |
| return wcrtomb(s, wc, 0); |
| |
| ilseq: |
| *x = 0; |
| errno = EILSEQ; |
| return -1; |
| } |