3facb07999a9f827cee5e9f1abdff5b985d1ac86
[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.1-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
26 #include "charEncoding.h"
27 #include "sci_malloc.h"
28 /*--------------------------------------------------------------------------*/
29 #ifdef _MSC_VER
30 #include <Windows.h>
31
32 char *wide_string_to_UTF8(const wchar_t *_wide)
33 {
34     char *buf = NULL;
35     DWORD size = 0;
36     DWORD dwFlags = 0;
37
38     if ((wchar_t *)NULL == _wide)
39     {
40         return (char *)NULL;
41     }
42     size = WideCharToMultiByte(CP_UTF8, dwFlags, _wide, -1, NULL, 0, NULL, 0);
43     if (size == 0)
44     {
45         return (char *)NULL;
46     }
47     buf = (char*)MALLOC(sizeof(char) * size);
48     if (buf)
49     {
50         WideCharToMultiByte(CP_UTF8, dwFlags, _wide, -1, buf, size, NULL, 0);
51         if (size <= 0)
52         {
53             FREE(buf);
54             return (char *)NULL;
55         }
56     }
57
58     buf[size - 1] = '\0';
59     return buf;
60 }
61 /*--------------------------------------------------------------------------*/
62 wchar_t *to_wide_string(const char *_UTFStr)
63 {
64     int nwide = 0;
65     wchar_t *_buf = NULL;
66     DWORD dwFlags = 0;
67     UINT codePage = CP_ACP;
68
69     if (_UTFStr == NULL)
70     {
71         return NULL;
72     }
73
74     if (IsValidUTF8(_UTFStr))
75     {
76         codePage = CP_UTF8;
77     }
78
79     nwide = MultiByteToWideChar(codePage, dwFlags, _UTFStr, -1, NULL, 0);
80     if (nwide == 0)
81     {
82         return NULL;
83     }
84
85     _buf = (wchar_t *)MALLOC(nwide * sizeof(wchar_t));
86     if (_buf == NULL)
87     {
88         return NULL;
89     }
90
91     if (MultiByteToWideChar(codePage, dwFlags, _UTFStr, -1, _buf, nwide) == 0)
92     {
93         FREE(_buf);
94         _buf = NULL;
95     }
96
97     _buf[nwide - 1] = L'\0';
98     return _buf;
99 }
100 /*--------------------------------------------------------------------------*/
101 int wcstat(char* filename, struct _stat *st)
102 {
103     int stat_result = 0;
104     wchar_t *wfilename = to_wide_string(filename);
105     stat_result = _wstat(wfilename, st);
106     FREE(wfilename);
107     return stat_result;
108 }
109 /*--------------------------------------------------------------------------*/
110 #else //Linux check for MAC OS X
111 char *wide_string_to_UTF8(const wchar_t *_wide)
112 {
113     char* pOutSave = NULL;
114     wchar_t* pSaveIn = NULL;
115     size_t iSize = 0;
116     size_t iLeftIn = 0;
117     size_t iLeftOut = 0;
118     char* pOut = NULL;
119     iconv_t cd_UTF16_to_UTF8 = iconv_open("UTF-8", "WCHAR_T");
120
121     if (_wide == NULL)
122     {
123         return NULL;
124     }
125
126     pSaveIn = (wchar_t*)_wide;
127     iLeftIn = wcslen(_wide) * sizeof(wchar_t);
128
129     iLeftOut = iLeftIn + (1 * sizeof(wchar_t));
130     pOut = (char*)MALLOC(iLeftOut);
131     memset(pOut, 0x00, iLeftOut);
132     pOutSave = pOut;
133
134     iSize = iconv(cd_UTF16_to_UTF8, (char**)&pSaveIn, &iLeftIn, &pOut, &iLeftOut);
135     iconv_close(cd_UTF16_to_UTF8);
136     if (iSize == (size_t)(-1))
137     {
138         return NULL;
139     }
140
141     return pOutSave;
142 }
143 /*--------------------------------------------------------------------------*/
144 wchar_t *to_wide_string(const char *_UTFStr)
145 {
146     wchar_t* pOutSave = NULL;
147     char* pInSave = NULL;
148     size_t iSize = 0;
149     size_t iLeftIn = 0;
150     size_t iLeftOut = 0;
151
152     wchar_t* pOut = NULL;
153
154     iconv_t cd_UTF8_to_UTF16 = iconv_open("WCHAR_T", "UTF-8");
155
156     if (_UTFStr == NULL)
157     {
158         return NULL;
159     }
160
161     iLeftIn = strlen(_UTFStr);
162     pInSave = (char*)_UTFStr;
163
164     iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
165     pOut = (wchar_t*)MALLOC(iLeftOut);
166     memset(pOut, 0x00, iLeftOut);
167     pOutSave = pOut;
168
169     iSize = iconv(cd_UTF8_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
170     iconv_close(cd_UTF8_to_UTF16);
171     if (iSize == (size_t)(-1))
172     {
173         iconv_t cd_ISO8851_to_UTF16 = iconv_open("WCHAR_T", "ISO_8859-1");
174
175         _UTFStr = pInSave;
176         iLeftIn = strlen(_UTFStr);
177
178         iLeftOut = (iLeftIn + 1) * sizeof(wchar_t);
179         pOut = pOutSave;
180         memset(pOut, 0x00, iLeftOut);
181
182
183         iSize = iconv(cd_ISO8851_to_UTF16, (char**)&_UTFStr, &iLeftIn, (char**)&pOut, &iLeftOut);
184         iconv_close(cd_ISO8851_to_UTF16);
185         if (iSize == (size_t)(-1))
186         {
187             return NULL;
188         }
189     }
190
191     return pOutSave;
192 }
193 /*--------------------------------------------------------------------------*/
194 int wcstat(char* filename, struct stat *st)
195 {
196     return stat(filename, st);
197 }
198 #endif
199 /*--------------------------------------------------------------------------*/
200 static int ReadUTF8Character(const char* str, int *nBytes)
201 {
202     const unsigned char* s = (const unsigned char*)(str);
203     unsigned char c = s[0];
204
205     if (c < 0x80)
206     {
207         *nBytes = 1;
208         return c;
209     }
210     else if (c < 0xC2)
211     {
212         return -1;
213     }
214     else if (c < 0xE0)
215     {
216         if (s[1] == 0 || (s[1] ^ 0x80) >= 0x40)
217         {
218             return -1;
219         }
220         *nBytes = 2;
221         return ((s[0] & 0x1F) << 6) + (s[1] ^ 0x80);
222     }
223     else if (c < 0xF0)
224     {
225         if (s[1] == 0 || s[2] == 0 || (s[1] ^ 0x80) >= 0x40
226                 || (s[2] ^ 0x80) >= 0x40 || (c == 0xE0 && s[1] < 0xA0))
227         {
228             return -1;
229         }
230         *nBytes = 3;
231         return ((s[0] & 0xF) << 12) + ((s[1] ^ 0x80) << 6) + (s[2] ^ 0x80);
232     }
233     else if (c < 0xF5)
234     {
235         if (s[1] == 0 || s[2] == 0 || s[3] == 0 || (s[1] ^ 0x80) >= 0x40
236                 || (s[2] ^ 0x80) >= 0x40 || (s[3] ^ 0x80) >= 0x40
237                 || (c == 0xF0 && s[1] < 0x90) || (c == 0xF4 && s[1] > 0x8F))
238         {
239             return -1;
240         }
241         *nBytes = 4;
242         return ((s[0] & 0x07) << 18) + ((s[1] ^ 0x80) << 12) + ((s[2] ^ 0x80) << 6)
243                + (s[3] ^ 0x80);
244     }
245     else
246     {
247         return -1;
248     }
249 }
250 /*--------------------------------------------------------------------------*/
251 BOOL IsValidUTF8(const char*  pStText)
252 {
253     const char* s =  pStText;
254     while (*s != 0)
255     {
256         int nBytes = 0;
257         if (ReadUTF8Character(s, &nBytes) < 0)
258         {
259             return FALSE;
260         }
261         s += nBytes;
262     }
263
264     return TRUE;
265 }
266 /*--------------------------------------------------------------------------*/