• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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", &paramsNApi);
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, &paramCount);
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, &param);
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, &paramLen);
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, &paramLen);
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, &paramLen);
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, &paramLen);
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", &paramsNApi);
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