1 /*
2 * Copyright (c) 2020-2021 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 "cjson_parser.h"
17 #if (FEATURE_LOCALIZATION_MODULE == 1)
18 #include "ace_log.h"
19 #include "global.h"
20 #include "js_fwk_common.h"
21 #if (defined(_WIN32) || defined(_WIN64))
22 #include <io.h>
23 #else
24 #include "gfx_utils/file.h"
25 #endif
26 #include "securec.h"
27 #include "string_util.h"
28 #include <string.h>
29
30 namespace OHOS {
31 namespace ACELite {
CJSONParser()32 CJSONParser::CJSONParser()
33 : isCached_(false),
34 isAllocated_(true),
35 startPos_(-1),
36 countries_(nullptr),
37 language_(nullptr),
38 filePath_(nullptr),
39 languageFile_(nullptr)
40 {
41 char left = '{';
42 leftDelemeter_ = left;
43 char right = '}';
44 rightDelemeter_ = right;
45 usedOffset_ = sizeof(uint32_t) * MAX_KEY_NUM;
46 }
47
Init()48 bool CJSONParser::Init()
49 {
50 const char * const filePath = JsAppContext::GetInstance()->GetCurrentAbilityPath();
51 const char * const folderName = "i18n";
52 filePath_ = RelocateResourceFilePath(filePath, folderName);
53 void *ram = ace_malloc(LOCALIZATION_SIZE);
54 if (ram == nullptr) {
55 HILOG_ERROR(HILOG_MODULE_ACE, "malloc cache ram failed");
56 isAllocated_ = false;
57 return false;
58 }
59 startPos_ = reinterpret_cast<uintptr_t>(ram);
60 return (filePath_ != nullptr);
61 }
62
FillPlaceholder(const char * format,jerry_value_t arg,jerry_length_t num,bool isPlural)63 char *CJSONParser::FillPlaceholder(const char *format, jerry_value_t arg, jerry_length_t num, bool isPlural)
64 {
65 if (format == nullptr) {
66 return nullptr;
67 }
68 if (isPlural) {
69 #ifdef LOCALIZATION_PLURAL
70 format = GetPluralValue(format, arg);
71 if (format == nullptr) {
72 return nullptr;
73 }
74 #endif
75 }
76 ListNode *values = nullptr; // store the value after split.
77 #ifdef LOCALIZATION_PLURAL
78 uint8_t length = FormatString(format, arg, values, isPlural, num);
79 if (isPlural) {
80 ACE_FREE(format);
81 }
82 #else
83 uint8_t length = FormatString(format, arg, values, num);
84 #endif // LOCALIZATION_PLURAL
85 char *result = nullptr;
86 if (values != nullptr) {
87 result = ToString(values, length);
88 ClearNode(values);
89 }
90 return result;
91 }
92
93 #ifdef LOCALIZATION_PLURAL
FormatString(const char * format,jerry_value_t arg,ListNode * & values,bool isPlural,jerry_length_t num)94 uint8_t CJSONParser::FormatString(const char *format,
95 jerry_value_t arg,
96 ListNode *&values,
97 bool isPlural,
98 jerry_length_t num)
99 #else
100 uint8_t CJSONParser::FormatString(const char *format, jerry_value_t arg, ListNode *&values, jerry_length_t num)
101 #endif
102 {
103 uint8_t length = 0;
104 int index = 0;
105 int leftIndex = IndexOf(format, leftDelemeter_, index); // get the index of '{'
106 while (leftIndex >= 0) {
107 char *value = SubStr(format, index, leftIndex - index);
108 if (AddNode(values, value)) {
109 length++;
110 } else {
111 ACE_FREE(value);
112 }
113 leftIndex++;
114 index = IndexOf(format, rightDelemeter_, leftIndex); // get the index of '}'
115 if (index > 0 && num > 1) {
116 char *content = SubStr(format, leftIndex, index - leftIndex);
117 #ifdef LOCALIZATION_PLURAL
118 char *contentValue = GetParamValue(content, arg, isPlural);
119 #else
120 char *contentValue = GetParamValue(content, arg);
121 #endif // LOCALIZATION_PLURAL
122 ACE_FREE(content);
123 if (AddNode(values, contentValue)) {
124 length++;
125 } else {
126 ACE_FREE(contentValue);
127 }
128 }
129 if ((index > 0) && (static_cast<size_t>(index) < strlen(format))) {
130 index++; // move the index '}' to the next char
131 } else {
132 // add the remain character to node.eg.the value is {count}aa, add the last aa to the node
133 char *currentVal = SubStr(format, index, strlen(format) - index);
134 if (AddNode(values, currentVal)) {
135 length++;
136 } else {
137 ACE_FREE(currentVal);
138 }
139 }
140 leftIndex = IndexOf(format, leftDelemeter_, index);
141 }
142 if (leftIndex < 0 && (static_cast<size_t>(index) < strlen(format))) {
143 char *currentVal = SubStr(format, index, strlen(format) - index);
144 if (AddNode(values, currentVal)) {
145 length++;
146 } else {
147 ACE_FREE(currentVal);
148 }
149 }
150 return length;
151 }
152
153 #ifdef LOCALIZATION_PLURAL
GetPluralValue(char * value,jerry_value_t param)154 char *CJSONParser::GetPluralValue(char *value, jerry_value_t param)
155 {
156 ListNode *plurals = nullptr;
157 int defaultNum = jerry_value_is_number(param) ? IntegerOf(param) : 1;
158 const char delemeter = '|'; // if the function is get plural, split the value in json by '|'
159 int len = Split(value, delemeter, plurals);
160 const int maxLen = 2;
161 // get the index in plural array
162 if (len <= maxLen) {
163 value = (defaultNum != 1) ? GetNode(plurals, 1) : GetNode(plurals, len);
164 } else {
165 int index = (abs(defaultNum) < maxLen) ? abs(defaultNum) : maxLen; // get the index in plurals
166 value = GetNode(plurals, len - index);
167 }
168 char *result = SubStr(value, 0, strlen(value));
169 if (plurals) {
170 ClearNode(plurals);
171 }
172 return result;
173 }
174 #endif // LOCALIZATION_PLURAL
175
AddNode(ListNode * & head,char * current)176 bool CJSONParser::AddNode(ListNode *&head, char *current)
177 {
178 if (current == nullptr || strlen(current) == 0) {
179 return false;
180 }
181 ListNode *node = new ListNode();
182 if (node == nullptr) {
183 HILOG_ERROR(HILOG_MODULE_ACE, "create node failed");
184 return false;
185 }
186 node->next = head;
187 node->value = current;
188 head = node;
189 return true;
190 }
191
GetNode(ListNode * node,int index)192 char *CJSONParser::GetNode(ListNode *node, int index)
193 {
194 for (int i = 0; i < index - 1; i++) {
195 if (node == nullptr) {
196 break;
197 }
198 node = node->next;
199 }
200 return (node == nullptr) ? nullptr : node->value;
201 }
202
ClearNode(ListNode * & node)203 void CJSONParser::ClearNode(ListNode *&node)
204 {
205 while (node != nullptr) {
206 ListNode *current = node->next;
207 ACE_FREE(node->value);
208 delete node;
209 node = current;
210 }
211 }
212
ToString(ListNode * node,uint8_t length)213 char *CJSONParser::ToString(ListNode *node, uint8_t length)
214 {
215 if (node == nullptr || (length == 0)) {
216 return nullptr;
217 }
218 char **temp = static_cast<char **>(ace_malloc(length * sizeof(char *)));
219 if (temp == nullptr) {
220 return nullptr;
221 }
222 // reverse node value
223 uint8_t index = 0;
224 uint16_t strLength = 0; // the length of result
225 while (node != nullptr) {
226 if ((length - index > 0) && (node->value != nullptr)) {
227 size_t valueLen = strlen(node->value);
228 if ((valueLen > (MAX_VALUE_LEN - 1)) || (strLength > (MAX_VALUE_LEN - 1)) ||
229 (strLength + valueLen > (MAX_VALUE_LEN - 1))) {
230 ACE_FREE(temp);
231 return nullptr;
232 }
233 temp[length - 1 - index] = node->value;
234 strLength += valueLen;
235 }
236 node = node->next;
237 index++;
238 }
239 // the strLength is no more than maxValueLen_ - 1
240 strLength++;
241 char *result = static_cast<char *>(ace_malloc(strLength));
242 if (result == nullptr) {
243 HILOG_ERROR(HILOG_MODULE_ACE, "malloc localization result failed");
244 ACE_FREE(temp);
245 return nullptr;
246 }
247 // convert the value in node to string
248 if (strcpy_s(result, strLength, temp[0]) != 0) {
249 HILOG_ERROR(HILOG_MODULE_ACE, "merge string failed");
250 ACE_FREE(result);
251 ACE_FREE(temp);
252 return nullptr;
253 }
254 for (int i = 1; i < length; i++) {
255 if (strcat_s(result, strLength, temp[i]) != 0) {
256 HILOG_INFO(HILOG_MODULE_ACE, "merge string failed");
257 ACE_FREE(result);
258 ACE_FREE(temp);
259 return nullptr;
260 }
261 }
262 ACE_FREE(temp);
263 return result;
264 }
265
SubStr(const char * src,size_t start,size_t length)266 char *CJSONParser::SubStr(const char *src, size_t start, size_t length)
267 {
268 if (src == nullptr || start >= strlen(src)) {
269 return nullptr;
270 }
271 if (length > (MAX_VALUE_LEN - 1)) {
272 HILOG_ERROR(HILOG_MODULE_ACE, "the length is too long");
273 return nullptr;
274 }
275 size_t len = length + 1;
276 char *result = static_cast<char *>(ace_malloc(len));
277 if (result == nullptr) {
278 HILOG_ERROR(HILOG_MODULE_ACE, "malloc failed");
279 return nullptr;
280 }
281 errno_t error = strncpy_s(result, len, src + start, length);
282 if (error != 0) {
283 HILOG_ERROR(HILOG_MODULE_ACE, "copy string failed");
284 ACE_FREE(result);
285 return nullptr;
286 }
287 result[length] = '\0';
288 return result;
289 }
290
ChangeLanguage()291 CJSONParser::LanguageState CJSONParser::ChangeLanguage()
292 {
293 char *currentLanguage = static_cast<char *>(ace_malloc(MAX_LANGUAGE_LENGTH));
294 char *currentOrigion = static_cast<char *>(ace_malloc(MAX_REGION_LENGTH));
295 if ((currentLanguage == nullptr) || (currentOrigion == nullptr)) {
296 HILOG_ERROR(HILOG_MODULE_ACE, "malloc system language info failed");
297 ACE_FREE(currentLanguage);
298 ACE_FREE(currentOrigion);
299 return LanguageState::LANGUAGE_FAIL;
300 }
301 int langRet = GLOBAL_GetLanguage(currentLanguage, MAX_LANGUAGE_LENGTH);
302 int regionRet = GLOBAL_GetRegion(currentOrigion, MAX_REGION_LENGTH);
303 LanguageState result = LanguageState::LANGUAGE_CHANGED;
304 if ((langRet != 0) || (regionRet != 0)) {
305 result = LanguageState::LANGUAGE_FAIL;
306 }
307 if ((language_ != nullptr) && (strcmp(currentLanguage, language_) == 0) &&
308 (countries_ != nullptr) && (strcmp(currentOrigion, countries_) == 0)) {
309 result = LanguageState::LANGUAGE_NOT_CHANGE;
310 }
311 if ((result == LanguageState::LANGUAGE_NOT_CHANGE) || (result == LanguageState::LANGUAGE_FAIL)) {
312 ace_free(currentOrigion);
313 currentOrigion = nullptr;
314 ace_free(currentLanguage);
315 currentLanguage = nullptr;
316 return result;
317 }
318 ACE_FREE(language_);
319 language_ = currentLanguage;
320 ACE_FREE(countries_);
321 countries_ = currentOrigion;
322 return LanguageState::LANGUAGE_CHANGED;
323 }
324
ChangeLanguageFileName()325 bool CJSONParser::ChangeLanguageFileName()
326 {
327 if ((language_ == nullptr) || (countries_ == nullptr)) {
328 if ((languageFile_ != nullptr) && (!strcmp(languageFile_, "en-US.json"))) {
329 return false;
330 }
331 ACE_FREE(languageFile_); // avoid leaking
332 languageFile_ = StringUtil::Copy("en-US.json");
333 return true;
334 }
335 uint8_t addedLen = 7; // the length of '-', ".json" and '\0'
336 uint8_t langLen = strlen(language_);
337 size_t fileLen = langLen + strlen(countries_) + addedLen;
338 char *languageFile = StringUtil::Malloc(fileLen);
339 if (languageFile == nullptr) {
340 return false;
341 }
342 errno_t error = strcpy_s(languageFile, fileLen, language_);
343 languageFile[langLen] = '-';
344 languageFile[langLen + 1] = '\0';
345 error += strcat_s(languageFile, fileLen, countries_);
346 error += strcat_s(languageFile, fileLen, ".json");
347 if (error > 0) {
348 ace_free(languageFile);
349 languageFile = nullptr;
350 return false;
351 }
352 if ((languageFile_ != nullptr) && (!strcmp(languageFile, languageFile_))) {
353 ace_free(languageFile);
354 languageFile = nullptr;
355 } else {
356 ACE_FREE(languageFile_);
357 languageFile_ = languageFile;
358 }
359 return true;
360 }
361
CacheFile()362 bool CJSONParser::CacheFile()
363 {
364 if (!ChangeLanguageFileName()) {
365 HILOG_ERROR(HILOG_MODULE_ACE, "prepare language file name failed, cache status[%{public}d]", isCached_);
366 return true;
367 }
368 isCached_ = false;
369 usedOffset_ = sizeof(uint32_t) * MAX_KEY_NUM;
370 if (!isAllocated_) {
371 HILOG_ERROR(HILOG_MODULE_ACE, "cache buffer not ready");
372 return false;
373 }
374 if (memset_s(reinterpret_cast<void *>(startPos_), usedOffset_, 0, usedOffset_) != EOK) {
375 HILOG_ERROR(HILOG_MODULE_ACE, "initial psram failed");
376 return false;
377 }
378 if (memset_s(reinterpret_cast<void *>(startPos_ + usedOffset_), LOCALIZATION_SIZE - usedOffset_, '\0',
379 LOCALIZATION_SIZE - usedOffset_) != EOK) {
380 HILOG_ERROR(HILOG_MODULE_ACE, "init cache content failed");
381 return false;
382 }
383 // set the keyIndex 0
384 for (int i = 0; i < MAX_KEY_NUM; i++) {
385 uint32_t *index = reinterpret_cast<uint32_t *>(startPos_ + i * sizeof(uint32_t));
386 *index = 0;
387 }
388 if (languageFile_ == nullptr) {
389 HILOG_ERROR(HILOG_MODULE_ACE, "waring: no correct language file name presented, will cach en-US as default");
390 // cache the default file en-US.json
391 languageFile_ = StringUtil::Copy("en-US.json");
392 }
393 uint32_t fileContentLength = 0;
394 char *content = ReadJSFile(filePath_, languageFile_, fileContentLength);
395 if (content == nullptr || fileContentLength == 0) {
396 HILOG_ERROR(HILOG_MODULE_ACE, "cache failing, read language file failed");
397 return false;
398 }
399 cJSON *json = cJSON_Parse(content);
400 ace_free(content);
401 content = nullptr;
402 if (json == nullptr) {
403 HILOG_ERROR(HILOG_MODULE_ACE, "cache failing, cJSON_Parse failed");
404 return false;
405 }
406 isCached_ = CacheValue(nullptr, *json);
407 cJSON_Delete(json);
408 json = nullptr;
409 return isCached_;
410 }
411
GetMergeKey(const char * key,const char * addKey)412 char *CJSONParser::GetMergeKey(const char *key, const char *addKey)
413 {
414 if (addKey == nullptr) {
415 return const_cast<char *>(key);
416 }
417 uint16_t addKeyLen = strlen(addKey);
418 uint32_t preLen = (key == nullptr) ? 0 : strlen(key);
419 const uint8_t addedLen = 2;
420 uint16_t mergeLen = preLen + addKeyLen + addedLen;
421 char *mergeKey = reinterpret_cast<char *>(ace_malloc(mergeLen));
422 if (mergeKey == nullptr) {
423 HILOG_ERROR(HILOG_MODULE_ACE, "merge key failed");
424 return nullptr;
425 }
426 if (key != nullptr) {
427 if ((strcpy_s(mergeKey, mergeLen, key) != EOK) || (strcat_s(mergeKey, mergeLen, ".") != EOK) ||
428 (strcat_s(mergeKey, mergeLen, addKey) != EOK)) {
429 HILOG_ERROR(HILOG_MODULE_ACE, "copy preKey failed");
430 ace_free(mergeKey);
431 return nullptr;
432 }
433 } else {
434 if (strcpy_s(mergeKey, mergeLen, addKey)) {
435 HILOG_ERROR(HILOG_MODULE_ACE, "copy json key failed\n");
436 ace_free(mergeKey);
437 return nullptr;
438 }
439 }
440 return mergeKey;
441 }
442
PutNumOrStrValue(const char * key,cJSON item)443 bool CJSONParser::PutNumOrStrValue(const char *key, cJSON item)
444 {
445 if (key == nullptr) {
446 HILOG_ERROR(HILOG_MODULE_ACE, "the json key is nullptr");
447 return false;
448 }
449 uint32_t index = FNVHash(key);
450 uint32_t *valueIndex = reinterpret_cast<uint32_t *>(startPos_ + index * sizeof(uint32_t));
451 if (valueIndex == nullptr) {
452 return false;
453 }
454 if (*valueIndex != 0) {
455 // the hash value is conflict
456 Node *currentNode = reinterpret_cast<Node *>(startPos_ + (*valueIndex));
457 while ((currentNode != nullptr) && (currentNode->nextIndex != 0)) {
458 currentNode = reinterpret_cast<Node *>(startPos_ + currentNode->nextIndex);
459 }
460 if (currentNode != nullptr) {
461 currentNode->nextIndex = usedOffset_;
462 }
463 } else {
464 *valueIndex = usedOffset_;
465 }
466 Node *node = reinterpret_cast<Node *>(startPos_ + usedOffset_);
467 usedOffset_ = GetUseLen(usedOffset_ + sizeof(Node));
468 if (usedOffset_ == 0) {
469 return false;
470 }
471 node->pathIndex = usedOffset_;
472 if (!CacheStrValue(key)) {
473 return false;
474 }
475 if (item.type == cJSON_Number) {
476 node->isNumber = true;
477 node->valueIndex = item.valuedouble;
478 return true;
479 }
480 node->valueIndex = usedOffset_;
481 return CacheStrValue(item.valuestring);
482 }
483
CacheStrValue(const char * value)484 bool CJSONParser::CacheStrValue(const char *value)
485 {
486 if (strcpy_s(reinterpret_cast<char *>(startPos_ + usedOffset_), LOCALIZATION_SIZE - usedOffset_, value)) {
487 HILOG_ERROR(HILOG_MODULE_ACE, "copy value failed");
488 return false;
489 }
490 usedOffset_ = GetUseLen(usedOffset_ + strlen(value) + 1);
491 if (usedOffset_ == 0) {
492 return false;
493 }
494 return true;
495 }
496
CacheValue(const char * key,cJSON item)497 bool CJSONParser::CacheValue(const char *key, cJSON item)
498 {
499 char *mergeKey = GetMergeKey(const_cast<char *>(key), item.string);
500 bool result = true;
501 if ((item.type == cJSON_Number) || (item.type == cJSON_String)) {
502 result = PutNumOrStrValue(mergeKey, item);
503 } else if (item.type == cJSON_Object) {
504 if ((item.child == nullptr) || (!CacheValue(mergeKey, *item.child))) {
505 result = false;
506 }
507 } else {
508 // if the object is array, skip it. find the array value through read json file
509 }
510 ACE_FREE(mergeKey);
511 if (!result) {
512 return false;
513 }
514 return (item.next == nullptr) || (CacheValue(key, *item.next));
515 }
516
GetValueFromFile(const char * key,jerry_value_t args,jerry_size_t argsNum,const char * languageFile,bool & nullValueFlag)517 jerry_value_t CJSONParser::GetValueFromFile(const char *key,
518 jerry_value_t args,
519 jerry_size_t argsNum,
520 const char *languageFile,
521 bool &nullValueFlag)
522 {
523 if (languageFile == nullptr || strlen(languageFile) == 0) {
524 HILOG_ERROR(HILOG_MODULE_ACE, "invalid language file name");
525 return UNDEFINED;
526 }
527 ListNode *keys = nullptr;
528 uint8_t keyCount = Split(key, '.', *&keys);
529 char *content = ReadJSFile(filePath_, languageFile);
530 cJSON *fileJson = cJSON_Parse(content);
531 ACE_FREE(content);
532 cJSON *curJsonItem = fileJson;
533 uint8_t curKeyIndex = 0;
534 do {
535 // get the current splited key
536 char *message = CJSONParser::GetNode(keys, keyCount - curKeyIndex);
537 curJsonItem = cJSON_GetObjectItem(curJsonItem, message);
538 curKeyIndex++;
539 } while (!(curKeyIndex == keyCount || (curJsonItem == nullptr)));
540 ClearNode(keys);
541 jerry_value_t result = UNDEFINED;
542 do {
543 if (curJsonItem == nullptr) {
544 break;
545 }
546 if (cJSON_IsNumber(curJsonItem)) {
547 result = jerry_create_number(curJsonItem->valuedouble);
548 break;
549 }
550 char *value = FillPlaceholder(curJsonItem->valuestring, args, argsNum);
551 if (value == nullptr) {
552 HILOG_ERROR(HILOG_MODULE_ACE, "get nullptr value after place holder filling, keyLen[%{public}d]",
553 strlen(key));
554 nullValueFlag = true;
555 break;
556 }
557 if (strlen(value) == 0) {
558 HILOG_ERROR(HILOG_MODULE_ACE, "warning: get 0 length str after place holder filling, keyLen[%{public}d]",
559 strlen(key));
560 }
561 result = jerry_create_string(reinterpret_cast<jerry_char_t *>(value));
562 ace_free(value);
563 value = nullptr;
564 } while (0);
565 cJSON_Delete(fileJson);
566 fileJson = nullptr;
567 return result;
568 }
569
GetValue(const char * key,const jerry_value_t args[],const jerry_size_t argsNum)570 jerry_value_t CJSONParser::GetValue(const char *key, const jerry_value_t args[], const jerry_size_t argsNum)
571 {
572 jerry_value_t arg = (argsNum > 1) ? args[1] : UNDEFINED;
573 // try finding from cache first
574 Node *node = GetValueFromCache(key);
575 if (node == nullptr) {
576 HILOG_ERROR(HILOG_MODULE_ACE, "warning: get value from cache failed, keyLen[%{public}d]", strlen(key));
577 // no node found from cache, searching from current language file then
578 bool nullValueFlag = false;
579 jerry_value_t resultFromFile = GetValueFromFile(key, arg, argsNum, languageFile_, nullValueFlag);
580 if (nullValueFlag) {
581 HILOG_INFO(HILOG_MODULE_ACE, "get undefined value for key[%{public}s]", key);
582 return resultFromFile;
583 }
584 if (!IS_UNDEFINED(resultFromFile) && !IS_ERROR_VALUE(resultFromFile)) {
585 // found
586 return resultFromFile;
587 }
588 jerry_release_value(resultFromFile);
589 HILOG_ERROR(HILOG_MODULE_ACE, "get error from current language file, try en-US last");
590 // failed, get from default language file last
591 resultFromFile = GetValueFromFile(key, arg, argsNum, "en-US.json", nullValueFlag);
592 if (nullValueFlag) {
593 HILOG_INFO(HILOG_MODULE_ACE, "get undefined value for key[%{public}s]", key);
594 return resultFromFile;
595 }
596 if (!IS_UNDEFINED(resultFromFile) && !IS_ERROR_VALUE(resultFromFile)) {
597 return resultFromFile;
598 }
599 jerry_release_value(resultFromFile);
600 HILOG_ERROR(HILOG_MODULE_ACE, "get error from default file, return the key, keyLen[%{public}d]", strlen(key));
601 return jerry_create_string((const jerry_char_t *)(key));
602 }
603
604 // cache node found, number case
605 if (node->isNumber) {
606 return jerry_create_number(node->valueIndex);
607 }
608 // NOT number case
609 const char *result = reinterpret_cast<char *>(startPos_ + (uint32_t)(node->valueIndex));
610 char *valueStr = FillPlaceholder(result, arg, argsNum);
611 if (valueStr == nullptr) {
612 HILOG_ERROR(HILOG_MODULE_ACE,
613 "get null value after place holder filling, valudeIndex[%{public}d], return the key",
614 (uint32_t)(node->valueIndex));
615 // empty value, return the key
616 return jerry_create_string((const jerry_char_t *)(key));
617 }
618 if (strlen(valueStr) == 0) {
619 HILOG_ERROR(HILOG_MODULE_ACE,
620 "warning: get empty value after place holder filling, valudeIndex[%{public}d], keyLen[%{public}d]",
621 (uint32_t)(node->valueIndex), strlen(key));
622 }
623 jerry_value_t valueJSValue = jerry_create_string(reinterpret_cast<jerry_char_t *>(valueStr));
624 ACE_FREE(valueStr);
625 return valueJSValue;
626 }
627
GetValueFromCache(const char * key)628 CJSONParser::Node *CJSONParser::GetValueFromCache(const char *key)
629 {
630 if (!isCached_) {
631 HILOG_ERROR(HILOG_MODULE_ACE, "warning: cache status is NO, keyLen[%{public}d]", strlen(key));
632 return nullptr;
633 }
634 uint16_t index = FNVHash(key);
635 uint32_t *valueIndex = reinterpret_cast<uint32_t *>(startPos_ + index * sizeof(uint32_t));
636 while ((valueIndex != nullptr) && (*valueIndex != 0)) {
637 Node *node = reinterpret_cast<Node *>(startPos_ + (*valueIndex));
638 if (node == nullptr) {
639 HILOG_ERROR(HILOG_MODULE_ACE,
640 "get value from cache failed, valueIndex[%{public}d], keyLen[%{public}d]",
641 (*valueIndex), strlen(key));
642 return nullptr;
643 }
644 char *nodeKey = reinterpret_cast<char *>(startPos_ + node->pathIndex);
645 if ((nodeKey != nullptr) && (!strcmp(key, nodeKey))) {
646 return node;
647 } else {
648 *valueIndex = node->nextIndex;
649 }
650 }
651 return nullptr;
652 }
653
Split(const char * target,char delemeter,ListNode * & node)654 uint8_t CJSONParser::Split(const char *target, char delemeter, ListNode *&node)
655 {
656 if (target == nullptr) {
657 return 0;
658 }
659 uint8_t nodeCount = 0;
660 char *current = nullptr;
661 int startPos = 0;
662 // get the position of delemeter
663 int pos = IndexOf(target, delemeter, startPos);
664 while (pos != -1) {
665 // add the value between startPos and index to node
666 current = SubStr(target, startPos, pos - startPos);
667 if (AddNode(node, current)) {
668 nodeCount++;
669 } else {
670 ACE_FREE(current);
671 }
672 startPos = pos + 1;
673 pos = IndexOf(target, delemeter, startPos);
674 }
675 if ((startPos != -1) && (static_cast<size_t>(startPos) < strlen(target))) {
676 current = SubStr(target, startPos, strlen(target) - startPos);
677 if (AddNode(node, current)) {
678 nodeCount++;
679 } else {
680 ACE_FREE(current);
681 }
682 }
683 // deal the key from lastIndex to strlen(target), the last find would return -1
684 return nodeCount;
685 }
686
IndexOf(const char * string,char delemeter,int index)687 int CJSONParser::IndexOf(const char *string, char delemeter, int index)
688 {
689 if (string == nullptr) {
690 return -1;
691 }
692 if ((index < 0) || (strlen(string) >= INT8_MAX) || (static_cast<size_t>(index) >= strlen(string))) {
693 return -1;
694 }
695 int length = strlen(string);
696 int i = index;
697 do {
698 if (string[i] == delemeter) {
699 return i;
700 }
701 i++;
702 } while (i < length);
703 // if the delemeter is not find return -1
704 return -1;
705 }
706
707 #ifdef LOCALIZATION_PLURAL
708 char *CJSONParser::GetParamValue(const char *attrName, jerry_value_t param, bool isPlural)
709 #else
710 char *CJSONParser::GetParamValue(const char *attrName, jerry_value_t param)
711 {
712 if (attrName == nullptr) {
713 return nullptr;
714 }
715 char *contentValue = nullptr; // store the value defined in param
716 uint16_t contentLen = 0;
717 #ifdef LOCALIZATION_PLURAL
718 if (jerry_value_is_number(param)) {
719 contentValue = MallocStringOf(param, &contentLen);
720 }
721 #else
722 jerry_value_t propName = jerry_create_string(reinterpret_cast<jerry_char_t const *>(attrName));
723 if (JerryHasProperty(param, propName)) { // get the placeholder {...} value defined in param
724 jerry_value_t paramValue = jerry_get_property(param, propName);
725 // the contentValue would be released in clearNode values
726 contentValue = MallocStringOf(paramValue, &contentLen);
727 jerry_release_value(paramValue);
728 }
729 jerry_release_value(propName);
730 #endif
731 // if the length of attrVal is 0, the node wouldn't add to the list
732 if ((contentValue != nullptr) && contentLen != 0) {
733 return contentValue;
734 }
735 ACE_FREE(contentValue); // if the contentValue is \0
736 return nullptr;
737 }
738 #endif
739 } // namespace ACELite
740 } // namespace OHOS
741 #endif
742