Coverity #1099102, #1099103, #1321340 fixed
[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     UINT codePage = CP_UTF8;
70
71     if (_UTFStr == NULL)
72     {
73         return NULL;
74     }
75
76     nwide = MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, _UTFStr, -1, NULL, 0);
77     if (nwide == 0)
78     {
79         if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION)
80         {
81             codePage = CP_ACP;
82             nwide = MultiByteToWideChar(codePage, 0, _UTFStr, -1, NULL, 0);
83         }
84
85         if (nwide == 0)
86         {
87             return NULL;
88         }
89     }
90
91     _buf = (wchar_t *)MALLOC(nwide * sizeof(wchar_t));
92     if (_buf == NULL)
93     {
94         return NULL;
95     }
96
97     if (MultiByteToWideChar(codePage, 0, _UTFStr, -1, _buf, nwide) == 0)
98     {
99         FREE(_buf);
100         _buf = NULL;
101     }
102
103     _buf[nwide - 1] = L'\0';
104     return _buf;
105 }
106 /*--------------------------------------------------------------------------*/
107 int wcstat(char* filename, struct _stat *st)
108 {
109     int stat_result = 0;
110     wchar_t *wfilename = to_wide_string(filename);
111     stat_result = _wstat(wfilename, st);
112     FREE(wfilename);
113     return stat_result;
114 }
115 /*--------------------------------------------------------------------------*/
116 #else
117 /*--------------------------------------------------------------------------*/
118 #ifdef __APPLE__ // Mac OS X
119 /*--------------------------------------------------------------------------*/
120 char *wide_string_to_UTF8(const wchar_t *_wide)
121 {
122     size_t iCharLen = 0;
123     wchar_t *pwstr = _wide;
124     char* pchar = NULL;
125     /* The value of MB_CUR_MAX is the maximum number of bytes
126     in a multibyte character for the current locale. */
127     int iMaxLen =  0;
128
129     if (_wide == NULL)
130     {
131         return NULL;
132     }
133
134     iMaxLen =  (int)wcslen(_wide) * MB_CUR_MAX ;
135
136     pchar = (char*) MALLOC(( iMaxLen + 1) * sizeof(char));
137     if (pchar == NULL)
138     {
139         return NULL;
140     }
141     iCharLen = wcstombs (pchar, pwstr, iMaxLen);
142     if ( iCharLen == (size_t)(-1) )
143     {
144         if (pchar)
145         {
146             FREE(pchar);
147             pchar = NULL;
148         }
149         return NULL;
150     }
151     pchar[iCharLen] = '\0';
152     return pchar;
153 }
154 /*--------------------------------------------------------------------------*/
155 wchar_t *to_wide_string(const char *_UTFStr)
156 {
157     wchar_t *_buf = NULL;
158     size_t pszLen = 0;
159     char *psz = _UTFStr;
160     mbstate_t ps;
161
162     if (_UTFStr == NULL)
163     {
164         return NULL;
165     }
166
167     memset (&ps, 0x00, sizeof(ps));
168     pszLen = mbsrtowcs(NULL, (const char**)&psz, 0, &ps);
169
170     if ( pszLen == (size_t)(-1) )
171     {
172         return NULL;
173     }
174
175     _buf = (wchar_t*)MALLOC((pszLen + 1) * sizeof(wchar_t));
176     if (_buf == NULL)
177     {
178         return NULL;
179     }
180
181     pszLen = mbsrtowcs(_buf, (const char**)&psz, (int)strlen(psz), &ps);
182
183     if ( pszLen == (size_t)(-1) )
184     {
185         FREE(_buf);
186         return NULL;
187     }
188     else
189     {
190         _buf[pszLen] = L'\0';
191     }
192     return _buf;
193 }
194 /*--------------------------------------------------------------------------*/
195 #else // Linux
196 /*--------------------------------------------------------------------------*/
197 char *wide_string_to_UTF8(const wchar_t *_wide)
198 {
199     char* pOutSave = NULL;
200     wchar_t* pSaveIn = NULL;
201     size_t iSize = 0;
202     size_t iLeftIn = 0;
203     size_t iLeftOut = 0;
204     char* pOut = NULL;
205     iconv_t cd_UTF16_to_UTF8;
206
207     if (_wide == NULL)
208     {
209         return NULL;
210     }
211
212     cd_UTF16_to_UTF8 = iconv_open("UTF-8", "WCHAR_T");
213
214     pSaveIn = (wchar_t*)_wide;
215     iLeftIn = wcslen(_wide) * sizeof(wchar_t);
216
217     iLeftOut = iLeftIn + (1 * sizeof(wchar_t));
218     pOut = (char*)MALLOC(iLeftOut);
219     memset(pOut, 0x00, iLeftOut);
220     pOutSave = pOut;
221
222     iSize = iconv(cd_UTF16_to_UTF8, (char**)&pSaveIn, &iLeftIn, &pOut, &iLeftOut);
223     iconv_close(cd_UTF16_to_UTF8);
224     if (iSize == (size_t)(-1))
225     {
226         FREE(pOutSave);
227         return NULL;
228     }
229
230     return pOutSave;
231 }
232 /*--------------------------------------------------------------------------*/
233 wchar_t *to_wide_string(const char *_UTFStr)
234 {
235     wchar_t* pOutSave = NULL;
236     char* pInSave = NULL;
237     size_t iSize = 0;
238     size_t iLeftIn = 0;
239     size_t iLeftOut = 0;
240     iconv_t cd_UTF8_to_UTF16 = NULL;
241     wchar_t* pOut = NULL;
242
243     if (_UTFStr == NULL)
244     {
245         return NULL;
246     }
247
248     cd_UTF8_to_UTF16 = iconv_open("WCHAR_T", "UTF-8");
249
250     iLeftIn = strlen(_UTFStr);
251     pInSave = (char*)_UTFStr;
252
253     iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
254     pOut = (wchar_t*)MALLOC(iLeftOut);
255     memset(pOut, 0x00, iLeftOut);
256     pOutSave = pOut;
257
258     iSize = iconv(cd_UTF8_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
259     iconv_close(cd_UTF8_to_UTF16);
260     if (iSize == (size_t)(-1))
261     {
262         iconv_t cd_ISO8851_to_UTF16 = iconv_open("WCHAR_T", "ISO_8859-1");
263
264         _UTFStr = pInSave;
265         iLeftIn = strlen(_UTFStr);
266
267         iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
268         pOut = pOutSave;
269         memset(pOut, 0x00, iLeftOut);
270
271
272         iSize = iconv(cd_ISO8851_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
273         iconv_close(cd_ISO8851_to_UTF16);
274         if (iSize == (size_t)(-1))
275         {
276             FREE(pOut);
277             return NULL;
278         }
279     }
280     return pOutSave;
281 }
282 /*--------------------------------------------------------------------------*/
283 #endif
284 /*--------------------------------------------------------------------------*/
285 int wcstat(char* filename, struct stat *st)
286 {
287     return stat(filename, st);
288 }
289 /*--------------------------------------------------------------------------*/
290 #endif
291 /*--------------------------------------------------------------------------*/
292 static int ReadUTF8Character(const char* str, int *nBytes)
293 {
294     const unsigned char* s = (const unsigned char*)(str);
295     unsigned char c = s[0];
296
297     if (c < 0x80)
298     {
299         *nBytes = 1;
300         return c;
301     }
302     else if (c < 0xC2)
303     {
304         return -1;
305     }
306     else if (c < 0xE0)
307     {
308         if (s[1] == 0 || (s[1] ^ 0x80) >= 0x40)
309         {
310             return -1;
311         }
312         *nBytes = 2;
313         return ((s[0] & 0x1F) << 6) + (s[1] ^ 0x80);
314     }
315     else if (c < 0xF0)
316     {
317         if (s[1] == 0 || s[2] == 0 || (s[1] ^ 0x80) >= 0x40
318                 || (s[2] ^ 0x80) >= 0x40 || (c == 0xE0 && s[1] < 0xA0))
319         {
320             return -1;
321         }
322         *nBytes = 3;
323         return ((s[0] & 0xF) << 12) + ((s[1] ^ 0x80) << 6) + (s[2] ^ 0x80);
324     }
325     else if (c < 0xF5)
326     {
327         if (s[1] == 0 || s[2] == 0 || s[3] == 0 || (s[1] ^ 0x80) >= 0x40
328                 || (s[2] ^ 0x80) >= 0x40 || (s[3] ^ 0x80) >= 0x40
329                 || (c == 0xF0 && s[1] < 0x90) || (c == 0xF4 && s[1] > 0x8F))
330         {
331             return -1;
332         }
333         *nBytes = 4;
334         return ((s[0] & 0x07) << 18) + ((s[1] ^ 0x80) << 12) + ((s[2] ^ 0x80) << 6)
335                + (s[3] ^ 0x80);
336     }
337     else
338     {
339         return -1;
340     }
341 }
342 /*--------------------------------------------------------------------------*/
343 BOOL IsValidUTF8(const char*  pStText)
344 {
345     const char* s =  pStText;
346     while (*s != 0)
347     {
348         int nBytes = 0;
349         if (ReadUTF8Character(s, &nBytes) < 0)
350         {
351             return FALSE;
352         }
353         s += nBytes;
354     }
355
356     return TRUE;
357 }
358 /*--------------------------------------------------------------------------*/