1 /*
2 * Copyright (c) 2021-2023 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 #include <cstddef>
19
20 #include "js_native_api_types.h"
21
22 #include "base/utils/string_utils.h"
23 #include "core/animation/curve.h"
24 #include "core/common/resource/resource_manager.h"
25 #include "core/common/resource/resource_object.h"
26 #include "core/common/resource/resource_wrapper.h"
27 #include "frameworks/bridge/common/utils/utils.h"
28
29 namespace OHOS::Ace::Napi {
30 using namespace OHOS::Ace;
31 namespace {
32
33 const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
34 constexpr int32_t NAPI_BUF_LENGTH = 256;
35 constexpr int32_t UNKNOWN_RESOURCE_ID = -1;
36 std::vector<std::string> RESOURCE_HEADS = { "app", "sys" };
37 } // namespace
38
39 static const std::unordered_map<int32_t, std::string> ERROR_CODE_TO_MSG {
40 { ERROR_CODE_PERMISSION_DENIED, "Permission denied. " },
41 { ERROR_CODE_PARAM_INVALID, "Parameter error. " },
42 { ERROR_CODE_SYSTEMCAP_ERROR, "Capability not supported. " },
43 { ERROR_CODE_INTERNAL_ERROR, "Internal error. " },
44 { ERROR_CODE_URI_ERROR, "Uri error. " },
45 { ERROR_CODE_PAGE_STACK_FULL, "Page stack error. " },
46 { 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,const std::vector<std::string> & params,int32_t containCount)66 void ReplaceHolder(std::string& originStr, const 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_env env,napi_value param)107 size_t GetParamLen(napi_env env, napi_value param)
108 {
109 size_t buffSize = 0;
110 napi_status status = napi_get_value_string_utf8(env, param, nullptr, 0, &buffSize);
111 if (status != napi_ok || buffSize == 0) {
112 return 0;
113 }
114 return buffSize;
115 }
116
GetNapiString(napi_env env,napi_value value,std::string & retStr,napi_valuetype & valueType)117 bool GetNapiString(napi_env env, napi_value value, std::string& retStr, napi_valuetype& valueType)
118 {
119 size_t ret = 0;
120 napi_typeof(env, value, &valueType);
121 if (valueType == napi_string) {
122 if (GetParamLen(env, value) == 0) {
123 return false;
124 }
125 size_t valueLen = GetParamLen(env, value) + 1;
126 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(valueLen);
127 napi_get_value_string_utf8(env, value, buffer.get(), valueLen, &ret);
128 retStr = buffer.get();
129 return true;
130 }
131 if (valueType == napi_object) {
132 ResourceInfo recv;
133 if (ParseResourceParam(env, value, recv)) {
134 ParseString(recv, retStr);
135 return true;
136 }
137 }
138 return false;
139 }
140
GetThemeConstants(const std::optional<std::string> & bundleName=std::nullopt,const std::optional<std::string> & moduleName=std::nullopt)141 RefPtr<ThemeConstants> GetThemeConstants(const std::optional<std::string>& bundleName = std::nullopt,
142 const std::optional<std::string>& moduleName = std::nullopt)
143 {
144 auto container = Container::Current();
145 if (!container) {
146 LOGW("container is null");
147 return nullptr;
148 }
149 auto pipelineContext = container->GetPipelineContext();
150 if (!pipelineContext) {
151 LOGE("pipelineContext is null!");
152 return nullptr;
153 }
154 auto themeManager = pipelineContext->GetThemeManager();
155 if (!themeManager) {
156 LOGE("themeManager is null!");
157 return nullptr;
158 }
159 if (bundleName.has_value() && moduleName.has_value()) {
160 return themeManager->GetThemeConstants(bundleName.value_or(""), moduleName.value_or(""));
161 }
162 return themeManager->GetThemeConstants();
163 }
164
CreateResourceWrapper(const ResourceInfo & info)165 RefPtr<ResourceWrapper> CreateResourceWrapper(const ResourceInfo& info)
166 {
167 auto bundleName = info.bundleName;
168 auto moduleName = info.moduleName;
169
170 RefPtr<ResourceAdapter> resourceAdapter = nullptr;
171 RefPtr<ThemeConstants> themeConstants = nullptr;
172 if (SystemProperties::GetResourceDecoupling()) {
173 if (bundleName.has_value() && moduleName.has_value()) {
174 auto resourceObject = AceType::MakeRefPtr<ResourceObject>(bundleName.value_or(""), moduleName.value_or(""));
175 resourceAdapter = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resourceObject);
176 } else {
177 resourceAdapter = ResourceManager::GetInstance().GetResourceAdapter();
178 }
179 if (!resourceAdapter) {
180 return nullptr;
181 }
182 } else {
183 themeConstants = GetThemeConstants(info.bundleName, info.moduleName);
184 if (!themeConstants) {
185 return nullptr;
186 }
187 }
188 auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
189 return resourceWrapper;
190 }
191
CreateNapiString(napi_env env,std::string rawStr)192 napi_value CreateNapiString(napi_env env, std::string rawStr)
193 {
194 napi_value retVal = nullptr;
195 napi_create_string_utf8(env, rawStr.c_str(), rawStr.length(), &retVal);
196 return retVal;
197 }
198
ConvertResourceType(const std::string & typeName,ResourceType & resType)199 bool ConvertResourceType(const std::string& typeName, ResourceType& resType)
200 {
201 static const std::unordered_map<std::string, ResourceType> resTypeMap {
202 { "color", ResourceType::COLOR },
203 { "media", ResourceType::MEDIA },
204 { "float", ResourceType::FLOAT },
205 { "string", ResourceType::STRING },
206 { "plural", ResourceType::PLURAL },
207 { "pattern", ResourceType::PATTERN },
208 { "boolean", ResourceType::BOOLEAN },
209 { "integer", ResourceType::INTEGER },
210 { "strarray", ResourceType::STRARRAY },
211 { "intarray", ResourceType::INTARRAY },
212 };
213 auto it = resTypeMap.find(typeName);
214 if (it == resTypeMap.end()) {
215 return false;
216 }
217 resType = it->second;
218 return true;
219 }
220
ParseDollarResource(napi_env env,napi_value value,ResourceType & resType,std::string & resName)221 bool ParseDollarResource(napi_env env, napi_value value, ResourceType& resType, std::string& resName)
222 {
223 napi_valuetype valueType = napi_undefined;
224 napi_typeof(env, value, &valueType);
225 if (valueType != napi_string) {
226 return false;
227 }
228 std::string resPath;
229 if (!GetNapiString(env, value, resPath, valueType)) {
230 return false;
231 }
232 std::vector<std::string> tokens;
233 StringUtils::StringSplitter(resPath, '.', tokens);
234 if (static_cast<int32_t>(tokens.size()) != 3) { // $r format like app.xxx.xxx, has 3 paragraph
235 return false;
236 }
237 if (std::find(RESOURCE_HEADS.begin(), RESOURCE_HEADS.end(), tokens[0]) == RESOURCE_HEADS.end()) {
238 return false;
239 }
240 if (!ConvertResourceType(tokens[1], resType)) {
241 return false;
242 }
243 resName = resPath;
244 return true;
245 }
246
CompleteResourceParam(napi_env env,napi_value value)247 void CompleteResourceParam(napi_env env, napi_value value)
248 {
249 napi_value idNApi = nullptr;
250 napi_valuetype valueType = napi_undefined;
251 napi_typeof(env, value, &valueType);
252 if (valueType != napi_object) {
253 return;
254 }
255 if (napi_get_named_property(env, value, "id", &idNApi) != napi_ok) {
256 return;
257 }
258 std::string resName;
259 ResourceType resType;
260 if (!ParseDollarResource(env, idNApi, resType, resName)) {
261 return;
262 }
263 bool hasProperty = false;
264 napi_value typeIdNApi = nullptr;
265 napi_value resourceIdNApi = nullptr;
266 napi_value typeKeyNApi = CreateNapiString(env, "type");
267 napi_value defaultNameNApi = CreateNapiString(env, "");
268 napi_value bundleNameKeyNApi = CreateNapiString(env, "bundleName");
269 napi_value moduleNameKeyNApi = CreateNapiString(env, "moduleName");
270 napi_create_int32(env, UNKNOWN_RESOURCE_ID, &resourceIdNApi);
271 napi_create_int32(env, static_cast<uint32_t>(resType), &typeIdNApi);
272 ModifyResourceParam(env, value, resType, resName);
273 napi_set_property(env, value, typeKeyNApi, typeIdNApi);
274 napi_set_property(env, value, CreateNapiString(env, "id"), resourceIdNApi);
275 napi_has_property(env, value, bundleNameKeyNApi, &hasProperty);
276 if (!hasProperty) {
277 napi_set_property(env, value, bundleNameKeyNApi, defaultNameNApi);
278 }
279 napi_has_property(env, value, moduleNameKeyNApi, &hasProperty);
280 if (!hasProperty) {
281 napi_set_property(env, value, moduleNameKeyNApi, defaultNameNApi);
282 }
283 }
284
ModifyResourceParam(napi_env env,napi_value value,const ResourceType & resType,const std::string & resName)285 void ModifyResourceParam(napi_env env, napi_value value, const ResourceType& resType, const std::string& resName)
286 {
287 // raw input : {"id":"app.xxx.xxx","params":[],"moduleName":"xxx","bundleName":"xxx"}
288 // modified output : {"id":-1, "params":["app.xxx.xxx"],"type":xxxx,"moduleName":"xxx","bundleName":"xxx"}
289 napi_value paramsNApi = nullptr;
290 napi_get_named_property(env, value, "params", ¶msNApi);
291 bool isArray = false;
292 if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
293 return;
294 }
295 if (!isArray) {
296 return;
297 }
298 uint32_t paramCount = 0;
299 bool hasProperty = false;
300 napi_get_array_length(env, paramsNApi, ¶mCount);
301 napi_value typeKeyNApi = CreateNapiString(env, "type");
302 napi_value resNameNApi = CreateNapiString(env, resName);
303 if (resType == ResourceType::PLURAL || resType == ResourceType::STRING) {
304 std::vector<napi_value> tmpParams;
305 for (uint32_t i = 0; i < paramCount; i++) {
306 napi_value param = nullptr;
307 napi_get_element(env, paramsNApi, i, ¶m);
308 tmpParams.insert(tmpParams.end(), param);
309 }
310 napi_set_element(env, paramsNApi, 0, resNameNApi);
311 uint32_t paramIndex = 1;
312 napi_has_property(env, value, typeKeyNApi, &hasProperty);
313 if (hasProperty) {
314 napi_value firstParam = nullptr;
315 napi_get_property(env, value, typeKeyNApi, &firstParam);
316 napi_set_element(env, paramsNApi, paramIndex, firstParam);
317 paramIndex++;
318 }
319 for (auto tmpParam : tmpParams) {
320 napi_set_element(env, paramsNApi, paramIndex, tmpParam);
321 paramIndex++;
322 }
323 } else {
324 napi_set_element(env, paramsNApi, 0, resNameNApi);
325 }
326 }
327
ParseCurveInfo(const std::string & curveString,std::string & curveTypeString,std::vector<float> & curveValue)328 void ParseCurveInfo(const std::string& curveString, std::string& curveTypeString, std::vector<float>& curveValue)
329 {
330 if (curveString.back() != ')') {
331 return;
332 }
333 std::string::size_type leftEmbracePosition = curveString.find_last_of('(');
334 if (leftEmbracePosition == std::string::npos) {
335 return;
336 }
337 curveTypeString = curveString.substr(0, leftEmbracePosition);
338 auto params = curveString.substr(leftEmbracePosition + 1, curveString.length() - leftEmbracePosition - 2);
339 if (curveTypeString.empty() || params.empty()) {
340 return;
341 }
342 std::vector<std::string> paramsVector;
343 StringUtils::StringSplitter(params, ',', paramsVector);
344 for (auto& param : paramsVector) {
345 Framework::RemoveHeadTailSpace(param);
346 if (param == "true" || param == "start") {
347 param = "1.000000";
348 }
349 if (param == "false" || param == "end") {
350 param = "0.000000";
351 }
352 curveValue.emplace_back(std::stof(param));
353 }
354 }
355
ParseCurve(napi_env env,napi_value value,std::string & curveTypeString,std::vector<float> & curveValue)356 napi_value ParseCurve(napi_env env, napi_value value, std::string& curveTypeString, std::vector<float>& curveValue)
357 {
358 CHECK_NULL_RETURN(value, nullptr);
359 napi_valuetype valueType = napi_undefined;
360 napi_typeof(env, value, &valueType);
361 NAPI_ASSERT(env, valueType == napi_object || valueType == napi_string, "The type of curve is incorrect");
362 if (valueType == napi_object) {
363 napi_value curveObjectNApi = nullptr;
364 napi_get_named_property(env, value, "__curveString", &curveObjectNApi);
365 value = curveObjectNApi;
366 }
367
368 size_t paramLen = 0;
369 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, ¶mLen);
370 NAPI_ASSERT(env, paramLen > 0 && paramLen < NAPI_BUF_LENGTH && status == napi_ok, "paramLen error");
371 char params[NAPI_BUF_LENGTH] = { 0 };
372 status = napi_get_value_string_utf8(env, value, params, paramLen + 1, ¶mLen);
373 NAPI_ASSERT(env, status == napi_ok, "Parse curve failed");
374
375 RefPtr<Curve> curve;
376 const std::string domAnimationDefaultCurveString = "ease-in-out";
377 if (params[0] == '\0') {
378 curve = Framework::CreateCurve(domAnimationDefaultCurveString);
379 } else {
380 curve = Framework::CreateCurve(params);
381 }
382 std::string curveString = curve->ToString();
383 LOGI("curveString %{public}s", curveString.c_str());
384 ParseCurveInfo(curveString, curveTypeString, curveValue);
385 LOGI("curveTypeString %{public}s", curveTypeString.c_str());
386 return nullptr;
387 }
388
GetValueType(napi_env env,napi_value value)389 napi_valuetype GetValueType(napi_env env, napi_value value)
390 {
391 if (value == nullptr) {
392 return napi_undefined;
393 }
394
395 napi_valuetype valueType = napi_undefined;
396 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
397 return valueType;
398 }
399
GetStringFromValueUtf8(napi_env env,napi_value value)400 std::optional<std::string> GetStringFromValueUtf8(napi_env env, napi_value value)
401 {
402 static constexpr size_t maxLength = 2048;
403 if (GetValueType(env, value) != napi_string) {
404 return std::nullopt;
405 }
406
407 size_t paramLen = 0;
408 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, ¶mLen);
409 if (paramLen == 0 || paramLen > maxLength || status != napi_ok) {
410 return std::nullopt;
411 }
412 char params[maxLength] = { 0 };
413 status = napi_get_value_string_utf8(env, value, params, paramLen + 1, ¶mLen);
414 if (status != napi_ok) {
415 return std::nullopt;
416 }
417 return params;
418 }
419
GetIntProperty(napi_env env,napi_value value,const std::string & key,int32_t & result)420 bool GetIntProperty(napi_env env, napi_value value, const std::string& key, int32_t& result)
421 {
422 CHECK_NULL_RETURN(value, false);
423 napi_valuetype valueType = napi_undefined;
424 napi_value propertyNApi = nullptr;
425 napi_get_named_property(env, value, key.c_str(), &propertyNApi);
426 if (valueType != napi_number) {
427 LOGE("The type of property is incorrect");
428 return false;
429 }
430 int32_t property = 0;
431 napi_status status = napi_get_value_int32(env, propertyNApi, &property);
432 if (status != napi_ok) {
433 LOGE("Get property failed");
434 return false;
435 }
436 return true;
437 }
438
CompleteColorAlphaIfIncomplete(uint32_t origin)439 static uint32_t CompleteColorAlphaIfIncomplete(uint32_t origin)
440 {
441 constexpr uint32_t colorAlphaOffset = 24;
442 constexpr uint32_t colorAlphaDefaultValue = 0xFF000000;
443 uint32_t result = origin;
444 if ((origin >> colorAlphaOffset) == 0) {
445 result = origin | colorAlphaDefaultValue;
446 }
447 return result;
448 }
449
ParseColorFromResourceObject(napi_env env,napi_value value,Color & colorResult)450 bool ParseColorFromResourceObject(napi_env env, napi_value value, Color& colorResult)
451 {
452 ResourceInfo resourceInfo;
453 if (!ParseResourceParam(env, value, resourceInfo)) {
454 LOGE("Parse color from resource failed");
455 return false;
456 }
457 auto themeConstants = GetThemeConstants(resourceInfo.bundleName, resourceInfo.moduleName);
458 if (themeConstants == nullptr) {
459 LOGE("themeConstants is nullptr");
460 return false;
461 }
462 if (resourceInfo.type == static_cast<int32_t>(ResourceType::STRING)) {
463 auto colorString = themeConstants->GetString(resourceInfo.type);
464 return Color::ParseColorString(colorString, colorResult);
465 }
466 if (resourceInfo.type == static_cast<int32_t>(ResourceType::INTEGER)) {
467 auto colorInt = themeConstants->GetInt(resourceInfo.type);
468 colorResult = Color(CompleteColorAlphaIfIncomplete(colorInt));
469 return true;
470 }
471 colorResult = themeConstants->GetColor(resourceInfo.resId);
472 return true;
473 }
474
ParseColor(napi_env env,napi_value value,Color & result)475 bool ParseColor(napi_env env, napi_value value, Color& result)
476 {
477 napi_valuetype valueType = GetValueType(env, value);
478 if (valueType != napi_number && valueType != napi_string && valueType != napi_object) {
479 return false;
480 }
481 if (valueType == napi_number) {
482 int32_t colorId = 0;
483 napi_get_value_int32(env, value, &colorId);
484 result = Color(CompleteColorAlphaIfIncomplete(static_cast<uint32_t>(colorId)));
485 return true;
486 }
487 if (valueType == napi_string) {
488 std::optional<std::string> colorString = GetStringFromValueUtf8(env, value);
489 if (!colorString.has_value()) {
490 LOGE("Parse color from string failed");
491 }
492 return Color::ParseColorString(colorString.value(), result);
493 }
494
495 return ParseColorFromResourceObject(env, value, result);
496 }
497
ParseResourceParam(napi_env env,napi_value value,ResourceInfo & info)498 bool ParseResourceParam(napi_env env, napi_value value, ResourceInfo& info)
499 {
500 CompleteResourceParam(env, value);
501 napi_value idNApi = nullptr;
502 napi_value typeNApi = nullptr;
503 napi_value paramsNApi = nullptr;
504 napi_value bundleNameNApi = nullptr;
505 napi_value moduleNameNApi = nullptr;
506 napi_valuetype valueType = napi_undefined;
507 napi_typeof(env, value, &valueType);
508 if (valueType == napi_object) {
509 napi_get_named_property(env, value, "id", &idNApi);
510 napi_get_named_property(env, value, "type", &typeNApi);
511 napi_get_named_property(env, value, "params", ¶msNApi);
512 napi_get_named_property(env, value, "bundleName", &bundleNameNApi);
513 napi_get_named_property(env, value, "moduleName", &moduleNameNApi);
514 } else {
515 return false;
516 }
517
518 napi_typeof(env, idNApi, &valueType);
519 if (valueType == napi_number) {
520 napi_get_value_int32(env, idNApi, &info.resId);
521 }
522
523 napi_typeof(env, typeNApi, &valueType);
524 if (valueType == napi_number) {
525 napi_get_value_int32(env, typeNApi, &info.type);
526 }
527
528 bool isArray = false;
529 if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
530 return false;
531 }
532
533 if (!isArray) {
534 return false;
535 }
536
537 uint32_t arrayLength = 0;
538 napi_get_array_length(env, paramsNApi, &arrayLength);
539
540 for (uint32_t i = 0; i < arrayLength; i++) {
541 size_t ret = 0;
542 napi_value indexValue = nullptr;
543 napi_get_element(env, paramsNApi, i, &indexValue);
544 napi_typeof(env, indexValue, &valueType);
545 if (valueType == napi_string) {
546 size_t strLen = GetParamLen(env, indexValue) + 1;
547 std::unique_ptr<char[]> indexStr = std::make_unique<char[]>(strLen);
548 napi_get_value_string_utf8(env, indexValue, indexStr.get(), strLen, &ret);
549 info.params.emplace_back(indexStr.get());
550 } else if (valueType == napi_number) {
551 int32_t num;
552 napi_get_value_int32(env, indexValue, &num);
553 info.params.emplace_back(std::to_string(num));
554 }
555 }
556
557 napi_typeof(env, bundleNameNApi, &valueType);
558 if (valueType == napi_string) {
559 size_t ret = 0;
560 size_t strLen = GetParamLen(env, bundleNameNApi) + 1;
561 std::unique_ptr<char[]> bundleNameStr = std::make_unique<char[]>(strLen);
562 napi_get_value_string_utf8(env, bundleNameNApi, bundleNameStr.get(), strLen, &ret);
563 info.bundleName = bundleNameStr.get();
564 }
565
566 napi_typeof(env, moduleNameNApi, &valueType);
567 if (valueType == napi_string) {
568 size_t ret = 0;
569 size_t strLen = GetParamLen(env, moduleNameNApi) + 1;
570 std::unique_ptr<char[]> moduleNameStr = std::make_unique<char[]>(strLen);
571 napi_get_value_string_utf8(env, moduleNameNApi, moduleNameStr.get(), strLen, &ret);
572 info.moduleName = moduleNameStr.get();
573 }
574
575 return true;
576 }
577
DimensionToString(Dimension dimension)578 std::string DimensionToString(Dimension dimension)
579 {
580 static const int32_t unitsNum = 6;
581 static const int32_t percentIndex = 3;
582 static const int32_t percentUnit = 100;
583 static std::array<std::string, unitsNum> units = { "px", "vp", "fp", "%", "lpx", "auto" };
584 auto unit = dimension.Unit();
585 auto value = dimension.Value();
586 if (unit == DimensionUnit::NONE) {
587 return StringUtils::DoubleToString(value).append("none");
588 }
589 if (units[static_cast<int>(unit)] == units[percentIndex]) {
590 return StringUtils::DoubleToString(value * percentUnit).append(units[static_cast<int>(unit)]);
591 }
592 return StringUtils::DoubleToString(value).append(units[static_cast<int>(unit)]);
593 }
594
ParseString(const ResourceInfo & info,std::string & result)595 bool ParseString(const ResourceInfo& info, std::string& result)
596 {
597 auto resourceWrapper = CreateResourceWrapper(info);
598
599 if (info.type == static_cast<int>(ResourceType::PLURAL)) {
600 std::string pluralResults;
601 if (info.resId == UNKNOWN_RESOURCE_ID) {
602 auto count = StringUtils::StringToInt(info.params[1]);
603 pluralResults = resourceWrapper->GetPluralStringByName(info.params[0], count);
604 ReplaceHolder(pluralResults, info.params, 2); // plural holder in index 2
605 } else {
606 auto count = StringUtils::StringToInt(info.params[0]);
607 pluralResults = resourceWrapper->GetPluralString(info.resId, count);
608 ReplaceHolder(pluralResults, info.params, 1);
609 }
610 result = pluralResults;
611 return true;
612 }
613 if (info.type == static_cast<int>(ResourceType::RAWFILE)) {
614 auto fileName = info.params[0];
615 result = resourceWrapper->GetRawfile(fileName);
616 return true;
617 }
618 if (info.type == static_cast<int>(ResourceType::FLOAT)) {
619 if (info.resId == UNKNOWN_RESOURCE_ID) {
620 result = DimensionToString(resourceWrapper->GetDimensionByName(info.params[0]));
621 } else {
622 result = DimensionToString(resourceWrapper->GetDimension(info.resId));
623 }
624 return true;
625 }
626 if (info.type == static_cast<int>(ResourceType::STRING)) {
627 std::string originStr;
628 if (info.resId == UNKNOWN_RESOURCE_ID) {
629 originStr = resourceWrapper->GetStringByName(info.params[0]);
630 ReplaceHolder(originStr, info.params, 1);
631 } else {
632 originStr = resourceWrapper->GetString(info.resId);
633 ReplaceHolder(originStr, info.params, 0);
634 }
635 result = originStr;
636 return true;
637 }
638 return true;
639 }
640
ErrorToMessage(int32_t code)641 std::string ErrorToMessage(int32_t code)
642 {
643 auto iter = ERROR_CODE_TO_MSG.find(code);
644 return (iter != ERROR_CODE_TO_MSG.end()) ? iter->second : "";
645 }
646
GetSingleParam(napi_env env,napi_callback_info info,napi_value * argv,napi_valuetype & valueType)647 bool GetSingleParam(napi_env env, napi_callback_info info, napi_value* argv, napi_valuetype& valueType)
648 {
649 size_t argc = 1;
650 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
651 if (argc != 1) {
652 return false;
653 }
654 napi_typeof(env, argv[0], &valueType);
655 return true;
656 }
657
658 // (Color | number | string | undifened)
GetOptionalColor(napi_env env,napi_value argv,napi_valuetype & valueType)659 std::optional<Color> GetOptionalColor(napi_env env, napi_value argv, napi_valuetype& valueType)
660 {
661 if (valueType == napi_number) {
662 uint32_t num;
663 uint32_t alpha = 0xff000000;
664 napi_get_value_uint32(env, argv, &num);
665 if ((num & alpha) == 0) {
666 num |= alpha;
667 }
668 return Color(num);
669 } else if (valueType == napi_string) {
670 std::string str;
671 bool result = GetNapiString(env, argv, str, valueType);
672 Color color;
673 if (!result || !Color::ParseColorString(str, color)) {
674 return std::nullopt;
675 }
676 return color;
677 } else {
678 return std::nullopt;
679 }
680 }
681
682 } // namespace OHOS::Ace::Napi
683