| #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; |
| } |
| |