|  | #include <stdlib.h> | 
|  |  | 
|  | /* | 
|  | * Use the FSS-UTF transformation proposed by posix. | 
|  | *	We define 7 byte types: | 
|  | *	T0	0xxxxxxx	7 free bits | 
|  | *	Tx	10xxxxxx	6 free bits | 
|  | *	T1	110xxxxx	5 free bits | 
|  | *	T2	1110xxxx	4 free bits | 
|  | * | 
|  | *	Encoding is as follows. | 
|  | *	From hex	Thru hex	Sequence		Bits | 
|  | *	00000000	0000007F	T0			7 | 
|  | *	00000080	000007FF	T1 Tx			11 | 
|  | *	00000800	0000FFFF	T2 Tx Tx		16 | 
|  | */ | 
|  |  | 
|  | int | 
|  | mblen(const char *s, size_t n) | 
|  | { | 
|  |  | 
|  | return mbtowc(0, s, n); | 
|  | } | 
|  |  | 
|  | int | 
|  | mbtowc(wchar_t *pwc, const char *s, size_t n) | 
|  | { | 
|  | int c, c1, c2; | 
|  | long l; | 
|  |  | 
|  | if(!s) | 
|  | return 0; | 
|  |  | 
|  | if(n < 1) | 
|  | goto bad; | 
|  | c = s[0] & 0xff; | 
|  | if((c & 0x80) == 0x00) { | 
|  | if(pwc) | 
|  | *pwc = c; | 
|  | if(c == 0) | 
|  | return 0; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | if(n < 2) | 
|  | goto bad; | 
|  | c1 = (s[1] ^ 0x80) & 0xff; | 
|  | if((c1 & 0xC0) != 0x00) | 
|  | goto bad; | 
|  | if((c & 0xE0) == 0xC0) { | 
|  | l = ((c << 6) | c1) & 0x7FF; | 
|  | if(l < 0x080) | 
|  | goto bad; | 
|  | if(pwc) | 
|  | *pwc = l; | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | if(n < 3) | 
|  | goto bad; | 
|  | c2 = (s[2] ^ 0x80) & 0xff; | 
|  | if((c2 & 0xC0) != 0x00) | 
|  | goto bad; | 
|  | if((c & 0xF0) == 0xE0) { | 
|  | l = ((((c << 6) | c1) << 6) | c2) & 0xFFFF; | 
|  | if(l < 0x0800) | 
|  | goto bad; | 
|  | if(pwc) | 
|  | *pwc = l; | 
|  | return 3; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * bad decoding | 
|  | */ | 
|  | bad: | 
|  | return -1; | 
|  |  | 
|  | } | 
|  |  | 
|  | int | 
|  | wctomb(char *s, wchar_t wchar) | 
|  | { | 
|  | long c; | 
|  |  | 
|  | if(!s) | 
|  | return 0; | 
|  |  | 
|  | c = wchar & 0xFFFF; | 
|  | if(c < 0x80) { | 
|  | s[0] = c; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | if(c < 0x800) { | 
|  | s[0] = 0xC0 | (c >> 6); | 
|  | s[1] = 0x80 | (c & 0x3F); | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | s[0] = 0xE0 |  (c >> 12); | 
|  | s[1] = 0x80 | ((c >> 6) & 0x3F); | 
|  | s[2] = 0x80 |  (c & 0x3F); | 
|  | return 3; | 
|  | } | 
|  |  | 
|  | size_t | 
|  | mbstowcs(wchar_t *pwcs, const char *s, size_t n) | 
|  | { | 
|  | int i, d, c; | 
|  |  | 
|  | for(i=0; i < n; i++) { | 
|  | c = *s & 0xff; | 
|  | if(c < 0x80) { | 
|  | *pwcs = c; | 
|  | if(c == 0) | 
|  | break; | 
|  | s++; | 
|  | } else { | 
|  | d = mbtowc(pwcs, s, 3); | 
|  | if(d <= 0) | 
|  | return (size_t)((d<0) ? -1 : i); | 
|  | s += d; | 
|  | } | 
|  | pwcs++; | 
|  | } | 
|  | return i; | 
|  | } | 
|  |  | 
|  | size_t | 
|  | wcstombs(char *s, const wchar_t *pwcs, size_t n) | 
|  | { | 
|  | int d; | 
|  | long c; | 
|  | char *p, *pe; | 
|  | char buf[3]; | 
|  |  | 
|  | p = s; | 
|  | pe = p+n-3; | 
|  | while(p < pe) { | 
|  | c = *pwcs++; | 
|  | if(c < 0x80) | 
|  | *p++ = c; | 
|  | else | 
|  | p += wctomb(p, c); | 
|  | if(c == 0) | 
|  | return p-s; | 
|  | } | 
|  | while(p < pe+3) { | 
|  | c = *pwcs++; | 
|  | d = wctomb(buf, c); | 
|  | if(p+d <= pe+3) { | 
|  | *p++ = buf[0]; | 
|  | if(d > 1) { | 
|  | *p++ = buf[1]; | 
|  | if(d > 2) | 
|  | *p++ = buf[2]; | 
|  | } | 
|  | } | 
|  | if(c == 0) | 
|  | break; | 
|  | } | 
|  | return p-s; | 
|  | } | 
|  |  |