mbwc.c - 9base - revived minimalist port of Plan 9 userland to Unix
HTML git clone git://git.suckless.org/9base
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
mbwc.c (2272B)
---
1 #include <stdlib.h>
2 #include "mbwc.h"
3
4 /*
5 * Use the FSS-UTF transformation proposed by posix.
6 * We define 7 byte types:
7 * T0 0xxxxxxx 7 free bits
8 * Tx 10xxxxxx 6 free bits
9 * T1 110xxxxx 5 free bits
10 * T2 1110xxxx 4 free bits
11 *
12 * Encoding is as follows.
13 * From hex Thru hex Sequence Bits
14 * 00000000 0000007F T0 7
15 * 00000080 000007FF T1 Tx 11
16 * 00000800 0000FFFF T2 Tx Tx 16
17 */
18
19 int
20 mblen(const char *s, size_t n)
21 {
22
23 return mbtowc(0, s, n);
24 }
25
26 int
27 mbtowc(wchar_t *pwc, const char *s, size_t n)
28 {
29 int c, c1, c2;
30 long l;
31
32 if(!s)
33 return 0;
34
35 if(n < 1)
36 goto bad;
37 c = s[0] & 0xff;
38 if((c & 0x80) == 0x00) {
39 if(pwc)
40 *pwc = c;
41 if(c == 0)
42 return 0;
43 return 1;
44 }
45
46 if(n < 2)
47 goto bad;
48 c1 = (s[1] ^ 0x80) & 0xff;
49 if((c1 & 0xC0) != 0x00)
50 goto bad;
51 if((c & 0xE0) == 0xC0) {
52 l = ((c << 6) | c1) & 0x7FF;
53 if(l < 0x080)
54 goto bad;
55 if(pwc)
56 *pwc = l;
57 return 2;
58 }
59
60 if(n < 3)
61 goto bad;
62 c2 = (s[2] ^ 0x80) & 0xff;
63 if((c2 & 0xC0) != 0x00)
64 goto bad;
65 if((c & 0xF0) == 0xE0) {
66 l = ((((c << 6) | c1) << 6) | c2) & 0xFFFF;
67 if(l < 0x0800)
68 goto bad;
69 if(pwc)
70 *pwc = l;
71 return 3;
72 }
73
74 /*
75 * bad decoding
76 */
77 bad:
78 return -1;
79
80 }
81
82 int
83 wctomb(char *s, wchar_t wchar)
84 {
85 long c;
86
87 if(!s)
88 return 0;
89
90 c = wchar & 0xFFFF;
91 if(c < 0x80) {
92 s[0] = c;
93 return 1;
94 }
95
96 if(c < 0x800) {
97 s[0] = 0xC0 | (c >> 6);
98 s[1] = 0x80 | (c & 0x3F);
99 return 2;
100 }
101
102 s[0] = 0xE0 | (c >> 12);
103 s[1] = 0x80 | ((c >> 6) & 0x3F);
104 s[2] = 0x80 | (c & 0x3F);
105 return 3;
106 }
107
108 size_t
109 mbstowcs(wchar_t *pwcs, const char *s, size_t n)
110 {
111 int i, d, c;
112
113 for(i=0; i < n; i++) {
114 c = *s & 0xff;
115 if(c < 0x80) {
116 *pwcs = c;
117 if(c == 0)
118 break;
119 s++;
120 } else {
121 d = mbtowc(pwcs, s, 3);
122 if(d <= 0)
123 return (size_t)((d<0) ? -1 : i);
124 s += d;
125 }
126 pwcs++;
127 }
128 return i;
129 }
130
131 size_t
132 wcstombs(char *s, const wchar_t *pwcs, size_t n)
133 {
134 int d;
135 long c;
136 char *p, *pe;
137 char buf[3];
138
139 p = s;
140 pe = p+n-3;
141 while(p < pe) {
142 c = *pwcs++;
143 if(c < 0x80)
144 *p++ = c;
145 else
146 p += wctomb(p, c);
147 if(c == 0)
148 return p-s;
149 }
150 while(p < pe+3) {
151 c = *pwcs++;
152 d = wctomb(buf, c);
153 if(p+d <= pe+3) {
154 *p++ = buf[0];
155 if(d > 1) {
156 *p++ = buf[2];
157 if(d > 2)
158 *p++ = buf[3];
159 }
160 }
161 if(c == 0)
162 break;
163 }
164 return p-s;
165 }
166