Merge remote-tracking branch 'origin/master' into YaSp
[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 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13 /*--------------------------------------------------------------------------*/
14 #ifndef _MSC_VER
15     #include <iconv.h>
16     #include <errno.h>
17 #endif
18
19 #include <wchar.h>
20 #include <wctype.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <locale.h>
25 #include "charEncoding.h"
26 #include "MALLOC.h"
27 /*--------------------------------------------------------------------------*/
28 #ifdef _MSC_VER
29 #include <Windows.h>
30
31 char *wide_string_to_UTF8(const wchar_t *_wide)
32 {
33         char *buf = NULL;
34         DWORD size = 0;
35         DWORD dwFlags = 0;
36
37         if ((wchar_t *)NULL == _wide) return (char *)NULL;
38         size = WideCharToMultiByte(CP_UTF8, dwFlags, _wide, -1, NULL, 0, NULL, 0);
39         if (size == 0) return (char *)NULL;
40         size += 1;
41         buf = (char*)MALLOC(sizeof(char)*size);
42         if (buf)
43         {
44                 WideCharToMultiByte(CP_UTF8, dwFlags, _wide, -1, buf, size, NULL, 0);
45                 if (size <= 0)
46                 {
47                         FREE(buf);
48                         return (char *)NULL;
49                 }
50         }
51         return buf;
52 }
53 /*--------------------------------------------------------------------------*/
54 wchar_t *to_wide_string(const char *_UTFStr)
55 {
56         int nwide = 0;
57         wchar_t *_buf = NULL;
58
59         /* About MultiByteToWideChar :
60         Starting with Windows Vista,
61         the function does not drop illegal code points
62         if the application does not set this flag.
63
64         Windows XP: To prevent the security problem of the non-shortest-form
65         versions of UTF-8 characters, MultiByteToWideChar deletes these characters.
66         */
67
68         DWORD dwFlags = 0;
69
70         if(_UTFStr == NULL) return NULL;
71         nwide = MultiByteToWideChar(CP_UTF8, dwFlags, _UTFStr, -1, NULL, 0);
72         if(nwide == 0) return NULL;
73         _buf = (wchar_t *)MALLOC(nwide * sizeof(wchar_t));
74         if(_buf == NULL) return NULL;
75         if(MultiByteToWideChar(CP_UTF8, dwFlags, _UTFStr, -1, _buf, nwide) == 0)
76         {
77                 FREE(_buf);
78                 _buf = NULL;
79         }
80         return _buf;
81 }
82 /*--------------------------------------------------------------------------*/
83 int wcstat(char* filename, struct _stat *st)
84 {
85         int stat_result = 0;
86         wchar_t *wfilename = to_wide_string(filename);
87         stat_result = _wstat(wfilename, st);
88         FREE(wfilename);
89         return stat_result;
90 }
91 /*--------------------------------------------------------------------------*/
92 #else //Linux check for MAC OS X
93 char *wide_string_to_UTF8(const wchar_t *_wide)
94 {
95     if(_wide == NULL) return NULL;
96     char* pOutSave = NULL;
97     wchar_t* pSaveIn = _wide;
98     size_t iSize = 0;
99     size_t iLeftIn = wcslen(_wide) * sizeof(wchar_t);
100     size_t iLeftOut = 0;
101
102     char* pOut = NULL;
103
104     iconv_t cd_UTF16_to_UTF8 = iconv_open("UTF-8", "UTF-32LE");
105
106     iLeftOut = iLeftIn + (1 * sizeof(wchar_t));
107     pOut = (char*)MALLOC(iLeftOut);
108     memset(pOut, 0x00, iLeftOut);
109     pOutSave = pOut;
110
111     iSize = iconv(cd_UTF16_to_UTF8, (char**)&pSaveIn, &iLeftIn, &pOut, &iLeftOut);
112     iconv_close(cd_UTF16_to_UTF8);
113     if(iSize == (size_t)(-1))
114     {
115         return NULL;
116     }
117
118     return pOutSave;
119 }
120 /*--------------------------------------------------------------------------*/
121 wchar_t *to_wide_string(const char *_UTFStr)
122 {
123     if(_UTFStr == NULL) return NULL;
124     wchar_t* pOutSave = NULL;
125     char* pInSave = _UTFStr;
126     size_t iSize = 0;
127     size_t iLeftIn = strlen(_UTFStr);
128     size_t iLeftOut = 0;
129
130     wchar_t* pOut = NULL;
131
132     iconv_t cd_UTF8_to_UTF16 = iconv_open("UTF-32LE", "UTF-8");
133
134     iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
135     pOut = (wchar_t*)MALLOC(iLeftOut);
136     memset(pOut, 0x00, iLeftOut);
137     pOutSave = pOut;
138
139     iSize = iconv(cd_UTF8_to_UTF16, &_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
140     iconv_close(cd_UTF8_to_UTF16);
141     if(iSize == (size_t)(-1))
142     {
143         iconv_t cd_ISO8851_to_UTF16 = iconv_open("UTF-32LE", "ISO_8859-1");
144
145         _UTFStr = pInSave;
146         iLeftIn = strlen(_UTFStr);
147
148         iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
149         pOut = pOutSave;
150         memset(pOut, 0x00, iLeftOut);
151
152
153         iSize = iconv(cd_ISO8851_to_UTF16, &_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
154         iconv_close(cd_ISO8851_to_UTF16);
155         if(iSize == (size_t)(-1))
156         {
157             return NULL;
158         }
159     }
160
161     return pOutSave;
162 }
163 /*--------------------------------------------------------------------------*/
164 int wcstat(char* filename, struct stat *st)
165 {
166         return stat(filename, st);
167 }
168 #endif
169 /*--------------------------------------------------------------------------*/
170 static int ReadUTF8Character(const char* str, int *nBytes)
171 {
172         const unsigned char* s = (const unsigned char*)(str);
173         unsigned char c = s[0];
174
175         if (c < 0x80)
176         {
177                 *nBytes = 1;
178                 return c;
179         }
180         else if (c < 0xC2)
181         {
182                 return -1;
183         }
184         else if (c < 0xE0)
185         {
186                 if (s[1] == 0 || (s[1] ^ 0x80) >= 0x40)
187                 {
188                         return -1;
189                 }
190                 *nBytes = 2;
191                 return ((s[0] & 0x1F) << 6) + (s[1] ^ 0x80);
192         }
193         else if (c < 0xF0)
194         {
195                 if (s[1] == 0 || s[2] == 0 || (s[1] ^ 0x80) >= 0x40
196                         || (s[2] ^ 0x80) >= 0x40 || (c == 0xE0 && s[1] < 0xA0))
197                 {
198                         return -1;
199                 }
200                 *nBytes = 3;
201                 return ((s[0] & 0xF) << 12) + ((s[1] ^ 0x80) << 6) + (s[2] ^ 0x80);
202         }
203         else if (c < 0xF5)
204         {
205                 if (s[1] == 0 || s[2] == 0 || s[3] == 0 || (s[1] ^ 0x80) >= 0x40
206                         || (s[2] ^ 0x80) >= 0x40 || (s[3] ^ 0x80) >= 0x40
207                         || (c == 0xF0 && s[1] < 0x90) || (c == 0xF4 && s[1] > 0x8F))
208                 {
209                         return -1;
210                 }
211                 *nBytes = 4;
212                 return ((s[0] & 0x07) << 18) + ((s[1] ^ 0x80) << 12) + ((s[2] ^ 0x80) << 6)
213                         + (s[3] ^ 0x80);
214         }
215         else
216         {
217                 return -1;
218         }
219 }
220 /*--------------------------------------------------------------------------*/
221 BOOL IsValidUTF8(const char*  pStText)
222 {
223         const char* s =  pStText;
224         while (*s != 0)
225         {
226                 int nBytes = 0;
227                 if (ReadUTF8Character(s, &nBytes) < 0)
228                 {
229                         return FALSE;
230                 }
231                 s += nBytes;
232         }
233
234         return TRUE;
235 }
236 /*--------------------------------------------------------------------------*/