utf-8-conv.c revision 1.1.1.2 1 1.1.1.2 lukem /* $NetBSD: utf-8-conv.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */
2 1.1.1.2 lukem
3 1.1.1.2 lukem /* OpenLDAP: pkg/ldap/libraries/libldap/utf-8-conv.c,v 1.16.2.5 2009/08/25 22:58:08 quanah Exp */
4 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 1.1 lukem *
6 1.1.1.2 lukem * Copyright 1998-2009 The OpenLDAP Foundation.
7 1.1 lukem * All rights reserved.
8 1.1 lukem *
9 1.1 lukem * Redistribution and use in source and binary forms, with or without
10 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
11 1.1 lukem * Public License.
12 1.1 lukem *
13 1.1 lukem * A copy of this license is available in the file LICENSE in the
14 1.1 lukem * top-level directory of the distribution or, alternatively, at
15 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
16 1.1 lukem */
17 1.1 lukem /* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
18 1.1 lukem *
19 1.1 lukem * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
20 1.1 lukem * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
21 1.1 lukem * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
22 1.1 lukem * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
23 1.1 lukem * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
24 1.1 lukem * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
25 1.1 lukem * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
26 1.1 lukem * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
27 1.1 lukem *---
28 1.1 lukem * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
29 1.1 lukem * can be found in the file "build/LICENSE-2.0.1" in this distribution
30 1.1 lukem * of OpenLDAP Software.
31 1.1 lukem */
32 1.1 lukem
33 1.1 lukem /*
34 1.1 lukem * UTF-8 Conversion Routines
35 1.1 lukem *
36 1.1 lukem * These routines convert between Wide Character and UTF-8,
37 1.1 lukem * or between MultiByte and UTF-8 encodings.
38 1.1 lukem *
39 1.1 lukem * Both single character and string versions of the functions are provided.
40 1.1 lukem * All functions return -1 if the character or string cannot be converted.
41 1.1 lukem */
42 1.1 lukem
43 1.1 lukem #include "portable.h"
44 1.1 lukem
45 1.1 lukem #if SIZEOF_WCHAR_T >= 4
46 1.1 lukem /* These routines assume ( sizeof(wchar_t) >= 4 ) */
47 1.1 lukem
48 1.1 lukem #include <stdio.h>
49 1.1 lukem #include <ac/stdlib.h> /* For wctomb, wcstombs, mbtowc, mbstowcs */
50 1.1 lukem #include <ac/string.h>
51 1.1 lukem #include <ac/time.h> /* for time_t */
52 1.1 lukem
53 1.1 lukem #include "ldap-int.h"
54 1.1 lukem
55 1.1 lukem #include <ldap_utf8.h>
56 1.1 lukem
57 1.1 lukem static unsigned char mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
58 1.1 lukem
59 1.1 lukem
60 1.1 lukem /*-----------------------------------------------------------------------------
61 1.1 lukem UTF-8 Format Summary
62 1.1 lukem
63 1.1 lukem ASCII chars 7 bits
64 1.1 lukem 0xxxxxxx
65 1.1 lukem
66 1.1 lukem 2-character UTF-8 sequence: 11 bits
67 1.1 lukem 110xxxxx 10xxxxxx
68 1.1 lukem
69 1.1 lukem 3-character UTF-8 16 bits
70 1.1 lukem 1110xxxx 10xxxxxx 10xxxxxx
71 1.1 lukem
72 1.1 lukem 4-char UTF-8 21 bits
73 1.1 lukem 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
74 1.1 lukem
75 1.1 lukem 5-char UTF-8 26 bits
76 1.1 lukem 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
77 1.1 lukem
78 1.1 lukem 6-char UTF-8 31 bits
79 1.1 lukem 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
80 1.1 lukem
81 1.1 lukem Unicode address space (0 - 0x10FFFF) 21 bits
82 1.1 lukem ISO-10646 address space (0 - 0x7FFFFFFF) 31 bits
83 1.1 lukem
84 1.1 lukem Note: This code does not prevent UTF-8 sequences which are longer than
85 1.1 lukem necessary from being decoded.
86 1.1 lukem */
87 1.1 lukem
88 1.1 lukem /*-----------------------------------------------------------------------------
89 1.1 lukem Convert a UTF-8 character to a wide char.
90 1.1 lukem Return the length of the UTF-8 input character in bytes.
91 1.1 lukem */
92 1.1 lukem int
93 1.1 lukem ldap_x_utf8_to_wc ( wchar_t *wchar, const char *utf8char )
94 1.1 lukem {
95 1.1 lukem int utflen, i;
96 1.1 lukem wchar_t ch;
97 1.1 lukem
98 1.1 lukem if (utf8char == NULL) return -1;
99 1.1 lukem
100 1.1 lukem /* Get UTF-8 sequence length from 1st byte */
101 1.1 lukem utflen = LDAP_UTF8_CHARLEN2(utf8char, utflen);
102 1.1 lukem
103 1.1 lukem if( utflen==0 || utflen > (int)LDAP_MAX_UTF8_LEN ) return -1;
104 1.1 lukem
105 1.1 lukem /* First byte minus length tag */
106 1.1 lukem ch = (wchar_t)(utf8char[0] & mask[utflen]);
107 1.1 lukem
108 1.1 lukem for(i=1; i < utflen; i++) {
109 1.1 lukem /* Subsequent bytes must start with 10 */
110 1.1 lukem if ((utf8char[i] & 0xc0) != 0x80) return -1;
111 1.1 lukem
112 1.1 lukem ch <<= 6; /* 6 bits of data in each subsequent byte */
113 1.1 lukem ch |= (wchar_t)(utf8char[i] & 0x3f);
114 1.1 lukem }
115 1.1 lukem
116 1.1 lukem if (wchar) *wchar = ch;
117 1.1 lukem
118 1.1 lukem return utflen;
119 1.1 lukem }
120 1.1 lukem
121 1.1 lukem /*-----------------------------------------------------------------------------
122 1.1 lukem Convert a UTF-8 string to a wide char string.
123 1.1 lukem No more than 'count' wide chars will be written to the output buffer.
124 1.1 lukem Return the size of the converted string in wide chars, excl null terminator.
125 1.1 lukem */
126 1.1 lukem int
127 1.1 lukem ldap_x_utf8s_to_wcs ( wchar_t *wcstr, const char *utf8str, size_t count )
128 1.1 lukem {
129 1.1 lukem size_t wclen = 0;
130 1.1 lukem int utflen, i;
131 1.1 lukem wchar_t ch;
132 1.1 lukem
133 1.1 lukem
134 1.1 lukem /* If input ptr is NULL or empty... */
135 1.1 lukem if (utf8str == NULL || !*utf8str) {
136 1.1 lukem if ( wcstr )
137 1.1 lukem *wcstr = 0;
138 1.1 lukem return 0;
139 1.1 lukem }
140 1.1 lukem
141 1.1 lukem /* Examine next UTF-8 character. If output buffer is NULL, ignore count */
142 1.1 lukem while ( *utf8str && (wcstr==NULL || wclen<count) ) {
143 1.1 lukem /* Get UTF-8 sequence length from 1st byte */
144 1.1 lukem utflen = LDAP_UTF8_CHARLEN2(utf8str, utflen);
145 1.1 lukem
146 1.1 lukem if( utflen==0 || utflen > (int)LDAP_MAX_UTF8_LEN ) return -1;
147 1.1 lukem
148 1.1 lukem /* First byte minus length tag */
149 1.1 lukem ch = (wchar_t)(utf8str[0] & mask[utflen]);
150 1.1 lukem
151 1.1 lukem for(i=1; i < utflen; i++) {
152 1.1 lukem /* Subsequent bytes must start with 10 */
153 1.1 lukem if ((utf8str[i] & 0xc0) != 0x80) return -1;
154 1.1 lukem
155 1.1 lukem ch <<= 6; /* 6 bits of data in each subsequent byte */
156 1.1 lukem ch |= (wchar_t)(utf8str[i] & 0x3f);
157 1.1 lukem }
158 1.1 lukem
159 1.1 lukem if (wcstr) wcstr[wclen] = ch;
160 1.1 lukem
161 1.1 lukem utf8str += utflen; /* Move to next UTF-8 character */
162 1.1 lukem wclen++; /* Count number of wide chars stored/required */
163 1.1 lukem }
164 1.1 lukem
165 1.1 lukem /* Add null terminator if there's room in the buffer. */
166 1.1 lukem if (wcstr && wclen < count) wcstr[wclen] = 0;
167 1.1 lukem
168 1.1 lukem return wclen;
169 1.1 lukem }
170 1.1 lukem
171 1.1 lukem
172 1.1 lukem /*-----------------------------------------------------------------------------
173 1.1 lukem Convert one wide char to a UTF-8 character.
174 1.1 lukem Return the length of the converted UTF-8 character in bytes.
175 1.1 lukem No more than 'count' bytes will be written to the output buffer.
176 1.1 lukem */
177 1.1 lukem int
178 1.1 lukem ldap_x_wc_to_utf8 ( char *utf8char, wchar_t wchar, size_t count )
179 1.1 lukem {
180 1.1 lukem int len=0;
181 1.1 lukem
182 1.1 lukem if (utf8char == NULL) /* Just determine the required UTF-8 char length. */
183 1.1 lukem { /* Ignore count */
184 1.1 lukem if( wchar < 0 )
185 1.1 lukem return -1;
186 1.1 lukem if( wchar < 0x80 )
187 1.1 lukem return 1;
188 1.1 lukem if( wchar < 0x800 )
189 1.1 lukem return 2;
190 1.1 lukem if( wchar < 0x10000 )
191 1.1 lukem return 3;
192 1.1 lukem if( wchar < 0x200000 )
193 1.1 lukem return 4;
194 1.1 lukem if( wchar < 0x4000000 )
195 1.1 lukem return 5;
196 1.1.1.2 lukem #if SIZEOF_WCHAR_T > 4
197 1.1.1.2 lukem /* UL is not strictly needed by ANSI C */
198 1.1.1.2 lukem if( wchar < (wchar_t)0x80000000UL )
199 1.1.1.2 lukem #endif /* SIZEOF_WCHAR_T > 4 */
200 1.1 lukem return 6;
201 1.1 lukem return -1;
202 1.1 lukem }
203 1.1 lukem
204 1.1 lukem
205 1.1 lukem if ( wchar < 0 ) { /* Invalid wide character */
206 1.1 lukem len = -1;
207 1.1 lukem
208 1.1 lukem } else if( wchar < 0x80 ) {
209 1.1 lukem if (count >= 1) {
210 1.1 lukem utf8char[len++] = (char)wchar;
211 1.1 lukem }
212 1.1 lukem
213 1.1 lukem } else if( wchar < 0x800 ) {
214 1.1 lukem if (count >=2) {
215 1.1 lukem utf8char[len++] = 0xc0 | ( wchar >> 6 );
216 1.1 lukem utf8char[len++] = 0x80 | ( wchar & 0x3f );
217 1.1 lukem }
218 1.1 lukem
219 1.1 lukem } else if( wchar < 0x10000 ) {
220 1.1 lukem if (count >= 3) {
221 1.1 lukem utf8char[len++] = 0xe0 | ( wchar >> 12 );
222 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f );
223 1.1 lukem utf8char[len++] = 0x80 | ( wchar & 0x3f );
224 1.1 lukem }
225 1.1 lukem
226 1.1 lukem } else if( wchar < 0x200000 ) {
227 1.1 lukem if (count >= 4) {
228 1.1 lukem utf8char[len++] = 0xf0 | ( wchar >> 18 );
229 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 12) & 0x3f );
230 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f );
231 1.1 lukem utf8char[len++] = 0x80 | ( wchar & 0x3f );
232 1.1 lukem }
233 1.1 lukem
234 1.1 lukem } else if( wchar < 0x4000000 ) {
235 1.1 lukem if (count >= 5) {
236 1.1 lukem utf8char[len++] = 0xf8 | ( wchar >> 24 );
237 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 18) & 0x3f );
238 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 12) & 0x3f );
239 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f );
240 1.1 lukem utf8char[len++] = 0x80 | ( wchar & 0x3f );
241 1.1 lukem }
242 1.1 lukem
243 1.1.1.2 lukem } else
244 1.1.1.2 lukem #if SIZEOF_WCHAR_T > 4
245 1.1.1.2 lukem /* UL is not strictly needed by ANSI C */
246 1.1.1.2 lukem if( wchar < (wchar_t)0x80000000UL )
247 1.1.1.2 lukem #endif /* SIZEOF_WCHAR_T > 4 */
248 1.1.1.2 lukem {
249 1.1 lukem if (count >= 6) {
250 1.1 lukem utf8char[len++] = 0xfc | ( wchar >> 30 );
251 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 24) & 0x3f );
252 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 18) & 0x3f );
253 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 12) & 0x3f );
254 1.1 lukem utf8char[len++] = 0x80 | ( (wchar >> 6) & 0x3f );
255 1.1 lukem utf8char[len++] = 0x80 | ( wchar & 0x3f );
256 1.1 lukem }
257 1.1 lukem
258 1.1.1.2 lukem #if SIZEOF_WCHAR_T > 4
259 1.1.1.2 lukem } else {
260 1.1 lukem len = -1;
261 1.1.1.2 lukem #endif /* SIZEOF_WCHAR_T > 4 */
262 1.1.1.2 lukem }
263 1.1 lukem
264 1.1 lukem return len;
265 1.1 lukem
266 1.1 lukem }
267 1.1 lukem
268 1.1 lukem
269 1.1 lukem /*-----------------------------------------------------------------------------
270 1.1 lukem Convert a wide char string to a UTF-8 string.
271 1.1 lukem No more than 'count' bytes will be written to the output buffer.
272 1.1 lukem Return the # of bytes written to the output buffer, excl null terminator.
273 1.1 lukem */
274 1.1 lukem int
275 1.1 lukem ldap_x_wcs_to_utf8s ( char *utf8str, const wchar_t *wcstr, size_t count )
276 1.1 lukem {
277 1.1 lukem int len = 0;
278 1.1 lukem int n;
279 1.1 lukem char *p = utf8str;
280 1.1 lukem wchar_t empty = 0; /* To avoid use of L"" construct */
281 1.1 lukem
282 1.1 lukem if (wcstr == NULL) /* Treat input ptr NULL as an empty string */
283 1.1 lukem wcstr = ∅
284 1.1 lukem
285 1.1 lukem if (utf8str == NULL) /* Just compute size of output, excl null */
286 1.1 lukem {
287 1.1 lukem while (*wcstr)
288 1.1 lukem {
289 1.1 lukem /* Get UTF-8 size of next wide char */
290 1.1 lukem n = ldap_x_wc_to_utf8( NULL, *wcstr++, LDAP_MAX_UTF8_LEN);
291 1.1 lukem if (n == -1)
292 1.1 lukem return -1;
293 1.1 lukem len += n;
294 1.1 lukem }
295 1.1 lukem
296 1.1 lukem return len;
297 1.1 lukem }
298 1.1 lukem
299 1.1 lukem
300 1.1 lukem /* Do the actual conversion. */
301 1.1 lukem
302 1.1 lukem n = 1; /* In case of empty wcstr */
303 1.1 lukem while (*wcstr)
304 1.1 lukem {
305 1.1 lukem n = ldap_x_wc_to_utf8( p, *wcstr++, count);
306 1.1 lukem
307 1.1 lukem if (n <= 0) /* If encoding error (-1) or won't fit (0), quit */
308 1.1 lukem break;
309 1.1 lukem
310 1.1 lukem p += n;
311 1.1 lukem count -= n; /* Space left in output buffer */
312 1.1 lukem }
313 1.1 lukem
314 1.1 lukem /* If not enough room for last character, pad remainder with null
315 1.1 lukem so that return value = original count, indicating buffer full. */
316 1.1 lukem if (n == 0)
317 1.1 lukem {
318 1.1 lukem while (count--)
319 1.1 lukem *p++ = 0;
320 1.1 lukem }
321 1.1 lukem
322 1.1 lukem /* Add a null terminator if there's room. */
323 1.1 lukem else if (count)
324 1.1 lukem *p = 0;
325 1.1 lukem
326 1.1 lukem if (n == -1) /* Conversion encountered invalid wide char. */
327 1.1 lukem return -1;
328 1.1 lukem
329 1.1 lukem /* Return the number of bytes written to output buffer, excl null. */
330 1.1 lukem return (p - utf8str);
331 1.1 lukem }
332 1.1 lukem
333 1.1 lukem
334 1.1 lukem /*-----------------------------------------------------------------------------
335 1.1 lukem Convert a UTF-8 character to a MultiByte character.
336 1.1 lukem Return the size of the converted character in bytes.
337 1.1 lukem */
338 1.1 lukem int
339 1.1 lukem ldap_x_utf8_to_mb ( char *mbchar, const char *utf8char,
340 1.1 lukem int (*f_wctomb)(char *mbchar, wchar_t wchar) )
341 1.1 lukem {
342 1.1 lukem wchar_t wchar;
343 1.1 lukem int n;
344 1.1 lukem char tmp[6]; /* Large enough for biggest multibyte char */
345 1.1 lukem
346 1.1 lukem if (f_wctomb == NULL) /* If no conversion function was given... */
347 1.1 lukem f_wctomb = wctomb; /* use the local ANSI C function */
348 1.1 lukem
349 1.1 lukem /* First convert UTF-8 char to a wide char */
350 1.1 lukem n = ldap_x_utf8_to_wc( &wchar, utf8char);
351 1.1 lukem
352 1.1 lukem if (n == -1)
353 1.1 lukem return -1; /* Invalid UTF-8 character */
354 1.1 lukem
355 1.1 lukem if (mbchar == NULL)
356 1.1 lukem n = f_wctomb( tmp, wchar );
357 1.1 lukem else
358 1.1 lukem n = f_wctomb( mbchar, wchar);
359 1.1 lukem
360 1.1 lukem return n;
361 1.1 lukem }
362 1.1 lukem
363 1.1 lukem /*-----------------------------------------------------------------------------
364 1.1 lukem Convert a UTF-8 string to a MultiByte string.
365 1.1 lukem No more than 'count' bytes will be written to the output buffer.
366 1.1 lukem Return the size of the converted string in bytes, excl null terminator.
367 1.1 lukem */
368 1.1 lukem int
369 1.1 lukem ldap_x_utf8s_to_mbs ( char *mbstr, const char *utf8str, size_t count,
370 1.1 lukem size_t (*f_wcstombs)(char *mbstr, const wchar_t *wcstr, size_t count) )
371 1.1 lukem {
372 1.1 lukem wchar_t *wcs;
373 1.1 lukem size_t wcsize;
374 1.1 lukem int n;
375 1.1 lukem
376 1.1 lukem if (f_wcstombs == NULL) /* If no conversion function was given... */
377 1.1 lukem f_wcstombs = wcstombs; /* use the local ANSI C function */
378 1.1 lukem
379 1.1 lukem if (utf8str == NULL || *utf8str == 0) /* NULL or empty input string */
380 1.1 lukem {
381 1.1 lukem if (mbstr)
382 1.1 lukem *mbstr = 0;
383 1.1 lukem return 0;
384 1.1 lukem }
385 1.1 lukem
386 1.1 lukem /* Allocate memory for the maximum size wchar string that we could get. */
387 1.1 lukem wcsize = strlen(utf8str) + 1;
388 1.1 lukem wcs = (wchar_t *)LDAP_MALLOC(wcsize * sizeof(wchar_t));
389 1.1 lukem if (wcs == NULL)
390 1.1 lukem return -1; /* Memory allocation failure. */
391 1.1 lukem
392 1.1 lukem /* First convert the UTF-8 string to a wide char string */
393 1.1 lukem n = ldap_x_utf8s_to_wcs( wcs, utf8str, wcsize);
394 1.1 lukem
395 1.1 lukem /* Then convert wide char string to multi-byte string */
396 1.1 lukem if (n != -1)
397 1.1 lukem {
398 1.1 lukem n = f_wcstombs(mbstr, wcs, count);
399 1.1 lukem }
400 1.1 lukem
401 1.1 lukem LDAP_FREE(wcs);
402 1.1 lukem
403 1.1 lukem return n;
404 1.1 lukem }
405 1.1 lukem
406 1.1 lukem /*-----------------------------------------------------------------------------
407 1.1 lukem Convert a MultiByte character to a UTF-8 character.
408 1.1 lukem 'mbsize' indicates the number of bytes of 'mbchar' to check.
409 1.1 lukem Returns the number of bytes written to the output character.
410 1.1 lukem */
411 1.1 lukem int
412 1.1 lukem ldap_x_mb_to_utf8 ( char *utf8char, const char *mbchar, size_t mbsize,
413 1.1 lukem int (*f_mbtowc)(wchar_t *wchar, const char *mbchar, size_t count) )
414 1.1 lukem {
415 1.1 lukem wchar_t wchar;
416 1.1 lukem int n;
417 1.1 lukem
418 1.1 lukem if (f_mbtowc == NULL) /* If no conversion function was given... */
419 1.1 lukem f_mbtowc = mbtowc; /* use the local ANSI C function */
420 1.1 lukem
421 1.1 lukem if (mbsize == 0) /* 0 is not valid. */
422 1.1 lukem return -1;
423 1.1 lukem
424 1.1 lukem if (mbchar == NULL || *mbchar == 0)
425 1.1 lukem {
426 1.1 lukem if (utf8char)
427 1.1 lukem *utf8char = 0;
428 1.1 lukem return 1;
429 1.1 lukem }
430 1.1 lukem
431 1.1 lukem /* First convert the MB char to a Wide Char */
432 1.1 lukem n = f_mbtowc( &wchar, mbchar, mbsize);
433 1.1 lukem
434 1.1 lukem if (n == -1)
435 1.1 lukem return -1;
436 1.1 lukem
437 1.1 lukem /* Convert the Wide Char to a UTF-8 character. */
438 1.1 lukem n = ldap_x_wc_to_utf8( utf8char, wchar, LDAP_MAX_UTF8_LEN);
439 1.1 lukem
440 1.1 lukem return n;
441 1.1 lukem }
442 1.1 lukem
443 1.1 lukem
444 1.1 lukem /*-----------------------------------------------------------------------------
445 1.1 lukem Convert a MultiByte string to a UTF-8 string.
446 1.1 lukem No more than 'count' bytes will be written to the output buffer.
447 1.1 lukem Return the size of the converted string in bytes, excl null terminator.
448 1.1 lukem */
449 1.1 lukem int
450 1.1 lukem ldap_x_mbs_to_utf8s ( char *utf8str, const char *mbstr, size_t count,
451 1.1 lukem size_t (*f_mbstowcs)(wchar_t *wcstr, const char *mbstr, size_t count) )
452 1.1 lukem {
453 1.1 lukem wchar_t *wcs;
454 1.1 lukem int n;
455 1.1 lukem size_t wcsize;
456 1.1 lukem
457 1.1 lukem if (mbstr == NULL) /* Treat NULL input string as an empty string */
458 1.1 lukem mbstr = "";
459 1.1 lukem
460 1.1 lukem if (f_mbstowcs == NULL) /* If no conversion function was given... */
461 1.1 lukem f_mbstowcs = mbstowcs; /* use the local ANSI C function */
462 1.1 lukem
463 1.1 lukem /* Allocate memory for the maximum size wchar string that we could get. */
464 1.1 lukem wcsize = strlen(mbstr) + 1;
465 1.1 lukem wcs = (wchar_t *)LDAP_MALLOC( wcsize * sizeof(wchar_t) );
466 1.1 lukem if (wcs == NULL)
467 1.1 lukem return -1;
468 1.1 lukem
469 1.1 lukem /* First convert multi-byte string to a wide char string */
470 1.1 lukem n = f_mbstowcs(wcs, mbstr, wcsize);
471 1.1 lukem
472 1.1 lukem /* Convert wide char string to UTF-8 string */
473 1.1 lukem if (n != -1)
474 1.1 lukem {
475 1.1 lukem n = ldap_x_wcs_to_utf8s( utf8str, wcs, count);
476 1.1 lukem }
477 1.1 lukem
478 1.1 lukem LDAP_FREE(wcs);
479 1.1 lukem
480 1.1 lukem return n;
481 1.1 lukem }
482 1.1 lukem
483 1.1.1.2 lukem #endif /* SIZEOF_WCHAR_T >= 4 */
484