2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "JSONVariantParser.h"
11 #include <rapidjson/reader.h>
13 class CJSONVariantParserHandler
16 explicit CJSONVariantParserHandler(CVariant
& parsedObject
);
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
);
28 bool Key(const char* str
, rapidjson::SizeType length
, bool copy
);
29 bool EndObject(rapidjson::SizeType memberCount
);
31 bool EndArray(rapidjson::SizeType elementCount
);
34 template <typename
... TArgs
>
35 bool Primitive(TArgs
... args
)
37 PushObject(CVariant(std::forward
<TArgs
>(args
)...));
43 void PushObject(CVariant variant
);
46 CVariant
& m_parsedObject
;
47 std::vector
<CVariant
*> m_parse
;
51 enum class PARSE_STATUS
57 PARSE_STATUS m_status
= PARSE_STATUS::Variable
;
60 CJSONVariantParserHandler::CJSONVariantParserHandler(CVariant
& parsedObject
)
61 : m_parsedObject(parsedObject
), m_parse(), m_key()
64 bool CJSONVariantParserHandler::Null()
66 PushObject(CVariant::ConstNullVariant
);
72 bool CJSONVariantParserHandler::Bool(bool b
)
77 bool CJSONVariantParserHandler::Int(int i
)
82 bool CJSONVariantParserHandler::Uint(unsigned u
)
87 bool CJSONVariantParserHandler::Int64(int64_t i
)
92 bool CJSONVariantParserHandler::Uint64(uint64_t u
)
97 bool CJSONVariantParserHandler::Double(double d
)
102 bool CJSONVariantParserHandler::RawNumber(const char* str
, rapidjson::SizeType length
, bool copy
)
104 return Primitive(str
, length
);
107 bool CJSONVariantParserHandler::String(const char* str
, rapidjson::SizeType length
, bool copy
)
109 return Primitive(str
, length
);
112 bool CJSONVariantParserHandler::StartObject()
114 PushObject(CVariant::VariantTypeObject
);
119 bool CJSONVariantParserHandler::Key(const char* str
, rapidjson::SizeType length
, bool copy
)
121 m_key
= std::string(str
, 0, length
);
126 bool CJSONVariantParserHandler::EndObject(rapidjson::SizeType memberCount
)
133 bool CJSONVariantParserHandler::StartArray()
135 PushObject(CVariant::VariantTypeArray
);
140 bool CJSONVariantParserHandler::EndArray(rapidjson::SizeType elementCount
)
147 void CJSONVariantParserHandler::PushObject(CVariant variant
)
149 const auto variant_type
= variant
.type();
151 if (m_status
== PARSE_STATUS::Object
)
153 (*m_parse
.back())[m_key
] = std::move(variant
);
154 m_parse
.push_back(&((*m_parse
.back())[m_key
]));
156 else if (m_status
== PARSE_STATUS::Array
)
158 CVariant
*temp
= m_parse
[m_parse
.size() - 1];
159 temp
->push_back(std::move(variant
));
160 m_parse
.push_back(&(*temp
)[temp
->size() - 1]);
162 else if (m_parse
.empty())
164 m_root
= std::move(variant
);
165 m_parse
.push_back(&m_root
);
168 if (variant_type
== CVariant::VariantTypeObject
)
169 m_status
= PARSE_STATUS::Object
;
170 else if (variant_type
== CVariant::VariantTypeArray
)
171 m_status
= PARSE_STATUS::Array
;
173 m_status
= PARSE_STATUS::Variable
;
176 void CJSONVariantParserHandler::PopObject()
178 assert(!m_parse
.empty());
179 CVariant
* variant
= m_parse
.back();
182 if (!m_parse
.empty())
184 variant
= m_parse
[m_parse
.size() - 1];
185 if (variant
->isObject())
186 m_status
= PARSE_STATUS::Object
;
187 else if (variant
->isArray())
188 m_status
= PARSE_STATUS::Array
;
190 m_status
= PARSE_STATUS::Variable
;
194 m_parsedObject
= *variant
;
195 m_status
= PARSE_STATUS::Variable
;
199 bool CJSONVariantParser::Parse(const char* json
, CVariant
& data
)
204 rapidjson::Reader reader
;
205 rapidjson::StringStream
stringStream(json
);
207 CJSONVariantParserHandler
handler(data
);
208 // use kParseIterativeFlag to eliminate possible stack overflow
209 // from json parsing via reentrant calls
210 if (reader
.Parse
<rapidjson::kParseIterativeFlag
>(stringStream
, handler
))
216 bool CJSONVariantParser::Parse(const std::string
& json
, CVariant
& data
)
218 return Parse(json
.c_str(), data
);