• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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