• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_UTILS_UTILS_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_UTILS_UTILS_H
18 
19 #include <algorithm>
20 #include <cctype>
21 #include <climits>
22 #include <cmath>
23 #include <cstring>
24 #include <iomanip>
25 #include <map>
26 #include <optional>
27 #include <sstream>
28 #include <string>
29 #include <unordered_map>
30 #include <unordered_set>
31 
32 #include "base/geometry/axis.h"
33 #include "base/json/json_util.h"
34 #include "base/log/log.h"
35 #include "base/resource/asset_manager.h"
36 #include "base/utils/linear_map.h"
37 #include "base/utils/string_utils.h"
38 #include "base/utils/utils.h"
39 #include "core/animation/animation_pub.h"
40 #include "core/animation/curve.h"
41 #include "core/animation/curves.h"
42 #include "core/animation/spring_curve.h"
43 #include "core/common/ime/text_input_action.h"
44 #include "core/common/ime/text_input_type.h"
45 #include "core/components/common/layout/constants.h"
46 #include "core/components/common/properties/clip_path.h"
47 #include "core/components/common/properties/decoration.h"
48 #include "core/components/common/properties/text_style.h"
49 #include "frameworks/bridge/common/dom/dom_type.h"
50 
51 namespace OHOS::Ace::Framework {
52 
53 constexpr int32_t OFFSET_VALUE_NUMBER = 2;
54 constexpr uint8_t UTF8_CHARATER_HEAD = 0xc0;
55 constexpr uint8_t UTF8_CHARATER_BODY = 0x80;
56 constexpr int32_t UNICODE_LENGTH = 4;
57 constexpr int32_t STRTOL_BASE = 10;
58 constexpr int32_t INVALID_PARAM = -1;
59 constexpr int32_t PLACE_HOLDER_LENGTH = 3;
60 
61 constexpr char INPUT_ACTION_NEXT[] = "next";
62 constexpr char INPUT_ACTION_GO[] = "go";
63 constexpr char INPUT_ACTION_DONE[] = "done";
64 constexpr char INPUT_ACTION_SEND[] = "send";
65 constexpr char INPUT_ACTION_SEARCH[] = "search";
66 constexpr char PLURAL_COUNT_POS[] = "{count}";
67 constexpr char DEFAULT_PLURAL_CHOICE[] = "other";
68 
69 const char DOUBLE_QUOTATION = '"';
70 const char BACKSLASH = '\\';
71 const char ESCAPE_CHARATER_START = '\x00';
72 const char ESCAPE_CHARATER_END = '\x1f';
73 const char UNICODE_BODY = '0';
74 const char UNICODE_HEAD[] = "\\u";
75 const char LEFT_CURLY_BRACES = '{';
76 const char RIGHT_CURLY_BRACES = '}';
77 
78 template<class T>
GetAssetContentImpl(const RefPtr<AssetManager> & assetManager,const std::string & url,T & content)79 bool GetAssetContentImpl(const RefPtr<AssetManager>& assetManager, const std::string& url, T& content)
80 {
81     if (!assetManager) {
82         LOGE("AssetManager is null");
83         return false;
84     }
85     auto jsAsset = assetManager->GetAsset(url);
86     if (jsAsset == nullptr) {
87         LOGW("uri:%{public}s Asset is null", url.c_str());
88         return false;
89     }
90     auto bufLen = jsAsset->GetSize();
91     auto buffer = jsAsset->GetData();
92     if ((buffer == nullptr) || (bufLen <= 0)) {
93         LOGE("uri:%{private}s buffer is null", url.c_str());
94         return false;
95     }
96     content.assign(buffer, buffer + bufLen);
97     return true;
98 }
99 
100 template<class T>
GetAssetContentAllowEmpty(const RefPtr<AssetManager> & assetManager,const std::string & url,T & content)101 bool GetAssetContentAllowEmpty(const RefPtr<AssetManager>& assetManager, const std::string& url, T& content)
102 {
103     if (!assetManager) {
104         LOGE("AssetManager is null");
105         return false;
106     }
107     auto jsAsset = assetManager->GetAsset(url);
108     if (jsAsset == nullptr) {
109         LOGW("uri:%{public}s Asset is null", url.c_str());
110         return false;
111     }
112     auto bufLen = jsAsset->GetSize();
113     auto buffer = jsAsset->GetData();
114     content.assign(buffer, buffer + bufLen);
115     return true;
116 }
117 
GetAssetPathImpl(const RefPtr<AssetManager> & assetManager,const std::string & url)118 inline std::string GetAssetPathImpl(const RefPtr<AssetManager>& assetManager, const std::string& url)
119 {
120     if (!assetManager) {
121         LOGE("AssetManager is null");
122         return "";
123     }
124     return assetManager->GetAssetPath(url);
125 }
126 
ParseFileData(const std::string & data)127 inline std::unique_ptr<JsonValue> ParseFileData(const std::string& data)
128 {
129     const char* endMsg = nullptr;
130     auto fileData = JsonUtil::ParseJsonString(data, &endMsg);
131     if (!fileData) {
132         LOGE("parse i18n data failed, error: %{private}s", endMsg);
133         return nullptr;
134     }
135     return fileData;
136 }
137 
StringToDouble(const std::string & value)138 inline double StringToDouble(const std::string& value)
139 {
140     return StringUtils::StringToDouble(value);
141 }
142 
StringToDimension(const std::string & value)143 inline Dimension StringToDimension(const std::string& value)
144 {
145     return StringUtils::StringToDimension(value);
146 }
147 
148 inline Dimension StringToDimensionWithUnit(const std::string& value, DimensionUnit defaultUnit = DimensionUnit::PX)
149 {
150     return StringUtils::StringToDimensionWithUnit(value, defaultUnit);
151 }
152 
StringToInt(const std::string & value)153 inline int32_t StringToInt(const std::string& value)
154 {
155     return StringUtils::StringToInt(value);
156 }
157 
StringToBool(const std::string & value)158 inline bool StringToBool(const std::string& value)
159 {
160     return value == "true";
161 }
162 
ConvertStrToBorderStyle(const std::string & style)163 inline BorderStyle ConvertStrToBorderStyle(const std::string& style)
164 {
165     static const LinearMapNode<BorderStyle> borderStyleTable[] = {
166         { "dashed", BorderStyle::DASHED },
167         { "dotted", BorderStyle::DOTTED },
168         { "solid", BorderStyle::SOLID },
169     };
170 
171     auto index = BinarySearchFindIndex(borderStyleTable, ArraySize(borderStyleTable), style.c_str());
172     return index < 0 ? BorderStyle::NONE : borderStyleTable[index].value;
173 }
174 
ConvertStrToBorderImageRepeat(const std::string & repeat)175 inline BorderImageRepeat ConvertStrToBorderImageRepeat(const std::string& repeat)
176 {
177     static const LinearMapNode<BorderImageRepeat> borderImageRepeatTable[] = {
178         { "repeat", BorderImageRepeat::REPEAT },
179         { "round", BorderImageRepeat::ROUND },
180         { "space", BorderImageRepeat::SPACE },
181         { "stretch", BorderImageRepeat::STRETCH },
182     };
183 
184     auto index = BinarySearchFindIndex(borderImageRepeatTable, ArraySize(borderImageRepeatTable), repeat.c_str());
185     return index < 0 ? BorderImageRepeat::STRETCH : borderImageRepeatTable[index].value;
186 }
187 
ConvertStrToBadgePosition(const std::string & badgePosition)188 inline BadgePosition ConvertStrToBadgePosition(const std::string& badgePosition)
189 {
190     static const LinearMapNode<BadgePosition> badgePositionTable[] = {
191         { "left", BadgePosition::LEFT },
192         { "right", BadgePosition::RIGHT },
193         { "rightTop", BadgePosition::RIGHT_TOP },
194     };
195     auto index = BinarySearchFindIndex(badgePositionTable, ArraySize(badgePositionTable), badgePosition.c_str());
196     return index < 0 ? BadgePosition::RIGHT_TOP : badgePositionTable[index].value;
197 }
198 
ConvertStrToBoxSizing(const std::string & value)199 inline BoxSizing ConvertStrToBoxSizing(const std::string& value)
200 {
201     static const LinearMapNode<BoxSizing> boxSizingTable[] = {
202         { "border-box", BoxSizing::BORDER_BOX },
203         { "content-box", BoxSizing::CONTENT_BOX },
204     };
205     auto index = BinarySearchFindIndex(boxSizingTable, ArraySize(boxSizingTable), value.c_str());
206     return index < 0 ? BoxSizing::BORDER_BOX : boxSizingTable[index].value;
207 }
208 
ConvertStrToImageRepeat(const std::string & repeat)209 inline ImageRepeat ConvertStrToImageRepeat(const std::string& repeat)
210 {
211     static const LinearMapNode<ImageRepeat> imageRepeatTable[] = {
212         { "no-repeat", ImageRepeat::NOREPEAT },
213         { "repeat", ImageRepeat::REPEAT },
214         { "repeat-x", ImageRepeat::REPEATX },
215         { "repeat-y", ImageRepeat::REPEATY },
216     };
217 
218     auto index = BinarySearchFindIndex(imageRepeatTable, ArraySize(imageRepeatTable), repeat.c_str());
219     return index < 0 ? ImageRepeat::NOREPEAT : imageRepeatTable[index].value;
220 }
221 
ConvertStrToFontWeight(const std::string & weight)222 inline FontWeight ConvertStrToFontWeight(const std::string& weight)
223 {
224     return StringUtils::StringToFontWeight(weight);
225 }
226 
ConvertStrToTextDecoration(const std::string & textDecoration)227 inline TextDecoration ConvertStrToTextDecoration(const std::string& textDecoration)
228 {
229     // this map should be sorted bu key.
230     static const LinearMapNode<TextDecoration> textDecorationTable[] = {
231         { DOM_TEXT_DECORATION_INHERIT, TextDecoration::INHERIT },
232         { DOM_TEXT_DECORATION_LINETHROUGH, TextDecoration::LINE_THROUGH },
233         { DOM_TEXT_DECORATION_NONE, TextDecoration::NONE },
234         { DOM_TEXT_DECORATION_OVERLINE, TextDecoration::OVERLINE },
235         { DOM_TEXT_DECORATION_UNDERLINE, TextDecoration::UNDERLINE },
236     };
237 
238     auto index = BinarySearchFindIndex(textDecorationTable, ArraySize(textDecorationTable), textDecoration.c_str());
239     return index < 0 ? TextDecoration::NONE : textDecorationTable[index].value;
240 }
241 
ConvertStrToWhiteSpace(const std::string & whiteSpace)242 inline WhiteSpace ConvertStrToWhiteSpace(const std::string& whiteSpace)
243 {
244     // this map should be sorted bu key.
245     static const LinearMapNode<WhiteSpace> whiteSpaceTable[] = {
246         { DOM_WHITE_SPACE_INHERIT, WhiteSpace::INHERIT },
247         { DOM_WHITE_SPACE_NORMAL, WhiteSpace::NORMAL },
248         { DOM_WHITE_SPACE_NOWRAP, WhiteSpace::NOWRAP },
249         { DOM_WHITE_SPACE_PRE, WhiteSpace::PRE },
250         { DOM_WHITE_SPACE_PRELINE, WhiteSpace::PRE_LINE },
251         { DOM_WHITE_SPACE_PREWRAP, WhiteSpace::PRE_WRAP },
252     };
253 
254     auto index = BinarySearchFindIndex(whiteSpaceTable, ArraySize(whiteSpaceTable), whiteSpace.c_str());
255     return index < 0 ? WhiteSpace::NORMAL : whiteSpaceTable[index].value;
256 }
257 
ConvertStrToTextVerticalAlign(const std::string & align)258 inline VerticalAlign ConvertStrToTextVerticalAlign(const std::string& align)
259 {
260     static const LinearMapNode<VerticalAlign> textVerticalAlignTable[] = {
261         {DOM_BOTTOM, VerticalAlign::BOTTOM},
262         {DOM_MIDDLE, VerticalAlign::CENTER},
263         {DOM_TOP, VerticalAlign::TOP},
264     };
265     auto index = BinarySearchFindIndex(textVerticalAlignTable, ArraySize(textVerticalAlignTable), align.c_str());
266     return index < 0 ? VerticalAlign::NONE : textVerticalAlignTable[index].value;
267 }
268 
ConvertStrToFontStyle(const std::string & fontStyle)269 inline FontStyle ConvertStrToFontStyle(const std::string& fontStyle)
270 {
271     return fontStyle == DOM_TEXT_FONT_STYLE_ITALIC ? FontStyle::ITALIC : FontStyle::NORMAL;
272 }
273 
ConvertStrToTextAlign(const std::string & align)274 inline TextAlign ConvertStrToTextAlign(const std::string& align)
275 {
276     static const LinearMapNode<TextAlign> textAlignTable[] = {
277         { DOM_CENTER, TextAlign::CENTER },
278         { DOM_END, TextAlign::END },
279         { DOM_LEFT, TextAlign::LEFT },
280         { DOM_RIGHT, TextAlign::RIGHT },
281         { DOM_START, TextAlign::START },
282     };
283 
284     auto index = BinarySearchFindIndex(textAlignTable, ArraySize(textAlignTable), align.c_str());
285     return index < 0 ? TextAlign::CENTER : textAlignTable[index].value;
286 }
287 
ConvertStrToTextOverflow(const std::string & overflow)288 inline TextOverflow ConvertStrToTextOverflow(const std::string& overflow)
289 {
290     return overflow == DOM_ELLIPSIS ? TextOverflow::ELLIPSIS : TextOverflow::CLIP;
291 }
292 
ConvertStrToOverflow(const std::string & val)293 inline Overflow ConvertStrToOverflow(const std::string& val)
294 {
295     const LinearMapNode<Overflow> overflowTable[] = {
296         { "auto", Overflow::SCROLL },
297         { "hidden", Overflow::FORCE_CLIP },
298         { "scroll", Overflow::SCROLL },
299         { "visible", Overflow::OBSERVABLE },
300     };
301     auto index = BinarySearchFindIndex(overflowTable, ArraySize(overflowTable), val.c_str());
302     return index < 0 ? Overflow::CLIP : overflowTable[index].value;
303 }
304 
ConvertStrToTextDirection(const std::string & val)305 inline TextDirection ConvertStrToTextDirection(const std::string& val)
306 {
307     const LinearMapNode<TextDirection> textDirectionTable[] = {
308         { "ltr", TextDirection::LTR },
309         { "rtl", TextDirection::RTL },
310         { "inherit", TextDirection::INHERIT },
311     };
312     auto index = BinarySearchFindIndex(textDirectionTable, ArraySize(textDirectionTable), val.c_str());
313     return index < 0 ? TextDirection::LTR : textDirectionTable[index].value;
314 }
ConvertStrToFontFamilies(const std::string & family)315 inline std::vector<std::string> ConvertStrToFontFamilies(const std::string& family)
316 {
317     std::vector<std::string> fontFamilies;
318     std::stringstream stream(family);
319     std::string fontFamily;
320     while (getline(stream, fontFamily, ',')) {
321         fontFamilies.emplace_back(fontFamily);
322     }
323     return fontFamilies;
324 }
325 
ConvertStrToFlexDirection(const std::string & flexKey)326 inline FlexDirection ConvertStrToFlexDirection(const std::string& flexKey)
327 {
328     return flexKey == DOM_FLEX_COLUMN ? FlexDirection::COLUMN : FlexDirection::ROW;
329 }
330 
ConvertStrToFlexAlign(const std::string & flexKey)331 inline FlexAlign ConvertStrToFlexAlign(const std::string& flexKey)
332 {
333     static const LinearMapNode<FlexAlign> flexMap[] = {
334         { DOM_ALIGN_ITEMS_BASELINE, FlexAlign::BASELINE },
335         { DOM_JUSTIFY_CONTENT_CENTER, FlexAlign::CENTER },
336         { DOM_JUSTIFY_CONTENT_END, FlexAlign::FLEX_END },
337         { DOM_JUSTIFY_CONTENT_START, FlexAlign::FLEX_START },
338         { DOM_JUSTIFY_CONTENT_AROUND, FlexAlign::SPACE_AROUND },
339         { DOM_JUSTIFY_CONTENT_BETWEEN, FlexAlign::SPACE_BETWEEN },
340         { DOM_JUSTIFY_CONTENT_EVENLY, FlexAlign::SPACE_EVENLY },
341         { DOM_ALIGN_ITEMS_STRETCH, FlexAlign::STRETCH },
342     };
343     auto index = BinarySearchFindIndex(flexMap, ArraySize(flexMap), flexKey.c_str());
344     return index < 0 ? FlexAlign::FLEX_START : flexMap[index].value;
345 }
346 
ConvertStrToOffset(const std::string & value)347 inline Offset ConvertStrToOffset(const std::string& value)
348 {
349     Offset offset;
350     std::vector<std::string> offsetValues;
351     std::stringstream stream(value);
352     std::string offsetValue;
353     while (getline(stream, offsetValue, ' ')) {
354         offsetValues.emplace_back(offsetValue);
355     }
356     // To avoid illegal input, such as "100px ".
357     offsetValues.resize(OFFSET_VALUE_NUMBER);
358     offset.SetX(StringToDouble(offsetValues[0]));
359     offset.SetY(StringToDouble(offsetValues[1]));
360     return offset;
361 }
362 
ConvertStrToQrcodeType(const std::string & value)363 inline QrcodeType ConvertStrToQrcodeType(const std::string& value)
364 {
365     return value == "circle" ? QrcodeType::CIRCLE : QrcodeType::RECT;
366 }
367 
ConvertStrToAnimationCurve(const std::string & value)368 inline AnimationCurve ConvertStrToAnimationCurve(const std::string& value)
369 {
370     return value == "standard" ? AnimationCurve::STANDARD : AnimationCurve::FRICTION;
371 }
372 
ConvertStrToTextInputAction(const std::string & action)373 inline TextInputAction ConvertStrToTextInputAction(const std::string& action)
374 {
375     TextInputAction inputAction;
376     if (action == INPUT_ACTION_NEXT) {
377         inputAction = TextInputAction::NEXT;
378     } else if (action == INPUT_ACTION_GO) {
379         inputAction = TextInputAction::GO;
380     } else if (action == INPUT_ACTION_DONE) {
381         inputAction = TextInputAction::DONE;
382     } else if (action == INPUT_ACTION_SEND) {
383         inputAction = TextInputAction::SEND;
384     } else if (action == INPUT_ACTION_SEARCH) {
385         inputAction = TextInputAction::SEARCH;
386     } else {
387         inputAction = TextInputAction::UNSPECIFIED;
388     }
389     return inputAction;
390 }
391 
ConvertStrToTextInputType(const std::string & type)392 inline TextInputType ConvertStrToTextInputType(const std::string& type)
393 {
394     TextInputType inputType;
395     if (type == DOM_INPUT_TYPE_NUMBER) {
396         inputType = TextInputType::NUMBER;
397     } else if (type == DOM_INPUT_TYPE_DATE || type == DOM_INPUT_TYPE_TIME) {
398         inputType = TextInputType::DATETIME;
399     } else if (type == DOM_INPUT_TYPE_EMAIL) {
400         inputType = TextInputType::EMAIL_ADDRESS;
401     } else if (type == DOM_INPUT_TYPE_PASSWORD) {
402         inputType = TextInputType::VISIBLE_PASSWORD;
403     } else {
404         inputType = TextInputType::TEXT;
405     }
406     return inputType;
407 }
408 
ConvertStrToTabBarMode(const std::string & value)409 inline TabBarMode ConvertStrToTabBarMode(const std::string& value)
410 {
411     std::string temp = value;
412     transform(temp.begin(), temp.end(), temp.begin(), tolower);
413     return temp == "fixed" ? TabBarMode::FIXED : TabBarMode::SCROLLABEL;
414 }
415 
416 RefPtr<Curve> CreateBuiltinCurve(const std::string& aniTimFunc);
417 
418 RefPtr<Curve> CreateCustomCurve(const std::string& aniTimFunc);
419 
420 ACE_EXPORT RefPtr<Curve> CreateCurve(const std::string& aniTimFunc);
421 
422 ACE_EXPORT TransitionType ParseTransitionType(const std::string& transitionType);
423 
424 ACE_EXPORT RefPtr<ClipPath> CreateClipPath(const std::string& value);
425 
StringToFillMode(const std::string & fillMode)426 inline FillMode StringToFillMode(const std::string& fillMode)
427 {
428     if (fillMode == DOM_ANIMATION_FILL_MODE_FORWARDS) {
429         return FillMode::FORWARDS;
430     } else if (fillMode == DOM_ANIMATION_FILL_MODE_BACKWARDS) {
431         return FillMode::BACKWARDS;
432     } else if (fillMode == DOM_ANIMATION_FILL_MODE_BOTH) {
433         return FillMode::BOTH;
434     } else {
435         return FillMode::NONE;
436     }
437 }
438 
StringToAnimationDirection(const std::string & direction)439 inline AnimationDirection StringToAnimationDirection(const std::string& direction)
440 {
441     if (direction == DOM_ANIMATION_DIRECTION_ALTERNATE) {
442         return AnimationDirection::ALTERNATE;
443     } else if (direction == DOM_ANIMATION_DIRECTION_REVERSE) {
444         return AnimationDirection::REVERSE;
445     } else if (direction == DOM_ANIMATION_DIRECTION_ALTERNATE_REVERSE) {
446         return AnimationDirection::ALTERNATE_REVERSE;
447     } else {
448         return AnimationDirection::NORMAL;
449     }
450 }
451 
StringToAnimationOperation(const std::string & direction)452 inline AnimationOperation StringToAnimationOperation(const std::string& direction)
453 {
454     if (direction == DOM_ANIMATION_PLAY_STATE_IDLE) {
455         return AnimationOperation::CANCEL;
456     } else if (direction == DOM_ANIMATION_PLAY_STATE_RUNNING) {
457         return AnimationOperation::RUNNING;
458     } else if (direction == DOM_ANIMATION_PLAY_STATE_PAUSED) {
459         return AnimationOperation::PAUSE;
460     } else if (direction == DOM_ANIMATION_PLAY_STATE_FINISHED) {
461         return AnimationOperation::FINISH;
462     } else {
463         return AnimationOperation::NONE;
464     }
465 }
466 
RemoveHeadTailSpace(std::string & value)467 inline void RemoveHeadTailSpace(std::string& value)
468 {
469     if (!value.empty()) {
470         auto start = value.find_first_not_of(' ');
471         if (start == std::string::npos) {
472             value.clear();
473         } else {
474             value = value.substr(start, value.find_last_not_of(' ') - start + 1);
475         }
476     }
477 }
478 
StrToGradientDirection(const std::string & direction)479 inline GradientDirection StrToGradientDirection(const std::string& direction)
480 {
481     static const LinearMapNode<GradientDirection> gradientDirectionTable[] = {
482         { DOM_GRADIENT_DIRECTION_LEFT, GradientDirection::LEFT },
483         { DOM_GRADIENT_DIRECTION_RIGHT, GradientDirection::RIGHT },
484         { DOM_GRADIENT_DIRECTION_TOP, GradientDirection::TOP },
485         { DOM_GRADIENT_DIRECTION_BOTTOM, GradientDirection::BOTTOM },
486     };
487 
488     auto index = BinarySearchFindIndex(gradientDirectionTable, ArraySize(gradientDirectionTable), direction.c_str());
489     return index < 0 ? GradientDirection::BOTTOM : gradientDirectionTable[index].value;
490 }
491 
492 bool ParseBackgroundImagePosition(const std::string& value, BackgroundImagePosition& backgroundImagePosition);
493 
494 bool ParseBackgroundImageSize(const std::string& value, BackgroundImageSize& backgroundImageSize);
495 
496 ImageObjectPosition ParseImageObjectPosition(const std::string& value);
497 
498 std::optional<RadialSizeType> ParseRadialGradientSize(const std::string& value);
499 
StartWith(const std::string & dst,const std::string & prefix)500 inline bool StartWith(const std::string& dst, const std::string& prefix)
501 {
502     return dst.compare(0, prefix.size(), prefix) == 0;
503 }
504 
EndWith(const std::string & dst,const std::string & suffix)505 inline bool EndWith(const std::string& dst, const std::string& suffix)
506 {
507     return dst.size() >= suffix.size() && dst.compare(dst.size() - suffix.size(), suffix.size(), suffix) == 0;
508 }
509 
ConvertTimeStr(const std::string & str)510 inline double ConvertTimeStr(const std::string& str)
511 {
512     std::string time(str);
513     StringUtils::TrimStr(time);
514     double result = 0.0;
515     if (EndWith(time, "ms")) {
516         result = StringToDouble(std::string(time.begin(), time.end() - 2.0));
517     } else if (EndWith(time, "s")) {
518         result = StringToDouble(std::string(time.begin(), time.end() - 1.0)) * 1000.0;
519     } else if (EndWith(time, "m")) {
520         result = StringToDouble(std::string(time.begin(), time.end() - 1.0)) * 60.0 * 1000.0;
521     } else {
522         result = StringToDouble(str);
523     }
524     return result;
525 }
526 
ConvertStrToWordBreak(const std::string & wordBreak)527 inline WordBreak ConvertStrToWordBreak(const std::string& wordBreak)
528 {
529     return StringUtils::StringToWordBreak(wordBreak);
530 }
531 
CheckTransformEnum(const std::string & str)532 inline bool CheckTransformEnum(const std::string& str)
533 {
534     const static std::unordered_set<std::string> offsetKeywords = { "left", "right", "center", "top", "bottom" };
535 
536     return offsetKeywords.find(str) != offsetKeywords.end();
537 }
538 
ConvertStrToTransformOrigin(const std::string & str,Axis axis)539 inline std::pair<bool, Dimension> ConvertStrToTransformOrigin(const std::string& str, Axis axis)
540 {
541     const static std::unordered_map<std::string, Dimension> xOffsetKeywords = {
542         { "left", 0.0_pct },
543         { "right", 1.0_pct },
544         { "center", 0.5_pct },
545     };
546     const static std::unordered_map<std::string, Dimension> yOffsetKeywords = {
547         { "top", 0.0_pct },
548         { "bottom", 1.0_pct },
549         { "center", 0.5_pct },
550     };
551 
552     if (axis == Axis::HORIZONTAL) {
553         auto pos = xOffsetKeywords.find(str);
554         if (pos != xOffsetKeywords.end()) {
555             return std::make_pair(true, pos->second);
556         }
557     } else if (axis == Axis::VERTICAL) {
558         auto pos = yOffsetKeywords.find(str);
559         if (pos != yOffsetKeywords.end()) {
560             return std::make_pair(true, pos->second);
561         }
562     }
563 
564     return std::make_pair(false, Dimension {});
565 }
566 
ParseUtf8TextLength(std::string & text)567 inline int32_t ParseUtf8TextLength(std::string& text)
568 {
569     int32_t trueLength = 0;
570     int32_t stringLength = 0;
571     while (stringLength < static_cast<int32_t>(text.length())) {
572         uint8_t stringChar = static_cast<uint8_t>(text[stringLength++]);
573         if ((stringChar & UTF8_CHARATER_HEAD) != UTF8_CHARATER_BODY) {
574             trueLength++;
575         }
576     }
577     return trueLength;
578 }
579 
ParseUtf8TextSubstrStartPos(std::string & text,int32_t targetPos)580 inline int32_t ParseUtf8TextSubstrStartPos(std::string& text, int32_t targetPos)
581 {
582     int32_t truePos = 0;
583     int32_t stringPos = 0;
584     while ((stringPos < static_cast<int32_t>(text.length())) && (truePos < targetPos)) {
585         uint8_t stringChar = static_cast<uint8_t>(text[stringPos++]);
586         if ((stringChar & UTF8_CHARATER_HEAD) != UTF8_CHARATER_BODY) {
587             truePos++;
588         }
589     }
590 
591     return stringPos;
592 }
593 
ParseUtf8TextSubstrEndPos(std::string & text,int32_t targetPos)594 inline int32_t ParseUtf8TextSubstrEndPos(std::string& text, int32_t targetPos)
595 {
596     auto stringPos = ParseUtf8TextSubstrStartPos(text, targetPos);
597     while (stringPos < static_cast<int32_t>(text.length())) {
598         uint8_t stringChar = static_cast<uint8_t>(text[stringPos]);
599         if ((stringChar & UTF8_CHARATER_HEAD) != UTF8_CHARATER_BODY) {
600             break;
601         }
602         stringPos++;
603     }
604 
605     return stringPos;
606 }
607 
HandleEscapeCharaterInUtf8TextForJson(std::string & text)608 inline void HandleEscapeCharaterInUtf8TextForJson(std::string& text)
609 {
610     for (size_t pos = 0; pos < text.size(); pos++) {
611         if ((text.at(pos) == DOUBLE_QUOTATION) || (text.at(pos) == BACKSLASH) ||
612             ((text.at(pos) >= ESCAPE_CHARATER_START) && (text.at(pos) <= ESCAPE_CHARATER_END))) {
613             std::ostringstream is;
614             is << UNICODE_HEAD << std::hex << std::setw(UNICODE_LENGTH) << std::setfill(UNICODE_BODY)
615                 << int(text.at(pos));
616             text.replace(pos, 1, is.str());
617         }
618     }
619 }
620 
ParseResourceInputNumberParam(const std::string & param)621 inline int32_t ParseResourceInputNumberParam(const std::string& param)
622 {
623     if (!StringUtils::IsNumber(param) || param.empty()) {
624         return INVALID_PARAM;
625     } else {
626         errno = 0;
627         char* pEnd = nullptr;
628         int64_t result = std::strtol(param.c_str(), &pEnd, STRTOL_BASE);
629         if ((result < INT_MIN || result > INT_MAX) || errno == ERANGE) {
630             return INT_MAX;
631         } else {
632             return static_cast<int32_t>(result);
633         }
634     }
635 }
636 
ReplacePlaceHolderArray(std::string & resultStr,const std::vector<std::string> & arrayResult)637 inline void ReplacePlaceHolderArray(std::string& resultStr, const std::vector<std::string>& arrayResult)
638 {
639     auto size = arrayResult.size();
640     size_t startPos = 0;
641     for (size_t i = 0; i < size; i++) {
642         std::string placeHolder;
643         placeHolder += LEFT_CURLY_BRACES;
644         placeHolder += (i + '0');
645         placeHolder += RIGHT_CURLY_BRACES;
646         if (startPos < resultStr.length()) {
647             auto pos = resultStr.find(placeHolder, startPos);
648             if (pos != std::string::npos) {
649                 resultStr.replace(pos, PLACE_HOLDER_LENGTH, arrayResult[i]);
650                 startPos = pos + arrayResult[i].length();
651             }
652         }
653     }
654 }
655 
ReplacePlaceHolder(std::string & resultStr,const std::unique_ptr<JsonValue> & argsPtr)656 inline void ReplacePlaceHolder(std::string& resultStr, const std::unique_ptr<JsonValue>& argsPtr)
657 {
658     auto placeHolderKey = argsPtr->GetChild()->GetKey();
659     std::string placeHolder;
660     placeHolder += LEFT_CURLY_BRACES;
661     placeHolder += placeHolderKey;
662     placeHolder += RIGHT_CURLY_BRACES;
663     auto pos = resultStr.find(placeHolder);
664     if (pos != std::string::npos) {
665         resultStr.replace(pos, placeHolder.length(), argsPtr->GetChild()->GetString());
666     }
667 }
668 
ParserPluralResource(const std::unique_ptr<JsonValue> & argsPtr,const std::string & choice,const std::string & count)669 inline std::string ParserPluralResource(const std::unique_ptr<JsonValue>& argsPtr, const std::string& choice,
670     const std::string& count)
671 {
672     std::string valueStr;
673     std::string defaultPluralStr(DEFAULT_PLURAL_CHOICE);
674     if (argsPtr->Contains(choice)) {
675         valueStr = argsPtr->GetValue(choice)->GetString();
676     } else if (argsPtr->Contains(defaultPluralStr)) {
677         valueStr = argsPtr->GetValue(defaultPluralStr)->GetString();
678     } else {
679         return std::string();
680     }
681 
682     std::string pluralStr(PLURAL_COUNT_POS);
683     auto pos = valueStr.find(pluralStr);
684     if (pos != std::string::npos) {
685         valueStr.replace(pos, pluralStr.length(), count);
686     }
687     return valueStr;
688 }
689 
690 } // namespace OHOS::Ace::Framework
691 
692 #endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_UTILS_UTILS_H
693