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