Merge pull request #26148 from ksooo/fix-secondstotimestring-warning
[xbmc.git] / xbmc / utils / JSONVariantParser.cpp
blob0790d53680cf41cc48750061f4a4a111292fb648
1 /*
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.
7 */
9 #include "JSONVariantParser.h"
11 #include <rapidjson/reader.h>
13 class CJSONVariantParserHandler
15 public:
16 explicit CJSONVariantParserHandler(CVariant& parsedObject);
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);
33 private:
34 template <typename... TArgs>
35 bool Primitive(TArgs... args)
37 PushObject(CVariant(std::forward<TArgs>(args)...));
38 PopObject();
40 return true;
43 void PushObject(CVariant variant);
44 void PopObject();
46 CVariant& m_parsedObject;
47 std::vector<CVariant *> m_parse;
48 std::string m_key;
49 CVariant m_root;
51 enum class PARSE_STATUS
53 Variable,
54 Array,
55 Object
57 PARSE_STATUS m_status = PARSE_STATUS::Variable;
60 CJSONVariantParserHandler::CJSONVariantParserHandler(CVariant& parsedObject)
61 : m_parsedObject(parsedObject), m_parse(), m_key()
62 { }
64 bool CJSONVariantParserHandler::Null()
66 PushObject(CVariant::ConstNullVariant);
67 PopObject();
69 return true;
72 bool CJSONVariantParserHandler::Bool(bool b)
74 return Primitive(b);
77 bool CJSONVariantParserHandler::Int(int i)
79 return Primitive(i);
82 bool CJSONVariantParserHandler::Uint(unsigned u)
84 return Primitive(u);
87 bool CJSONVariantParserHandler::Int64(int64_t i)
89 return Primitive(i);
92 bool CJSONVariantParserHandler::Uint64(uint64_t u)
94 return Primitive(u);
97 bool CJSONVariantParserHandler::Double(double d)
99 return Primitive(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);
116 return true;
119 bool CJSONVariantParserHandler::Key(const char* str, rapidjson::SizeType length, bool copy)
121 m_key = std::string(str, 0, length);
123 return true;
126 bool CJSONVariantParserHandler::EndObject(rapidjson::SizeType memberCount)
128 PopObject();
130 return true;
133 bool CJSONVariantParserHandler::StartArray()
135 PushObject(CVariant::VariantTypeArray);
137 return true;
140 bool CJSONVariantParserHandler::EndArray(rapidjson::SizeType elementCount)
142 PopObject();
144 return true;
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;
172 else
173 m_status = PARSE_STATUS::Variable;
176 void CJSONVariantParserHandler::PopObject()
178 assert(!m_parse.empty());
179 CVariant* variant = m_parse.back();
180 m_parse.pop_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;
189 else
190 m_status = PARSE_STATUS::Variable;
192 else
194 m_parsedObject = *variant;
195 m_status = PARSE_STATUS::Variable;
199 bool CJSONVariantParser::Parse(const char* json, CVariant& data)
201 if (json == nullptr)
202 return false;
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))
211 return true;
213 return false;
216 bool CJSONVariantParser::Parse(const std::string& json, CVariant& data)
218 return Parse(json.c_str(), data);