]> git.proxmox.com Git - libgit2.git/blob - src/win32/utf-conv.c
Merge pull request #2188 from libgit2/cmn/config-snapshot
[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 #ifndef WC_ERR_INVALID_CHARS
12 # define WC_ERR_INVALID_CHARS 0x80
13 #endif
14
15 GIT_INLINE(DWORD) get_wc_flags(void)
16 {
17 static char inited = 0;
18 static DWORD flags;
19
20 /* Invalid code point check supported on Vista+ only */
21 if (!inited) {
22 flags = git_has_win32_version(6, 0, 0) ? WC_ERR_INVALID_CHARS : 0;
23 inited = 1;
24 }
25
26 return flags;
27 }
28
29 /**
30 * Converts a UTF-8 string to wide characters.
31 *
32 * @param dest The buffer to receive the wide string.
33 * @param dest_size The size of the buffer, in characters.
34 * @param src The UTF-8 string to convert.
35 * @return The length of the wide string, in characters (not counting the NULL terminator), or < 0 for failure
36 */
37 int git__utf8_to_16(wchar_t *dest, size_t dest_size, const char *src)
38 {
39 /* Length of -1 indicates NULL termination of the input string. Subtract 1 from the result to
40 * turn 0 into -1 (an error code) and to not count the NULL terminator as part of the string's
41 * length. MultiByteToWideChar never returns int's minvalue, so underflow is not possible */
42 return MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, dest, (int)dest_size) - 1;
43 }
44
45 /**
46 * Converts a wide string to UTF-8.
47 *
48 * @param dest The buffer to receive the UTF-8 string.
49 * @param dest_size The size of the buffer, in bytes.
50 * @param src The wide string to convert.
51 * @return The length of the UTF-8 string, in bytes (not counting the NULL terminator), or < 0 for failure
52 */
53 int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src)
54 {
55 /* Length of -1 indicates NULL termination of the input string. Subtract 1 from the result to
56 * turn 0 into -1 (an error code) and to not count the NULL terminator as part of the string's
57 * length. WideCharToMultiByte never returns int's minvalue, so underflow is not possible */
58 return WideCharToMultiByte(CP_UTF8, get_wc_flags(), src, -1, dest, (int)dest_size, NULL, NULL) - 1;
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 return -1;
81
82 *dest = git__malloc(utf16_size * sizeof(wchar_t));
83
84 if (!*dest)
85 return -1;
86
87 utf16_size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, *dest, utf16_size);
88
89 if (!utf16_size) {
90 git__free(*dest);
91 *dest = NULL;
92 }
93
94 /* Subtract 1 from the result to turn 0 into -1 (an error code) and to not count the NULL
95 * terminator as part of the string's length. MultiByteToWideChar never returns int's minvalue,
96 * so underflow is not possible */
97 return utf16_size - 1;
98 }
99
100 /**
101 * Converts a wide string to UTF-8.
102 * Memory is allocated to hold the converted string.
103 * The caller is responsible for freeing the string with git__free.
104 *
105 * @param dest Receives a pointer to the UTF-8 string.
106 * @param src The wide string to convert.
107 * @return The length of the UTF-8 string, in bytes (not counting the NULL terminator), or < 0 for failure
108 */
109 int git__utf16_to_8_alloc(char **dest, const wchar_t *src)
110 {
111 int utf8_size;
112 DWORD dwFlags = get_wc_flags();
113
114 *dest = NULL;
115
116 /* Length of -1 indicates NULL termination of the input string */
117 utf8_size = WideCharToMultiByte(CP_UTF8, dwFlags, src, -1, NULL, 0, NULL, NULL);
118
119 if (!utf8_size)
120 return -1;
121
122 *dest = git__malloc(utf8_size);
123
124 if (!*dest)
125 return -1;
126
127 utf8_size = WideCharToMultiByte(CP_UTF8, dwFlags, src, -1, *dest, utf8_size, NULL, NULL);
128
129 if (!utf8_size) {
130 git__free(*dest);
131 *dest = NULL;
132 }
133
134 /* Subtract 1 from the result to turn 0 into -1 (an error code) and to not count the NULL
135 * terminator as part of the string's length. MultiByteToWideChar never returns int's minvalue,
136 * so underflow is not possible */
137 return utf8_size - 1;
138 }