/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_UTILS_UTILS_H #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_UTILS_UTILS_H #include #include #include #include #include #include #include #include #include #include #include #include #include "base/error/error_code.h" #include "base/geometry/axis.h" #include "base/json/json_util.h" #include "base/log/log.h" #include "base/resource/asset_manager.h" #include "base/utils/linear_map.h" #include "base/utils/string_utils.h" #include "base/utils/utils.h" #include "core/animation/animation_pub.h" #include "core/animation/curve.h" #include "core/animation/curves.h" #include "core/animation/spring_curve.h" #include "core/common/ime/text_input_action.h" #include "core/common/ime/text_input_type.h" #include "core/components/common/layout/constants.h" #include "core/components/common/properties/clip_path.h" #include "core/components/common/properties/decoration.h" #include "core/components/common/properties/text_style.h" #include "frameworks/bridge/common/dom/dom_type.h" namespace OHOS::Ace::Framework { constexpr int32_t OFFSET_VALUE_NUMBER = 2; constexpr uint8_t UTF8_CHARATER_HEAD = 0xc0; constexpr uint8_t UTF8_CHARATER_BODY = 0x80; constexpr int32_t UNICODE_LENGTH = 4; constexpr int32_t STRTOL_BASE = 10; constexpr int32_t INVALID_PARAM = -1; constexpr int32_t PLACE_HOLDER_LENGTH = 3; constexpr char INPUT_ACTION_NEXT[] = "next"; constexpr char INPUT_ACTION_GO[] = "go"; constexpr char INPUT_ACTION_DONE[] = "done"; constexpr char INPUT_ACTION_SEND[] = "send"; constexpr char INPUT_ACTION_SEARCH[] = "search"; constexpr char PLURAL_COUNT_POS[] = "{count}"; constexpr char DEFAULT_PLURAL_CHOICE[] = "other"; const char DOUBLE_QUOTATION = '"'; const char BACKSLASH = '\\'; const char ESCAPE_CHARATER_START = '\x00'; const char ESCAPE_CHARATER_END = '\x1f'; const char UNICODE_BODY = '0'; const char UNICODE_HEAD[] = "\\u"; const char LEFT_CURLY_BRACES = '{'; const char RIGHT_CURLY_BRACES = '}'; template bool GetAssetContentImpl(const RefPtr& assetManager, const std::string& url, T& content) { if (!assetManager) { return false; } auto jsAsset = assetManager->GetAsset(url); if (jsAsset == nullptr) { return false; } auto bufLen = jsAsset->GetSize(); auto buffer = jsAsset->GetData(); if ((buffer == nullptr) || (bufLen <= 0)) { return false; } content.assign(buffer, buffer + bufLen); return true; } template bool GetAssetContentAllowEmpty(const RefPtr& assetManager, const std::string& url, T& content) { if (!assetManager) { return false; } auto jsAsset = assetManager->GetAsset(url); if (jsAsset == nullptr) { return false; } auto bufLen = jsAsset->GetSize(); auto buffer = jsAsset->GetData(); content.assign(buffer, buffer + bufLen); return true; } inline std::string GetAssetPathImpl(const RefPtr& assetManager, const std::string& url) { if (!assetManager) { return {}; } return assetManager->GetAssetPath(url, true); } inline std::unique_ptr ParseFileData(const std::string& data) { const char* endMsg = nullptr; auto fileData = JsonUtil::ParseJsonString(data, &endMsg); if (!fileData) { return nullptr; } return fileData; } inline double StringToDouble(const std::string& value) { return StringUtils::StringToDouble(value); } inline Dimension StringToDimension(const std::string& value) { return StringUtils::StringToDimension(value); } inline Dimension StringToDimensionWithUnit(const std::string& value, DimensionUnit defaultUnit = DimensionUnit::PX) { return StringUtils::StringToDimensionWithUnit(value, defaultUnit); } inline int32_t StringToInt(const std::string& value) { return StringUtils::StringToInt(value); } inline bool StringToBool(const std::string& value) { return value == "true"; } inline BorderStyle ConvertStrToBorderStyle(const std::string& style) { static const LinearMapNode borderStyleTable[] = { { "dashed", BorderStyle::DASHED }, { "dotted", BorderStyle::DOTTED }, { "solid", BorderStyle::SOLID }, }; auto index = BinarySearchFindIndex(borderStyleTable, ArraySize(borderStyleTable), style.c_str()); return index < 0 ? BorderStyle::NONE : borderStyleTable[index].value; } inline BorderImageRepeat ConvertStrToBorderImageRepeat(const std::string& repeat) { static const LinearMapNode borderImageRepeatTable[] = { { "repeat", BorderImageRepeat::REPEAT }, { "round", BorderImageRepeat::ROUND }, { "space", BorderImageRepeat::SPACE }, { "stretch", BorderImageRepeat::STRETCH }, }; auto index = BinarySearchFindIndex(borderImageRepeatTable, ArraySize(borderImageRepeatTable), repeat.c_str()); return index < 0 ? BorderImageRepeat::STRETCH : borderImageRepeatTable[index].value; } inline BadgePosition ConvertStrToBadgePosition(const std::string& badgePosition) { static const LinearMapNode badgePositionTable[] = { { "left", BadgePosition::LEFT }, { "right", BadgePosition::RIGHT }, { "rightTop", BadgePosition::RIGHT_TOP }, }; auto index = BinarySearchFindIndex(badgePositionTable, ArraySize(badgePositionTable), badgePosition.c_str()); return index < 0 ? BadgePosition::RIGHT_TOP : badgePositionTable[index].value; } inline BoxSizing ConvertStrToBoxSizing(const std::string& value) { static const LinearMapNode boxSizingTable[] = { { "border-box", BoxSizing::BORDER_BOX }, { "content-box", BoxSizing::CONTENT_BOX }, }; auto index = BinarySearchFindIndex(boxSizingTable, ArraySize(boxSizingTable), value.c_str()); return index < 0 ? BoxSizing::BORDER_BOX : boxSizingTable[index].value; } inline ImageRepeat ConvertStrToImageRepeat(const std::string& repeat) { static const LinearMapNode imageRepeatTable[] = { { "no-repeat", ImageRepeat::NO_REPEAT }, { "repeat", ImageRepeat::REPEAT }, { "repeat-x", ImageRepeat::REPEAT_X }, { "repeat-y", ImageRepeat::REPEAT_Y }, }; auto index = BinarySearchFindIndex(imageRepeatTable, ArraySize(imageRepeatTable), repeat.c_str()); return index < 0 ? ImageRepeat::NO_REPEAT : imageRepeatTable[index].value; } inline std::pair ParseFontWeight(const std::string& weight, FontWeight defaultFontWeight = FontWeight::NORMAL) { return StringUtils::ParseFontWeight(weight, defaultFontWeight); } inline FontWeight ConvertStrToFontWeight(const std::string& weight, FontWeight defaultFontWeight = FontWeight::NORMAL) { return StringUtils::StringToFontWeight(weight, defaultFontWeight); } inline TextDecoration ConvertStrToTextDecoration(const std::string& textDecoration) { // this map should be sorted by key. static const LinearMapNode textDecorationTable[] = { { DOM_TEXT_DECORATION_INHERIT, TextDecoration::INHERIT }, { DOM_TEXT_DECORATION_LINETHROUGH, TextDecoration::LINE_THROUGH }, { DOM_TEXT_DECORATION_NONE, TextDecoration::NONE }, { DOM_TEXT_DECORATION_OVERLINE, TextDecoration::OVERLINE }, { DOM_TEXT_DECORATION_UNDERLINE, TextDecoration::UNDERLINE }, }; auto index = BinarySearchFindIndex(textDecorationTable, ArraySize(textDecorationTable), textDecoration.c_str()); return index < 0 ? TextDecoration::NONE : textDecorationTable[index].value; } inline TextDecorationStyle ConvertStrToTextDecorationStyle(const std::string& textDecorationStyle) { // this map should be sorted by key. static const LinearMapNode textDecorationStyleTable[] = { { DOM_TEXT_DECORATION_STYLE_DASHED, TextDecorationStyle::DASHED }, { DOM_TEXT_DECORATION_STYLE_DOTTED, TextDecorationStyle::DOTTED }, { DOM_TEXT_DECORATION_STYLE_DOUBLE, TextDecorationStyle::DOUBLE }, { DOM_TEXT_DECORATION_STYLE_SOLID, TextDecorationStyle::SOLID }, { DOM_TEXT_DECORATION_STYLE_WAVY, TextDecorationStyle::WAVY }, }; auto index = BinarySearchFindIndex( textDecorationStyleTable, ArraySize(textDecorationStyleTable), textDecorationStyle.c_str()); return index < 0 ? TextDecorationStyle::SOLID : textDecorationStyleTable[index].value; } inline WhiteSpace ConvertStrToWhiteSpace(const std::string& whiteSpace) { // this map should be sorted by key. static const LinearMapNode whiteSpaceTable[] = { { DOM_WHITE_SPACE_INHERIT, WhiteSpace::INHERIT }, { DOM_WHITE_SPACE_NORMAL, WhiteSpace::NORMAL }, { DOM_WHITE_SPACE_NOWRAP, WhiteSpace::NOWRAP }, { DOM_WHITE_SPACE_PRE, WhiteSpace::PRE }, { DOM_WHITE_SPACE_PRELINE, WhiteSpace::PRE_LINE }, { DOM_WHITE_SPACE_PREWRAP, WhiteSpace::PRE_WRAP }, }; auto index = BinarySearchFindIndex(whiteSpaceTable, ArraySize(whiteSpaceTable), whiteSpace.c_str()); return index < 0 ? WhiteSpace::NORMAL : whiteSpaceTable[index].value; } inline VerticalAlign ConvertStrToTextVerticalAlign(const std::string& align) { static const LinearMapNode textVerticalAlignTable[] = { { DOM_BOTTOM, VerticalAlign::BOTTOM }, { DOM_MIDDLE, VerticalAlign::CENTER }, { DOM_TOP, VerticalAlign::TOP }, }; auto index = BinarySearchFindIndex(textVerticalAlignTable, ArraySize(textVerticalAlignTable), align.c_str()); return index < 0 ? VerticalAlign::NONE : textVerticalAlignTable[index].value; } inline FontStyle ConvertStrToFontStyle(const std::string& fontStyle) { return fontStyle == DOM_TEXT_FONT_STYLE_ITALIC ? FontStyle::ITALIC : FontStyle::NORMAL; } inline TextAlign ConvertStrToTextAlign(const std::string& align) { static const LinearMapNode textAlignTable[] = { { DOM_CENTER, TextAlign::CENTER }, { DOM_END, TextAlign::END }, { DOM_LEFT, TextAlign::LEFT }, { DOM_RIGHT, TextAlign::RIGHT }, { DOM_START, TextAlign::START }, }; auto index = BinarySearchFindIndex(textAlignTable, ArraySize(textAlignTable), align.c_str()); return index < 0 ? TextAlign::CENTER : textAlignTable[index].value; } inline TextOverflow ConvertStrToTextOverflow(const std::string& overflow) { return overflow == DOM_ELLIPSIS ? TextOverflow::ELLIPSIS : TextOverflow::CLIP; } inline Overflow ConvertStrToOverflow(const std::string& val) { const LinearMapNode overflowTable[] = { { "auto", Overflow::SCROLL }, { "hidden", Overflow::FORCE_CLIP }, { "scroll", Overflow::SCROLL }, { "visible", Overflow::OBSERVABLE }, }; auto index = BinarySearchFindIndex(overflowTable, ArraySize(overflowTable), val.c_str()); return index < 0 ? Overflow::CLIP : overflowTable[index].value; } inline TextDirection ConvertStrToTextDirection(const std::string& val) { const LinearMapNode textDirectionTable[] = { { "inherit", TextDirection::INHERIT }, { "ltr", TextDirection::LTR }, { "rtl", TextDirection::RTL }, }; auto index = BinarySearchFindIndex(textDirectionTable, ArraySize(textDirectionTable), val.c_str()); return index < 0 ? TextDirection::LTR : textDirectionTable[index].value; } inline std::vector ConvertStrToFontFamilies(const std::string& family) { std::vector fontFamilies; std::stringstream stream(family); std::string fontFamily; while (getline(stream, fontFamily, ',')) { fontFamilies.emplace_back(fontFamily); } return fontFamilies; } inline FlexDirection ConvertStrToFlexDirection(const std::string& flexKey) { return flexKey == DOM_FLEX_COLUMN ? FlexDirection::COLUMN : FlexDirection::ROW; } inline FlexAlign ConvertStrToFlexAlign(const std::string& flexKey) { static const LinearMapNode flexMap[] = { { DOM_ALIGN_ITEMS_BASELINE, FlexAlign::BASELINE }, { DOM_JUSTIFY_CONTENT_CENTER, FlexAlign::CENTER }, { DOM_JUSTIFY_CONTENT_END, FlexAlign::FLEX_END }, { DOM_JUSTIFY_CONTENT_START, FlexAlign::FLEX_START }, { DOM_JUSTIFY_CONTENT_AROUND, FlexAlign::SPACE_AROUND }, { DOM_JUSTIFY_CONTENT_BETWEEN, FlexAlign::SPACE_BETWEEN }, { DOM_JUSTIFY_CONTENT_EVENLY, FlexAlign::SPACE_EVENLY }, { DOM_ALIGN_ITEMS_STRETCH, FlexAlign::STRETCH }, }; auto index = BinarySearchFindIndex(flexMap, ArraySize(flexMap), flexKey.c_str()); return index < 0 ? FlexAlign::FLEX_START : flexMap[index].value; } inline Offset ConvertStrToOffset(const std::string& value) { Offset offset; std::vector offsetValues; std::stringstream stream(value); std::string offsetValue; while (getline(stream, offsetValue, ' ')) { offsetValues.emplace_back(offsetValue); } // To avoid illegal input, such as "100px ". offsetValues.resize(OFFSET_VALUE_NUMBER); offset.SetX(StringToDouble(offsetValues[0])); offset.SetY(StringToDouble(offsetValues[1])); return offset; } inline QrcodeType ConvertStrToQrcodeType(const std::string& value) { return value == "circle" ? QrcodeType::CIRCLE : QrcodeType::RECT; } inline AnimationCurve ConvertStrToAnimationCurve(const std::string& value) { return value == "standard" ? AnimationCurve::STANDARD : AnimationCurve::FRICTION; } inline TextInputAction ConvertStrToTextInputAction(const std::string& action) { TextInputAction inputAction; if (action == INPUT_ACTION_NEXT) { inputAction = TextInputAction::NEXT; } else if (action == INPUT_ACTION_GO) { inputAction = TextInputAction::GO; } else if (action == INPUT_ACTION_DONE) { inputAction = TextInputAction::DONE; } else if (action == INPUT_ACTION_SEND) { inputAction = TextInputAction::SEND; } else if (action == INPUT_ACTION_SEARCH) { inputAction = TextInputAction::SEARCH; } else { inputAction = TextInputAction::UNSPECIFIED; } return inputAction; } inline TextInputType ConvertStrToTextInputType(const std::string& type) { TextInputType inputType; if (type == DOM_INPUT_TYPE_NUMBER) { inputType = TextInputType::NUMBER; } else if (type == DOM_INPUT_TYPE_DATE || type == DOM_INPUT_TYPE_TIME) { inputType = TextInputType::DATETIME; } else if (type == DOM_INPUT_TYPE_EMAIL) { inputType = TextInputType::EMAIL_ADDRESS; } else if (type == DOM_INPUT_TYPE_PASSWORD) { inputType = TextInputType::VISIBLE_PASSWORD; } else { inputType = TextInputType::TEXT; } return inputType; } inline TabBarMode ConvertStrToTabBarMode(const std::string& value) { std::string temp = value; transform(temp.begin(), temp.end(), temp.begin(), tolower); return temp == "fixed" ? TabBarMode::FIXED : TabBarMode::SCROLLABLE; } ACE_FORCE_EXPORT RefPtr CreateBuiltinCurve(const std::string& aniTimFunc); ACE_FORCE_EXPORT RefPtr CreateCustomCurve(const std::string& aniTimFunc); ACE_FORCE_EXPORT RefPtr CreateCurve(const std::function& jsFunc); ACE_FORCE_EXPORT RefPtr CreateCurve(const std::string& aniTimFunc, bool useDefault = true); ACE_FORCE_EXPORT bool ParseCurveParam( const std::string& aniTimFunc, std::string& curveName, std::vector& paramsVector); ACE_FORCE_EXPORT RefPtr CreateCurveExceptSpring( const std::string& aniTimFunc, const std::function& jsFunc = nullptr); ACE_EXPORT TransitionType ParseTransitionType(const std::string& transitionType); ACE_EXPORT RefPtr CreateClipPath(const std::string& value); inline FillMode StringToFillMode(const std::string& fillMode) { if (fillMode == DOM_ANIMATION_FILL_MODE_FORWARDS) { return FillMode::FORWARDS; } else if (fillMode == DOM_ANIMATION_FILL_MODE_BACKWARDS) { return FillMode::BACKWARDS; } else if (fillMode == DOM_ANIMATION_FILL_MODE_BOTH) { return FillMode::BOTH; } else { return FillMode::NONE; } } inline AnimationDirection StringToAnimationDirection(const std::string& direction) { if (direction == DOM_ANIMATION_DIRECTION_ALTERNATE) { return AnimationDirection::ALTERNATE; } else if (direction == DOM_ANIMATION_DIRECTION_REVERSE) { return AnimationDirection::REVERSE; } else if (direction == DOM_ANIMATION_DIRECTION_ALTERNATE_REVERSE) { return AnimationDirection::ALTERNATE_REVERSE; } else { return AnimationDirection::NORMAL; } } inline AnimationOperation StringToAnimationOperation(const std::string& direction) { if (direction == DOM_ANIMATION_PLAY_STATE_IDLE) { return AnimationOperation::CANCEL; } else if (direction == DOM_ANIMATION_PLAY_STATE_RUNNING) { return AnimationOperation::RUNNING; } else if (direction == DOM_ANIMATION_PLAY_STATE_PAUSED) { return AnimationOperation::PAUSE; } else if (direction == DOM_ANIMATION_PLAY_STATE_FINISHED) { return AnimationOperation::FINISH; } else { return AnimationOperation::NONE; } } inline void RemoveHeadTailSpace(std::string& value) { if (!value.empty()) { auto start = value.find_first_not_of(' '); if (start == std::string::npos) { value.clear(); } else { value = value.substr(start, value.find_last_not_of(' ') - start + 1); } } } inline GradientDirection StrToGradientDirection(const std::string& direction) { static const LinearMapNode gradientDirectionTable[] = { { DOM_GRADIENT_DIRECTION_LEFT, GradientDirection::LEFT }, { DOM_GRADIENT_DIRECTION_RIGHT, GradientDirection::RIGHT }, { DOM_GRADIENT_DIRECTION_TOP, GradientDirection::TOP }, { DOM_GRADIENT_DIRECTION_BOTTOM, GradientDirection::BOTTOM }, }; auto index = BinarySearchFindIndex(gradientDirectionTable, ArraySize(gradientDirectionTable), direction.c_str()); return index < 0 ? GradientDirection::BOTTOM : gradientDirectionTable[index].value; } std::string CurveIntToString(int curve); bool ParseBackgroundImagePosition(const std::string& value, BackgroundImagePosition& backgroundImagePosition); bool ParseBackgroundImageSize(const std::string& value, BackgroundImageSize& backgroundImageSize); ImageObjectPosition ParseImageObjectPosition(const std::string& value); std::optional ParseRadialGradientSize(const std::string& value); inline bool StartWith(const std::string& dst, const std::string& prefix) { return dst.compare(0, prefix.size(), prefix) == 0; } inline bool EndWith(const std::string& dst, const std::string& suffix) { return dst.size() >= suffix.size() && dst.compare(dst.size() - suffix.size(), suffix.size(), suffix) == 0; } inline double ConvertTimeStr(const std::string& str) { std::string time(str); StringUtils::TrimStr(time); double result = 0.0; if (EndWith(time, "ms")) { // remove 2 char "ms" result = StringToDouble(std::string(time.begin(), time.end() - 2.0)); } else if (EndWith(time, "s")) { // transform s to ms result = StringToDouble(std::string(time.begin(), time.end() - 1.0)) * 1000.0; } else if (EndWith(time, "m")) { // transform m to ms result = StringToDouble(std::string(time.begin(), time.end() - 1.0)) * 60.0 * 1000.0; } else { result = StringToDouble(str); } return result; } inline WordBreak ConvertStrToWordBreak(const std::string& wordBreak) { return StringUtils::StringToWordBreak(wordBreak); } inline bool CheckTransformEnum(const std::string& str) { const static std::unordered_set offsetKeywords = { "left", "right", "center", "top", "bottom" }; return offsetKeywords.find(str) != offsetKeywords.end(); } inline std::pair ConvertStrToTransformOrigin(const std::string& str, Axis axis) { const static std::unordered_map xOffsetKeywords = { { "left", 0.0_pct }, { "right", 1.0_pct }, { "center", 0.5_pct }, }; const static std::unordered_map yOffsetKeywords = { { "top", 0.0_pct }, { "bottom", 1.0_pct }, { "center", 0.5_pct }, }; if (axis == Axis::HORIZONTAL) { auto pos = xOffsetKeywords.find(str); if (pos != xOffsetKeywords.end()) { return std::make_pair(true, pos->second); } } else if (axis == Axis::VERTICAL) { auto pos = yOffsetKeywords.find(str); if (pos != yOffsetKeywords.end()) { return std::make_pair(true, pos->second); } } return std::make_pair(false, Dimension {}); } inline int32_t ParseUtf8TextLength(std::string& text) { int32_t trueLength = 0; int32_t stringLength = 0; while (stringLength < static_cast(text.length())) { uint8_t stringChar = static_cast(text[stringLength++]); if ((stringChar & UTF8_CHARATER_HEAD) != UTF8_CHARATER_BODY) { trueLength++; } } return trueLength; } inline int32_t ParseUtf8TextSubstrStartPos(std::string& text, int32_t targetPos) { int32_t truePos = 0; int32_t stringPos = 0; while ((stringPos < static_cast(text.length())) && (truePos < targetPos)) { uint8_t stringChar = static_cast(text[stringPos++]); if ((stringChar & UTF8_CHARATER_HEAD) != UTF8_CHARATER_BODY) { truePos++; } } return stringPos; } inline int32_t ParseUtf8TextSubstrEndPos(std::string& text, int32_t targetPos) { auto stringPos = ParseUtf8TextSubstrStartPos(text, targetPos); while (stringPos < static_cast(text.length())) { uint8_t stringChar = static_cast(text[stringPos]); if ((stringChar & UTF8_CHARATER_HEAD) != UTF8_CHARATER_BODY) { break; } stringPos++; } return stringPos; } inline void HandleEscapeCharaterInUtf8TextForJson(std::string& text) { for (size_t pos = 0; pos < text.size(); pos++) { if ((text.at(pos) == DOUBLE_QUOTATION) || (text.at(pos) == BACKSLASH) || ((text.at(pos) >= ESCAPE_CHARATER_START) && (text.at(pos) <= ESCAPE_CHARATER_END))) { std::ostringstream is; is << UNICODE_HEAD << std::hex << std::setw(UNICODE_LENGTH) << std::setfill(UNICODE_BODY) << int(text.at(pos)); text.replace(pos, 1, is.str()); } } } inline int32_t ParseResourceInputNumberParam(const std::string& param) { if (!StringUtils::IsNumber(param) || param.empty()) { return INVALID_PARAM; } else { errno = 0; char* pEnd = nullptr; int64_t result = std::strtol(param.c_str(), &pEnd, STRTOL_BASE); return ((result < INT_MIN || result > INT_MAX) || errno == ERANGE) ? INT_MAX : static_cast(result); } } inline void ReplacePlaceHolderArray(std::string& resultStr, const std::vector& arrayResult) { auto size = arrayResult.size(); size_t startPos = 0; for (size_t i = 0; i < size; i++) { std::string placeHolder; placeHolder += LEFT_CURLY_BRACES; placeHolder += (i + '0'); placeHolder += RIGHT_CURLY_BRACES; if (startPos < resultStr.length()) { auto pos = resultStr.find(placeHolder, startPos); if (pos != std::string::npos) { resultStr.replace(pos, PLACE_HOLDER_LENGTH, arrayResult[i]); startPos = pos + arrayResult[i].length(); } } } } inline void ReplacePlaceHolder(std::string& resultStr, const std::unique_ptr& argsPtr) { auto placeHolderKey = argsPtr->GetChild()->GetKey(); std::string placeHolder; placeHolder += LEFT_CURLY_BRACES; placeHolder += placeHolderKey; placeHolder += RIGHT_CURLY_BRACES; auto pos = resultStr.find(placeHolder); if (pos != std::string::npos) { resultStr.replace(pos, placeHolder.length(), argsPtr->GetChild()->GetString()); } } inline std::string ParserPluralResource( const std::unique_ptr& argsPtr, const std::string& choice, const std::string& count) { std::string valueStr; std::string defaultPluralStr(DEFAULT_PLURAL_CHOICE); if (argsPtr->Contains(choice)) { valueStr = argsPtr->GetValue(choice)->GetString(); } else if (argsPtr->Contains(defaultPluralStr)) { valueStr = argsPtr->GetValue(defaultPluralStr)->GetString(); } else { return std::string(); } std::string pluralStr(PLURAL_COUNT_POS); auto pos = valueStr.find(pluralStr); if (pos != std::string::npos) { valueStr.replace(pos, pluralStr.length(), count); } return valueStr; } } // namespace OHOS::Ace::Framework #endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_COMMON_UTILS_UTILS_H