]> git.proxmox.com Git - libgit2.git/blob - src/win32/utf-conv.c
Merge pull request #3597 from ethomson/filter_registration
[libgit2.git] / src / win32 / utf-conv.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "common.h"
9 #include "utf-conv.h"
10
11 GIT_INLINE(void) git__set_errno(void)
12 {
13 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
14 errno = ENAMETOOLONG;
15 else
16 errno = EINVAL;
17 }
18
19 /**
20 * Converts a UTF-8 string to wide characters.
21 *
22 * @param dest The buffer to receive the wide string.
23 * @param dest_size The size of the buffer, in characters.
24 * @param src The UTF-8 string to convert.
25 * @return The length of the wide string, in characters (not counting the NULL terminator), or < 0 for failure
26 */
27 int git__utf8_to_16(wchar_t *dest, size_t dest_size, const char *src)
28 {
29 int len;
30
31 /* Length of -1 indicates NULL termination of the input string. Subtract 1 from the result to
32 * turn 0 into -1 (an error code) and to not count the NULL terminator as part of the string's
33 * length. MultiByteToWideChar never returns int's minvalue, so underflow is not possible */
34 if ((len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, dest, (int)dest_size) - 1) < 0)
35 git__set_errno();
36
37 return len;
38 }
39
40 /**
41 * Converts a wide string to UTF-8.
42 *
43 * @param dest The buffer to receive the UTF-8 string.
44 * @param dest_size The size of the buffer, in bytes.
45 * @param src The wide string to convert.
46 * @return The length of the UTF-8 string, in bytes (not counting the NULL terminator), or < 0 for failure
47 */
48 int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src)
49 {
50 int len;
51
52 /* Length of -1 indicates NULL termination of the input string. Subtract 1 from the result to
53 * turn 0 into -1 (an error code) and to not count the NULL terminator as part of the string's
54 * length. WideCharToMultiByte never returns int's minvalue, so underflow is not possible */
55 if ((len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, dest, (int)dest_size, NULL, NULL) - 1) < 0)
56 git__set_errno();
57
58 return len;
59 }
60
61 /**
62 * Converts a UTF-8 string to wide characters.
63 * Memory is allocated to hold the converted string.
64 * The caller is responsible for freeing the string with git__free.
65 *
66 * @param dest Receives a pointer to the wide string.
67 * @param src The UTF-8 string to convert.
68 * @return The length of the wide string, in characters (not counting the NULL terminator), or < 0 for failure
69 */
70 int git__utf8_to_16_alloc(wchar_t **dest, const char *src)
71 {
72 int utf16_size;
73
74 *dest = NULL;
75
76 /* Length of -1 indicates NULL termination of the input string */
77 utf16_size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, NULL, 0);
78
79 if (!utf16_size) {
80 git__set_errno();
81 return -1;
82 }
83
84 if (!(*dest = git__mallocarray(utf16_size, sizeof(wchar_t)))) {
85 errno = ENOMEM;
86 return -1;
87 }
88
89 utf16_size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, *dest, utf16_size);
90
91 if (!utf16_size) {
92 git__set_errno();
93
94 git__free(*dest);
95 *dest = NULL;
96 }
97
98 /* Subtract 1 from the result to turn 0 into -1 (an error code) and to not count the NULL
99 * terminator as part of the string's length. MultiByteToWideChar never returns int's minvalue,
100 * so underflow is not possible */
101 return utf16_size - 1;
102 }
103
104 /**
105 * Converts a wide string to UTF-8.
106 * Memory is allocated to hold the converted string.
107 * The caller is responsible for freeing the string with git__free.
108 *
109 * @param dest Receives a pointer to the UTF-8 string.
110 * @param src The wide string to convert.
111 * @return The length of the UTF-8 string, in bytes (not counting the NULL terminator), or < 0 for failure
112 */
113 int git__utf16_to_8_alloc(char **dest, const wchar_t *src)
114 {
115 int utf8_size;
116
117 *dest = NULL;
118
119 /* Length of -1 indicates NULL termination of the input string */
120 utf8_size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, NULL, 0, NULL, NULL);
121
122 if (!utf8_size) {
123 git__set_errno();
124 return -1;
125 }
126
127 *dest = git__malloc(utf8_size);
128
129 if (!*dest) {
130 errno = ENOMEM;
131 return -1;
132 }
133
134 utf8_size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, *dest, utf8_size, NULL, NULL);
135
136 if (!utf8_size) {
137 git__set_errno();
138
139 git__free(*dest);
140 *dest = NULL;
141 }
142
143 /* Subtract 1 from the result to turn 0 into -1 (an error code) and to not count the NULL
144 * terminator as part of the string's length. MultiByteToWideChar never returns int's minvalue,
145 * so underflow is not possible */
146 return utf8_size - 1;
147 }