blob: 2eb4abaedd96081a63b90d9169bd27bb99a91bab [file] [log] [blame]
/**
* 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.
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "mingw-wchar.h"
/**
* __mingw_wcrtomb_cp is internal implementation for C95 functions wcrtomb and
* wcsrtombs.
*
* In order to perform conversion we need the following information:
*
* - code page used by active locale (which can be a thread locale for
* msvcr80.dll and later); obtained by calling ___lc_codepage_func
*
* - maximum character length in used code page; obtained by calling
* ___mb_cur_max_func
*
* crtdll.dll's ___lc_codepage_func is quite expensive as it obtains this
* information by parsing return value of setlocale(LC_CTYPE, NULL). Using
* __mingw_wcrtomb_cp allows wcsrtombs call both ___lc_codepage_func and
* ___mb_cur_max_func only once.
*/
size_t __mingw_wcrtomb_cp (
char *__restrict__ mbc,
wchar_t wc,
mbstate_t *__restrict__ state,
unsigned cp,
int mb_cur_max
) {
/* Set `state` to initial state */
if (mbc == NULL) {
if (state != NULL) {
*state = 0;
}
return 1;
}
/* Detect invalid conversion state */
if (state != NULL && *state) {
errno = EINVAL;
return (size_t) -1;
}
/* Store terminating L'\0' */
if (wc == L'\0') {
if (mbc != NULL) {
mbc[0] = '\0';
}
return 1;
}
/* 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:
errno = EILSEQ;
return (size_t) -1;
}