00211b450084d83940450cd0bc7bb0ed115e0800
[scilab.git] / scilab / modules / localization / src / c / charEncoding.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2008 - Yung-Jang Lee
4 * Copyright (C) 2009 - DIGITEO - Antoine ELIAS , Allan CORNET
5 *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14 *
15 */
16 /*--------------------------------------------------------------------------*/
17 #ifndef _MSC_VER
18 #include <iconv.h>
19 #include <errno.h>
20 #endif
21
22 #include <wchar.h>
23 #include <wctype.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <locale.h>
28
29 #include "charEncoding.h"
30 #include "sci_malloc.h"
31 /*--------------------------------------------------------------------------*/
32 #ifdef _MSC_VER
33 #include <Windows.h>
34
35 char *wide_string_to_UTF8(const wchar_t *_wide)
36 {
37     char *buf = NULL;
38     DWORD size = 0;
39     DWORD dwFlags = 0;
40
41     if ((wchar_t *)NULL == _wide)
42     {
43         return (char *)NULL;
44     }
45     size = WideCharToMultiByte(CP_UTF8, dwFlags, _wide, -1, NULL, 0, NULL, 0);
46     if (size == 0)
47     {
48         return (char *)NULL;
49     }
50     buf = (char*)MALLOC(sizeof(char) * size);
51     if (buf)
52     {
53         WideCharToMultiByte(CP_UTF8, dwFlags, _wide, -1, buf, size, NULL, 0);
54         if (size <= 0)
55         {
56             FREE(buf);
57             return (char *)NULL;
58         }
59     }
60
61     buf[size - 1] = '\0';
62     return buf;
63 }
64 /*--------------------------------------------------------------------------*/
65 wchar_t *to_wide_string(const char *_UTFStr)
66 {
67     int nwide = 0;
68     wchar_t *_buf = NULL;
69     DWORD dwFlags = 0;
70     UINT codePage = CP_ACP;
71
72     if (_UTFStr == NULL)
73     {
74         return NULL;
75     }
76
77     if (IsValidUTF8(_UTFStr))
78     {
79         codePage = CP_UTF8;
80     }
81
82     nwide = MultiByteToWideChar(codePage, dwFlags, _UTFStr, -1, NULL, 0);
83     if (nwide == 0)
84     {
85         return NULL;
86     }
87
88     _buf = (wchar_t *)MALLOC(nwide * sizeof(wchar_t));
89     if (_buf == NULL)
90     {
91         return NULL;
92     }
93
94     if (MultiByteToWideChar(codePage, dwFlags, _UTFStr, -1, _buf, nwide) == 0)
95     {
96         FREE(_buf);
97         _buf = NULL;
98     }
99
100     _buf[nwide - 1] = L'\0';
101     return _buf;
102 }
103 /*--------------------------------------------------------------------------*/
104 int wcstat(char* filename, struct _stat *st)
105 {
106     int stat_result = 0;
107     wchar_t *wfilename = to_wide_string(filename);
108     stat_result = _wstat(wfilename, st);
109     FREE(wfilename);
110     return stat_result;
111 }
112 /*--------------------------------------------------------------------------*/
113 #else
114 /*--------------------------------------------------------------------------*/
115 #ifdef __APPLE__ // Mac OS X
116 /*--------------------------------------------------------------------------*/
117 char *wide_string_to_UTF8(const wchar_t *_wide)
118 {
119     size_t iCharLen = 0;
120     wchar_t *pwstr = _wide;
121     char* pchar = NULL;
122     /* The value of MB_CUR_MAX is the maximum number of bytes
123     in a multibyte character for the current locale. */
124     int iMaxLen =  0;
125
126     if (_wide == NULL)
127     {
128         return NULL;
129     }
130
131     iMaxLen =  (int)wcslen(_wide) * MB_CUR_MAX ;
132
133     pchar = (char*) MALLOC(( iMaxLen + 1) * sizeof(char));
134     if (pchar == NULL)
135     {
136         return NULL;
137     }
138     iCharLen = wcstombs (pchar, pwstr, iMaxLen);
139     if ( iCharLen == (size_t)(-1) )
140     {
141         if (pchar)
142         {
143             FREE(pchar);
144             pchar = NULL;
145         }
146         return NULL;
147     }
148     pchar[iCharLen] = '\0';
149     return pchar;
150 }
151 /*--------------------------------------------------------------------------*/
152 wchar_t *to_wide_string(const char *_UTFStr)
153 {
154     wchar_t *_buf = NULL;
155     size_t pszLen = 0;
156     char *psz = _UTFStr;
157     mbstate_t ps;
158
159     if (_UTFStr == NULL)
160     {
161         return NULL;
162     }
163
164     memset (&ps, 0x00, sizeof(ps));
165     pszLen = mbsrtowcs(NULL, (const char**)&psz, 0, &ps);
166
167     if ( pszLen == (size_t)(-1) )
168     {
169         return NULL;
170     }
171
172     _buf = (wchar_t*)MALLOC((pszLen + 1) * sizeof(wchar_t));
173     if (_buf == NULL)
174     {
175         return NULL;
176     }
177
178     pszLen = mbsrtowcs(_buf, (const char**)&psz, (int)strlen(psz), &ps);
179
180     if ( pszLen == (size_t)(-1) )
181     {
182         FREE(_buf);
183         return NULL;
184     }
185     else
186     {
187         _buf[pszLen] = L'\0';
188     }
189     return _buf;
190 }
191 /*--------------------------------------------------------------------------*/
192 #else // Linux
193 /*--------------------------------------------------------------------------*/
194 char *wide_string_to_UTF8(const wchar_t *_wide)
195 {
196     char* pOutSave = NULL;
197     wchar_t* pSaveIn = NULL;
198     size_t iSize = 0;
199     size_t iLeftIn = 0;
200     size_t iLeftOut = 0;
201     char* pOut = NULL;
202     iconv_t cd_UTF16_to_UTF8 = iconv_open("UTF-8", "WCHAR_T");
203
204     if (_wide == NULL)
205     {
206         return NULL;
207     }
208
209     pSaveIn = (wchar_t*)_wide;
210     iLeftIn = wcslen(_wide) * sizeof(wchar_t);
211
212     iLeftOut = iLeftIn + (1 * sizeof(wchar_t));
213     pOut = (char*)MALLOC(iLeftOut);
214     memset(pOut, 0x00, iLeftOut);
215     pOutSave = pOut;
216
217     iSize = iconv(cd_UTF16_to_UTF8, (char**)&pSaveIn, &iLeftIn, &pOut, &iLeftOut);
218     iconv_close(cd_UTF16_to_UTF8);
219     if (iSize == (size_t)(-1))
220     {
221         return NULL;
222     }
223
224     return pOutSave;
225 }
226 /*--------------------------------------------------------------------------*/
227 wchar_t *to_wide_string(const char *_UTFStr)
228 {
229     wchar_t* pOutSave = NULL;
230     char* pInSave = NULL;
231     size_t iSize = 0;
232     size_t iLeftIn = 0;
233     size_t iLeftOut = 0;
234     iconv_t cd_UTF8_to_UTF16 = NULL;
235     wchar_t* pOut = NULL;
236
237     if (_UTFStr == NULL)
238     {
239         return NULL;
240     }
241
242     cd_UTF8_to_UTF16 = iconv_open("WCHAR_T", "UTF-8");
243
244     iLeftIn = strlen(_UTFStr);
245     pInSave = (char*)_UTFStr;
246
247     iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
248     pOut = (wchar_t*)MALLOC(iLeftOut);
249     memset(pOut, 0x00, iLeftOut);
250     pOutSave = pOut;
251
252     iSize = iconv(cd_UTF8_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
253     iconv_close(cd_UTF8_to_UTF16);
254     if (iSize == (size_t)(-1))
255     {
256         iconv_t cd_ISO8851_to_UTF16 = iconv_open("WCHAR_T", "ISO_8859-1");
257
258         _UTFStr = pInSave;
259         iLeftIn = strlen(_UTFStr);
260
261         iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
262         pOut = pOutSave;
263         memset(pOut, 0x00, iLeftOut);
264
265
266         iSize = iconv(cd_ISO8851_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
267         iconv_close(cd_ISO8851_to_UTF16);
268         if (iSize == (size_t)(-1))
269         {
270             return NULL;
271         }
272     }
273
274     return pOutSave;
275 }
276 /*--------------------------------------------------------------------------*/
277 #endif
278 /*--------------------------------------------------------------------------*/
279 int wcstat(char* filename, struct stat *st)
280 {
281     return stat(filename, st);
282 }
283 /*--------------------------------------------------------------------------*/
284 #endif
285 /*--------------------------------------------------------------------------*/
286 static int ReadUTF8Character(const char* str, int *nBytes)
287 {
288     const unsigned char* s = (const unsigned char*)(str);
289     unsigned char c = s[0];
290
291     if (c < 0x80)
292     {
293         *nBytes = 1;
294         return c;
295     }
296     else if (c < 0xC2)
297     {
298         return -1;
299     }
300     else if (c < 0xE0)
301     {
302         if (s[1] == 0 || (s[1] ^ 0x80) >= 0x40)
303         {
304             return -1;
305         }
306         *nBytes = 2;
307         return ((s[0] & 0x1F) << 6) + (s[1] ^ 0x80);
308     }
309     else if (c < 0xF0)
310     {
311         if (s[1] == 0 || s[2] == 0 || (s[1] ^ 0x80) >= 0x40
312                 || (s[2] ^ 0x80) >= 0x40 || (c == 0xE0 && s[1] < 0xA0))
313         {
314             return -1;
315         }
316         *nBytes = 3;
317         return ((s[0] & 0xF) << 12) + ((s[1] ^ 0x80) << 6) + (s[2] ^ 0x80);
318     }
319     else if (c < 0xF5)
320     {
321         if (s[1] == 0 || s[2] == 0 || s[3] == 0 || (s[1] ^ 0x80) >= 0x40
322                 || (s[2] ^ 0x80) >= 0x40 || (s[3] ^ 0x80) >= 0x40
323                 || (c == 0xF0 && s[1] < 0x90) || (c == 0xF4 && s[1] > 0x8F))
324         {
325             return -1;
326         }
327         *nBytes = 4;
328         return ((s[0] & 0x07) << 18) + ((s[1] ^ 0x80) << 12) + ((s[2] ^ 0x80) << 6)
329                + (s[3] ^ 0x80);
330     }
331     else
332     {
333         return -1;
334     }
335 }
336 /*--------------------------------------------------------------------------*/
337 BOOL IsValidUTF8(const char*  pStText)
338 {
339     const char* s =  pStText;
340     while (*s != 0)
341     {
342         int nBytes = 0;
343         if (ReadUTF8Character(s, &nBytes) < 0)
344         {
345             return FALSE;
346         }
347         s += nBytes;
348     }
349
350     return TRUE;
351 }
352 /*--------------------------------------------------------------------------*/