b24a491c7264a545d34eeb158da6f462dc15dce4
[public/netxms.git] / src / libnetxms / unicode.cpp
1 /* $Id: unicode.cpp,v 1.16 2006-10-13 09:44:23 victor Exp $ */
2 /*
3 ** NetXMS - Network Management System
4 ** Copyright (C) 2003, 2004, 2005, 2006 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: unicode.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25
26
27 //
28 // Static data
29 //
30
31 static char m_cpDefault[MAX_CODEPAGE_LEN] = "";
32
33
34 #ifndef _WIN32
35
36 #if HAVE_ICONV_H
37 #include <iconv.h>
38 #endif
39
40
41 //
42 // UNICODE character set
43 //
44
45 #ifndef __DISABLE_ICONV
46
47 #if HAVE_ICONV_UCS_2_INTERNAL
48 #define UCS2_CODEPAGE_NAME "UCS-2-INTERNAL"
49 #elif HAVE_ICONV_UCS_2
50 #define UCS2_CODEPAGE_NAME "UCS-2"
51 #elif HAVE_ICONV_UCS2
52 #define UCS2_CODEPAGE_NAME "UCS2"
53 #elif HAVE_ICONV_UCS_2BE && WORDS_BIGENDIAN
54 #define UCS2_CODEPAGE_NAME "UCS-2BE"
55 #else
56 #warning Cannot determine valid UCS-2 codepage name
57 #undef HAVE_ICONV
58 #endif
59
60 #endif /* __DISABLE_ICONV */
61
62
63 //
64 // Set application's default codepage
65 //
66
67 void LIBNETXMS_EXPORTABLE SetDefaultCodepage(char *cp)
68 {
69 strncpy(m_cpDefault, cp, MAX_CODEPAGE_LEN);
70 m_cpDefault[MAX_CODEPAGE_LEN - 1] = 0;
71 }
72
73
74 //
75 // Calculate length of wide character string
76 //
77
78 #if !HAVE_USEABLE_WCHAR
79
80 int LIBNETXMS_EXPORTABLE nx_wcslen(WCHAR *pStr)
81 {
82 int iLen = 0;
83 WCHAR *pCurr = pStr;
84
85 while(*pCurr++)
86 iLen++;
87 return iLen;
88 }
89
90 #endif
91
92
93 //
94 // Convert UNICODE string to single-byte string
95 //
96
97 int LIBNETXMS_EXPORTABLE WideCharToMultiByte(int iCodePage, DWORD dwFlags,
98 WCHAR *pWideCharStr, int cchWideChar,
99 char *pByteStr, int cchByteChar,
100 char *pDefaultChar, BOOL *pbUsedDefChar)
101 {
102 #if HAVE_ICONV && !defined(__DISABLE_ICONV)
103 iconv_t cd;
104 int nRet;
105 char *inbuf, *outbuf;
106 size_t inbytes, outbytes;
107 char cp[MAX_CODEPAGE_LEN + 16];
108
109 // Calculate required length. Because iconv cannot calculate
110 // resulting multibyte string length, assume the worst case - 3 bytes
111 // per character for UTF-8 and 2 bytes per character for other encodings
112 if (cchByteChar == 0)
113 {
114 return wcslen(pWideCharStr) * (iCodePage == CP_UTF8 ? 3 : 2) + 1;
115 }
116
117 strcpy(cp, m_cpDefault);
118 #if HAVE_ICONV_IGNORE
119 strcat(cp, "//IGNORE");
120 #endif
121 cd = iconv_open(iCodePage == CP_UTF8 ? "UTF-8" : cp, UCS2_CODEPAGE_NAME);
122 if (cd != (iconv_t)(-1))
123 {
124 inbuf = (char *)pWideCharStr;
125 inbytes = ((cchWideChar == -1) ? wcslen(pWideCharStr) + 1 : cchWideChar) * sizeof(WCHAR);
126 outbuf = pByteStr;
127 outbytes = cchByteChar;
128 nRet = iconv(cd, (ICONV_CONST char **)&inbuf, &inbytes, &outbuf, &outbytes);
129 iconv_close(cd);
130 if (nRet == -1)
131 {
132 if (errno == EILSEQ)
133 {
134 nRet = cchByteChar - outbytes;
135 }
136 else
137 {
138 nRet = 0;
139 }
140 }
141 if ((cchWideChar == -1) && (outbytes > 0))
142 {
143 *outbuf = 0;
144 }
145 }
146 else
147 {
148 *pByteStr = 0;
149 nRet = 0;
150 }
151 return nRet;
152
153 #else
154
155 WCHAR *pSrc;
156 char *pDest;
157 int iPos, iSize;
158
159 if (cchByteChar == 0)
160 {
161 return wcslen(pWideCharStr) + 1;
162 }
163
164 iSize = (cchWideChar == -1) ? wcslen(pWideCharStr) : cchWideChar;
165 if (iSize >= cchByteChar)
166 iSize = cchByteChar - 1;
167 for(pSrc = pWideCharStr, iPos = 0, pDest = pByteStr; iPos < iSize; iPos++, pSrc++, pDest++)
168 *pDest = (*pSrc < 256) ? (char)(*pSrc) : '?';
169 *pDest = 0;
170 return iSize;
171
172 #endif /* HAVE_ICONV */
173 }
174
175
176 //
177 // Convert single-byte to UNICODE string
178 //
179
180 int LIBNETXMS_EXPORTABLE MultiByteToWideChar(int iCodePage, DWORD dwFlags,
181 char *pByteStr, int cchByteChar,
182 WCHAR *pWideCharStr, int cchWideChar)
183 {
184 #if HAVE_ICONV && !defined(__DISABLE_ICONV)
185
186 iconv_t cd;
187 int nRet;
188 char *inbuf, *outbuf;
189 size_t inbytes, outbytes;
190
191 if (cchWideChar == 0)
192 {
193 return strlen(pByteStr) + 1;
194 }
195
196 cd = iconv_open(UCS2_CODEPAGE_NAME, iCodePage == CP_UTF8 ? "UTF-8" : m_cpDefault);
197 if (cd != (iconv_t)(-1))
198 {
199 inbuf = pByteStr;
200 inbytes = (cchByteChar == -1) ? strlen(pByteStr) + 1 : cchByteChar;
201 outbuf = (char *)pWideCharStr;
202 outbytes = cchWideChar * sizeof(WCHAR);
203 nRet = iconv(cd, (ICONV_CONST char **)&inbuf, &inbytes, &outbuf, &outbytes);
204 iconv_close(cd);
205 if (nRet == -1)
206 {
207 if (errno == EILSEQ)
208 {
209 nRet = (cchWideChar * sizeof(WCHAR) - outbytes) / sizeof(WCHAR);
210 }
211 else
212 {
213 nRet = 0;
214 }
215 }
216 if ((cchByteChar == -1) && (outbytes > 1))
217 {
218 *((WCHAR *)outbuf) = 0;
219 }
220 }
221 else
222 {
223 *pWideCharStr = 0;
224 nRet = 0;
225 }
226 return nRet;
227
228 #else
229
230 char *pSrc;
231 WCHAR *pDest;
232 int iPos, iSize;
233
234 if (cchWideChar == 0)
235 {
236 return strlen(pByteStr) + 1;
237 }
238
239 iSize = (cchByteChar == -1) ? strlen(pByteStr) : cchByteChar;
240 if (iSize >= cchWideChar)
241 iSize = cchWideChar - 1;
242 for(pSrc = pByteStr, iPos = 0, pDest = pWideCharStr; iPos < iSize; iPos++, pSrc++, pDest++)
243 *pDest = (WCHAR)(*pSrc);
244 *pDest = 0;
245 return iSize;
246
247 #endif
248 }
249
250 #endif /* not _WIN32 */
251
252
253 //
254 // UNICODE version of inet_addr()
255 //
256
257 DWORD LIBNETXMS_EXPORTABLE inet_addr_w(WCHAR *pszAddr)
258 {
259 char szBuffer[256];
260
261 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
262 pszAddr, -1, szBuffer, 256, NULL, NULL);
263 return inet_addr(szBuffer);
264 }
265
266
267 //
268 // Convert multibyte string to wide string using current codepage and
269 // allocating wide string dynamically
270 //
271
272 WCHAR LIBNETXMS_EXPORTABLE *WideStringFromMBString(char *pszString)
273 {
274 WCHAR *pwszOut;
275 int nLen;
276
277 nLen = strlen(pszString) + 1;
278 pwszOut = (WCHAR *)malloc(nLen * sizeof(WCHAR));
279 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszString, -1, pwszOut, nLen);
280 return pwszOut;
281 }
282
283
284 //
285 // Convert wide string to multibyte string using current codepage and
286 // allocating multibyte string dynamically
287 //
288
289 char LIBNETXMS_EXPORTABLE *MBStringFromWideString(WCHAR *pwszString)
290 {
291 char *pszOut;
292 int nLen;
293
294 nLen = wcslen(pwszString) + 1;
295 pszOut = (char *)malloc(nLen);
296 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
297 pwszString, -1, pszOut, nLen, NULL, NULL);
298 return pszOut;
299 }
300
301
302 //
303 // Convert wide string to UTF8 string allocating UTF8 string dynamically
304 //
305
306 char LIBNETXMS_EXPORTABLE *UTF8StringFromWideString(WCHAR *pwszString)
307 {
308 char *pszOut;
309 int nLen;
310
311 nLen = WideCharToMultiByte(CP_UTF8, 0, pwszString, -1, NULL, 0, NULL, NULL);
312 pszOut = (char *)malloc(nLen);
313 WideCharToMultiByte(CP_UTF8, 0, pwszString, -1, pszOut, nLen, NULL, NULL);
314 return pszOut;
315 }