1/** 2 * Copyright (c) 2021-2022 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 LIBPANDABASE_UTILS_JSON_PARSER_H 17#define LIBPANDABASE_UTILS_JSON_PARSER_H 18 19#include <string> 20#include <vector> 21#include <unordered_map> 22#include <variant> 23#include <memory> 24#include <algorithm> 25 26#include "macros.h" 27 28WEAK_FOR_LTO_START 29 30namespace panda { 31 32class JsonObject { 33public: 34 class Value; 35 using StringT = std::string; 36 using NumT = double; 37 using BoolT = bool; 38 using ArrayT = std::vector<Value>; 39 using Key = StringT; 40 using JsonObjPointer = std::unique_ptr<JsonObject>; 41 42 class Value { 43 public: 44 Value() = default; 45 ~Value() = default; 46 NO_COPY_SEMANTIC(Value); 47 Value(Value &&rhs) noexcept: value_(std::move(rhs.value_)) 48 { 49 rhs.value_ = std::monostate {}; 50 } 51 Value &operator=(Value &&rhs) noexcept 52 { 53 value_ = std::move(rhs.value_); 54 rhs.value_ = std::monostate {}; 55 return *this; 56 } 57 58 template <typename T> 59 void SetValue(T &&rhs) noexcept 60 { 61 value_ = std::forward<T>(rhs); 62 } 63 64 template <typename T> 65 T *Get() 66 { 67 return std::get_if<T>(&value_); 68 } 69 template <typename T> 70 const T *Get() const 71 { 72 return std::get_if<T>(&value_); 73 } 74 75 private: 76 std::variant<std::monostate, StringT, NumT, BoolT, ArrayT, JsonObjPointer> value_; 77 }; 78 79 // Recursive descent parser: 80 class Parser { 81 public: 82 explicit Parser(JsonObject *target) : current_obj_(target) {} 83 bool Parse(const std::string &text); 84 bool Parse(std::streambuf *stream_buf); 85 86 virtual ~Parser() = default; 87 88 NO_COPY_SEMANTIC(Parser); 89 NO_MOVE_SEMANTIC(Parser); 90 91 private: 92 bool Parse(); 93 94 bool GetJsonObject(JsonObject *empty_obj); 95 bool GetValue(); 96 bool GetString(char delim); 97 bool GetJsonString(); 98 bool GetNum(); 99 bool GetBool(); 100 bool GetArray(); 101 bool InsertKeyValuePairIn(JsonObject *obj); 102 103 char GetSymbol(); 104 char PeekSymbol(); 105 bool TryGetSymbol(int symbol); 106 107 static bool IsWhitespace(int symbol); 108 109 private: 110 std::istream istream_ {nullptr}; 111 JsonObject *current_obj_ {nullptr}; 112 Value parsed_temp_; 113 StringT string_temp_; 114 115 size_t log_recursion_level_ {0}; 116 }; 117 118public: 119 JsonObject() = default; 120 ~JsonObject() = default; 121 NO_COPY_SEMANTIC(JsonObject); 122 NO_MOVE_SEMANTIC(JsonObject); 123 explicit JsonObject(const std::string &text) 124 { 125 Parser(this).Parse(text); 126 } 127 explicit JsonObject(std::streambuf *stream_buf) 128 { 129 Parser(this).Parse(stream_buf); 130 } 131 132 size_t GetSize() const 133 { 134 ASSERT(values_map_.size() == keys_.size()); 135 ASSERT(values_map_.size() == string_map_.size()); 136 return values_map_.size(); 137 } 138 139 size_t GetIndexByKey(const Key &key) const 140 { 141 auto it = std::find(keys_.begin(), keys_.end(), key); 142 if (it != keys_.end()) { 143 return it - keys_.begin(); 144 } 145 return static_cast<size_t>(-1); 146 } 147 const auto &GetKeyByIndex(size_t idx) const 148 { 149 ASSERT(idx < GetSize()); 150 return keys_[idx]; 151 } 152 153 template <typename T> 154 const T *GetValue(const Key &key) const 155 { 156 auto iter = values_map_.find(key); 157 return (iter == values_map_.end()) ? nullptr : iter->second.Get<T>(); 158 } 159 const StringT *GetValueSourceString(const Key &key) const 160 { 161 auto iter = string_map_.find(key); 162 return (iter == string_map_.end()) ? nullptr : &iter->second; 163 } 164 template <typename T> 165 const T *GetValue(size_t idx) const 166 { 167 auto iter = values_map_.find(GetKeyByIndex(idx)); 168 return (iter == values_map_.end()) ? nullptr : iter->second.Get<T>(); 169 } 170 171 const auto &GetUnorderedMap() const 172 { 173 return values_map_; 174 } 175 176 bool IsValid() const 177 { 178 return is_valid_; 179 } 180 181private: 182 bool is_valid_ {false}; 183 std::unordered_map<Key, Value> values_map_; 184 // String representation is stored additionally as a "source" of scalar values: 185 std::unordered_map<Key, StringT> string_map_; 186 187 // Stores the order in which keys were added (allows to access elements by index): 188 std::vector<Key> keys_; 189}; 190 191} // namespace panda 192 193WEAK_FOR_LTO_END 194 195#endif // LIBPANDABASE_UTILS_JSON_PARSER_H 196