• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 
16 #include "i18n_memory_adapter.h"
17 #include "str_util.h"
18 #include "measure_format_impl.h"
19 
20 using namespace OHOS::I18N;
21 
MeasureFormatImpl(LocaleInfo & localeinfo,I18nStatus & status)22 MeasureFormatImpl::MeasureFormatImpl(LocaleInfo &localeinfo, I18nStatus &status)
23 {
24     if (localeinfo.GetId() == nullptr) {
25         status = I18nStatus::IERROR;
26         return;
27     }
28     locale = localeinfo;
29     pluralFormat = new PluralFormat(localeinfo, status);
30     if (status != I18nStatus::ISUCCESS || pluralFormat == nullptr) {
31         status = I18nStatus::IERROR;
32         return;
33     }
34     int numberFormatStatus = 0;
35     numberFormat = new NumberFormat(localeinfo, numberFormatStatus);
36     if (numberFormatStatus || numberFormat == nullptr) {
37         status = I18nStatus::IERROR;
38         return;
39     }
40 }
41 
~MeasureFormatImpl()42 MeasureFormatImpl::~MeasureFormatImpl()
43 {
44     DeallocateMemory();
45     if (pluralFormat != nullptr) {
46         delete pluralFormat;
47         pluralFormat = nullptr;
48     }
49     if (numberFormat != nullptr) {
50         delete numberFormat;
51         numberFormat = nullptr;
52     }
53 }
54 
Format(double num,std::string & unit,MeasureFormatType type,I18nStatus & status)55 std::string MeasureFormatImpl::Format(double num, std::string &unit, MeasureFormatType type, I18nStatus &status)
56 {
57     formattedDouble = num;
58     return FormatInner(false, unit, type, status);
59 }
60 
Format(int num,std::string & unit,MeasureFormatType type,I18nStatus & status)61 std::string MeasureFormatImpl::Format(int num, std::string &unit, MeasureFormatType type, I18nStatus &status)
62 {
63     formattedInteger = num;
64     return FormatInner(true, unit, type, status);
65 }
66 
FormatInner(bool isInteger,std::string & unit,MeasureFormatType type,I18nStatus & status)67 std::string MeasureFormatImpl::FormatInner(bool isInteger, std::string &unit, MeasureFormatType type,
68     I18nStatus &status)
69 {
70     int unitIndex = SearchUnits(unit, status);
71     if (status != I18nStatus::ISUCCESS) {
72         return "";
73     }
74     int pluralIndex = ComputePluralIndex(isInteger, status);
75     if (status != I18nStatus::ISUCCESS) {
76         return "";
77     }
78     std::string formattedUnit = ComputeFormattedUnit(unitIndex, pluralIndex, type, status);
79     if (status != I18nStatus::ISUCCESS) {
80         return "";
81     }
82     std::string formattedNumber = ComputeFormattedNumber(isInteger, status);
83     if (status != I18nStatus::ISUCCESS) {
84         return "";
85     }
86 
87     char result[MAX_MEASURE_FORMAT_LENGTH];
88     int concatenate = 0;
89     if (isNumberFirst) {
90         concatenate = sprintf_s(result, MAX_MEASURE_FORMAT_LENGTH, pattern.c_str(), formattedNumber.c_str(),
91             formattedUnit.c_str());
92     } else {
93         concatenate = sprintf_s(result, MAX_MEASURE_FORMAT_LENGTH, pattern.c_str(), formattedUnit.c_str(),
94             formattedNumber.c_str());
95     }
96     if (concatenate < 0) {
97         status = I18nStatus::IERROR;
98         return "";
99     }
100     return result;
101 }
102 
SearchUnits(std::string & target,I18nStatus & status)103 int MeasureFormatImpl::SearchUnits(std::string &target, I18nStatus &status)
104 {
105     for (int i = 0; i < unitCount; i++) {
106         if (target.compare(units[i]) == 0) {
107             return i;
108         }
109     }
110     status = I18nStatus::IERROR;
111     return -1;
112 }
113 
ComputePluralIndex(bool isInteger,I18nStatus & status)114 int MeasureFormatImpl::ComputePluralIndex(bool isInteger, I18nStatus &status)
115 {
116     if (isInteger) {
117         return pluralFormat->GetPluralRuleIndex(formattedInteger, status);
118     } else {
119         return pluralFormat->GetPluralRuleIndex(formattedDouble, status);
120     }
121 }
122 
ComputeFormattedUnit(int unitIndex,int pluralIndex,MeasureFormatType type,I18nStatus & status)123 std::string MeasureFormatImpl::ComputeFormattedUnit(int unitIndex, int pluralIndex, MeasureFormatType type,
124     I18nStatus &status)
125 {
126     int index = unitIndex * MEASURE_FORMAT_TYPE_NUM + (int)type;
127     std::string formattedUnit = formattedUnits[index][pluralIndex];
128     if (formattedUnit.length() != 0) {
129         return formattedUnit;
130     }
131     formattedUnit = formattedUnits[index][MEASURE_PLURAL_NUM - 1];
132     if (formattedUnit.length() != 0) {
133         return formattedUnit;
134     }
135     type = ConvertType(type, status);
136     if (status != I18nStatus::ISUCCESS) {
137         return "";
138     }
139     formattedUnit = ComputeFormattedUnit(unitIndex, pluralIndex, type, status);
140     if (status != I18nStatus::ISUCCESS) {
141         return "";
142     }
143     return formattedUnit;
144 }
145 
ConvertType(MeasureFormatType type,I18nStatus & status)146 MeasureFormatType MeasureFormatImpl::ConvertType(MeasureFormatType type, I18nStatus &status)
147 {
148     if (type == MeasureFormatType::MEASURE_SHORT) {
149         return MeasureFormatType::MEASURE_MEDIUM;
150     } else if (type == MeasureFormatType::MEASURE_FULL) {
151         return MeasureFormatType::MEASURE_LONG;
152     } else if (type == MeasureFormatType::MEASURE_LONG) {
153         return MeasureFormatType::MEASURE_MEDIUM;
154     } else {
155         status = I18nStatus::IERROR;
156         return MeasureFormatType::MEASURE_MEDIUM;
157     }
158 }
159 
ComputeFormattedNumber(bool isInteger,I18nStatus & status)160 std::string MeasureFormatImpl::ComputeFormattedNumber(bool isInteger, I18nStatus &status)
161 {
162     std::string formattedNumber;
163     int numberFormatStatus = 0;
164     if (isInteger) {
165         formattedNumber = numberFormat->Format(formattedInteger, NumberFormatType::DECIMAL, numberFormatStatus);
166     } else {
167         formattedNumber = numberFormat->Format(formattedDouble, NumberFormatType::DECIMAL, numberFormatStatus);
168     }
169     if (numberFormatStatus) {
170         status = I18nStatus::IERROR;
171         return "";
172     }
173     return formattedNumber;
174 }
175 
Init(const DataResource & resource)176 bool MeasureFormatImpl::Init(const DataResource &resource)
177 {
178     if (units != nullptr || formattedUnits != nullptr) {
179         DeallocateMemory();
180     }
181     std::string unprocessedMeasureData = resource.GetString(DataResourceType::MEASURE_FORMAT_PATTERNS);
182     bool status = InitMeasureFormat(unprocessedMeasureData);
183     if (!status) {
184         return false;
185     }
186     return true;
187 }
188 
InitMeasureFormat(std::string & unprocessedMeasureData)189 bool MeasureFormatImpl::InitMeasureFormat(std::string &unprocessedMeasureData)
190 {
191     int end = 0;
192     while (end < unprocessedMeasureData.length() && unprocessedMeasureData[end] != PLURAL_SEP) {
193         end++;
194     }
195     unitCount = std::stoi(std::string(unprocessedMeasureData, 0, end));
196     int itemCount = MEASURE_BASE_ITEM_COUNT + unitCount * MEASURE_SINGLE_UNIT_COUNT;
197     std::string *items = new std::string[itemCount];
198     if (items == nullptr) {
199         return false;
200     }
201     Split(unprocessedMeasureData, items, itemCount, PLURAL_SEP);
202     // items[1] is unit list, such as h|min|kcal|time...
203     if (!ParseUnits(items[1])) {
204         return false;
205     }
206     // items[2] is pattern
207     pattern = items[2];
208     // items[3] represent number and unit which comes first.
209     if (strcmp(items[3].c_str(), "#") == 0) {
210         isNumberFirst = true;
211     } else {
212         isNumberFirst = false;
213     }
214     formattedUnitCount = unitCount * MEASURE_FORMAT_TYPE_NUM;
215     if (!AllocaFormattedUnits()) {
216         return false;
217     }
218     int itemStartIndex = MEASURE_BASE_ITEM_COUNT;
219     for (int i = 0; i < unitCount; i++) {
220         for (int j = 0; j < MEASURE_FORMAT_TYPE_NUM; j++) {
221             FillFormattedUnits(i, j, items, itemStartIndex);
222             itemStartIndex += MEASURE_PLURAL_NUM;
223         }
224     }
225     if (items != nullptr) {
226         delete[] items;
227         items = nullptr;
228     }
229     return true;
230 }
231 
ParseUnits(std::string & unitsList)232 bool MeasureFormatImpl::ParseUnits(std::string &unitsList)
233 {
234     units = new std::string[unitCount];
235     if (units == nullptr) {
236         return false;
237     }
238     int begin = 0;
239     int end = 0;
240     int unitsLength = unitsList.length();
241     int count = 0;
242     while (count < unitCount) {
243         while (end < unitsLength && unitsList[end] != MEASURE_UNIT_SEP) {
244             end++;
245         }
246         if (end >= unitsLength) {
247             break;
248         }
249         units[count] = std::string(unitsList, begin, end - begin);
250         count++;
251         end++;
252         begin = end;
253     }
254     if (count < unitCount && end > begin) {
255         units[count] = std::string(unitsList, begin, end - begin);
256     }
257     if ((count + 1 != unitCount) || end < unitsLength) {
258         return false;
259     }
260     return true;
261 }
262 
AllocaFormattedUnits()263 bool MeasureFormatImpl::AllocaFormattedUnits()
264 {
265     formattedUnits = new std::string *[formattedUnitCount];
266     if (formattedUnits == nullptr) {
267         return false;
268     }
269     for (int i = 0; i < formattedUnitCount; i++) {
270         formattedUnits[i] = new std::string[MEASURE_PLURAL_NUM];
271         if (formattedUnits[i] == nullptr) {
272             return false;
273         }
274     }
275     return true;
276 }
277 
FillFormattedUnits(int unitIndex,int typeIndex,std::string * items,int itemStartIndex)278 void MeasureFormatImpl::FillFormattedUnits(int unitIndex, int typeIndex, std::string *items, int itemStartIndex)
279 {
280     for (int i = 0; i < MEASURE_PLURAL_NUM; i++) {
281         int index = unitIndex * MEASURE_FORMAT_TYPE_NUM + typeIndex;
282         formattedUnits[index][i] = items[itemStartIndex + i];
283     }
284 }
285 
DeallocateMemory()286 void MeasureFormatImpl::DeallocateMemory()
287 {
288     if (units != nullptr) {
289         delete[] units;
290         units = nullptr;
291     }
292     if (formattedUnits != nullptr) {
293         for (int i = 0; i < formattedUnitCount; i++) {
294             if (formattedUnits[i] != nullptr) {
295                 delete[] formattedUnits[i];
296             }
297         }
298         delete[] formattedUnits;
299     }
300 }