Coverity: Localization module Resource Leaks 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     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         FREE(pOutSave);
222         return NULL;
223     }
224
225     return pOutSave;
226 }
227 /*--------------------------------------------------------------------------*/
228 wchar_t *to_wide_string(const char *_UTFStr)
229 {
230     wchar_t* pOutSave = NULL;
231     char* pInSave = NULL;
232     size_t iSize = 0;
233     size_t iLeftIn = 0;
234     size_t iLeftOut = 0;
235     iconv_t cd_UTF8_to_UTF16 = NULL;
236     wchar_t* pOut = NULL;
237
238     if (_UTFStr == NULL)
239     {
240         return NULL;
241     }
242
243     cd_UTF8_to_UTF16 = iconv_open("WCHAR_T", "UTF-8");
244
245     iLeftIn = strlen(_UTFStr);
246     pInSave = (char*)_UTFStr;
247
248     iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
249     pOut = (wchar_t*)MALLOC(iLeftOut);
250     memset(pOut, 0x00, iLeftOut);
251     pOutSave = pOut;
252
253     iSize = iconv(cd_UTF8_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
254     iconv_close(cd_UTF8_to_UTF16);
255     if (iSize == (size_t)(-1))
256     {
257         iconv_t cd_ISO8851_to_UTF16 = iconv_open("WCHAR_T", "ISO_8859-1");
258
259         _UTFStr = pInSave;
260         iLeftIn = strlen(_UTFStr);
261
262         iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
263         pOut = pOutSave;
264         memset(pOut, 0x00, iLeftOut);
265
266
267         iSize = iconv(cd_ISO8851_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
268         iconv_close(cd_ISO8851_to_UTF16);
269         if (iSize == (size_t)(-1))
270         {
271             FREE(pOut);
272             return NULL;
273         }
274     }
275     return pOutSave;
276 }
277 /*--------------------------------------------------------------------------*/
278 #endif
279 /*--------------------------------------------------------------------------*/
280 int wcstat(char* filename, struct stat *st)
281 {
282     return stat(filename, st);
283 }
284 /*--------------------------------------------------------------------------*/
285 #endif
286 /*--------------------------------------------------------------------------*/
287 static int ReadUTF8Character(const char* str, int *nBytes)
288 {
289     const unsigned char* s = (const unsigned char*)(str);
290     unsigned char c = s[0];
291
292     if (c < 0x80)
293     {
294         *nBytes = 1;
295         return c;
296     }
297     else if (c < 0xC2)
298     {
299         return -1;
300     }
301     else if (c < 0xE0)
302     {
303         if (s[1] == 0 || (s[1] ^ 0x80) >= 0x40)
304         {
305             return -1;
306         }
307         *nBytes = 2;
308         return ((s[0] & 0x1F) << 6) + (s[1] ^ 0x80);
309     }
310     else if (c < 0xF0)
311     {
312         if (s[1] == 0 || s[2] == 0 || (s[1] ^ 0x80) >= 0x40
313                 || (s[2] ^ 0x80) >= 0x40 || (c == 0xE0 && s[1] < 0xA0))
314         {
315             return -1;
316         }
317         *nBytes = 3;
318         return ((s[0] & 0xF) << 12) + ((s[1] ^ 0x80) << 6) + (s[2] ^ 0x80);
319     }
320     else if (c < 0xF5)
321     {
322         if (s[1] == 0 || s[2] == 0 || s[3] == 0 || (s[1] ^ 0x80) >= 0x40
323                 || (s[2] ^ 0x80) >= 0x40 || (s[3] ^ 0x80) >= 0x40
324                 || (c == 0xF0 && s[1] < 0x90) || (c == 0xF4 && s[1] > 0x8F))
325         {
326             return -1;
327         }
328         *nBytes = 4;
329         return ((s[0] & 0x07) << 18) + ((s[1] ^ 0x80) << 12) + ((s[2] ^ 0x80) << 6)
330                + (s[3] ^ 0x80);
331     }
332     else
333     {
334         return -1;
335     }
336 }
337 /*--------------------------------------------------------------------------*/
338 BOOL IsValidUTF8(const char*  pStText)
339 {
340     const char* s =  pStText;
341     while (*s != 0)
342     {
343         int nBytes = 0;
344         if (ReadUTF8Character(s, &nBytes) < 0)
345         {
346             return FALSE;
347         }
348         s += nBytes;
349     }
350
351     return TRUE;
352 }
353 /*--------------------------------------------------------------------------*/