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(const CVariant
& variant
);
46 CVariant
& m_parsedObject
;
47 std::vector
<CVariant
*> m_parse
;
51 enum class PARSE_STATUS
57 PARSE_STATUS m_status
;
60 CJSONVariantParserHandler::CJSONVariantParserHandler(CVariant
& parsedObject
)
61 : m_parsedObject(parsedObject
),
64 m_status(PARSE_STATUS::Variable
)
67 bool CJSONVariantParserHandler::Null()
69 PushObject(CVariant::ConstNullVariant
);
75 bool CJSONVariantParserHandler::Bool(bool b
)
80 bool CJSONVariantParserHandler::Int(int i
)
85 bool CJSONVariantParserHandler::Uint(unsigned u
)
90 bool CJSONVariantParserHandler::Int64(int64_t i
)
95 bool CJSONVariantParserHandler::Uint64(uint64_t u
)
100 bool CJSONVariantParserHandler::Double(double d
)
105 bool CJSONVariantParserHandler::RawNumber(const char* str
, rapidjson::SizeType length
, bool copy
)
107 return Primitive(str
, length
);
110 bool CJSONVariantParserHandler::String(const char* str
, rapidjson::SizeType length
, bool copy
)
112 return Primitive(str
, length
);
115 bool CJSONVariantParserHandler::StartObject()
117 PushObject(CVariant::VariantTypeObject
);
122 bool CJSONVariantParserHandler::Key(const char* str
, rapidjson::SizeType length
, bool copy
)
124 m_key
= std::string(str
, 0, length
);
129 bool CJSONVariantParserHandler::EndObject(rapidjson::SizeType memberCount
)
136 bool CJSONVariantParserHandler::StartArray()
138 PushObject(CVariant::VariantTypeArray
);
143 bool CJSONVariantParserHandler::EndArray(rapidjson::SizeType elementCount
)
150 void CJSONVariantParserHandler::PushObject(const CVariant
& variant
)
152 if (m_status
== PARSE_STATUS::Object
)
154 (*m_parse
[m_parse
.size() - 1])[m_key
] = variant
;
155 m_parse
.push_back(&(*m_parse
[m_parse
.size() - 1])[m_key
]);
157 else if (m_status
== PARSE_STATUS::Array
)
159 CVariant
*temp
= m_parse
[m_parse
.size() - 1];
160 temp
->push_back(variant
);
161 m_parse
.push_back(&(*temp
)[temp
->size() - 1]);
163 else if (m_parse
.empty())
166 m_parse
.push_back(&m_root
);
169 if (variant
.isObject())
170 m_status
= PARSE_STATUS::Object
;
171 else if (variant
.isArray())
172 m_status
= PARSE_STATUS::Array
;
174 m_status
= PARSE_STATUS::Variable
;
177 void CJSONVariantParserHandler::PopObject()
179 CVariant
*variant
= m_parse
[m_parse
.size() - 1];
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
);