1 /*
2 * Copyright (c) 2021-2022 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 #include "measure_data.h"
16 #include <string>
17 #include <unordered_map>
18 #include <cmath>
19 #include "i18n_hilog.h"
20 #include "utils.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
25 using namespace std;
26 const double FT_TO_M = 0.3048;
27 const double FT2_TO_M2 = FT_TO_M * FT_TO_M;
28 const double FT3_TO_M3 = FT_TO_M * FT2_TO_M2;
29 const double IN3_TO_M3 = FT3_TO_M3 / (12 * 12 * 12);
30 const double GAL_IMP_TO_M3 = 0.00454609;
31 const double GAL_TO_M3 = 231 * IN3_TO_M3;
32 const int REGION_OFFSET = 7;
33 const int BASE_VALUE_SIZE = 2;
34 const int FACTOR_SIZE = 2;
35 const int CHAR_OFFSET = 48;
36 const int MAX_UNIT_NUM = 500;
37 const size_t REGION_SIZE = 2;
38
39 const std::unordered_map<std::string, std::vector<std::string>> USAGE_001 {
40 { "area-land-agricult", { "hectare" } },
41 { "area-land-commercl", { "hectare" } },
42 { "area-land-residntl", { "hectare" } },
43 { "length-person", { "centimeter" } },
44 { "length-person-small", { "centimeter" } },
45 { "length-rainfall", { "millimeter" } },
46 { "length-road", { "meter" } },
47 { "length-road-small", { "meter" } },
48 { "length-snowfall", { "centimeter" } },
49 { "length-vehicle", { "meter" } },
50 { "length-visiblty", { "meter" } },
51 { "length-visiblty-small", { "meter" } },
52 { "speed-road-travel", { "kilometer-per-hour" } },
53 { "speed-wind", { "kilometer-per-hour" } },
54 { "temperature-person", { "celsius" } },
55 { "temperature-weather", { "celsius" } },
56 { "volume-vehicle-fuel", { "liter" } },
57 };
58
59 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DEFAULT_001 {
60 { "length", { "kilometer", "meter", "centimeter" } },
61 { "area", { "square-kilometer", "hectare", "square-meter", "square-centimeter" } },
62 { "speed", { "kilometer-per-hour" } },
63 { "temperature", { "celsius" } },
64 { "volume", { "cubic-meter", "cubic-centimeter" } },
65 };
66
67 const std::unordered_map<std::string, std::vector<std::string>> USAGE_AT {
68 { "length-person", { "meter", "centimeter" } },
69 };
70
71 const std::unordered_map<std::string, std::vector<std::string>> USAGE_BR {
72 { "length-person-informal", { "meter", "centimeter" } },
73 { "length-rainfall", { "centimeter" } },
74 };
75
76 const std::unordered_map<std::string, std::vector<std::string>> USAGE_BS {
77 { "temperature-weather", { "fahrenheit" } },
78 };
79
80 const std::unordered_map<std::string, std::vector<std::string>> USAGE_CA {
81 { "length-person", { "inch" } },
82 { "length-person-informal", { "foot", "inch" } },
83 { "length-person-small-informal", { "inch" } },
84 };
85
86 const std::unordered_map<std::string, std::vector<std::string>> USAGE_CN {
87 { "length-person-informal", { "meter", "centimeter" } },
88 };
89
90 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DE {
91 { "length-person-informal", { "meter", "centimeter" } },
92 { "length-visiblty", { "meter" } },
93 };
94
95 const std::unordered_map<std::string, std::vector<std::string>> USAGE_GB {
96 { "area-land-agricult", { "acre" } },
97 { "area-land-commercl", { "acre" } },
98 { "area-land-residntl", { "acre" } },
99 { "length-person", { "inch" } },
100 { "length-person-informal", { "foot", "inch" } },
101 { "length-person-small-informal", { "inch" } },
102 { "length-road", { "yard" } },
103 { "length-road-small", { "yard" } },
104 { "length-vehicle", { "foot", "inch" } },
105 { "length-visiblty", { "mile", "foot" } },
106 { "length-visiblty-small", { "foot" } },
107 { "speed-road-travel", { "mile-per-hour" } },
108 };
109
110 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DEFAULT_GB {
111 { "length", { "mile", "foot", "inch" } },
112 { "area", { "square-mile", "acre", "square-foot", "square-inch" } },
113 { "speed", { "mile-per-hour" } },
114 { "volume", { "cubic-foot", "cubic-inch" } },
115 };
116
117 const std::unordered_map<std::string, std::vector<std::string>> USAGE_KR {
118 { "speed-wind", { "meter-per-second" } },
119 };
120
121 const std::unordered_map<std::string, std::vector<std::string>> USAGE_MX {
122 { "length-person-informal", { "meter", "centimeter" } },
123 { "length-vehicle", { "meter", "centimeter" } },
124 };
125
126 const std::unordered_map<std::string, std::vector<std::string>> USAGE_NL {
127 { "length-person-informal", { "meter", "centimeter" } },
128 { "length-visiblty", { "meter" } },
129 };
130
131 const std::unordered_map<std::string, std::vector<std::string>> USAGE_NO {
132 { "length-person-informal", { "meter", "centimeter" } },
133 { "speed-wind", { "meter-per-second" } },
134 };
135
136 const std::unordered_map<std::string, std::vector<std::string>> USAGE_SE {
137 { "length-person", { "meter", "centimeter" } },
138 { "length-road", { "mile-scandinavian", "kilometer" } },
139 { "length-road-informal", { "mile-scandinavian" } },
140 { "speed-wind", { "meter-per-second" } },
141 };
142
143 const std::unordered_map<std::string, std::vector<std::string>> USAGE_US {
144 { "area-land-agricult", { "acre" } },
145 { "area-land-commercl", { "acre" } },
146 { "area-land-residntl", { "acre" } },
147 { "length-person", { "inch" } },
148 { "length-person-informal", { "foot", "inch" } },
149 { "length-person-small", { "inch" } },
150 { "length-rainfall", { "inch" } },
151 { "length-road", { "mile" } },
152 { "length-road-small", { "foot" } },
153 { "length-snowfall", { "inch" } },
154 { "length-vehicle", { "foot", "inch" } },
155 { "length-visiblty", { "mile", "foot" } },
156 { "length-visiblty-small", { "foot" } },
157 { "speed-road-travel", { "mile-per-hour" } },
158 { "speed-wind", { "mile-per-hour" } },
159 { "temperature-person", { "fahrenheit" } },
160 { "temperature-weather", { "fahrenheit" } },
161 { "volume-vehicle-fuel", { "gallon" } },
162 };
163
164 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DEFAULT_US {
165 { "length", { "mile", "foot", "inch" } },
166 { "area", { "square-mile", "acre", "square-foot", "square-inch" } },
167 { "speed", { "mile-per-hour" } },
168 { "temperature", { "fahrenheit" } },
169 { "volume", { "cubic-foot", "cubic-inch" } },
170 };
171
172 const std::unordered_map<std::string, std::vector<double>> CONVERT_FACTORS {
173 { "acre", { FT2_TO_M2 * 43560, 0 } },
174 { "hectare", { 10000, 0 } },
175 { "dunam", { 1000, 0 } },
176 { "fathom", { FT_TO_M * 6, 0 } },
177 { "foot", { FT_TO_M, 0 } },
178 { "furlong", { FT_TO_M * 660, 0 } },
179 { "inch", { FT_TO_M / 12, 0 } },
180 { "meter", { 1, 0 } },
181 { "mile", { FT_TO_M * 5280, 0 } },
182 { "mile-scandinavian", { 10000, 0 } },
183 { "nautical-mile", { 1852, 0 } },
184 { "point", { FT_TO_M / 864, 0 } },
185 { "yard", { FT_TO_M * 3, 0 } },
186 { "knot", { 1852 / 3600.0, 0 } },
187 { "kilometer-per-hour", { 1000 / 3600.0, 0 } },
188 { "celsius", { 1, 273.15 }},
189 { "fahrenheit", {5.0 / 9, 2298.35 / 9 }},
190 { "kelvin", { 1, 0 } },
191 { "acre-foot", { 43560 * FT3_TO_M3, 0 } },
192 { "bushel", { GAL_IMP_TO_M3 * 8, 0 } },
193 { "bushel-UK", { GAL_IMP_TO_M3 * 8, 0 } },
194 { "bushel-US", { IN3_TO_M3 * 2150.42, 0 } },
195 { "cup", { GAL_IMP_TO_M3 / 16, 0 } },
196 { "cup-UK", { GAL_IMP_TO_M3 / 16, 0 } },
197 { "cup-US", { GAL_TO_M3 / 16, 0 } },
198 { "cup-metric", {0.00025, 0 } },
199 { "fluid-ounce", { GAL_IMP_TO_M3 / 128, 0 } },
200 { "fluid-ounce-imperial", { GAL_IMP_TO_M3 / 160, 0 } },
201 { "gallon", { GAL_TO_M3, 0 } },
202 { "gallon-imperial", { GAL_IMP_TO_M3, 0 } },
203 { "liter", {0.001, 0 } },
204 { "pint-metric", { 0.0005, 0 } },
205 { "pint", { GAL_IMP_TO_M3 / 8, 0 } },
206 { "pint-UK", { GAL_IMP_TO_M3 / 8, 0 } },
207 { "pint-US", { GAL_TO_M3 / 8, 0 } },
208 { "quart", { GAL_IMP_TO_M3 / 4, 0 } },
209 { "quart-UK", { GAL_IMP_TO_M3 / 4, 0 } },
210 { "quart-US", { GAL_TO_M3 / 4, 0 } },
211 { "tablespoon", { GAL_IMP_TO_M3 / 256, 0 } },
212 { "tablespoon-UK", { GAL_IMP_TO_M3 / 256, 0 } },
213 { "tablespoon-US", { GAL_TO_M3 / 256, 0 } },
214 { "teaspoon", { GAL_IMP_TO_M3 / (16 * 48), 0 } },
215 { "teaspoon-UK", { GAL_IMP_TO_M3 / (16 * 48), 0 } },
216 { "teaspoon-US", { GAL_TO_M3 / (16 * 48), 0 } },
217 { "barrel", { GAL_IMP_TO_M3 * 36, 0 } },
218 { "barrel-UK", { GAL_IMP_TO_M3 * 36, 0 } },
219 { "barrel-US", { GAL_TO_M3 * 42, 0 } },
220 { "hour", { 3600, 0 } },
221 { "second", { 1, 0 } },
222 { "byte", { 1, 0 } },
223 { "kilobyte", { pow(10, 3), 0 } },
224 { "megabyte", { pow(10, 6), 0 } },
225 { "gigabyte", { pow(10, 9), 0 } },
226 { "terabyte", { pow(10, 12), 0 } },
227 { "petabyte", { pow(10, 15), 0 } },
228 };
229
230 const std::unordered_map<std::string, std::string> CONVERT_TO_UNIT {
231 { "acre", "square-meter" },
232 { "hectare", "square-meter" },
233 { "dunam", "square-meter" },
234 { "fathom", "meter" },
235 { "foot", "meter" },
236 { "furlong", "meter" },
237 { "inch", "meter" },
238 { "meter", "meter" },
239 { "mile", "meter" },
240 { "mile-scandinavian", "meter" },
241 { "nautical-mile", "meter" },
242 { "point", "meter" },
243 { "yard", "meter" },
244 { "knot", "meter-per-second" },
245 { "kilometer-per-hour", "meter-per-second" },
246 { "celsius", "kelvin" },
247 { "fahrenheit", "kelvin" },
248 { "kelvin", "kelvin" },
249 { "acre-foot", "cubic-meter" },
250 { "bushel", "cubic-meter" },
251 { "bushel-UK", "cubic-meter" },
252 { "bushel-US", "cubic-meter" },
253 { "cup", "cubic-meter" },
254 { "cup-UK", "cubic-meter" },
255 { "cup-US", "cubic-meter" },
256 { "cup-metric", "cubic-meter" },
257 { "fluid-ounce", "cubic-meter" },
258 { "fluid-ounce-imperial", "cubic-meter" },
259 { "gallon", "cubic-meter" },
260 { "gallon-imperial", "cubic-meter" },
261 { "liter", "cubic-meter" },
262 { "pint-metric", "cubic-meter" },
263 { "pint", "cubic-meter" },
264 { "pint-UK", "cubic-meter" },
265 { "pint-US", "cubic-meter" },
266 { "quart", "cubic-meter" },
267 { "quart-UK", "cubic-meter" },
268 { "quart-US", "cubic-meter" },
269 { "tablespoon", "cubic-meter" },
270 { "tablespoon-UK", "cubic-meter" },
271 { "tablespoon-US", "cubic-meter" },
272 { "teaspoon", "cubic-meter" },
273 { "teaspoon-UK", "cubic-meter" },
274 { "teaspoon-US", "cubic-meter" },
275 { "barrel", "cubic-meter" },
276 { "barrel-US", "cubic-meter" },
277 { "barrel-UK", "cubic-meter" },
278 { "hour", "second" },
279 { "second", "second" },
280 { "byte", "byte" },
281 { "kilobyte", "byte" },
282 { "megabyte", "byte" },
283 { "gigabyte", "byte" },
284 { "terabyte", "byte" },
285 { "petabyte", "byte" },
286 };
287
288 const std::unordered_map<std::string, double> PREFIX_VALUE {
289 { "deci", pow(10, -1) },
290 { "centi", pow(10, -2) },
291 { "milli", pow(10, -3) },
292 { "micro", pow(10, -6) },
293 { "nano", pow(10, -9) },
294 { "pico", pow(10, -12) },
295 { "kilo", pow(10, 3) },
296 { "hecto", pow(10, 2) },
297 { "mega", pow(10, 6) },
298 };
299
300 const std::vector<std::string> BYTE_VALUE {
301 "byte",
302 "kilobyte",
303 "megabyte",
304 "gigabyte",
305 "terabyte",
306 "petabyte"
307 };
308
309 const std::vector<std::pair<std::string, double>> DATE_VALUE {
310 { "second", 1 },
311 { "minute", 60 },
312 { "hour", 60 },
313 { "day", 24},
314 { "month", 30 },
315 { "year", 365 / 30 }
316 };
317
318 const std::unordered_map<std::string, double> POWER_VALUE {
319 { "square-", 2 },
320 { "cubic-", 3 },
321 };
322
GetMask(const string & region)323 uint32_t GetMask(const string ®ion)
324 {
325 if (region.length() < REGION_SIZE) {
326 HILOG_ERROR_I18N("GetMask: region is invalid.");
327 return 0;
328 }
329 uint32_t firstChar = (region.c_str()[0] - CHAR_OFFSET);
330 uint32_t secondChar = (region.c_str()[1] - CHAR_OFFSET);
331 return (firstChar << REGION_OFFSET) | secondChar;
332 }
333
GetDefaultPreferredUnit(const string & region,const string & type,vector<string> & units)334 void GetDefaultPreferredUnit(const string ®ion, const string &type, vector<string> &units)
335 {
336 switch (GetMask(region)) {
337 case 0x00000B92: {
338 if (USAGE_DEFAULT_GB.count(type) > 0) {
339 units.assign(USAGE_DEFAULT_GB.at(type).begin(), USAGE_DEFAULT_GB.at(type).end());
340 }
341 break;
342 }
343 case 0x000012A3: {
344 if (USAGE_DEFAULT_US.count(type) > 0) {
345 units.assign(USAGE_DEFAULT_US.at(type).begin(), USAGE_DEFAULT_US.at(type).end());
346 }
347 break;
348 }
349 default: {
350 if (USAGE_DEFAULT_001.count(type) > 0) {
351 units.assign(USAGE_DEFAULT_001.at(type).begin(), USAGE_DEFAULT_001.at(type).end());
352 }
353 break;
354 }
355 }
356 }
357
GetFallbackPreferredUnit(const string & region,const string & usage,vector<string> & units)358 void GetFallbackPreferredUnit(const string ®ion, const string &usage, vector<string> &units)
359 {
360 switch (GetMask(region)) {
361 case 0x00000EA8: {
362 if (USAGE_MX.count(usage) > 0) {
363 units.assign(USAGE_MX.at(usage).begin(), USAGE_MX.at(usage).end());
364 return;
365 }
366 break;
367 }
368 case 0x00000F1C: {
369 if (USAGE_NL.count(usage) > 0) {
370 units.assign(USAGE_NL.at(usage).begin(), USAGE_NL.at(usage).end());
371 return;
372 }
373 break;
374 }
375 case 0x00000F1F:
376 case 0x0000101C:
377 case 0x00001125: {
378 if (USAGE_NO.count(usage) > 0) {
379 units.assign(USAGE_NO.at(usage).begin(), USAGE_NO.at(usage).end());
380 return;
381 }
382 break;
383 }
384 case 0x00001195: {
385 if (USAGE_SE.count(usage) > 0) {
386 units.assign(USAGE_SE.at(usage).begin(), USAGE_SE.at(usage).end());
387 return;
388 }
389 break;
390 }
391 case 0x000012A3: {
392 if (USAGE_US.count(usage) > 0) {
393 units.assign(USAGE_US.at(usage).begin(), USAGE_US.at(usage).end());
394 return;
395 }
396 break;
397 }
398 default: {
399 if (USAGE_001.count(usage) > 0) {
400 units.assign(USAGE_001.at(usage).begin(), USAGE_001.at(usage).end());
401 return;
402 }
403 break;
404 }
405 }
406 }
407
GetRestPreferredUnit(const string & region,const string & usage,vector<string> & units)408 void GetRestPreferredUnit(const string ®ion, const string &usage, vector<string> &units)
409 {
410 switch (GetMask(region)) {
411 case 0x00000991:
412 case 0x00000C9E: {
413 if (USAGE_CA.count(usage) > 0) {
414 units.assign(USAGE_CA.at(usage).begin(), USAGE_CA.at(usage).end());
415 return;
416 }
417 break;
418 }
419 case 0x0000099E:
420 case 0x00000A1B:
421 case 0x00001024: {
422 if (USAGE_CN.count(usage) > 0) {
423 units.assign(USAGE_CN.at(usage).begin(), USAGE_CN.at(usage).end());
424 return;
425 }
426 break;
427 }
428 case 0x00000A15: {
429 if (USAGE_DE.count(usage) > 0) {
430 units.assign(USAGE_DE.at(usage).begin(), USAGE_DE.at(usage).end());
431 return;
432 }
433 break;
434 }
435 case 0x00000B92: {
436 if (USAGE_GB.count(usage) > 0) {
437 units.assign(USAGE_GB.at(usage).begin(), USAGE_GB.at(usage).end());
438 return;
439 }
440 break;
441 }
442 case 0x00000DA2: {
443 if (USAGE_KR.count(usage) > 0) {
444 units.assign(USAGE_KR.at(usage).begin(), USAGE_KR.at(usage).end());
445 return;
446 }
447 break;
448 }
449 default: {
450 GetFallbackPreferredUnit(region, usage, units);
451 break;
452 }
453 }
454 if (!units.size()) {
455 GetDefaultPreferredUnit(region, usage, units);
456 }
457 }
458
GetPreferredUnit(const string & region,const string & usage,vector<string> & units)459 void GetPreferredUnit(const string ®ion, const string &usage, vector<string> &units)
460 {
461 switch (GetMask(region)) {
462 case 0x000008A4:
463 case 0x00000915:
464 case 0x00000A2A:
465 case 0x00000A97:
466 case 0x00000AA3:
467 case 0x00000B22:
468 case 0x00000C1B:
469 case 0x00000C94:
470 case 0x00000C9C:
471 case 0x00000CA4:
472 case 0x00000D1F:
473 case 0x00000EA9:
474 case 0x00001191:
475 case 0x00001222:
476 case 0x0000131E: {
477 if (USAGE_AT.count(usage) > 0) {
478 units.assign(USAGE_AT.at(usage).begin(), USAGE_AT.at(usage).end());
479 return;
480 }
481 break;
482 }
483 case 0x00000922: {
484 if (USAGE_BR.count(usage) > 0) {
485 units.assign(USAGE_BR.at(usage).begin(), USAGE_BR.at(usage).end());
486 return;
487 }
488 break;
489 }
490 case 0x00000923:
491 case 0x0000092A:
492 case 0x00001022:
493 case 0x00001027: {
494 if (USAGE_BS.count(usage) > 0) {
495 units.assign(USAGE_BS.at(usage).begin(), USAGE_BS.at(usage).end());
496 return;
497 }
498 break;
499 }
500 default: {
501 GetRestPreferredUnit(region, usage, units);
502 break;
503 }
504 }
505 if (!units.size()) {
506 GetRestPreferredUnit(region, usage, units);
507 }
508 }
509
ComputeFactorValue(const string & unit,const string & measSys,vector<double> & factors)510 void ComputeFactorValue(const string &unit, const string &measSys, vector<double> &factors)
511 {
512 string unitKey = unit + "-" + measSys;
513 if (CONVERT_FACTORS.count(unitKey) > 0) {
514 factors[0] = CONVERT_FACTORS.at(unitKey)[0];
515 factors[1] = CONVERT_FACTORS.at(unitKey)[1];
516 return;
517 }
518 if (CONVERT_FACTORS.count(unit) > 0) {
519 factors[0] = CONVERT_FACTORS.at(unit)[0];
520 factors[1] = CONVERT_FACTORS.at(unit)[1];
521 }
522 }
523
ComputeSIPrefixValue(const string & unit)524 double ComputeSIPrefixValue(const string &unit)
525 {
526 for (auto& prefixValue : PREFIX_VALUE) {
527 if (!unit.rfind(prefixValue.first, 0)) {
528 return prefixValue.second;
529 }
530 }
531 return 0.0;
532 }
533
ComputePowerValue(const string & unit,const string & measSys,vector<double> & factors)534 void ComputePowerValue(const string &unit, const string &measSys, vector<double> &factors)
535 {
536 for (auto& powerValue : POWER_VALUE) {
537 if (!unit.rfind(powerValue.first, 0)) {
538 string baseUnit = unit.substr(powerValue.first.length());
539 double value = ComputeSIPrefixValue(baseUnit);
540 double compare = 0.0;
541 if (fabs(value - compare) < 1e-6) {
542 ComputeFactorValue(baseUnit, measSys, factors);
543 }
544 factors[0] = pow(factors[0], powerValue.second);
545 }
546 }
547 }
548
ComputeValue(const string & unit,const string & measSys,vector<double> & factors)549 int ComputeValue(const string &unit, const string &measSys, vector<double> &factors)
550 {
551 if (unit.find("-per-") != string::npos) {
552 vector<string> baseValues;
553 Split(unit, "-per-", baseValues);
554 if (baseValues.size() == BASE_VALUE_SIZE) {
555 vector<double> numerator = { 1.0, 0.0 };
556 int status = ComputeValue(baseValues[0], measSys, numerator);
557 if (!status) {
558 return 0;
559 }
560 vector<double> denominator = { 1.0, 0.0 };
561 status = ComputeValue(baseValues[1], measSys, denominator);
562 if (!status) {
563 return 0;
564 }
565 factors[0] = numerator[0] / denominator[0];
566 return 1;
567 }
568 }
569 double compare = 0.0;
570 factors[0] = ComputeSIPrefixValue(unit);
571 if (fabs(factors[0] - compare) < 1e-6) {
572 ComputePowerValue(unit, measSys, factors);
573 }
574 if (fabs(factors[0] - compare) < 1e-6) {
575 ComputeFactorValue(unit, measSys, factors);
576 }
577 if (fabs(factors[0] - compare) < 1e-6) {
578 factors[0] = 1.0;
579 return 0;
580 }
581 return 1;
582 }
583
ConvertByte(double & number,std::string & unit)584 bool ConvertByte(double& number, std::string& unit)
585 {
586 double tempNumber = number;
587 if (tempNumber < 0) {
588 tempNumber *= -1;
589 }
590 std::string tempUnit = unit;
591 int indexFirst = -1;
592 for (size_t i = 0; i < BYTE_VALUE.size(); i++) {
593 if (BYTE_VALUE[i] == tempUnit) {
594 indexFirst = static_cast<int>(i);
595 break;
596 }
597 }
598 bool status = (indexFirst >= 0);
599 size_t indexSecond = status ? static_cast<size_t>(indexFirst) : 0;
600 for (size_t i = indexSecond; i > 0; i--) {
601 if (tempNumber < 1) {
602 // 10 ^ 3 is the threshold for carry
603 tempNumber *= pow(10, 3);
604 tempUnit = BYTE_VALUE[i - 1];
605 indexSecond = i - 1;
606 }
607 }
608
609 for (size_t i = indexSecond + 1; i < BYTE_VALUE.size(); i++) {
610 // 900 is the threshold for carry
611 if (tempNumber > 900) {
612 // 10 ^ 3 is the threshold for carry
613 tempNumber /= pow(10, 3);
614 tempUnit = BYTE_VALUE[i];
615 } else {
616 break;
617 }
618 }
619
620 if (status) {
621 number = tempNumber;
622 unit = tempUnit;
623 return true;
624 }
625 return false;
626 }
627
ConvertDate(double & number,std::string & unit)628 bool ConvertDate(double& number, std::string& unit)
629 {
630 double tempNumber = number;
631 if (tempNumber < 0) {
632 tempNumber *= -1;
633 }
634 std::string tempUnit = unit;
635
636 int indexFirst = -1;
637 for (size_t i = 0; i < DATE_VALUE.size(); i++) {
638 if (DATE_VALUE[i].first == tempUnit) {
639 indexFirst = static_cast<int>(i);
640 break;
641 }
642 }
643 bool status = (indexFirst >= 0);
644 size_t indexSecond = status ? static_cast<size_t>(indexFirst) : 0;
645 for (size_t i = indexSecond; i > 0; i--) {
646 if (tempNumber < 1) {
647 tempNumber *= DATE_VALUE[i].second;
648 tempUnit = DATE_VALUE[i - 1].first;
649 indexSecond = i - 1;
650 }
651 }
652
653 for (size_t i = indexSecond + 1; i < DATE_VALUE.size(); i++) {
654 if ((tempNumber / DATE_VALUE[i].second) >= 1) {
655 tempNumber /= DATE_VALUE[i].second;
656 tempUnit = DATE_VALUE[i].first;
657 } else {
658 break;
659 }
660 }
661
662 if (status) {
663 number = floor(tempNumber);
664 number *= -1;
665 unit = tempUnit;
666 return true;
667 }
668 return false;
669 }
670
Convert(double & value,const string & fromUnit,const string & fromMeasSys,const string & toUnit,const string & toMeasSys)671 int Convert(double &value, const string &fromUnit, const string &fromMeasSys, const string &toUnit,
672 const string &toMeasSys)
673 {
674 double baseResult = 0.0;
675 double result = 0.0;
676 vector<double> fromFactors = {0.0, 0.0};
677 string fromUnitType;
678 string toUnitType;
679 icu::MeasureUnit unitArray[MAX_UNIT_NUM];
680 UErrorCode icuStatus = U_ZERO_ERROR;
681 icu::MeasureUnit::getAvailable(unitArray, MAX_UNIT_NUM, icuStatus);
682 if (!U_SUCCESS(icuStatus)) {
683 return 0;
684 }
685 for (icu::MeasureUnit curUnit : unitArray) {
686 if (!strcmp(curUnit.getSubtype(), fromUnit.c_str())) {
687 fromUnitType = curUnit.getType();
688 }
689 if (!strcmp(curUnit.getSubtype(), toUnit.c_str())) {
690 toUnitType = curUnit.getType();
691 }
692 }
693 if (fromUnitType.empty() || toUnitType.empty() || strcmp(fromUnitType.c_str(), toUnitType.c_str())) {
694 return 0;
695 }
696 int status = ComputeValue(fromUnit, fromMeasSys, fromFactors);
697 if (!status) {
698 return 0;
699 }
700 vector<double> toFactors = {0.0, 0.0};
701 status = ComputeValue(toUnit, toMeasSys, toFactors);
702 if (!status) {
703 return 0;
704 }
705 if (fromFactors.size() == FACTOR_SIZE) {
706 baseResult = fromFactors[0] * value + fromFactors[1];
707 }
708 if (toFactors.size() == FACTOR_SIZE) {
709 result = (baseResult - toFactors[1]) / toFactors[0];
710 }
711 value = result;
712 return 1;
713 }
714 } // namespace I18n
715 } // namespace Global
716 } // namespace OHOS