win: add uv__convert_utf8_to_utf16()

This is an internal helper function for converting UTF-8 strings
to UTF-16 strings. It performs the inverse operation of the
existing uv__convert_utf16_to_utf8() function.

Fixes: https://github.com/libuv/libuv/issues/1198
PR-URL: https://github.com/libuv/libuv/pull/1234
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
cjihrig 2017-03-01 15:56:36 -05:00
parent ee02f60c90
commit 53995a3825
2 changed files with 61 additions and 87 deletions

View File

@ -331,6 +331,7 @@ int uv_current_pid();
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
/*

View File

@ -1325,6 +1325,47 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
}
/*
* Converts a UTF-8 string into a UTF-16 one. The resulting string is
* null-terminated.
*
* If utf8 is null terminated, utf8len can be set to -1, otherwise it must
* be specified.
*/
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
int bufsize;
if (utf8 == NULL)
return UV_EINVAL;
/* Check how much space we need */
bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
/* Allocate the destination buffer adding an extra byte for the terminating
* NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so
* we do it ourselves always, just in case. */
*utf16 = uv__malloc(sizeof(WCHAR) * (bufsize + 1));
if (*utf16 == NULL)
return UV_ENOMEM;
/* Convert to UTF-16 */
bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
if (bufsize == 0) {
uv__free(*utf16);
*utf16 = NULL;
return uv_translate_sys_error(GetLastError());
}
(*utf16)[bufsize] = '\0';
return 0;
}
int uv__getpwuid_r(uv_passwd_t* pwd) {
HANDLE token;
wchar_t username[UNLEN + 1];
@ -1402,24 +1443,10 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
if (name == NULL || buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
/* Determine the size of the wide character name */
bufsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
r = uv__convert_utf8_to_utf16(name, -1, &name_w);
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
/* Convert the environment variable name to a wide character string */
name_w = uv__malloc(sizeof(wchar_t) * bufsize);
if (name_w == NULL)
return UV_ENOMEM;
bufsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, name_w, bufsize);
if (bufsize == 0) {
uv__free(name_w);
return uv_translate_sys_error(GetLastError());
}
if (r != 0)
return r;
len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);
uv__free(name_w);
@ -1465,99 +1492,45 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
int uv_os_setenv(const char* name, const char* value) {
wchar_t* name_w;
wchar_t* value_w;
DWORD bufsize;
int r;
if (name == NULL || value == NULL)
return UV_EINVAL;
name_w = NULL;
value_w = NULL;
r = 0;
r = uv__convert_utf8_to_utf16(name, -1, &name_w);
/* Determine the size of the wide character name */
bufsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
if (r != 0)
return r;
if (bufsize == 0) {
r = uv_translate_sys_error(GetLastError());
goto out;
r = uv__convert_utf8_to_utf16(value, -1, &value_w);
if (r != 0) {
uv__free(name_w);
return r;
}
/* Convert the environment variable name to a wide character string */
name_w = uv__malloc(sizeof(wchar_t) * bufsize);
if (name_w == NULL) {
r = UV_ENOMEM;
goto out;
}
bufsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, name_w, bufsize);
if (bufsize == 0) {
r = uv_translate_sys_error(GetLastError());
goto out;
}
/* Determine the size of the wide character value */
bufsize = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
if (bufsize == 0) {
r = uv_translate_sys_error(GetLastError());
goto out;
}
/* Convert the environment variable value to a wide character string */
value_w = uv__malloc(sizeof(wchar_t) * bufsize);
if (value_w == NULL) {
r = UV_ENOMEM;
goto out;
}
bufsize = MultiByteToWideChar(CP_UTF8, 0, value, -1, value_w, bufsize);
if (bufsize == 0) {
r = uv_translate_sys_error(GetLastError());
goto out;
}
if (SetEnvironmentVariableW(name_w, value_w) == 0)
r = uv_translate_sys_error(GetLastError());
out:
r = SetEnvironmentVariableW(name_w, value_w);
uv__free(name_w);
uv__free(value_w);
return r;
if (r == 0)
return uv_translate_sys_error(GetLastError());
return 0;
}
int uv_os_unsetenv(const char* name) {
wchar_t* name_w;
DWORD bufsize;
int r;
if (name == NULL)
return UV_EINVAL;
/* Determine the size of the wide character name */
bufsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
r = uv__convert_utf8_to_utf16(name, -1, &name_w);
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
/* Convert the environment variable name to a wide character string */
name_w = uv__malloc(sizeof(wchar_t) * bufsize);
if (name_w == NULL)
return UV_ENOMEM;
bufsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, name_w, bufsize);
if (bufsize == 0) {
uv__free(name_w);
return uv_translate_sys_error(GetLastError());
}
if (r != 0)
return r;
r = SetEnvironmentVariableW(name_w, NULL);
uv__free(name_w);