eaafd7cb6615235fd1f83cc497e4039a08b23a6c
[musl] / src / ctype / wcwidth.c
1 #include <inttypes.h>
2 #include <wchar.h>
3 #include <wctype.h>
4
5 #define R(a,b,w) { (b), (w)/2, (b)-(a) }
6
7 static const struct range {
8         uint32_t base:20;
9         uint32_t width:1;
10         uint32_t len:11;
11 } ranges[] = {
12         R(0x0300, 0x036F, 0),
13         R(0x0483, 0x0486, 0),
14         R(0x0488, 0x0489, 0),
15         R(0x0591, 0x05BD, 0),
16         R(0x05BF, 0x05BF, 0),
17         R(0x05C1, 0x05C2, 0),
18         R(0x05C4, 0x05C5, 0),
19         R(0x05C7, 0x05C7, 0),
20         R(0x0600, 0x0603, 0),
21         R(0x0610, 0x0615, 0),
22         R(0x064B, 0x065E, 0),
23         R(0x0670, 0x0670, 0),
24         R(0x06D6, 0x06E4, 0),
25         R(0x06E7, 0x06E8, 0),
26         R(0x06EA, 0x06ED, 0),
27         R(0x070F, 0x070F, 0),
28         R(0x0711, 0x0711, 0),
29         R(0x0730, 0x074A, 0),
30         R(0x07A6, 0x07B0, 0),
31         R(0x07EB, 0x07F3, 0),
32         R(0x0901, 0x0902, 0),
33         R(0x093C, 0x093C, 0),
34         R(0x0941, 0x0948, 0),
35         R(0x094D, 0x094D, 0),
36         R(0x0951, 0x0954, 0),
37         R(0x0962, 0x0963, 0),
38         R(0x0981, 0x0981, 0),
39         R(0x09BC, 0x09BC, 0),
40         R(0x09C1, 0x09C4, 0),
41         R(0x09CD, 0x09CD, 0),
42         R(0x09E2, 0x09E3, 0),
43         R(0x0A01, 0x0A02, 0),
44         R(0x0A3C, 0x0A3C, 0),
45         R(0x0A41, 0x0A42, 0),
46         R(0x0A47, 0x0A48, 0),
47         R(0x0A4B, 0x0A4D, 0),
48         R(0x0A70, 0x0A71, 0),
49         R(0x0A81, 0x0A82, 0),
50         R(0x0ABC, 0x0ABC, 0),
51         R(0x0AC1, 0x0AC5, 0),
52         R(0x0AC7, 0x0AC8, 0),
53         R(0x0ACD, 0x0ACD, 0),
54         R(0x0AE2, 0x0AE3, 0),
55         R(0x0B01, 0x0B01, 0),
56         R(0x0B3C, 0x0B3C, 0),
57         R(0x0B3F, 0x0B3F, 0),
58         R(0x0B41, 0x0B43, 0),
59         R(0x0B4D, 0x0B4D, 0),
60         R(0x0B56, 0x0B56, 0),
61         R(0x0B82, 0x0B82, 0),
62         R(0x0BC0, 0x0BC0, 0),
63         R(0x0BCD, 0x0BCD, 0),
64         R(0x0C3E, 0x0C40, 0),
65         R(0x0C46, 0x0C48, 0),
66         R(0x0C4A, 0x0C4D, 0),
67         R(0x0C55, 0x0C56, 0),
68         R(0x0CBC, 0x0CBC, 0),
69         R(0x0CBF, 0x0CBF, 0),
70         R(0x0CC6, 0x0CC6, 0),
71         R(0x0CCC, 0x0CCD, 0),
72         R(0x0CE2, 0x0CE3, 0),
73         R(0x0D41, 0x0D43, 0),
74         R(0x0D4D, 0x0D4D, 0),
75         R(0x0DCA, 0x0DCA, 0),
76         R(0x0DD2, 0x0DD4, 0),
77         R(0x0DD6, 0x0DD6, 0),
78         R(0x0E31, 0x0E31, 0),
79         R(0x0E34, 0x0E3A, 0),
80         R(0x0E47, 0x0E4E, 0),
81         R(0x0EB1, 0x0EB1, 0),
82         R(0x0EB4, 0x0EB9, 0),
83         R(0x0EBB, 0x0EBC, 0),
84         R(0x0EC8, 0x0ECD, 0),
85         R(0x0F18, 0x0F19, 0),
86         R(0x0F35, 0x0F35, 0),
87         R(0x0F37, 0x0F37, 0),
88         R(0x0F39, 0x0F39, 0),
89         R(0x0F71, 0x0F7E, 0),
90         R(0x0F80, 0x0F84, 0),
91         R(0x0F86, 0x0F87, 0),
92         R(0x0F90, 0x0F97, 0),
93         R(0x0F99, 0x0FBC, 0),
94         R(0x0FC6, 0x0FC6, 0),
95         R(0x102D, 0x1030, 0),
96         R(0x1032, 0x1032, 0),
97         R(0x1036, 0x1037, 0),
98         R(0x1039, 0x1039, 0),
99         R(0x1058, 0x1059, 0),
100         R(0x1100, 0x115F, 2),
101         R(0x1160, 0x11FF, 0),
102         R(0x135F, 0x135F, 0),
103         R(0x1712, 0x1714, 0),
104         R(0x1732, 0x1734, 0),
105         R(0x1752, 0x1753, 0),
106         R(0x1772, 0x1773, 0),
107         R(0x17B4, 0x17B5, 0),
108         R(0x17B7, 0x17BD, 0),
109         R(0x17C6, 0x17C6, 0),
110         R(0x17C9, 0x17D3, 0),
111         R(0x17DD, 0x17DD, 0),
112         R(0x180B, 0x180D, 0),
113         R(0x18A9, 0x18A9, 0),
114         R(0x1920, 0x1922, 0),
115         R(0x1927, 0x1928, 0),
116         R(0x1932, 0x1932, 0),
117         R(0x1939, 0x193B, 0),
118         R(0x1A17, 0x1A18, 0),
119         R(0x1B00, 0x1B03, 0),
120         R(0x1B34, 0x1B34, 0),
121         R(0x1B36, 0x1B3A, 0),
122         R(0x1B3C, 0x1B3C, 0),
123         R(0x1B42, 0x1B42, 0),
124         R(0x1B6B, 0x1B73, 0),
125         R(0x1DC0, 0x1DCA, 0),
126         R(0x1DFE, 0x1DFF, 0),
127         R(0x200B, 0x200F, 0),
128         R(0x202A, 0x202E, 0),
129         R(0x2060, 0x2063, 0),
130         R(0x206A, 0x206F, 0),
131         R(0x20D0, 0x20EF, 0),
132         R(0x2329, 0x232A, 2),
133         R(0x2E80, 0x3029, 2),
134         R(0x302A, 0x302F, 0),
135         R(0x3030, 0x303E, 2),
136         R(0x3099, 0x309A, 0),
137         R(0xA806, 0xA806, 0),
138         R(0xA80B, 0xA80B, 0),
139         R(0xA825, 0xA826, 0),
140         R(0xF900, 0xFAFF, 2),
141         R(0xFB1E, 0xFB1E, 0),
142         R(0xFE00, 0xFE0F, 0),
143         R(0xFE20, 0xFE23, 0),
144         R(0xFE30, 0xFE6F, 2),
145         R(0xFEFF, 0xFEFF, 0),
146         R(0xFF00, 0xFF60, 2),
147         R(0xFFE0, 0xFFE6, 2),
148         R(0x10A01, 0x10A03, 0),
149         R(0x10A05, 0x10A06, 0),
150         R(0x10A0C, 0x10A0F, 0),
151         R(0x10A38, 0x10A3A, 0),
152         R(0x10A3F, 0x10A3F, 0),
153         R(0x1D167, 0x1D169, 0),
154         R(0x1D173, 0x1D182, 0),
155         R(0x1D185, 0x1D18B, 0),
156         R(0x1D1AA, 0x1D1AD, 0),
157         R(0x1D242, 0x1D244, 0),
158         R(0xE0001, 0xE0001, 0),
159         R(0xE0020, 0xE007F, 0),
160         R(0xE0100, 0xE01EF, 0),
161 };
162
163 /* Note: because the len field is only 10 bits, we must special-case
164  * the two huge ranges of full width characters and exclude them
165  * from the binary search table. */
166
167 int wcwidth(wchar_t wc)
168 {
169         int a, n;
170         uint32_t c = wc;
171
172         if (c-0x20 < 0x5f) return 1;
173         if (!iswprint(c)) return wc ? -1 : 0;
174         if (c-0x20000 < 0x20000) return 2;
175
176         /* The following code is a branchless binary search. */
177         a = 0;
178         n = sizeof ranges / sizeof ranges[0];
179         do {
180                 n >>= 1;
181                 a += n+1 & (signed)(ranges[a+n].base-c)>>31;
182         } while (n);
183         if (ranges[a].base-c <= ranges[a].len)
184                 return 2*ranges[a].width;
185         return 1 + (c-0x3040 < 0xd800-0x3040);
186 }