1 #include <wctype.h>
2 #ifndef __LITEOS__
3 #include <ctype.h>
4 #include <dlfcn.h>
5 #include <stddef.h>
6 #include <string.h>
7 #include "locale_impl.h"
8 #endif
9
10 static const unsigned char tab[];
11
12 static const unsigned char rulebases[512];
13 static const int rules[];
14
15 static const unsigned char exceptions[][2];
16
17 #include "casemap.h"
18
casemap(unsigned c,int dir)19 static int casemap(unsigned c, int dir)
20 {
21 unsigned b, x, y, v, rt, xb, xn;
22 int r, rd, c0 = c;
23
24 if (c >= 0x20000) return c;
25
26 b = c>>8;
27 c &= 255;
28 x = c/3;
29 y = c%3;
30
31 /* lookup entry in two-level base-6 table */
32 v = tab[tab[b]*86+x];
33 static const int mt[] = { 2048, 342, 57 };
34 v = (v*mt[y]>>11)%6;
35
36 /* use the bit vector out of the tables as an index into
37 * a block-specific set of rules and decode the rule into
38 * a type and a case-mapping delta. */
39 r = rules[rulebases[b]+v];
40 rt = r & 255;
41 rd = r >> 8;
42
43 /* rules 0/1 are simple lower/upper case with a delta.
44 * apply according to desired mapping direction. */
45 if (rt < 2) return c0 + (rd & -(rt^dir));
46
47 /* binary search. endpoints of the binary search for
48 * this block are stored in the rule delta field. */
49 xn = rd & 0xff;
50 xb = (unsigned)rd >> 8;
51 while (xn) {
52 unsigned try = exceptions[xb+xn/2][0];
53 if (try == c) {
54 r = rules[exceptions[xb+xn/2][1]];
55 rt = r & 255;
56 rd = r >> 8;
57 if (rt < 2) return c0 + (rd & -(rt^dir));
58 /* Hard-coded for the four exceptional titlecase */
59 return c0 + (dir ? -1 : 1);
60 } else if (try > c) {
61 xn /= 2;
62 } else {
63 xb += xn/2;
64 xn -= xn/2;
65 }
66 }
67 return c0;
68 }
69
70 #ifndef __LITEOS__
71 #define ICU_UC_SO "libhmicuuc.z.so"
72 #define UCASE_TOUPPER "ucase_toupper"
73 #define ICU_GET_VERSION_NUM_SYMBOL "GetIcuVersion"
74 static void* g_hmicu_handle = NULL;
75 static char* g_hmicu_version = NULL;
76 static wint_t (*g_hm_ucase_toupper)(wint_t);
77 static char* (*f_hmicu_version)(void);
78 static char valid_icu_symbol[64];
79
get_hmicu_handle(void)80 static void get_hmicu_handle(void)
81 {
82 if (!g_hmicu_handle) {
83 g_hmicu_handle = dlopen(ICU_UC_SO, RTLD_LOCAL);
84 }
85 }
86
get_icu_version_num(void)87 static void get_icu_version_num(void) {
88 get_hmicu_handle();
89 if (g_hmicu_handle) {
90 f_hmicu_version = dlsym(g_hmicu_handle, ICU_GET_VERSION_NUM_SYMBOL);
91 }
92
93 if (f_hmicu_version) {
94 g_hmicu_version = f_hmicu_version();
95 }
96 }
97
find_hmicu_symbol(const char * symbol_name)98 static void* find_hmicu_symbol(const char* symbol_name) {
99 get_icu_version_num();
100 if (g_hmicu_version) {
101 snprintf(valid_icu_symbol, sizeof(valid_icu_symbol), "%s_%s", symbol_name, g_hmicu_version);
102 return dlsym(g_hmicu_handle, valid_icu_symbol);
103 }
104 return NULL;
105 }
106 #endif
107
towlower(wint_t wc)108 wint_t towlower(wint_t wc)
109 {
110 #ifndef __LITEOS__
111 if (wc < 0x80) {
112 if (wc >= 'A' && wc <= 'Z') return wc | 0x20;
113 return wc;
114 }
115 #endif
116 return casemap(wc, 0);
117 }
118
towupper(wint_t wc)119 wint_t towupper(wint_t wc)
120 {
121 #ifndef __LITEOS__
122 if (wc < 0x80) {
123 if (wc >= 'a' && wc <= 'z') return wc ^ 0x20;
124 return wc;
125 }
126 if (!g_hm_ucase_toupper) {
127 typedef wint_t (*f)(wint_t);
128 g_hm_ucase_toupper = (f)find_hmicu_symbol(UCASE_TOUPPER);
129 }
130 return g_hm_ucase_toupper ? g_hm_ucase_toupper(wc) : casemap(wc, 1);
131 #else
132 return casemap(wc, 1);
133 #endif
134 }
135
__towupper_l(wint_t c,locale_t l)136 wint_t __towupper_l(wint_t c, locale_t l)
137 {
138 #ifndef __LITEOS__
139 #ifdef FEATURE_ICU_LOCALE
140 if (icu_locale_wctype_enable && l && l->cat[LC_CTYPE]
141 && l->cat[LC_CTYPE]->flag == ICU_VALID) {
142 char* type_name = (char*)(l->cat[LC_CTYPE]->name);
143 if (!strcmp(type_name, "zh_CN") || !strcmp(type_name, "en_US.UTF-8")) {
144 return g_icu_opt_func.u_toupper(c);
145 }
146 }
147 #endif
148 #endif
149 return towupper(c);
150 }
151
__towlower_l(wint_t c,locale_t l)152 wint_t __towlower_l(wint_t c, locale_t l)
153 {
154 #ifndef __LITEOS__
155 #ifdef FEATURE_ICU_LOCALE
156 if (icu_locale_wctype_enable && l && l->cat[LC_CTYPE]
157 && l->cat[LC_CTYPE]->flag == ICU_VALID) {
158 char* type_name = (char*)(l->cat[LC_CTYPE]->name);
159 if (!strcmp(type_name, "zh_CN") || !strcmp(type_name, "en_US.UTF-8")) {
160 return g_icu_opt_func.u_tolower(c);
161 }
162 }
163 #endif
164 #endif
165 return towlower(c);
166 }
167
168 weak_alias(__towupper_l, towupper_l);
169 weak_alias(__towlower_l, towlower_l);
170