/* * Copyright (C) the libgit2 contributors. All rights reserved. * * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ #include "utf-conv.h" GIT_INLINE(void) git__set_errno(void) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) errno = ENAMETOOLONG; else errno = EINVAL; } int git_utf8_to_16(wchar_t *dest, size_t dest_size, const char *src) { /* Length of -1 indicates NULL termination of the input string. */ return git_utf8_to_16_with_len(dest, dest_size, src, -1); } int git_utf8_to_16_with_len( wchar_t *dest, size_t _dest_size, const char *src, int src_len) { int dest_size = (int)min(_dest_size, INT_MAX); int len; /* * Subtract 1 from the result to turn 0 into -1 (an error code) and * to not count the NULL terminator as part of the string's length. * MultiByteToWideChar never returns int's minvalue, so underflow * is not possible. */ len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, src_len, dest, dest_size) - 1; if (len < 0) git__set_errno(); return len; } int git_utf8_from_16(char *dest, size_t dest_size, const wchar_t *src) { /* Length of -1 indicates NULL termination of the input string. */ return git_utf8_from_16_with_len(dest, dest_size, src, -1); } int git_utf8_from_16_with_len( char *dest, size_t _dest_size, const wchar_t *src, int src_len) { int dest_size = (int)min(_dest_size, INT_MAX); int len; /* * Subtract 1 from the result to turn 0 into -1 (an error code) and * to not count the NULL terminator as part of the string's length. * WideCharToMultiByte never returns int's minvalue, so underflow * is not possible. */ len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, src_len, dest, dest_size, NULL, NULL) - 1; if (len < 0) git__set_errno(); return len; } int git_utf8_to_16_alloc(wchar_t **dest, const char *src) { /* Length of -1 indicates NULL termination of the input string. */ return git_utf8_to_16_alloc_with_len(dest, src, -1); } int git_utf8_to_16_alloc_with_len(wchar_t **dest, const char *src, int src_len) { int utf16_size; *dest = NULL; utf16_size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, src_len, NULL, 0); if (!utf16_size) { git__set_errno(); return -1; } *dest = git__mallocarray(utf16_size, sizeof(wchar_t)); GIT_ERROR_CHECK_ALLOC(*dest); utf16_size = git_utf8_to_16_with_len(*dest, (size_t)utf16_size, src, src_len); if (utf16_size < 0) { git__free(*dest); *dest = NULL; } return utf16_size; } int git_utf8_from_16_alloc(char **dest, const wchar_t *src) { /* Length of -1 indicates NULL termination of the input string. */ return git_utf8_from_16_alloc_with_len(dest, src, -1); } int git_utf8_from_16_alloc_with_len(char **dest, const wchar_t *src, int src_len) { int utf8_size; *dest = NULL; utf8_size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, src_len, NULL, 0, NULL, NULL); if (!utf8_size) { git__set_errno(); return -1; } *dest = git__malloc(utf8_size); GIT_ERROR_CHECK_ALLOC(*dest); utf8_size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, src_len, *dest, utf8_size, NULL, NULL); if (utf8_size < 0) { git__free(*dest); *dest = NULL; } return utf8_size; }