1 /* 2 * Copyright (c) 2021-2024 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 #ifndef ECMASCRIPT_BASE_JSON_PARSE_INL_H 17 #define ECMASCRIPT_BASE_JSON_PARSE_INL_H 18 19 #include <cerrno> 20 21 #include "ecmascript/base/json_helper.h" 22 #include "ecmascript/base/builtins_base.h" 23 #include "ecmascript/base/number_helper.h" 24 #include "ecmascript/base/string_helper.h" 25 #include "ecmascript/base/utf_helper.h" 26 #include "ecmascript/ecma_string-inl.h" 27 #include "ecmascript/ecma_string.h" 28 #include "ecmascript/js_array.h" 29 #include "ecmascript/js_function.h" 30 #include "ecmascript/js_handle.h" 31 #include "ecmascript/js_map.h" 32 #include "ecmascript/global_env.h" 33 #include "ecmascript/js_tagged_value.h" 34 #include "ecmascript/message_string.h" 35 #include "ecmascript/object_factory.h" 36 #include "ecmascript/object_fast_operator-inl.h" 37 #include "ecmascript/shared_objects/js_shared_map.h" 38 39 namespace panda::ecmascript::base { 40 constexpr unsigned int UNICODE_DIGIT_LENGTH = 4; 41 constexpr unsigned int NUMBER_TEN = 10; 42 constexpr unsigned int NUMBER_SIXTEEN = 16; 43 constexpr unsigned int INTEGER_MAX_LEN = 9; 44 45 constexpr unsigned char CODE_SPACE = 0x20; 46 constexpr unsigned char ASCII_END = 0X7F; 47 enum class Tokens : uint8_t { 48 // six structural tokens 49 OBJECT = 0, 50 ARRAY, 51 NUMBER, 52 STRING, 53 LITERAL_TRUE, 54 LITERAL_FALSE, 55 LITERAL_NULL, 56 TOKEN_ILLEGAL, 57 MAP, 58 }; 59 60 struct JsonContinuation { 61 enum class ContinuationType : uint8_t { 62 RETURN = 0, 63 ARRAY, 64 OBJECT, 65 MAP, 66 }; JsonContinuationJsonContinuation67 JsonContinuation(ContinuationType type, size_t index) : type_(type), index_(index) {} 68 69 ContinuationType type_ {ContinuationType::RETURN}; 70 size_t index_ {0}; 71 }; 72 73 template<typename T> 74 class JsonParser { 75 protected: 76 using BigIntMode = base::JsonHelper::BigIntMode; 77 using ParseReturnType = base::JsonHelper::ParseReturnType; 78 using ParseOptions = base::JsonHelper::ParseOptions; 79 using TransformType = base::JsonHelper::TransformType; 80 using Text = const T *; 81 using ContType = JsonContinuation::ContinuationType; 82 // Instantiation of the class is prohibited 83 JsonParser() = default; 84 JsonParser(JSThread *thread, TransformType transformType, 85 ParseOptions options = ParseOptions()) thread_(thread)86 : thread_(thread), transformType_(transformType), parseOptions_(options) 87 { 88 } 89 virtual ~JsonParser() = default; 90 NO_COPY_SEMANTIC(JsonParser); 91 NO_MOVE_SEMANTIC(JsonParser); 92 93 JSHandle<JSTaggedValue> Launch(Text begin, Text end); 94 IsInObjOrArrayOrMap(ContType type)95 inline bool IsInObjOrArrayOrMap(ContType type) 96 { 97 return type == ContType::ARRAY || type == ContType::OBJECT || type == ContType::MAP; 98 } 99 EmptyArrayCheck()100 inline bool EmptyArrayCheck() 101 { 102 GetNextNonSpaceChar(); 103 return *current_ == ']'; 104 } 105 EmptyObjectCheck()106 inline bool EmptyObjectCheck() 107 { 108 GetNextNonSpaceChar(); 109 return *current_ == '}'; 110 } 111 GetSJsonPrototype()112 JSHandle<JSTaggedValue> GetSJsonPrototype() 113 { 114 JSHandle<JSFunction> sObjFunction(thread_->GetEcmaVM()->GetGlobalEnv()->GetSObjectFunction()); 115 JSHandle<JSTaggedValue> jsonPrototype = JSHandle<JSTaggedValue>(thread_, sObjFunction->GetFunctionPrototype()); 116 return jsonPrototype; 117 } 118 GetSMapPrototype()119 JSHandle<JSTaggedValue> GetSMapPrototype() 120 { 121 auto globalEnv = thread_->GetEcmaVM()->GetGlobalEnv(); 122 JSHandle<JSTaggedValue> proto = globalEnv->GetSharedMapPrototype(); 123 return proto; 124 } 125 126 JSTaggedValue ParseJSONText(); 127 128 JSHandle<JSTaggedValue> CreateJsonArray(JsonContinuation continuation, 129 std::vector<JSHandle<JSTaggedValue>> &elementsList); 130 131 JSHandle<JSTaggedValue> CreateSJsonArray([[maybe_unused]] JsonContinuation continuation, 132 [[maybe_unused]] std::vector<JSHandle<JSTaggedValue>> &elementsList); 133 134 JSHandle<JSTaggedValue> CreateJsonObject(JsonContinuation continuation, 135 std::vector<JSHandle<JSTaggedValue>> &propertyList); 136 137 JSHandle<JSTaggedValue> CreateSJsonObject(JsonContinuation continuation, 138 std::vector<JSHandle<JSTaggedValue>> &propertyList); 139 140 JSHandle<JSSharedMap> CreateSharedMap(); 141 142 JSHandle<JSMap> CreateMap(); 143 144 JSHandle<JSTaggedValue> CreateJsonMap(JsonContinuation continuation, 145 std::vector<JSHandle<JSTaggedValue>> &propertyList); 146 147 JSHandle<JSTaggedValue> CreateSJsonMap(JsonContinuation continuation, 148 std::vector<JSHandle<JSTaggedValue>> &propertyList); 149 150 JSTaggedValue SetPropertyByValue(const JSHandle<JSTaggedValue> &receiver, const JSHandle<JSTaggedValue> &key, 151 const JSHandle<JSTaggedValue> &value); 152 153 JSTaggedValue ParseNumber(bool inObjorArr = false); 154 155 JSTaggedValue ConvertToNumber(const std::string &str, bool negative, bool hasExponent, bool hasDecimal); 156 157 bool ParseStringLength(size_t &length, bool &isAscii, bool inObjorArr); 158 159 bool CheckBackslash(Text &text, Text last, bool &isAscii); 160 161 template<typename Char> 162 void ParseBackslash(Char *&p); 163 164 template<typename Char> 165 void CopyCharWithBackslash(Char *&p); 166 167 JSHandle<JSTaggedValue> ParseStringWithBackslash(bool inObjorArr); 168 virtual void ParticalParseString(std::string& str, Text current, Text nextCurrent) = 0; 169 170 virtual JSHandle<JSTaggedValue> ParseString(bool inObjorArr = false) = 0; 171 172 void SkipEndWhiteSpace(); 173 174 void SkipStartWhiteSpace(); 175 176 void GetNextNonSpaceChar(); 177 178 Tokens ParseToken(); 179 180 JSTaggedValue ParseLiteralTrue(); 181 182 JSTaggedValue ParseLiteralFalse(); 183 184 JSTaggedValue ParseLiteralNull(); 185 186 bool MatchText(const char *str, uint32_t matchLen); 187 188 bool ReadNumberRange(bool &isFast, int32_t &fastInteger); 189 190 Text AdvanceLastNumberCharacter(Text current); 191 192 bool IsNumberCharacter(T ch); 193 194 bool IsNumberSignalCharacter(T ch); 195 196 bool IsExponentNumber(); 197 198 bool IsDecimalsLegal(bool &hasExponent); 199 200 bool IsExponentLegal(bool &hasExponent); 201 202 bool CheckZeroBeginNumber(bool &hasExponent, bool &hasDecimal); 203 204 bool CheckNonZeroBeginNumber(bool &hasExponent, bool &hasDecimal); 205 Advance()206 inline void Advance() 207 { 208 ++current_; 209 } 210 AdvanceMultiStep(int step)211 inline void AdvanceMultiStep(int step) 212 { 213 current_ += step; 214 } 215 216 Text end_ {nullptr}; 217 Text current_ {nullptr}; 218 Text range_ {nullptr}; 219 JSThread *thread_ {nullptr}; 220 ObjectFactory *factory_ {nullptr}; 221 GlobalEnv *env_ {nullptr}; 222 TransformType transformType_ {TransformType::NORMAL}; 223 ParseOptions parseOptions_; 224 JSHandle<JSHClass> initialJSArrayClass_; 225 JSHandle<JSHClass> initialJSObjectClass_; 226 }; 227 228 class PUBLIC_API Utf8JsonParser final : public JsonParser<uint8_t> { 229 public: 230 Utf8JsonParser() = default; 231 Utf8JsonParser(JSThread *thread, TransformType transformType, 232 ParseOptions options = ParseOptions()) JsonParser(thread,transformType,options)233 : JsonParser(thread, transformType, options) {} 234 ~Utf8JsonParser() = default; 235 NO_COPY_SEMANTIC(Utf8JsonParser); 236 NO_MOVE_SEMANTIC(Utf8JsonParser); 237 238 JSHandle<JSTaggedValue> PUBLIC_API Parse(const JSHandle<EcmaString> &strHandle); 239 240 private: 241 void ParticalParseString(std::string& str, Text current, Text nextCurrent) override; 242 243 static void UpdatePointersListener(void *utf8Parser); 244 245 JSHandle<JSTaggedValue> ParseString(bool inObjOrArrOrMap = false) override; 246 247 bool ReadJsonStringRange(bool &isFastString); 248 249 bool IsFastParseJsonString(bool &isFastString); 250 251 const uint8_t *begin_ {nullptr}; 252 JSHandle<EcmaString> sourceString_; 253 }; 254 255 class Utf16JsonParser final : public JsonParser<uint16_t> { 256 public: 257 Utf16JsonParser() = default; 258 Utf16JsonParser(JSThread *thread, TransformType transformType, 259 ParseOptions options = ParseOptions()) JsonParser(thread,transformType,options)260 : JsonParser(thread, transformType, options) {} 261 ~Utf16JsonParser() = default; 262 NO_COPY_SEMANTIC(Utf16JsonParser); 263 NO_MOVE_SEMANTIC(Utf16JsonParser); 264 265 JSHandle<JSTaggedValue> Parse(EcmaString *str); 266 267 private: 268 void ParticalParseString(std::string& str, Text current, Text nextCurrent) override; 269 JSHandle<JSTaggedValue> ParseString(bool inObjOrArrOrMap = false) override; 270 271 bool ReadJsonStringRange(bool &isFastString, bool &isAscii); 272 273 bool IsFastParseJsonString(bool &isFastString, bool &isAscii); 274 275 bool IsLegalAsciiCharacter(uint16_t c, bool &isAscii); 276 }; 277 278 class Internalize { 279 public: 280 using TransformType = base::JsonHelper::TransformType; 281 static JSHandle<JSTaggedValue> InternalizeJsonProperty(JSThread *thread, const JSHandle<JSObject> &holder, 282 const JSHandle<JSTaggedValue> &name, 283 const JSHandle<JSTaggedValue> &receiver, 284 TransformType transformType); 285 private: 286 static bool RecurseAndApply(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &name, 287 const JSHandle<JSTaggedValue> &receiver, TransformType transformType); 288 }; 289 } // namespace panda::ecmascript::base 290 291 #endif // ECMASCRIPT_BASE_JSON_PARSE_INL_H 292