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 #include "styled_number_format.h"
17
18 #include <unordered_map>
19 #include "unicode/formattedvalue.h"
20 #include "i18n_hilog.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
StyledNumberFormat(bool isNumberFormat,std::shared_ptr<NumberFormat> numberFormat,std::shared_ptr<SimpleNumberFormat> simpleNumberFormat)25 StyledNumberFormat::StyledNumberFormat(bool isNumberFormat, std::shared_ptr<NumberFormat> numberFormat,
26 std::shared_ptr<SimpleNumberFormat> simpleNumberFormat)
27 : isNumberFormat(isNumberFormat), numberFormat(numberFormat), simpleNumberFormat(simpleNumberFormat)
28 {
29 }
30
Format(double number)31 std::string StyledNumberFormat::Format(double number)
32 {
33 if (isNumberFormat && numberFormat) {
34 return numberFormat->Format(number);
35 }
36 if (!isNumberFormat && simpleNumberFormat) {
37 return simpleNumberFormat->Format(number);
38 }
39 return "";
40 }
41
ParseToParts(double number)42 std::vector<StyledNumberFormat::NumberPart> StyledNumberFormat::ParseToParts(double number)
43 {
44 if (isNumberFormat && numberFormat) {
45 if (numberFormat->IsRelativeTimeFormat(number)) {
46 icu::FormattedRelativeDateTime formattedValue = numberFormat->FormatToFormattedRelativeDateTime(number);
47 return ParseToParts(formattedValue);
48 } else {
49 icu::number::FormattedNumber formattedValue = numberFormat->FormatToFormattedNumber(number);
50 return ParseToParts(formattedValue);
51 }
52 }
53 if (!isNumberFormat && simpleNumberFormat) {
54 icu::number::FormattedNumber formattedValue = simpleNumberFormat->FormatToFormattedNumber(number);
55 return ParseToParts(formattedValue);
56 }
57 return {};
58 }
59
ParseToParts(icu::number::FormattedNumber & formattedValue)60 std::vector<StyledNumberFormat::NumberPart> StyledNumberFormat::ParseToParts(
61 icu::number::FormattedNumber &formattedValue)
62 {
63 std::vector<NumberPart> result;
64 UErrorCode status = U_ZERO_ERROR;
65 icu::ConstrainedFieldPosition constrainedPos;
66 constrainedPos.constrainCategory(UFIELD_CATEGORY_NUMBER);
67 while (formattedValue.nextPosition(constrainedPos, status)) {
68 if (U_FAILURE(status)) {
69 HILOG_ERROR_I18N("StyledNumberFormat::ParseToParts get nextPosition faild");
70 break;
71 }
72 size_t startIndex = (size_t)constrainedPos.getStart();
73 if (constrainedPos.getCategory() != UFIELD_CATEGORY_NUMBER) {
74 continue;
75 }
76 switch (constrainedPos.getField()) {
77 case UNUM_PERCENT_FIELD:
78 case UNUM_PERMILL_FIELD:
79 case UNUM_MEASURE_UNIT_FIELD:
80 case UNUM_CURRENCY_FIELD: {
81 result.push_back({"unit", startIndex,
82 static_cast<size_t>(constrainedPos.getLimit() - startIndex)});
83 break;
84 }
85 case UNUM_DECIMAL_SEPARATOR_FIELD: {
86 result.push_back({"decimal", startIndex,
87 static_cast<size_t>(constrainedPos.getLimit() - startIndex)});
88 break;
89 }
90 case UNUM_EXPONENT_SYMBOL_FIELD:
91 case UNUM_EXPONENT_SIGN_FIELD:
92 case UNUM_EXPONENT_FIELD:
93 case UNUM_SIGN_FIELD:
94 case UNUM_COMPACT_FIELD:
95 case UNUM_INTEGER_FIELD: {
96 result.push_back({"integer", startIndex,
97 static_cast<size_t>(constrainedPos.getLimit() - startIndex)});
98 break;
99 }
100 case UNUM_FRACTION_FIELD: {
101 result.push_back({"fraction", startIndex,
102 static_cast<size_t>(constrainedPos.getLimit() - startIndex)});
103 break;
104 }
105 default:
106 break;
107 }
108 }
109 return result;
110 }
111
ParseToParts(icu::FormattedRelativeDateTime & formattedValue)112 std::vector<StyledNumberFormat::NumberPart> StyledNumberFormat::ParseToParts(
113 icu::FormattedRelativeDateTime &formattedValue)
114 {
115 std::vector<NumberPart> result;
116 UErrorCode status = U_ZERO_ERROR;
117 icu::UnicodeString formatResult = formattedValue.toString(status);
118 if (U_FAILURE(status)) {
119 HILOG_ERROR_I18N("StyledNumberFormat::ParseToParts toString faild");
120 return result;
121 }
122 std::string numberStr;
123 formatResult.toUTF8String(numberStr);
124 icu::ConstrainedFieldPosition constrainedPos;
125 constrainedPos.constrainCategory(UFIELD_CATEGORY_NUMBER);
126 size_t prevIndex = 0;
127 size_t length = numberStr.length();
128 while (formattedValue.nextPosition(constrainedPos, status)) {
129 if (U_FAILURE(status)) {
130 HILOG_ERROR_I18N("StyledNumberFormat::ParseToParts get nextPosition faild");
131 break;
132 }
133 size_t startIndex = (size_t)constrainedPos.getStart();
134 if (constrainedPos.getCategory() != UFIELD_CATEGORY_NUMBER ||
135 constrainedPos.getField() == UNUM_GROUPING_SEPARATOR_FIELD) {
136 continue;
137 }
138 if (constrainedPos.getField() == UNUM_DECIMAL_SEPARATOR_FIELD) {
139 result.push_back({"decimal", startIndex, static_cast<size_t>(constrainedPos.getLimit() - startIndex)});
140 }
141 if (constrainedPos.getField() == UNUM_INTEGER_FIELD) {
142 result.push_back({"integer", startIndex, static_cast<size_t>(constrainedPos.getLimit() - startIndex)});
143 }
144 if (constrainedPos.getField() == UNUM_FRACTION_FIELD) {
145 result.push_back({"fraction", startIndex, static_cast<size_t>(constrainedPos.getLimit() - startIndex)});
146 }
147 if (startIndex > prevIndex) {
148 result.push_back({"unit", prevIndex, startIndex - prevIndex});
149 }
150 prevIndex = (size_t)constrainedPos.getLimit();
151 }
152 if (prevIndex < length) {
153 result.push_back({"unit", prevIndex, length - prevIndex});
154 }
155 return result;
156 }
157 } // namespace I18n
158 } // namespace Global
159 } // namespace OHOS