• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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