aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/mbyte.c
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-08-15 09:32:18 +0200
committerGitHub <noreply@github.com>2019-08-15 09:32:18 +0200
commit6261d2658fdff93a732b02d8fd6e386245968f2d (patch)
tree3dd5de174ff4b0b555a49cff30937a2304b71857 /src/nvim/mbyte.c
parenteb9f3308bc329c212009820817d35c6ab7a88117 (diff)
parent975be7e5dcf6a2ee59a6fc236e75b434b6ce4423 (diff)
downloadrneovim-6261d2658fdff93a732b02d8fd6e386245968f2d.tar.gz
rneovim-6261d2658fdff93a732b02d8fd6e386245968f2d.tar.bz2
rneovim-6261d2658fdff93a732b02d8fd6e386245968f2d.zip
Merge #10761 from justinmk/win-utf-libuv-align
utf8_to_utf16, utf16_to_utf8: align with libuv
Diffstat (limited to 'src/nvim/mbyte.c')
-rw-r--r--src/nvim/mbyte.c129
1 files changed, 66 insertions, 63 deletions
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index fae7635d34..29b8dc0ef2 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -1356,83 +1356,86 @@ 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();
- }
-
- ssize_t buf_sz = wchar_len * sizeof(wchar_t);
-
- if (buf_sz == 0) {
- *strw = NULL;
- return 0;
+ // 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());
}
- char *buf = xmalloc(buf_sz);
- char *pos = buf;
+ // 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));
- 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);
+ // Convert to UTF-16.
+ bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
+ if (bufsize == 0) {
+ XFREE_CLEAR(*utf16);
+ return uv_translate_sys_error(GetLastError());
}
- *strw = (wchar_t *)pos;
+ (*utf16)[bufsize] = L'\0';
return 0;
}
-/// Reassigns `str` to a new, allocated pointer to a UTF8 string.
-int utf16_to_utf8(const wchar_t *strw, char **str)
+/// Converts string from UTF-16 to UTF-8.
+///
+/// @param utf16 UTF-16 string.
+/// @param utf16len Length of `utf16`. May be -1 if `utf16` is NUL-terminated.
+/// @param utf8[out,allocated] NUL-terminated UTF-8 string, or NULL on error
+/// @return 0 on success, or libuv error code
+int utf16_to_utf8(const wchar_t *utf16, int utf16len, char **utf8)
FUNC_ATTR_NONNULL_ALL
{
- *str = NULL;
- // Compute the space required to store the string as UTF-8.
- DWORD utf8_len = WideCharToMultiByte(CP_UTF8,
- 0,
- strw,
- -1,
- NULL,
- 0,
- NULL,
- NULL);
- if (utf8_len == 0) {
- return GetLastError();
- }
-
- *str = xmallocz(utf8_len);
+ // Compute the space needed for the converted UTF-8 string.
+ DWORD bufsize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ utf16,
+ utf16len,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (bufsize == 0) {
+ *utf8 = NULL;
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ // Allocate the destination buffer adding an extra byte for the terminating
+ // NULL. If `utf16len` is not -1 WideCharToMultiByte will not add it, so
+ // we do it ourselves always, just in case.
+ *utf8 = xmalloc(bufsize + 1);
// Convert to UTF-8.
- utf8_len = WideCharToMultiByte(CP_UTF8,
- 0,
- strw,
- -1,
- *str,
- utf8_len,
- NULL,
- NULL);
- if (utf8_len == 0) {
- XFREE_CLEAR(*str);
- return GetLastError();
- }
- (*str)[utf8_len] = '\0';
-
+ bufsize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ utf16,
+ utf16len,
+ *utf8,
+ bufsize,
+ NULL,
+ NULL);
+ if (bufsize == 0) {
+ XFREE_CLEAR(*utf8);
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ (*utf8)[bufsize] = '\0';
return 0;
}