utf8_to_utf16: align with libuv

- take a size parameter
- always NUL-terminate the result
- return libuv error code
- handle error in caller only (avoid redundant messages)

53995a3825
4c945f4936
This commit is contained in:
Justin M. Keyes
2019-08-13 05:47:58 +02:00
parent fc60d92795
commit 8727f7a6a4
4 changed files with 47 additions and 51 deletions

View File

@@ -1356,45 +1356,41 @@ static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1,
# define CP_UTF8 65001 /* magic number from winnls.h */
#endif
/// Reassigns `strw` to a new, allocated pointer to a UTF16 string.
int utf8_to_utf16(const char *str, wchar_t **strw)
/// Converts string from UTF-8 to UTF-16.
///
/// @param utf8 UTF-8 string.
/// @param utf8len Length of `utf8`. May be -1 if `utf8` is NUL-terminated.
/// @param utf16[out,allocated] NUL-terminated UTF-16 string, or NULL on error
/// @return 0 on success, or libuv error code
int utf8_to_utf16(const char *utf8, int utf8len, wchar_t **utf16)
FUNC_ATTR_NONNULL_ALL
{
ssize_t wchar_len = 0;
// Compute the length needed to store the converted widechar string.
wchar_len = MultiByteToWideChar(CP_UTF8,
0, // dwFlags: must be 0 for utf8
str, // lpMultiByteStr: string to convert
-1, // -1 => process up to NUL
NULL, // lpWideCharStr: converted string
0); // 0 => return length, don't convert
if (wchar_len == 0) {
return GetLastError();
// Compute the length needed for the converted UTF-16 string.
int bufsize = MultiByteToWideChar(CP_UTF8,
0, // dwFlags: must be 0 for UTF-8
utf8, // -1: process up to NUL
utf8len,
NULL,
0); // 0: get length, don't convert
if (bufsize == 0) {
*utf16 = NULL;
return uv_translate_sys_error(GetLastError());
}
ssize_t buf_sz = wchar_len * sizeof(wchar_t);
// 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 = xmalloc(sizeof(wchar_t) * (bufsize + 1));
if (buf_sz == 0) {
*strw = NULL;
return 0;
// Convert to UTF-16.
bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
if (bufsize == 0) {
xfree(*utf16);
*utf16 = NULL;
return uv_translate_sys_error(GetLastError());
}
char *buf = xmalloc(buf_sz);
char *pos = buf;
int r = MultiByteToWideChar(CP_UTF8,
0,
str,
-1,
(wchar_t *)pos,
wchar_len);
assert(r == wchar_len);
if (r != wchar_len) {
EMSG2("MultiByteToWideChar failed: %d", r);
}
*strw = (wchar_t *)pos;
(*utf16)[bufsize] = L'\0';
return 0;
}