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