Cleanup: Fix unused variable warning in lite build
[blender.git] / intern / utfconv / utfconv.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2012 Blender Foundation.
17  * All rights reserved.
18  *
19  */
20
21 #include "utfconv.h"
22
23 size_t count_utf_8_from_16(const wchar_t *string16)
24 {
25   int i;
26   size_t count = 0;
27   wchar_t u = 0;
28   if (!string16) {
29     return 0;
30   }
31
32   for (i = 0; (u = string16[i]); i++) {
33     if (u < 0x0080) {
34       count += 1;
35     }
36     else {
37       if (u < 0x0800) {
38         count += 2;
39       }
40       else {
41         if (u < 0xD800) {
42           count += 3;
43         }
44         else {
45           if (u < 0xDC00) {
46             i++;
47             if ((u = string16[i]) == 0) {
48               break;
49             }
50             if (u >= 0xDC00 && u < 0xE000) {
51               count += 4;
52             }
53           }
54           else {
55             if (u < 0xE000) {
56               /*illigal*/;
57             }
58             else {
59               count += 3;
60             }
61           }
62         }
63       }
64     }
65   }
66
67   return ++count;
68 }
69
70 size_t count_utf_16_from_8(const char *string8)
71 {
72   size_t count = 0;
73   char u;
74   char type = 0;
75   unsigned int u32 = 0;
76
77   if (!string8) {
78     return 0;
79   }
80
81   for (; (u = *string8); string8++) {
82     if (type == 0) {
83       if ((u & 0x01 << 7) == 0) {
84         count++;
85         u32 = 0;
86         continue;
87       }  // 1 utf-8 char
88       if ((u & 0x07 << 5) == 0xC0) {
89         type = 1;
90         u32 = u & 0x1F;
91         continue;
92       }  // 2 utf-8 char
93       if ((u & 0x0F << 4) == 0xE0) {
94         type = 2;
95         u32 = u & 0x0F;
96         continue;
97       }  // 3 utf-8 char
98       if ((u & 0x1F << 3) == 0xF0) {
99         type = 3;
100         u32 = u & 0x07;
101         continue;
102       }  // 4 utf-8 char
103       continue;
104     }
105     if ((u & 0xC0) == 0x80) {
106       u32 = (u32 << 6) | (u & 0x3F);
107       type--;
108     }
109     else {
110       u32 = 0;
111       type = 0;
112     }
113
114     if (type == 0) {
115       if ((0 < u32 && u32 < 0xD800) || (0xE000 <= u32 && u32 < 0x10000)) {
116         count++;
117       }
118       else if (0x10000 <= u32 && u32 < 0x110000) {
119         count += 2;
120       }
121       u32 = 0;
122     }
123   }
124
125   return ++count;
126 }
127
128 int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
129 {
130   char *out8end = out8 + size8;
131   wchar_t u = 0;
132   int err = 0;
133   if (!size8 || !in16 || !out8) {
134     return UTF_ERROR_NULL_IN;
135   }
136   out8end--;
137
138   for (; out8 < out8end && (u = *in16); in16++, out8++) {
139     if (u < 0x0080) {
140       *out8 = u;
141     }
142     else if (u < 0x0800) {
143       if (out8 + 1 >= out8end) {
144         break;
145       }
146       *out8++ = (0x3 << 6) | (0x1F & (u >> 6));
147       *out8 = (0x1 << 7) | (0x3F & (u));
148     }
149     else if (u < 0xD800 || u >= 0xE000) {
150       if (out8 + 2 >= out8end) {
151         break;
152       }
153       *out8++ = (0x7 << 5) | (0xF & (u >> 12));
154       *out8++ = (0x1 << 7) | (0x3F & (u >> 6));
155       *out8 = (0x1 << 7) | (0x3F & (u));
156     }
157     else if (u < 0xDC00) {
158       wchar_t u2 = *++in16;
159
160       if (!u2) {
161         break;
162       }
163       if (u2 >= 0xDC00 && u2 < 0xE000) {
164         if (out8 + 3 >= out8end) {
165           break;
166         }
167         unsigned int uc = 0x10000 + (u2 - 0xDC00) + ((u - 0xD800) << 10);
168
169         *out8++ = (0xF << 4) | (0x7 & (uc >> 18));
170         *out8++ = (0x1 << 7) | (0x3F & (uc >> 12));
171         *out8++ = (0x1 << 7) | (0x3F & (uc >> 6));
172         *out8 = (0x1 << 7) | (0x3F & (uc));
173       }
174       else {
175         out8--;
176         err |= UTF_ERROR_ILLCHAR;
177       }
178     }
179     else if (u < 0xE000) {
180       out8--;
181       err |= UTF_ERROR_ILLCHAR;
182     }
183   }
184
185   *out8 = *out8end = 0;
186
187   if (*in16) {
188     err |= UTF_ERROR_SMALL;
189   }
190
191   return err;
192 }
193
194 int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)
195 {
196   char u;
197   char type = 0;
198   unsigned int u32 = 0;
199   wchar_t *out16end = out16 + size16;
200   int err = 0;
201   if (!size16 || !in8 || !out16) {
202     return UTF_ERROR_NULL_IN;
203   }
204   out16end--;
205
206   for (; out16 < out16end && (u = *in8); in8++) {
207     if (type == 0) {
208       if ((u & 0x01 << 7) == 0) {
209         *out16 = u;
210         out16++;
211         u32 = 0;
212         continue;
213       }  // 1 utf-8 char
214       if ((u & 0x07 << 5) == 0xC0) {
215         type = 1;
216         u32 = u & 0x1F;
217         continue;
218       }  // 2 utf-8 char
219       if ((u & 0x0F << 4) == 0xE0) {
220         type = 2;
221         u32 = u & 0x0F;
222         continue;
223       }  // 3 utf-8 char
224       if ((u & 0x1F << 3) == 0xF0) {
225         type = 3;
226         u32 = u & 0x07;
227         continue;
228       }  // 4 utf-8 char
229       err |= UTF_ERROR_ILLCHAR;
230       continue;
231     }
232     if ((u & 0xC0) == 0x80) {
233       u32 = (u32 << 6) | (u & 0x3F);
234       type--;
235     }
236     else {
237       u32 = 0;
238       type = 0;
239       err |= UTF_ERROR_ILLSEQ;
240     }
241
242     if (type == 0) {
243       if ((0 < u32 && u32 < 0xD800) || (0xE000 <= u32 && u32 < 0x10000)) {
244         *out16 = u32;
245         out16++;
246       }
247       else if (0x10000 <= u32 && u32 < 0x110000) {
248         if (out16 + 1 >= out16end) {
249           break;
250         }
251         u32 -= 0x10000;
252         *out16 = 0xD800 + (u32 >> 10);
253         out16++;
254         *out16 = 0xDC00 + (u32 & 0x3FF);
255         out16++;
256       }
257       u32 = 0;
258     }
259   }
260
261   *out16 = *out16end = 0;
262
263   if (*in8) {
264     err |= UTF_ERROR_SMALL;
265   }
266
267   return err;
268 }
269
270 /* UNUSED FUNCTIONS */
271 #if 0
272 static int is_ascii(const char *in8)
273 {
274   for (; *in8; in8++)
275     if (0x80 & *in8)
276       return 0;
277
278   return 1;
279 }
280
281 static void utf_8_cut_end(char *inout8, size_t maxcutpoint)
282 {
283   char *cur = inout8 + maxcutpoint;
284   char cc;
285   if (!inout8)
286     return;
287
288   cc = *cur;
289 }
290 #endif
291
292 char *alloc_utf_8_from_16(const wchar_t *in16, size_t add)
293 {
294   size_t bsize = count_utf_8_from_16(in16);
295   char *out8 = NULL;
296   if (!bsize) {
297     return NULL;
298   }
299   out8 = (char *)malloc(sizeof(char) * (bsize + add));
300   conv_utf_16_to_8(in16, out8, bsize);
301   return out8;
302 }
303
304 wchar_t *alloc_utf16_from_8(const char *in8, size_t add)
305 {
306   size_t bsize = count_utf_16_from_8(in8);
307   wchar_t *out16 = NULL;
308   if (!bsize) {
309     return NULL;
310   }
311   out16 = (wchar_t *)malloc(sizeof(wchar_t) * (bsize + add));
312   conv_utf_8_to_16(in8, out16, bsize);
313   return out16;
314 }