• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifdef FEATURE_ICU_LOCALE
17 #include <stdio.h>
18 #include <dlfcn.h>
19 #include <musl_log.h>
20 #include <string.h>
21 #include "locale_impl.h"
22 
23 #define ICU_UC_SO "libhmicuuc.z.so"
24 #define ICU_I18N_SO "libhmicui18n.z.so"
25 
26 static void *g_icuuc_handle = NULL;
27 static void *g_icui18n_handle = NULL;
28 hidden struct icu_opt_func g_icu_opt_func = { NULL };
29 static int dlopen_fail_flag = 0;
30 static int icuuc_handle_init_succeed = 0;
31 static int icuuc_wctype_handle_init_succeed = 0;
32 bool icu_locale_wctype_enable = false;
33 pthread_mutex_t icu_wctype_init_mutex = PTHREAD_MUTEX_INITIALIZER;
34 
get_icu_handle(icu_so_type type,const char * symbol_name)35 static void *get_icu_handle(icu_so_type type, const char *symbol_name)
36 {
37 	void *cur_handle;
38 	char *cur_so;
39 	if (type == ICU_UC) {
40 		cur_handle = g_icuuc_handle;
41 		cur_so = ICU_UC_SO;
42 	} else {
43 		cur_handle = g_icui18n_handle;
44 		cur_so = ICU_I18N_SO;
45 	}
46 
47 	if (!cur_handle && !dlopen_fail_flag) {
48 		cur_handle = dlopen(cur_so, RTLD_LOCAL);
49         if (type == ICU_UC) {
50             g_icuuc_handle = cur_handle;
51         } else {
52             g_icui18n_handle = cur_handle;
53         }
54 	}
55 	if (!cur_handle) {
56 		dlopen_fail_flag = 1;
57 		MUSL_LOGE("dlopen icu so for musl locale fail %{public}s", dlerror());
58 		return NULL;
59 	}
60 	return dlsym(cur_handle, symbol_name);
61 }
62 
get_icu_version_num()63 static char *get_icu_version_num()
64 {
65 	if (!(g_icu_opt_func.get_icu_version)) {
66 		g_icu_opt_func.get_icu_version = get_icu_handle(ICU_UC, ICU_GET_VERSION_NUM_SYMBOL);
67 	}
68 	if (g_icu_opt_func.get_icu_version) {
69 		return g_icu_opt_func.get_icu_version();
70 	} else {
71 		return "";
72 	}
73 }
74 
get_icu_symbol(icu_so_type type,void ** icu_symbol_handle,const char * symbol_name)75 void get_icu_symbol(icu_so_type type, void **icu_symbol_handle, const char *symbol_name)
76 {
77 	if (!(*icu_symbol_handle)) {
78 		char *icu_version = get_icu_version_num();
79 		char *valid_icu_symbol = malloc(strlen(symbol_name) + strlen(icu_version) + 2);
80 		sprintf(valid_icu_symbol, "%s_%s", symbol_name, icu_version);
81 		*icu_symbol_handle = get_icu_handle(type, valid_icu_symbol);
82 		free(valid_icu_symbol);
83 	}
84 }
85 
set_icu_directory()86 void set_icu_directory()
87 {
88 	if (!(g_icu_opt_func.set_data_directory)) {
89 		g_icu_opt_func.set_data_directory = get_icu_handle(ICU_UC, ICU_SET_DATA_DIRECTORY_SYMBOL);
90 		if (g_icu_opt_func.set_data_directory) {
91 			g_icu_opt_func.set_data_directory();
92 		}
93 	}
94 }
95 
96 /* ICU methods don't need charset for locale, process the given locale name */
get_valid_icu_locale_name(const char * name,const char * icu_name,int icu_name_len)97 void get_valid_icu_locale_name(const char *name, const char *icu_name, int icu_name_len)
98 {
99 	char *pos = memchr(name, '.', strlen(name));
100 	int valid_len;
101 	if (pos) {
102 		valid_len = pos - name;
103 	} else {
104 		valid_len = strlen(name);
105 	}
106 	if (icu_name_len > valid_len) {
107 		strncpy((char *)icu_name, name, valid_len);
108 	}
109 }
110 
set_wctype_icu_enable()111 int set_wctype_icu_enable()
112 {
113     pthread_mutex_lock(&icu_wctype_init_mutex);
114     if (!icuuc_wctype_handle_init()){
115         pthread_mutex_unlock(&icu_wctype_init_mutex);
116         return ICU_SYMBOL_LOAD_ERROR;
117     }
118 
119     icu_locale_wctype_enable = true;
120     pthread_mutex_unlock(&icu_wctype_init_mutex);
121     return ICU_ZERO_ERROR;
122 }
123 
icuuc_wctype_handle_init()124 bool icuuc_wctype_handle_init()
125 {
126     if (icuuc_wctype_handle_init_succeed) {
127         return true;
128     }
129     if (!g_icu_opt_func.u_isalnum) {
130         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isalnum), ICU_UCHAR_ISALNUM_SYMBOL);
131         if (!g_icu_opt_func.u_isalnum) {
132             return false;
133         }
134     }
135     if (!g_icu_opt_func.u_isalpha) {
136         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isalpha), ICU_UCHAR_ISALPHA_SYMBOL);
137         if (!g_icu_opt_func.u_isalpha) {
138             return false;
139         }
140     }
141     if (!g_icu_opt_func.u_isblank) {
142         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isblank), ICU_UCHAR_ISBLANK_SYMBOL);
143         if (!g_icu_opt_func.u_isblank) {
144             return false;
145         }
146     }
147     if (!g_icu_opt_func.u_iscntrl) {
148         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_iscntrl), ICU_UCHAR_ISCNTRL_SYMBOL);
149         if (!g_icu_opt_func.u_iscntrl) {
150             return false;
151         }
152     }
153     if (!g_icu_opt_func.u_isdigit) {
154         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isdigit), ICU_UCHAR_ISDIGIT_SYMBOL);
155         if (!g_icu_opt_func.u_isdigit) {
156             return false;
157         }
158     }
159     if (!g_icu_opt_func.u_isgraph) {
160         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isgraph), ICU_UCHAR_ISGRAPH_SYMBOL);
161         if (!g_icu_opt_func.u_isgraph) {
162             return false;
163         }
164     }
165     if (!g_icu_opt_func.u_islower) {
166         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_islower), ICU_UCHAR_ISLOWER_SYMBOL);
167         if (!g_icu_opt_func.u_islower) {
168             return false;
169         }
170     }
171     if (!g_icu_opt_func.u_isprint) {
172         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isprint), ICU_UCHAR_ISPRINT_SYMBOL);
173         if (!g_icu_opt_func.u_isprint) {
174             return false;
175         }
176     }
177     if (!g_icu_opt_func.u_ispunct) {
178         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_ispunct), ICU_UCHAR_ISPUNCT_SYMBOL);
179         if (!g_icu_opt_func.u_ispunct) {
180             return false;
181         }
182     }
183     if (!g_icu_opt_func.u_isspace) {
184         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isspace), ICU_UCHAR_ISSPACE_SYMBOL);
185         if (!g_icu_opt_func.u_isspace) {
186             return false;
187         }
188     }
189     if (!g_icu_opt_func.u_isupper) {
190         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isupper), ICU_UCHAR_ISUPPER_SYMBOL);
191         if (!g_icu_opt_func.u_isupper) {
192             return false;
193         }
194     }
195     if (!g_icu_opt_func.u_isxdigit) {
196         get_icu_symbol(ICU_I18N, (void **)&(g_icu_opt_func.u_isxdigit), ICU_UCHAR_ISXDIGIT_SYMBOL);
197         if (!g_icu_opt_func.u_isxdigit) {
198             return false;
199         }
200     }
201     if (!g_icu_opt_func.u_tolower) {
202         get_icu_symbol(ICU_UC, (void **)&(g_icu_opt_func.u_tolower), ICU_UCHAR_TOLOWER_SYMBOL);
203         if (!g_icu_opt_func.u_tolower) {
204             return false;
205         }
206     }
207     if (!g_icu_opt_func.u_toupper) {
208         get_icu_symbol(ICU_UC, (void **)&(g_icu_opt_func.u_toupper), ICU_UCHAR_TOUPPER_SYMBOL);
209         if (!g_icu_opt_func.u_toupper) {
210             return false;
211         }
212     }
213     icuuc_wctype_handle_init_succeed = true;
214     return true;
215 }
216 
icuuc_handle_init()217 bool icuuc_handle_init()
218 {
219     if (icuuc_handle_init_succeed) {
220         return true;
221     }
222 
223     if (!g_icu_opt_func.set_data_directory) {
224         g_icu_opt_func.set_data_directory = get_icu_handle(ICU_UC, ICU_SET_DATA_DIRECTORY_SYMBOL);
225         if (g_icu_opt_func.set_data_directory) {
226             g_icu_opt_func.set_data_directory();
227         } else {
228             return false;
229         }
230     }
231     if (!g_icu_opt_func.ucnv_open) {
232         get_icu_symbol(ICU_UC, (void **)&(g_icu_opt_func.ucnv_open), ICU_UCNV_OPEN_SYMBOL);
233         if (!g_icu_opt_func.ucnv_open) {
234             return false;
235         }
236     }
237     if (!g_icu_opt_func.ucnv_setToUCallBack) {
238         get_icu_symbol(ICU_UC, (void **)&(g_icu_opt_func.ucnv_setToUCallBack), ICU_UCNV_SETTOUCALLBACK_SYMBOL);
239         if (!g_icu_opt_func.ucnv_setToUCallBack) {
240             return false;
241         }
242     }
243     if (!g_icu_opt_func.ucnv_setFromUCallBack) {
244         get_icu_symbol(ICU_UC, (void **)&(g_icu_opt_func.ucnv_setFromUCallBack), ICU_UCNV_SETFROMUCALLBACK_SYMBOL);
245         if (!g_icu_opt_func.ucnv_setFromUCallBack) {
246             return false;
247         }
248     }
249     if (!g_icu_opt_func.ucnv_convertEx) {
250         get_icu_symbol(ICU_UC, (void **)&(g_icu_opt_func.ucnv_convertEx), ICU_UCNV_CONVERTEX_SYMBOL);
251         if (!g_icu_opt_func.ucnv_convertEx) {
252             return false;
253         }
254     }
255     if (!g_icu_opt_func.ucnv_close) {
256         get_icu_symbol(ICU_UC, (void **)&(g_icu_opt_func.ucnv_close), ICU_UCNV_CLOSE_SYMBOL);
257         if (!g_icu_opt_func.ucnv_close) {
258             return false;
259         }
260     }
261     icuuc_handle_init_succeed = 1;
262     errno = 0;
263     return true;
264 }
265 #endif
266