summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/JSONVariantParser.cpp
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
committermanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
commitbe933ef2241d79558f91796cc5b3a161f72ebf9c (patch)
treefe3ab2f130e20c99001f2d7a81d610c78c96a3f4 /xbmc/utils/JSONVariantParser.cpp
parent5f8335c1e49ce108ef3481863833c98efa00411b (diff)
downloadkodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.gz
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.bz2
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.zip
sync with upstream
Diffstat (limited to 'xbmc/utils/JSONVariantParser.cpp')
-rw-r--r--xbmc/utils/JSONVariantParser.cpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/xbmc/utils/JSONVariantParser.cpp b/xbmc/utils/JSONVariantParser.cpp
new file mode 100644
index 0000000..f003cdf
--- /dev/null
+++ b/xbmc/utils/JSONVariantParser.cpp
@@ -0,0 +1,217 @@
1/*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#include "JSONVariantParser.h"
10
11#include <rapidjson/reader.h>
12
13class CJSONVariantParserHandler
14{
15public:
16 explicit CJSONVariantParserHandler(CVariant& parsedObject);
17
18 bool Null();
19 bool Bool(bool b);
20 bool Int(int i);
21 bool Uint(unsigned u);
22 bool Int64(int64_t i);
23 bool Uint64(uint64_t u);
24 bool Double(double d);
25 bool RawNumber(const char* str, rapidjson::SizeType length, bool copy);
26 bool String(const char* str, rapidjson::SizeType length, bool copy);
27 bool StartObject();
28 bool Key(const char* str, rapidjson::SizeType length, bool copy);
29 bool EndObject(rapidjson::SizeType memberCount);
30 bool StartArray();
31 bool EndArray(rapidjson::SizeType elementCount);
32
33private:
34 template <typename... TArgs>
35 bool Primitive(TArgs... args)
36 {
37 PushObject(CVariant(std::forward<TArgs>(args)...));
38 PopObject();
39
40 return true;
41 }
42
43 void PushObject(CVariant variant);
44 void PopObject();
45
46 CVariant& m_parsedObject;
47 std::vector<CVariant *> m_parse;
48 std::string m_key;
49
50 enum class PARSE_STATUS
51 {
52 Variable,
53 Array,
54 Object
55 };
56 PARSE_STATUS m_status;
57};
58
59CJSONVariantParserHandler::CJSONVariantParserHandler(CVariant& parsedObject)
60 : m_parsedObject(parsedObject),
61 m_parse(),
62 m_key(),
63 m_status(PARSE_STATUS::Variable)
64{ }
65
66bool CJSONVariantParserHandler::Null()
67{
68 PushObject(CVariant::ConstNullVariant);
69 PopObject();
70
71 return true;
72}
73
74bool CJSONVariantParserHandler::Bool(bool b)
75{
76 return Primitive(b);
77}
78
79bool CJSONVariantParserHandler::Int(int i)
80{
81 return Primitive(i);
82}
83
84bool CJSONVariantParserHandler::Uint(unsigned u)
85{
86 return Primitive(u);
87}
88
89bool CJSONVariantParserHandler::Int64(int64_t i)
90{
91 return Primitive(i);
92}
93
94bool CJSONVariantParserHandler::Uint64(uint64_t u)
95{
96 return Primitive(u);
97}
98
99bool CJSONVariantParserHandler::Double(double d)
100{
101 return Primitive(d);
102}
103
104bool CJSONVariantParserHandler::RawNumber(const char* str, rapidjson::SizeType length, bool copy)
105{
106 return Primitive(str, length);
107}
108
109bool CJSONVariantParserHandler::String(const char* str, rapidjson::SizeType length, bool copy)
110{
111 return Primitive(str, length);
112}
113
114bool CJSONVariantParserHandler::StartObject()
115{
116 PushObject(CVariant::VariantTypeObject);
117
118 return true;
119}
120
121bool CJSONVariantParserHandler::Key(const char* str, rapidjson::SizeType length, bool copy)
122{
123 m_key = std::string(str, 0, length);
124
125 return true;
126}
127
128bool CJSONVariantParserHandler::EndObject(rapidjson::SizeType memberCount)
129{
130 PopObject();
131
132 return true;
133}
134
135bool CJSONVariantParserHandler::StartArray()
136{
137 PushObject(CVariant::VariantTypeArray);
138
139 return true;
140}
141
142bool CJSONVariantParserHandler::EndArray(rapidjson::SizeType elementCount)
143{
144 PopObject();
145
146 return true;
147}
148
149void CJSONVariantParserHandler::PushObject(CVariant variant)
150{
151 if (m_status == PARSE_STATUS::Object)
152 {
153 (*m_parse[m_parse.size() - 1])[m_key] = variant;
154 m_parse.push_back(&(*m_parse[m_parse.size() - 1])[m_key]);
155 }
156 else if (m_status == PARSE_STATUS::Array)
157 {
158 CVariant *temp = m_parse[m_parse.size() - 1];
159 temp->push_back(variant);
160 m_parse.push_back(&(*temp)[temp->size() - 1]);
161 }
162 else if (m_parse.empty())
163 m_parse.push_back(new CVariant(variant));
164
165 if (variant.isObject())
166 m_status = PARSE_STATUS::Object;
167 else if (variant.isArray())
168 m_status = PARSE_STATUS::Array;
169 else
170 m_status = PARSE_STATUS::Variable;
171}
172
173void CJSONVariantParserHandler::PopObject()
174{
175 CVariant *variant = m_parse[m_parse.size() - 1];
176 m_parse.pop_back();
177
178 if (!m_parse.empty())
179 {
180 variant = m_parse[m_parse.size() - 1];
181 if (variant->isObject())
182 m_status = PARSE_STATUS::Object;
183 else if (variant->isArray())
184 m_status = PARSE_STATUS::Array;
185 else
186 m_status = PARSE_STATUS::Variable;
187 }
188 else
189 {
190 m_parsedObject = *variant;
191 delete variant;
192
193 m_status = PARSE_STATUS::Variable;
194 }
195}
196
197bool CJSONVariantParser::Parse(const char* json, CVariant& data)
198{
199 if (json == nullptr)
200 return false;
201
202 rapidjson::Reader reader;
203 rapidjson::StringStream stringStream(json);
204
205 CJSONVariantParserHandler handler(data);
206 // use kParseIterativeFlag to eliminate possible stack overflow
207 // from json parsing via reentrant calls
208 if (reader.Parse<rapidjson::kParseIterativeFlag>(stringStream, handler))
209 return true;
210
211 return false;
212}
213
214bool CJSONVariantParser::Parse(const std::string& json, CVariant& data)
215{
216 return Parse(json.c_str(), data);
217}