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