• 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 #define _GNU_SOURCE
18 #include <stdlib.h>
19 #include <locale.h>
20 #include <ctype.h>
21 #include <string.h>
22 #include <math.h>
23 #include <wchar.h>
24 #include "locale_impl.h"
25 
icu_wchar_trans(wchar_t * src,u_char * des,int des_size)26 static int icu_wchar_trans(wchar_t *src, u_char *des, int des_size)
27 {
28 	get_icu_symbol(ICU_I18N, &(g_icu_opt_func.u_strFrom_utf32), ICU_SYMBOL(u_strFromUTF32));
29 
30 	if (!g_icu_opt_func.u_strFrom_utf32) {
31 		return DLSYM_ICU_FAIL;
32 	}
33 
34 	int icu_status = 0;
35 	void *res_tmp = g_icu_opt_func.u_strFrom_utf32(des, des_size, NULL, src, -1, &icu_status);
36 	if (icu_status > 0) {
37 		return ICU_ERROR;
38 	}
39 	return DLSYM_ICU_SUCC;
40 }
41 
icu_wcstod_l(char * loc_name,wchar_t * s,int * cur_status,int * parse_pos)42 static double icu_wcstod_l(char *loc_name, wchar_t *s, int *cur_status, int *parse_pos)
43 {
44 	char *icu_locale_name = NULL;
45 	icu_locale_name = get_valid_icu_locale_name(loc_name);
46 
47 	void *fmt = icu_unum_open(icu_locale_name, cur_status);
48 	if (*cur_status == DLSYM_ICU_FAIL || *cur_status == ICU_ERROR) {
49 		icu_unum_close(fmt);
50 		return 0;
51 	}
52 
53 	int n = wcslen(s);
54 	u_char *ustr = (u_char *)calloc((n + 1), sizeof(u_char));
55 	*cur_status = icu_wchar_trans(s, ustr, n);
56 	if (*cur_status == DLSYM_ICU_FAIL || *cur_status == ICU_ERROR) {
57 		free(ustr);
58 		icu_unum_close(fmt);
59 		return 0;
60 	}
61 
62 	double res = icu_parse_double(fmt, ustr, parse_pos, cur_status);
63 	if (*cur_status == DLSYM_ICU_FAIL || *cur_status == ICU_ERROR) {
64 		free(ustr);
65 		icu_unum_close(fmt);
66 		return 0;
67 	}
68 	free(ustr);
69 	icu_unum_close(fmt);
70 	return res;
71 }
72 
wcstod_l(const wchar_t * restrict s,wchar_t ** restrict p,locale_t l)73 double wcstod_l(const wchar_t *restrict s, wchar_t **restrict p, locale_t l)
74 {
75 	if (l && s && l->cat[LC_NUMERIC] && l->cat[LC_NUMERIC]->flag == ICU_VALID) {
76 		int cur_status = DLSYM_ICU_SUCC;
77 		int sign = 1;
78 		int parse_pos = 0;
79 		wchar_t *tmp_s = (wchar_t *)s;
80 		while (tmp_s && iswspace(*tmp_s)) {
81 			tmp_s++;
82 		}
83 		if (*tmp_s == L'+' || *tmp_s == L'-') {
84 			sign -= 2 * (*tmp_s == L'-');
85 			++tmp_s;
86 		}
87 
88 		int i;
89 		for (i = 0; i < 8 && towlower(*(tmp_s + i)) == L"infinity"[i]; i++) {}
90 		if (i == 3 || i == 8 || i > 3) {
91 			if (i != 8) {
92 				*p = tmp_s + 3;
93 			} else {
94 				*p = tmp_s + i;
95 			}
96 			return sign * INFINITY;
97 		}
98 
99 		double res = icu_wcstod_l(l->cat[LC_NUMERIC]->name, tmp_s, &cur_status, &parse_pos);
100 		if (cur_status == DLSYM_ICU_SUCC || cur_status == ICU_ERROR) {
101 			*p = parse_pos ? tmp_s + parse_pos : (char *)s;
102 			return sign * res;
103 		}
104 	}
105 
106 	return wcstod(s, p);
107 }
108 #endif
109