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