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 #ifndef OHOS_ACELITE_CJSON_PARSER_H 16 #define OHOS_ACELITE_CJSON_PARSER_H 17 #include "acelite_config.h" 18 19 #if (FEATURE_LOCALIZATION_MODULE == 1) 20 #include <cJSON.h> 21 #include <jerryscript.h> 22 #ifdef __LITEOS_A__ 23 #include "dirent.h" 24 #include "unistd.h" 25 #endif 26 #include "ace_mem_base.h" 27 #include "js_app_context.h" 28 #include "non_copyable.h" 29 30 namespace OHOS { 31 namespace ACELite { 32 class CJSONParser final : public MemoryHeap { 33 public: 34 ACE_DISALLOW_COPY_AND_MOVE(CJSONParser); 35 struct ListNode : public MemoryHeap { 36 char *value = nullptr; 37 ListNode *next = nullptr; 38 }; 39 40 // can't create the node object.it is used to store the json node is psram/ram 41 struct Node { 42 double valueIndex = 0; 43 uint32_t pathIndex = 0; // the path value index in psram 44 uint16_t nextIndex = 0; // the conflicy Node index in array 45 bool isNumber = false; 46 }; 47 48 enum LanguageState : uint8_t { 49 LANGUAGE_FAIL, 50 LANGUAGE_NOT_CHANGE, 51 LANGUAGE_CHANGED 52 }; 53 54 CJSONParser(); 55 ~CJSONParser()56 ~CJSONParser() 57 { 58 void *value = reinterpret_cast<void *>(startPos_); 59 ACE_FREE(value); 60 ACE_FREE(countries_); 61 ACE_FREE(language_); 62 ACE_FREE(filePath_); 63 ACE_FREE(languageFile_); 64 } 65 66 /** 67 * @brief: replace the placeholder in result with the data defined by user 68 * if plural is true, it will replace the number in placeholder, 69 * replace the same name in js object. 70 */ 71 char *FillPlaceholder(const char *format, jerry_value_t arg, jerry_length_t num, bool isPlural = false); 72 73 /** 74 * @brief: init localization, get the resource file path 75 * and get the localization cache ram 76 */ 77 bool Init(); 78 79 /** 80 * @brief: merge string destination and resource, save the merge result in destination 81 * if check is true, it will free destination string 82 */ 83 char *SubStr(const char *src, size_t start, size_t length); 84 85 /** 86 * @brief: split the string by delemeter and save the split result in node 87 * 88 * @return the length of node 89 */ 90 uint8_t Split(const char *target, char delemeter, ListNode *&node); 91 92 static bool AddNode(ListNode *&head, char *current); 93 static char *GetNode(ListNode *node, int index); 94 static void ClearNode(ListNode *&node); 95 static char *ToString(ListNode *node, uint8_t length); 96 97 /** 98 * @brief get localization format result 99 * @param key: the json path 100 * @param args: the args defined the value of placeholder 101 * @return the JS value of localization result 102 */ 103 jerry_value_t GetValue(const char *key, const jerry_value_t args[], jerry_size_t argsNum); 104 105 /** 106 * @brief judge the system language and origion is changed 107 * @return 1: the system language is changed 108 * 0: the system language 109 * -1: get system language failed 110 */ 111 LanguageState ChangeLanguage(); 112 113 /** 114 * @brief cache the frist file in fileList to PSRAM/RAM 115 * @return the cache result, true: cache file success 116 * fail: the fileList is null or the file is too large 117 */ 118 bool CacheFile(); 119 120 private: 121 enum conValue { 122 PRIME_OFFSET_1 = 3, 123 PRIME_OFFSET_2 = 5, 124 PRIME_OFFSET_3 = 7, 125 PRIME_OFFSET_4 = 13, 126 PRIME_OFFSET_5 = 17, 127 MAX_KEY_NUM = 500, 128 MAX_VALUE_LEN = 1024, 129 LOCALIZATION_SIZE = 10240, 130 NFV_PRIME = 16777619 131 }; 132 133 /** 134 * @Brief: get the position of delemeter after index 135 * @return if the index is upper than the length of string, return -1 136 * else if the index is not defined in string, return the length, else return the position of it 137 */ 138 int IndexOf(const char *string, char delemeter, int index); 139 140 /** 141 * @Brief: split the string defined in value by '|', and get value in the split string 142 * For example: the string is car|cars, if the value of param is odd, assign value car,else cars 143 */ 144 #ifdef LOCALIZATION_PLURAL 145 char *GetPluralValue(char *value, jerry_value_t param); 146 uint8_t FormatString(const char *format, jerry_value_t arg, ListNode *&node, bool isPlural, jerry_value_t num); 147 /** 148 * @brief: get the value defined in param 149 * @param: attrName:the attribute name in param, for example "name" 150 * param: the object defined attrName, for example {"name":"Jane"} 151 * @return: the value in param 152 */ 153 char *GetParamValue(const char *attrName, jerry_value_t param, bool isPlural); 154 #else 155 uint8_t FormatString(const char *format, jerry_value_t arg, ListNode *&node, jerry_value_t num); 156 char *GetParamValue(const char *attrName, jerry_value_t param); 157 #endif 158 159 char* GetMergeKey(const char *key, const char *addKey); 160 161 bool CacheValue(const char *key, cJSON item); 162 163 bool PutNumOrStrValue(const char *key, cJSON item); 164 165 bool CacheStrValue(const char *value); 166 167 /** 168 * @brief get value from file in fileList 169 * @param key JSON path 170 * @param args the value to replace the placeholder 171 * @param argsNum the num of args 172 * @param languageFile the target json file name 173 * @return the js value of target value 174 */ 175 jerry_value_t GetValueFromFile(const char *key, 176 jerry_value_t args, 177 jerry_size_t argsNum, 178 const char *languageFile, 179 bool &nullValueFlag); 180 181 /** 182 * @brief get 4-byte aligned offset 183 * @param addr the used offset 184 * @return the nearest 4-byte aligned offset 185 */ GetUseLen(uint32_t usedOffset)186 uint32_t GetUseLen(uint32_t usedOffset) 187 { 188 const uint8_t align = 2; 189 uint32_t len = usedOffset + (1 << align); 190 len = (len >> align) << align; 191 if (len > LOCALIZATION_SIZE) { 192 isCached_ = false; // cache json file failed 193 return 0; 194 } 195 return len; 196 } 197 198 /** 199 * @brief get the string hash value.the hash algorithm is NFV-1a hash 200 * the Algorithm URL is https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1_hash 201 * @param key the string need to hash 202 * @return the hash result which is the index array number 203 */ FNVHash(const char * key)204 uint16_t FNVHash(const char *key) 205 { 206 uint64_t hash = 2166136261; 207 uint32_t len = strlen(key); 208 for (uint32_t i = 0; i < len; i++) { 209 uint8_t keyVal = key[i]; 210 hash = (hash ^ keyVal) * NFV_PRIME; 211 } 212 hash += hash << PRIME_OFFSET_4; 213 hash ^= hash >> PRIME_OFFSET_3; 214 hash += hash << PRIME_OFFSET_1; 215 hash ^= hash >> PRIME_OFFSET_5; 216 hash += hash << PRIME_OFFSET_2; 217 return hash % MAX_KEY_NUM; 218 } 219 220 Node *GetValueFromCache(const char *key); 221 bool ChangeLanguageFileName(); 222 223 #ifdef TARGET_SIMULATOR 224 #if (defined(_WIN32) || (defined(_WIN64))) 225 int GetWinFiles(ListNode *&fileList); 226 #else 227 int GetFiles(ListNode *&fileList); 228 #endif 229 bool CheckLanguageFileName(char *languageFile); 230 #endif 231 bool IsFileExistFullMatch(const char *fileName); 232 233 bool isCached_; 234 bool isAllocated_; 235 char leftDelemeter_; 236 char rightDelemeter_; 237 uint32_t usedOffset_; 238 uintptr_t startPos_; 239 char *countries_; // the current country and origion 240 char *language_; // the current system language 241 char *filePath_; 242 char *languageFile_; 243 }; 244 } // namespace ACELite 245 } // namespace OHOS 246 #endif // FEATURE_LOCALIZATION_MODULE 247 #endif // OHOS_ACELITE_CJSON_PARSER_H 248