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, ¶mLen);
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, ¶mLen);
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", ¶msNApi);
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, ¶mCount);
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, ¶m);
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", ¶msNApi) != 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, ¶mCount);
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", ¶msNApi);
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