• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "napi_utils.h"
17 
18 namespace OHOS::Ace::Napi {
19 namespace {
20 
21 enum class ResourceType : uint32_t {
22     COLOR = 10001,
23     FLOAT,
24     STRING,
25     PLURAL,
26     BOOLEAN,
27     INTARRAY,
28     INTEGER,
29     PATTERN,
30     STRARRAY,
31     MEDIA = 20000,
32     RAWFILE = 30000
33 };
34 
35 const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
36 
37 } // namespace
38 
39 static const std::unordered_map<int32_t, std::string> ERROR_CODE_TO_MSG {
40     { Framework::ERROR_CODE_PERMISSION_DENIED, "Permission denied. " },
41     { Framework::ERROR_CODE_PARAM_INVALID, "Parameter error. " },
42     { Framework::ERROR_CODE_SYSTEMCAP_ERROR, "Capability not supported. " },
43     { Framework::ERROR_CODE_INTERNAL_ERROR, "Internal error. " },
44     { Framework::ERROR_CODE_URI_ERROR, "Uri error. " },
45     { Framework::ERROR_CODE_PAGE_STACK_FULL, "Page stack error. " },
46     { Framework::ERROR_CODE_URI_ERROR_LITE, "Uri error. " }
47 };
48 
NapiThrow(napi_env env,const std::string & message,int32_t errCode)49 void NapiThrow(napi_env env, const std::string& message, int32_t errCode)
50 {
51     napi_value code = nullptr;
52     std::string strCode = std::to_string(errCode);
53     napi_create_string_utf8(env, strCode.c_str(), strCode.length(), &code);
54 
55     napi_value msg = nullptr;
56     auto iter = ERROR_CODE_TO_MSG.find(errCode);
57     std::string strMsg = (iter != ERROR_CODE_TO_MSG.end() ? iter->second : "") + message;
58     LOGE("napi throw errCode %d strMsg %s", errCode, strMsg.c_str());
59     napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg);
60 
61     napi_value error = nullptr;
62     napi_create_error(env, code, msg, &error);
63     napi_throw(env, error);
64 }
65 
ReplaceHolder(std::string & originStr,std::vector<std::string> & params,int32_t containCount)66 void ReplaceHolder(std::string& originStr, std::vector<std::string>& params, int32_t containCount)
67 {
68     auto size = static_cast<int32_t>(params.size());
69     if (containCount == size) {
70         return;
71     }
72     std::string::const_iterator start = originStr.begin();
73     std::string::const_iterator end = originStr.end();
74     std::smatch matches;
75     bool shortHolderType = false;
76     bool firstMatch = true;
77     int searchTime = 0;
78     while (std::regex_search(start, end, matches, RESOURCE_APP_STRING_PLACEHOLDER)) {
79         std::string pos = matches[2];
80         std::string type = matches[4];
81         if (firstMatch) {
82             firstMatch = false;
83             shortHolderType = pos.length() == 0;
84         } else {
85             if (static_cast<uint32_t>(shortHolderType) ^ ((uint32_t)(pos.length() == 0))) {
86                 LOGE("wrong place holder,stop parse string");
87                 return;
88             }
89         }
90 
91         std::string replaceContentStr;
92         std::string::size_type index;
93         if (shortHolderType) {
94             index = static_cast<uint32_t>(searchTime + containCount);
95         } else {
96             index = static_cast<uint32_t>(StringUtils::StringToInt(pos) - 1 + containCount);
97         }
98         replaceContentStr = params[index];
99 
100         originStr.replace(matches[0].first - originStr.begin(), matches[0].length(), replaceContentStr);
101         start = originStr.begin() + matches.prefix().length() + replaceContentStr.length();
102         end = originStr.end();
103         searchTime++;
104     }
105 }
106 
GetParamLen(napi_value param)107 size_t GetParamLen(napi_value param)
108 {
109     auto nativeValue = reinterpret_cast<NativeValue*>(param);
110     auto resultValue = nativeValue->ToString();
111     auto nativeString = reinterpret_cast<NativeString*>(resultValue->GetInterface(NativeString::INTERFACE_ID));
112     size_t len = nativeString->GetLength();
113     return len;
114 }
115 
GetThemeConstants()116 RefPtr<ThemeConstants> GetThemeConstants()
117 {
118     auto container = Container::Current();
119     if (!container) {
120         LOGW("container is null");
121         return nullptr;
122     }
123     auto pipelineContext = container->GetPipelineContext();
124     if (!pipelineContext) {
125         LOGE("pipelineContext is null!");
126         return nullptr;
127     }
128     auto themeManager = pipelineContext->GetThemeManager();
129     if (!themeManager) {
130         LOGE("themeManager is null!");
131         return nullptr;
132     }
133     return themeManager->GetThemeConstants();
134 }
135 
ParseResourceParam(napi_env env,napi_value value,int32_t & id,int32_t & type,std::vector<std::string> & params)136 bool ParseResourceParam(napi_env env, napi_value value, int32_t& id, int32_t& type, std::vector<std::string>& params)
137 {
138     napi_value idNApi = nullptr;
139     napi_value typeNApi = nullptr;
140     napi_value paramsNApi = nullptr;
141     napi_valuetype valueType = napi_undefined;
142     napi_typeof(env, value, &valueType);
143     if (valueType == napi_object) {
144         napi_get_named_property(env, value, "id", &idNApi);
145         napi_get_named_property(env, value, "type", &typeNApi);
146         napi_get_named_property(env, value, "params", &paramsNApi);
147     } else {
148         return false;
149     }
150 
151     napi_typeof(env, idNApi, &valueType);
152     if (valueType == napi_number) {
153         napi_get_value_int32(env, idNApi, &id);
154     }
155 
156     napi_typeof(env, typeNApi, &valueType);
157     if (valueType == napi_number) {
158         napi_get_value_int32(env, typeNApi, &type);
159     }
160 
161     bool isArray = false;
162     if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
163         return false;
164     }
165 
166     if (!isArray) {
167         return false;
168     }
169 
170     uint32_t arrayLength = 0;
171     napi_get_array_length(env, paramsNApi, &arrayLength);
172 
173     for (uint32_t i = 0; i < arrayLength; i++) {
174         size_t ret = 0;
175         napi_value indexValue = nullptr;
176         napi_get_element(env, paramsNApi, i, &indexValue);
177         napi_typeof(env, indexValue, &valueType);
178         if (valueType == napi_string) {
179             size_t strLen = GetParamLen(indexValue) + 1;
180             std::unique_ptr<char[]> indexStr = std::make_unique<char[]>(strLen);
181             napi_get_value_string_utf8(env, indexValue, indexStr.get(), strLen, &ret);
182             params.emplace_back(indexStr.get());
183         } else if (valueType == napi_number) {
184             int32_t num;
185             napi_get_value_int32(env, indexValue, &num);
186             params.emplace_back(std::to_string(num));
187         }
188     }
189     return true;
190 }
191 
ParseString(int32_t resId,int32_t type,std::vector<std::string> & params,std::string & result)192 bool ParseString(int32_t resId, int32_t type, std::vector<std::string>& params, std::string& result)
193 {
194     auto themeConstants = GetThemeConstants();
195     if (!themeConstants) {
196         LOGE("themeConstants is nullptr");
197         return false;
198     }
199 
200     if (type == static_cast<int>(ResourceType::PLURAL)) {
201         auto count = StringUtils::StringToDouble(params[0]);
202         auto pluralResults = themeConstants->GetStringArray(resId);
203         auto pluralChoice = Localization::GetInstance()->PluralRulesFormat(count);
204         auto iter = std::find(pluralResults.begin(), pluralResults.end(), pluralChoice);
205         std::string originStr;
206         if (iter != pluralResults.end() && ++iter != pluralResults.end()) {
207             originStr = *iter;
208         }
209         ReplaceHolder(originStr, params, 1);
210         result = originStr;
211     } else {
212         auto originStr = themeConstants->GetString(resId);
213         ReplaceHolder(originStr, params, 0);
214         result = originStr;
215     }
216     return true;
217 }
218 
ErrorToMessage(int32_t code)219 std::string ErrorToMessage(int32_t code)
220 {
221     auto iter = ERROR_CODE_TO_MSG.find(code);
222     return (iter != ERROR_CODE_TO_MSG.end()) ? iter->second : "";
223 }
224 
225 } // namespace OHOS::Ace::Napi
226