2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2012 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Alexandr Kuznetsov, Andrea Weikert
23 * ***** END GPL LICENSE BLOCK *****
28 size_t count_utf_8_from_16(const wchar_t *string16)
37 for (i = 0; (u = string16[i]); i++) {
52 if ((u = string16[i]) == 0) {
55 if (u >= 0xDC00 && u < 0xE000) {
76 size_t count_utf_16_from_8(const char *string8)
83 if (!string8) return 0;
85 for (; (u = *string8); string8++) {
87 if ((u & 0x01 << 7) == 0) { count++; u32 = 0; continue; } //1 utf-8 char
88 if ((u & 0x07 << 5) == 0xC0) { type = 1; u32 = u & 0x1F; continue; } //2 utf-8 char
89 if ((u & 0x0F << 4) == 0xE0) { type = 2; u32 = u & 0x0F; continue; } //3 utf-8 char
90 if ((u & 0x1F << 3) == 0xF0) { type = 3; u32 = u & 0x07; continue; } //4 utf-8 char
94 if ((u & 0xC0) == 0x80) {
95 u32 = (u32 << 6) | (u & 0x3F);
105 if ((0 < u32 && u32 < 0xD800) || (0xE000 <= u32 && u32 < 0x10000)) count++;
106 else if (0x10000 <= u32 && u32 < 0x110000) count += 2;
115 int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
117 char *out8end = out8 + size8;
120 if (!size8 || !in16 || !out8) return UTF_ERROR_NULL_IN;
123 for (; out8 < out8end && (u = *in16); in16++, out8++) {
127 else if (u < 0x0800) {
128 if (out8 + 1 >= out8end) break;
129 *out8++ = (0x3 << 6) | (0x1F & (u >> 6));
130 *out8 = (0x1 << 7) | (0x3F & (u));
132 else if (u < 0xD800 || u >= 0xE000) {
133 if (out8 + 2 >= out8end) break;
134 *out8++ = (0x7 << 5) | (0xF & (u >> 12));
135 *out8++ = (0x1 << 7) | (0x3F & (u >> 6));;
136 *out8 = (0x1 << 7) | (0x3F & (u));
138 else if (u < 0xDC00) {
139 wchar_t u2 = *++in16;
142 if (u2 >= 0xDC00 && u2 < 0xE000) {
143 if (out8 + 3 >= out8end) break; else {
144 unsigned int uc = 0x10000 + (u2 - 0xDC00) + ((u - 0xD800) << 10);
146 *out8++ = (0xF << 4) | (0x7 & (uc >> 18));
147 *out8++ = (0x1 << 7) | (0x3F & (uc >> 12));
148 *out8++ = (0x1 << 7) | (0x3F & (uc >> 6));
149 *out8 = (0x1 << 7) | (0x3F & (uc));
153 out8--; err |= UTF_ERROR_ILLCHAR;
156 else if (u < 0xE000) {
157 out8--; err |= UTF_ERROR_ILLCHAR;
161 *out8 = *out8end = 0;
163 if (*in16) err |= UTF_ERROR_SMALL;
169 int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)
174 wchar_t *out16end = out16 + size16;
176 if (!size16 || !in8 || !out16) return UTF_ERROR_NULL_IN;
179 for (; out16 < out16end && (u = *in8); in8++) {
181 if ((u & 0x01 << 7) == 0) { *out16 = u; out16++; u32 = 0; continue; } //1 utf-8 char
182 if ((u & 0x07 << 5) == 0xC0) { type = 1; u32 = u & 0x1F; continue; } //2 utf-8 char
183 if ((u & 0x0F << 4) == 0xE0) { type = 2; u32 = u & 0x0F; continue; } //3 utf-8 char
184 if ((u & 0x1F << 3) == 0xF0) { type = 3; u32 = u & 0x07; continue; } //4 utf-8 char
185 err |= UTF_ERROR_ILLCHAR;
189 if ((u & 0xC0) == 0x80) {
190 u32 = (u32 << 6) | (u & 0x3F);
194 u32 = 0; type = 0; err |= UTF_ERROR_ILLSEQ;
198 if ((0 < u32 && u32 < 0xD800) || (0xE000 <= u32 && u32 < 0x10000)) {
202 else if (0x10000 <= u32 && u32 < 0x110000) {
203 if (out16 + 1 >= out16end) break;
205 *out16 = 0xD800 + (u32 >> 10);
207 *out16 = 0xDC00 + (u32 & 0x3FF);
215 *out16 = *out16end = 0;
217 if (*in8) err |= UTF_ERROR_SMALL;
222 int is_ascii(const char *in8)
225 if (0x80 & *in8) return 0;
230 void utf_8_cut_end(char *inout8, size_t maxcutpoint)
232 char *cur = inout8 + maxcutpoint;
241 char *alloc_utf_8_from_16(const wchar_t *in16, size_t add)
243 size_t bsize = count_utf_8_from_16(in16);
245 if (!bsize) return NULL;
246 out8 = (char *)malloc(sizeof(char) * (bsize + add));
247 conv_utf_16_to_8(in16, out8, bsize);
251 wchar_t *alloc_utf16_from_8(const char *in8, size_t add)
253 size_t bsize = count_utf_16_from_8(in8);
254 wchar_t *out16 = NULL;
255 if (!bsize) return NULL;
256 out16 = (wchar_t *) malloc(sizeof(wchar_t) * (bsize + add));
257 conv_utf_8_to_16(in8, out16, bsize);