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