• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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/napi_parser.h"
17 
18 #include <optional>
19 #include <regex>
20 
21 #include "core/common/container.h"
22 #include "core/common/resource/resource_manager.h"
23 #include "core/components/theme/resource_adapter.h"
24 
25 namespace OHOS::Ace::Kit {
26 
27 namespace {
28 const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
29 constexpr int32_t UNKNOWN_RESOURCE_ID = -1;
30 constexpr char BUNDLE_NAME[] = "bundleName";
31 std::vector<std::string> RESOURCE_HEADS = { "app", "sys" };
32 } // namespace
33 
34 struct ResourceInfo {
35     int32_t resId = 0;
36     int32_t type = 0;
37     std::vector<std::string> params;
38     std::optional<std::string> bundleName = std::nullopt;
39     std::optional<std::string> moduleName = std::nullopt;
40 };
41 
42 enum class ResourceType : uint32_t {
43     COLOR = 10001,
44     FLOAT,
45     STRING,
46     PLURAL,
47     BOOLEAN,
48     INTARRAY,
49     INTEGER,
50     PATTERN,
51     STRARRAY,
52     MEDIA = 20000,
53     RAWFILE = 30000
54 };
55 
56 enum class ResourceStruct { CONSTANT, DYNAMIC_V1, DYNAMIC_V2 };
57 
58 bool GetNapiString(napi_env env, napi_value value, std::string& retStr, napi_valuetype& valueType);
59 
60 bool ParseResourceParam(napi_env env, napi_value value, ResourceInfo& info);
61 
GetValueType(napi_env env,napi_value value)62 napi_valuetype GetValueType(napi_env env, napi_value value)
63 {
64     if (value == nullptr) {
65         return napi_undefined;
66     }
67 
68     napi_valuetype valueType = napi_undefined;
69     NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
70     return valueType;
71 }
72 
ReplaceHolder(std::string & originStr,const std::vector<std::string> & params,uint32_t containCount)73 void ReplaceHolder(std::string& originStr, const std::vector<std::string>& params, uint32_t containCount)
74 {
75     auto size = static_cast<uint32_t>(params.size());
76     if (containCount == size) {
77         return;
78     }
79     std::string::const_iterator start = originStr.begin();
80     std::string::const_iterator end = originStr.end();
81     std::smatch matches;
82     bool shortHolderType = false;
83     bool firstMatch = true;
84     uint32_t searchTime = 0;
85     while (std::regex_search(start, end, matches, RESOURCE_APP_STRING_PLACEHOLDER)) {
86         std::string pos = matches[2];
87         std::string type = matches[4];
88         if (firstMatch) {
89             firstMatch = false;
90             shortHolderType = pos.length() == 0;
91         } else {
92             if (static_cast<uint32_t>(shortHolderType) ^ static_cast<uint32_t>(pos.length() == 0)) {
93                 LOGE("wrong place holder,stop parse string");
94                 return;
95             }
96         }
97 
98         std::string replaceContentStr;
99         std::string::size_type index = 0;
100         if (shortHolderType) {
101             index = static_cast<std::string::size_type>(searchTime + containCount);
102         } else {
103             int32_t indexTmp = StringUtils::StringToInt(pos) + static_cast<int32_t>(containCount) - 1;
104             if (indexTmp >= 0) {
105                 index = static_cast<std::string::size_type>(indexTmp);
106             } else {
107                 LOGE("indexTmp err:%{public}d", indexTmp);
108             }
109         }
110         if (static_cast<uint32_t>(index) < size) {
111             replaceContentStr = params[index];
112         } else {
113             LOGE("index = %{public}d size = %{public}d", static_cast<uint32_t>(index), size);
114         }
115         originStr.replace(matches[0].first - originStr.begin(), matches[0].length(), replaceContentStr);
116         start = originStr.begin() + matches.prefix().length() + replaceContentStr.length();
117         end = originStr.end();
118         searchTime++;
119     }
120 }
121 
GetParamLen(napi_env env,napi_value param)122 size_t GetParamLen(napi_env env, napi_value param)
123 {
124     size_t buffSize = 0;
125     napi_status status = napi_get_value_string_utf8(env, param, nullptr, 0, &buffSize);
126     if (status != napi_ok || buffSize == 0) {
127         return 0;
128     }
129     return buffSize;
130 }
131 
NapiStringToString(napi_env env,napi_value value,std::string & retStr)132 bool NapiStringToString(napi_env env, napi_value value, std::string& retStr)
133 {
134     size_t ret = 0;
135     napi_valuetype valueType = napi_undefined;
136     napi_typeof(env, value, &valueType);
137     if (valueType != napi_string) {
138         return false;
139     }
140     if (GetParamLen(env, value) == 0) {
141         return false;
142     }
143     size_t valueLen = GetParamLen(env, value) + 1;
144     std::unique_ptr<char[]> buffer = std::make_unique<char[]>(valueLen);
145     napi_get_value_string_utf8(env, value, buffer.get(), valueLen, &ret);
146     retStr = buffer.get();
147     return true;
148 }
149 
CompleteColorAlphaIfIncomplete(uint32_t origin)150 static uint32_t CompleteColorAlphaIfIncomplete(uint32_t origin)
151 {
152     constexpr uint32_t colorAlphaOffset = 24;
153     constexpr uint32_t colorAlphaDefaultValue = 0xFF000000;
154     uint32_t result = origin;
155     if ((origin >> colorAlphaOffset) == 0) {
156         result = origin | colorAlphaDefaultValue;
157     }
158     return result;
159 }
160 
CreateNapiString(napi_env env,const std::string & rawStr)161 napi_value CreateNapiString(napi_env env, const std::string& rawStr)
162 {
163     napi_value retVal = nullptr;
164     napi_create_string_utf8(env, rawStr.c_str(), rawStr.length(), &retVal);
165     return retVal;
166 }
167 
CreateResourceWrapper(const ResourceInfo & info)168 RefPtr<ResourceAdapter> CreateResourceWrapper(const ResourceInfo& info)
169 {
170     auto bundleName = info.bundleName;
171     auto moduleName = info.moduleName;
172 
173     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
174     if (bundleName.has_value() && moduleName.has_value()) {
175         auto resourceObject = AceType::MakeRefPtr<ResourceObject>(
176             bundleName.value_or(""), moduleName.value_or(""), Container::CurrentIdSafely());
177         resourceAdapter = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resourceObject);
178     } else {
179         resourceAdapter = ResourceManager::GetInstance().GetResourceAdapter(Container::CurrentIdSafely());
180     }
181     return resourceAdapter;
182 }
183 
ParseIntegerToString(const ResourceInfo & info,std::string & result)184 bool ParseIntegerToString(const ResourceInfo& info, std::string& result)
185 {
186     auto resourceWrapper = CreateResourceWrapper(info);
187     if (resourceWrapper == nullptr) {
188         return false;
189     }
190     if (info.type == static_cast<int>(ResourceType::INTEGER)) {
191         if (info.resId == UNKNOWN_RESOURCE_ID) {
192             result = std::to_string(resourceWrapper->GetIntByName(info.params[0]));
193         } else {
194             result = std::to_string(resourceWrapper->GetInt(info.resId));
195         }
196         return true;
197     }
198     return true;
199 }
200 
DimensionToString(Dimension dimension)201 std::string DimensionToString(Dimension dimension)
202 {
203     static const int32_t unitsNum = 6;
204     static const int32_t percentIndex = 3;
205     static const int32_t percentUnit = 100;
206     static std::array<std::string, unitsNum> units = { "px", "vp", "fp", "%", "lpx", "auto" };
207     auto unit = dimension.Unit();
208     auto value = dimension.Value();
209     if (unit == DimensionUnit::NONE) {
210         return StringUtils::DoubleToString(value).append("none");
211     }
212     if (units[static_cast<int>(unit)] == units[percentIndex]) {
213         return StringUtils::DoubleToString(value * percentUnit).append(units[static_cast<int>(unit)]);
214     }
215     return StringUtils::DoubleToString(value).append(units[static_cast<int>(unit)]);
216 }
217 
ParseString(const ResourceInfo & info,std::string & result)218 bool ParseString(const ResourceInfo& info, std::string& result)
219 {
220     auto resourceWrapper = CreateResourceWrapper(info);
221     if (resourceWrapper == nullptr) {
222         return false;
223     }
224     if (info.type == static_cast<int>(ResourceType::PLURAL)) {
225         std::string pluralResults;
226         if (info.resId == UNKNOWN_RESOURCE_ID) {
227             auto count = StringUtils::StringToInt(info.params[1]);
228             pluralResults = resourceWrapper->GetPluralStringByName(info.params[0], count);
229             ReplaceHolder(pluralResults, info.params, 2); // plural holder in index 2
230         } else {
231             pluralResults = resourceWrapper->GetPluralString(info.resId, StringUtils::StringToInt(info.params[0]));
232             ReplaceHolder(pluralResults, info.params, 1);
233         }
234         result = pluralResults;
235         return true;
236     }
237     if (info.type == static_cast<int>(ResourceType::RAWFILE)) {
238         result = resourceWrapper->GetRawfile(info.params[0]);
239         return true;
240     }
241     if (info.type == static_cast<int>(ResourceType::FLOAT)) {
242         if (info.resId == UNKNOWN_RESOURCE_ID) {
243             result = DimensionToString(resourceWrapper->GetDimensionByName(info.params[0]));
244         } else {
245             result = DimensionToString(resourceWrapper->GetDimension(info.resId));
246         }
247         return true;
248     }
249     if (info.type == static_cast<int>(ResourceType::STRING)) {
250         std::string originStr;
251         if (info.resId == UNKNOWN_RESOURCE_ID) {
252             originStr = resourceWrapper->GetStringByName(info.params[0]);
253             ReplaceHolder(originStr, info.params, 1);
254         } else {
255             originStr = resourceWrapper->GetString(info.resId);
256             ReplaceHolder(originStr, info.params, 0);
257         }
258         result = originStr;
259         return true;
260     }
261     if (info.type == static_cast<int>(ResourceType::COLOR)) {
262         result = resourceWrapper->GetColor(info.resId).ColorToString();
263         return true;
264     }
265     if (info.type == static_cast<int>(ResourceType::INTEGER)) {
266         result = std::to_string(resourceWrapper->GetInt(info.resId));
267         return true;
268     }
269     return true;
270 }
271 
ConvertResourceType(const std::string & typeName,ResourceType & resType)272 bool ConvertResourceType(const std::string& typeName, ResourceType& resType)
273 {
274     static const std::unordered_map<std::string, ResourceType> resTypeMap {
275         { "color", ResourceType::COLOR },
276         { "media", ResourceType::MEDIA },
277         { "float", ResourceType::FLOAT },
278         { "string", ResourceType::STRING },
279         { "plural", ResourceType::PLURAL },
280         { "pattern", ResourceType::PATTERN },
281         { "boolean", ResourceType::BOOLEAN },
282         { "integer", ResourceType::INTEGER },
283         { "strarray", ResourceType::STRARRAY },
284         { "intarray", ResourceType::INTARRAY },
285     };
286     auto it = resTypeMap.find(typeName);
287     if (it == resTypeMap.end()) {
288         return false;
289     }
290     resType = it->second;
291     return true;
292 }
293 
ParseDollarResource(napi_env env,napi_value value,ResourceType & resType,std::string & resName,std::string & moduleName)294 bool ParseDollarResource(
295     napi_env env, napi_value value, ResourceType& resType, std::string& resName, std::string& moduleName)
296 {
297     napi_valuetype valueType = napi_undefined;
298     napi_typeof(env, value, &valueType);
299     if (valueType != napi_string) {
300         return false;
301     }
302     std::string resPath;
303     if (!GetNapiString(env, value, resPath, valueType)) {
304         return false;
305     }
306     std::vector<std::string> tokens;
307     StringUtils::StringSplitter(resPath, '.', tokens);
308     // $r format like app.xxx.xxx, has 3 paragraph
309     if (static_cast<int32_t>(tokens.size()) != 3) {
310         return false;
311     }
312     std::string maybeModuleName = tokens[0];
313     // [*] or app/hsp at least has 3 chars
314     if (maybeModuleName.size() < 3) {
315         return false;
316     }
317     char begin = *maybeModuleName.begin();
318     char end = maybeModuleName.at(maybeModuleName.size() - 1);
319     bool headCheckPass = false;
320     if (begin == '[' && end == ']') {
321         // moduleName not include 2 brackets
322         moduleName = maybeModuleName.substr(1, maybeModuleName.size() - 2);
323         headCheckPass = true;
324     }
325     if (std::find(RESOURCE_HEADS.begin(), RESOURCE_HEADS.end(), tokens[0]) == RESOURCE_HEADS.end() && !headCheckPass) {
326         return false;
327     }
328     if (!ConvertResourceType(tokens[1], resType)) {
329         return false;
330     }
331     resName = resPath;
332     return true;
333 }
334 
PreFixEmptyBundleName(napi_env env,napi_value value)335 void PreFixEmptyBundleName(napi_env env, napi_value value)
336 {
337     napi_value bundleNameNApi = nullptr;
338     if (napi_get_named_property(env, value, BUNDLE_NAME, &bundleNameNApi) != napi_ok) {
339         return;
340     }
341     std::string bundleName;
342     NapiStringToString(env, bundleNameNApi, bundleName);
343     if (bundleName.empty()) {
344         auto container = Container::CurrentSafely();
345         CHECK_NULL_VOID(container);
346         bundleName = container->GetBundleName();
347         bundleNameNApi = CreateNapiString(env, bundleName);
348         napi_set_named_property(env, value, BUNDLE_NAME, bundleNameNApi);
349     }
350 }
351 
CheckResourceStruct(napi_env env,napi_value value)352 ResourceStruct CheckResourceStruct(napi_env env, napi_value value)
353 {
354     napi_value idNApi = nullptr;
355     napi_valuetype valueType = napi_undefined;
356     napi_typeof(env, value, &valueType);
357     if (valueType != napi_object) {
358         return ResourceStruct::CONSTANT;
359     }
360     if (napi_get_named_property(env, value, "id", &idNApi) != napi_ok) {
361         return ResourceStruct::CONSTANT;
362     }
363     napi_typeof(env, idNApi, &valueType);
364     if (valueType == napi_string) {
365         return ResourceStruct::DYNAMIC_V1;
366     }
367     if (valueType == napi_number) {
368         int32_t id = 0;
369         napi_get_value_int32(env, idNApi, &id);
370         if (id == UNKNOWN_RESOURCE_ID) {
371             return ResourceStruct::DYNAMIC_V2;
372         }
373     }
374     return ResourceStruct::CONSTANT;
375 }
376 
GetStringFromValueUtf8(napi_env env,napi_value value)377 std::optional<std::string> GetStringFromValueUtf8(napi_env env, napi_value value)
378 {
379     static constexpr size_t maxLength = 2048;
380     if (GetValueType(env, value) != napi_string) {
381         return std::nullopt;
382     }
383 
384     size_t paramLen = 0;
385     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &paramLen);
386     if (paramLen == 0 || paramLen > maxLength || status != napi_ok) {
387         return std::nullopt;
388     }
389     char params[maxLength] = { 0 };
390     status = napi_get_value_string_utf8(env, value, params, paramLen + 1, &paramLen);
391     if (status != napi_ok) {
392         return std::nullopt;
393     }
394     return params;
395 }
396 
GetNapiString(napi_env env,napi_value value,std::string & retStr,napi_valuetype & valueType)397 bool GetNapiString(napi_env env, napi_value value, std::string& retStr, napi_valuetype& valueType)
398 {
399     if (NapiStringToString(env, value, retStr)) {
400         return true;
401     }
402     napi_typeof(env, value, &valueType);
403     if (valueType == napi_object) {
404         ResourceInfo recv;
405         if (ParseResourceParam(env, value, recv)) {
406             ParseString(recv, retStr);
407             return true;
408         }
409     }
410     return false;
411 }
412 
ModifyResourceParam(napi_env env,napi_value value,const ResourceType & resType,const std::string & resName)413 void ModifyResourceParam(napi_env env, napi_value value, const ResourceType& resType, const std::string& resName)
414 {
415     // raw input : {"id":"app.xxx.xxx","params":[],"moduleName":"xxx","bundleName":"xxx"}
416     // modified output : {"id":-1, "params":["app.xxx.xxx"],"type":xxxx,"moduleName":"xxx","bundleName":"xxx"}
417     napi_value paramsNApi = nullptr;
418     napi_get_named_property(env, value, "params", &paramsNApi);
419     bool isArray = false;
420     if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
421         return;
422     }
423     if (!isArray) {
424         return;
425     }
426     uint32_t paramCount = 0;
427     bool hasProperty = false;
428     napi_get_array_length(env, paramsNApi, &paramCount);
429     napi_value typeKeyNApi = CreateNapiString(env, "type");
430     napi_value resNameNApi = CreateNapiString(env, resName);
431     if (resType == ResourceType::PLURAL || resType == ResourceType::STRING) {
432         std::vector<napi_value> tmpParams;
433         for (uint32_t i = 0; i < paramCount; i++) {
434             napi_value param = nullptr;
435             napi_get_element(env, paramsNApi, i, &param);
436             tmpParams.insert(tmpParams.end(), param);
437         }
438         napi_set_element(env, paramsNApi, 0, resNameNApi);
439         uint32_t paramIndex = 1;
440         napi_has_property(env, value, typeKeyNApi, &hasProperty);
441         if (hasProperty) {
442             napi_value firstParam = nullptr;
443             napi_get_property(env, value, typeKeyNApi, &firstParam);
444             napi_set_element(env, paramsNApi, paramIndex, firstParam);
445             paramIndex++;
446         }
447         for (auto tmpParam : tmpParams) {
448             napi_set_element(env, paramsNApi, paramIndex, tmpParam);
449             paramIndex++;
450         }
451     } else {
452         napi_set_element(env, paramsNApi, 0, resNameNApi);
453     }
454 }
455 
CompleteResourceParamV1(napi_env env,napi_value value)456 void CompleteResourceParamV1(napi_env env, napi_value value)
457 {
458     napi_value idNApi = nullptr;
459     napi_valuetype valueType = napi_undefined;
460     napi_typeof(env, value, &valueType);
461     if (valueType != napi_object) {
462         return;
463     }
464     if (napi_get_named_property(env, value, "id", &idNApi) != napi_ok) {
465         return;
466     }
467     std::string resName;
468     std::string moduleName;
469     ResourceType resType;
470     if (!ParseDollarResource(env, idNApi, resType, resName, moduleName)) {
471         return;
472     }
473     bool hasProperty = false;
474     napi_value typeIdNApi = nullptr;
475     napi_value resourceIdNApi = nullptr;
476     napi_value typeKeyNApi = CreateNapiString(env, "type");
477     napi_value defaultNameNApi = CreateNapiString(env, "");
478     napi_value bundleNameKeyNApi = CreateNapiString(env, "bundleName");
479     napi_value moduleNameKeyNApi = CreateNapiString(env, "moduleName");
480     napi_create_int32(env, UNKNOWN_RESOURCE_ID, &resourceIdNApi);
481     napi_create_int32(env, static_cast<uint32_t>(resType), &typeIdNApi);
482     ModifyResourceParam(env, value, resType, resName);
483     napi_set_property(env, value, typeKeyNApi, typeIdNApi);
484     napi_set_property(env, value, CreateNapiString(env, "id"), resourceIdNApi);
485     napi_has_property(env, value, bundleNameKeyNApi, &hasProperty);
486     if (!hasProperty) {
487         napi_set_property(env, value, bundleNameKeyNApi, defaultNameNApi);
488     }
489     napi_has_property(env, value, moduleNameKeyNApi, &hasProperty);
490     if (!hasProperty) {
491         napi_set_property(env, value, moduleNameKeyNApi, defaultNameNApi);
492     }
493 }
494 
CompleteResourceParamV2(napi_env env,napi_value value)495 void CompleteResourceParamV2(napi_env env, napi_value value)
496 {
497     napi_value paramsNApi = nullptr;
498     if (napi_get_named_property(env, value, "params", &paramsNApi) != napi_ok) {
499         return;
500     }
501     bool isArray = false;
502     napi_is_array(env, paramsNApi, &isArray);
503     if (!isArray) {
504         return;
505     }
506     uint32_t paramCount = 0;
507     napi_get_array_length(env, paramsNApi, &paramCount);
508     if (paramCount <= 0) {
509         return;
510     }
511     napi_value resNameNApi = nullptr;
512     napi_get_element(env, paramsNApi, 0, &resNameNApi);
513     std::string resName;
514     std::string moduleName;
515     ResourceType resType;
516     if (!ParseDollarResource(env, resNameNApi, resType, resName, moduleName)) {
517         return;
518     }
519     napi_value typeIdNApi = nullptr;
520     napi_value typeKeyNApi = CreateNapiString(env, "type");
521     napi_create_int32(env, static_cast<uint32_t>(resType), &typeIdNApi);
522     napi_set_property(env, value, typeKeyNApi, typeIdNApi);
523     if (!moduleName.empty()) {
524         napi_value moduleNameNApi = CreateNapiString(env, moduleName);
525         napi_value moduleNameKeyNApi = CreateNapiString(env, "moduleName");
526         napi_set_property(env, value, moduleNameKeyNApi, moduleNameNApi);
527     }
528 }
529 
CompleteResourceParam(napi_env env,napi_value value)530 void CompleteResourceParam(napi_env env, napi_value value)
531 {
532     PreFixEmptyBundleName(env, value);
533     ResourceStruct resourceStruct = CheckResourceStruct(env, value);
534     switch (resourceStruct) {
535         case ResourceStruct::CONSTANT:
536             return;
537         case ResourceStruct::DYNAMIC_V1:
538             CompleteResourceParamV1(env, value);
539             return;
540         case ResourceStruct::DYNAMIC_V2:
541             CompleteResourceParamV2(env, value);
542             return;
543         default:
544             return;
545     }
546 }
547 
ParseResourceParam(napi_env env,napi_value value,ResourceInfo & info)548 bool ParseResourceParam(napi_env env, napi_value value, ResourceInfo& info)
549 {
550     CompleteResourceParam(env, value);
551     napi_value idNApi = nullptr;
552     napi_value typeNApi = nullptr;
553     napi_value paramsNApi = nullptr;
554     napi_value bundleNameNApi = nullptr;
555     napi_value moduleNameNApi = nullptr;
556     napi_valuetype valueType = napi_undefined;
557     napi_typeof(env, value, &valueType);
558     if (valueType == napi_object) {
559         napi_get_named_property(env, value, "id", &idNApi);
560         napi_get_named_property(env, value, "type", &typeNApi);
561         napi_get_named_property(env, value, "params", &paramsNApi);
562         napi_get_named_property(env, value, "bundleName", &bundleNameNApi);
563         napi_get_named_property(env, value, "moduleName", &moduleNameNApi);
564     } else {
565         return false;
566     }
567 
568     napi_typeof(env, idNApi, &valueType);
569     if (valueType == napi_number) {
570         napi_get_value_int32(env, idNApi, &info.resId);
571     }
572 
573     napi_typeof(env, typeNApi, &valueType);
574     if (valueType == napi_number) {
575         napi_get_value_int32(env, typeNApi, &info.type);
576     }
577 
578     bool isArray = false;
579     if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
580         return false;
581     }
582 
583     if (!isArray) {
584         return false;
585     }
586 
587     uint32_t arrayLength = 0;
588     napi_get_array_length(env, paramsNApi, &arrayLength);
589 
590     for (uint32_t i = 0; i < arrayLength; i++) {
591         size_t ret = 0;
592         napi_value indexValue = nullptr;
593         napi_get_element(env, paramsNApi, i, &indexValue);
594         napi_typeof(env, indexValue, &valueType);
595         if (valueType == napi_string) {
596             size_t strLen = GetParamLen(env, indexValue) + 1;
597             std::unique_ptr<char[]> indexStr = std::make_unique<char[]>(strLen);
598             napi_get_value_string_utf8(env, indexValue, indexStr.get(), strLen, &ret);
599             info.params.emplace_back(indexStr.get());
600         } else if (valueType == napi_number) {
601             int32_t num;
602             napi_get_value_int32(env, indexValue, &num);
603             info.params.emplace_back(std::to_string(num));
604         }
605     }
606 
607     napi_typeof(env, bundleNameNApi, &valueType);
608     if (valueType == napi_string) {
609         size_t ret = 0;
610         size_t strLen = GetParamLen(env, bundleNameNApi) + 1;
611         std::unique_ptr<char[]> bundleNameStr = std::make_unique<char[]>(strLen);
612         napi_get_value_string_utf8(env, bundleNameNApi, bundleNameStr.get(), strLen, &ret);
613         info.bundleName = bundleNameStr.get();
614     }
615 
616     napi_typeof(env, moduleNameNApi, &valueType);
617     if (valueType == napi_string) {
618         size_t ret = 0;
619         size_t strLen = GetParamLen(env, moduleNameNApi) + 1;
620         std::unique_ptr<char[]> moduleNameStr = std::make_unique<char[]>(strLen);
621         napi_get_value_string_utf8(env, moduleNameNApi, moduleNameStr.get(), strLen, &ret);
622         info.moduleName = moduleNameStr.get();
623     }
624 
625     return true;
626 }
627 
ParseColorFromResourceObject(napi_env env,napi_value value,Color & colorResult)628 bool ParseColorFromResourceObject(napi_env env, napi_value value, Color& colorResult)
629 {
630     ResourceInfo resourceInfo;
631     if (!ParseResourceParam(env, value, resourceInfo)) {
632         return false;
633     }
634     auto resourceWrapper = CreateResourceWrapper(resourceInfo);
635     if (resourceWrapper == nullptr) {
636         return false;
637     }
638     if (resourceInfo.type == static_cast<int32_t>(ResourceType::STRING)) {
639         auto colorString = resourceWrapper->GetString(resourceInfo.type);
640         return Color::ParseColorString(colorString, colorResult);
641     }
642     if (resourceInfo.type == static_cast<int32_t>(ResourceType::INTEGER)) {
643         auto colorInt = resourceWrapper->GetInt(resourceInfo.type);
644         colorResult = Color(CompleteColorAlphaIfIncomplete(colorInt));
645         return true;
646     }
647     colorResult = resourceWrapper->GetColor(resourceInfo.resId);
648     return true;
649 }
650 
ParseColor(napi_env env,napi_value value,Color & result)651 bool ParseColor(napi_env env, napi_value value, Color& result)
652 {
653     napi_valuetype valueType = GetValueType(env, value);
654     if (valueType != napi_number && valueType != napi_string && valueType != napi_object) {
655         return false;
656     }
657     if (valueType == napi_number) {
658         int32_t colorId = 0;
659         napi_get_value_int32(env, value, &colorId);
660         result = Color(CompleteColorAlphaIfIncomplete(static_cast<uint32_t>(colorId)));
661         return true;
662     }
663     if (valueType == napi_string) {
664         std::optional<std::string> colorString = GetStringFromValueUtf8(env, value);
665         if (!colorString.has_value()) {
666             return false;
667         }
668         return Color::ParseColorString(colorString.value(), result);
669     }
670 
671     return ParseColorFromResourceObject(env, value, result);
672 }
673 
ParseDimension(napi_env env,CalcDimension & result,napi_value napiValue,DimensionUnit defaultUnit,bool isSupportPercent)674 bool ACE_FORCE_EXPORT ParseDimension(
675     napi_env env, CalcDimension& result, napi_value napiValue, DimensionUnit defaultUnit, bool isSupportPercent)
676 {
677     napi_valuetype valueType = napi_undefined;
678     napi_typeof(env, napiValue, &valueType);
679     if (valueType == napi_number) {
680         double value = 0;
681         napi_get_value_double(env, napiValue, &value);
682 
683         result.SetUnit(defaultUnit);
684         result.SetValue(value);
685         return true;
686     } else if (valueType == napi_string) {
687         std::string valueString;
688         if (!GetNapiString(env, napiValue, valueString, valueType)) {
689             return false;
690         }
691         if (valueString.back() == '%' && !isSupportPercent) {
692             return false;
693         }
694         return StringUtils::StringToCalcDimensionNG(valueString, result, false, defaultUnit);
695     } else if (valueType == napi_object) {
696         ResourceInfo recv;
697         std::string parameterStr;
698         if (!ParseResourceParam(env, napiValue, recv)) {
699             return false;
700         }
701         if (!ParseString(recv, parameterStr)) {
702             return false;
703         }
704         if (!ParseIntegerToString(recv, parameterStr)) {
705             return false;
706         }
707         result = StringUtils::StringToDimensionWithUnit(parameterStr, defaultUnit);
708         return true;
709     }
710     return false;
711 }
712 
713 } // namespace OHOS::Ace::Kit
714