remove LFS64 programming interfaces (macro-only) from _GNU_SOURCE
[musl] / src / ctype / towctrans.c
1 #include <wctype.h>
2
3 static const unsigned char tab[];
4
5 static const unsigned char rulebases[512];
6 static const int rules[];
7
8 static const unsigned char exceptions[][2];
9
10 #include "casemap.h"
11
12 static int casemap(unsigned c, int dir)
13 {
14         unsigned b, x, y, v, rt, xb, xn;
15         int r, rd, c0 = c;
16
17         if (c >= 0x20000) return c;
18
19         b = c>>8;
20         c &= 255;
21         x = c/3;
22         y = c%3;
23
24         /* lookup entry in two-level base-6 table */
25         v = tab[tab[b]*86+x];
26         static const int mt[] = { 2048, 342, 57 };
27         v = (v*mt[y]>>11)%6;
28
29         /* use the bit vector out of the tables as an index into
30          * a block-specific set of rules and decode the rule into
31          * a type and a case-mapping delta. */
32         r = rules[rulebases[b]+v];
33         rt = r & 255;
34         rd = r >> 8;
35
36         /* rules 0/1 are simple lower/upper case with a delta.
37          * apply according to desired mapping direction. */
38         if (rt < 2) return c0 + (rd & -(rt^dir));
39
40         /* binary search. endpoints of the binary search for
41          * this block are stored in the rule delta field. */
42         xn = rd & 0xff;
43         xb = (unsigned)rd >> 8;
44         while (xn) {
45                 unsigned try = exceptions[xb+xn/2][0];
46                 if (try == c) {
47                         r = rules[exceptions[xb+xn/2][1]];
48                         rt = r & 255;
49                         rd = r >> 8;
50                         if (rt < 2) return c0 + (rd & -(rt^dir));
51                         /* Hard-coded for the four exceptional titlecase */
52                         return c0 + (dir ? -1 : 1);
53                 } else if (try > c) {
54                         xn /= 2;
55                 } else {
56                         xb += xn/2;
57                         xn -= xn/2;
58                 }
59         }
60         return c0;
61 }
62
63 wint_t towlower(wint_t wc)
64 {
65         return casemap(wc, 0);
66 }
67
68 wint_t towupper(wint_t wc)
69 {
70         return casemap(wc, 1);
71 }
72
73 wint_t __towupper_l(wint_t c, locale_t l)
74 {
75         return towupper(c);
76 }
77
78 wint_t __towlower_l(wint_t c, locale_t l)
79 {
80         return towlower(c);
81 }
82
83 weak_alias(__towupper_l, towupper_l);
84 weak_alias(__towlower_l, towlower_l);