From be933ef2241d79558f91796cc5b3a161f72ebf9c Mon Sep 17 00:00:00 2001 From: manuel Date: Mon, 19 Oct 2020 00:52:24 +0200 Subject: sync with upstream --- xbmc/utils/JSONVariantParser.cpp | 217 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 xbmc/utils/JSONVariantParser.cpp (limited to 'xbmc/utils/JSONVariantParser.cpp') 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 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "JSONVariantParser.h" + +#include + +class CJSONVariantParserHandler +{ +public: + explicit CJSONVariantParserHandler(CVariant& parsedObject); + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned u); + bool Int64(int64_t i); + bool Uint64(uint64_t u); + bool Double(double d); + bool RawNumber(const char* str, rapidjson::SizeType length, bool copy); + bool String(const char* str, rapidjson::SizeType length, bool copy); + bool StartObject(); + bool Key(const char* str, rapidjson::SizeType length, bool copy); + bool EndObject(rapidjson::SizeType memberCount); + bool StartArray(); + bool EndArray(rapidjson::SizeType elementCount); + +private: + template + bool Primitive(TArgs... args) + { + PushObject(CVariant(std::forward(args)...)); + PopObject(); + + return true; + } + + void PushObject(CVariant variant); + void PopObject(); + + CVariant& m_parsedObject; + std::vector m_parse; + std::string m_key; + + enum class PARSE_STATUS + { + Variable, + Array, + Object + }; + PARSE_STATUS m_status; +}; + +CJSONVariantParserHandler::CJSONVariantParserHandler(CVariant& parsedObject) + : m_parsedObject(parsedObject), + m_parse(), + m_key(), + m_status(PARSE_STATUS::Variable) +{ } + +bool CJSONVariantParserHandler::Null() +{ + PushObject(CVariant::ConstNullVariant); + PopObject(); + + return true; +} + +bool CJSONVariantParserHandler::Bool(bool b) +{ + return Primitive(b); +} + +bool CJSONVariantParserHandler::Int(int i) +{ + return Primitive(i); +} + +bool CJSONVariantParserHandler::Uint(unsigned u) +{ + return Primitive(u); +} + +bool CJSONVariantParserHandler::Int64(int64_t i) +{ + return Primitive(i); +} + +bool CJSONVariantParserHandler::Uint64(uint64_t u) +{ + return Primitive(u); +} + +bool CJSONVariantParserHandler::Double(double d) +{ + return Primitive(d); +} + +bool CJSONVariantParserHandler::RawNumber(const char* str, rapidjson::SizeType length, bool copy) +{ + return Primitive(str, length); +} + +bool CJSONVariantParserHandler::String(const char* str, rapidjson::SizeType length, bool copy) +{ + return Primitive(str, length); +} + +bool CJSONVariantParserHandler::StartObject() +{ + PushObject(CVariant::VariantTypeObject); + + return true; +} + +bool CJSONVariantParserHandler::Key(const char* str, rapidjson::SizeType length, bool copy) +{ + m_key = std::string(str, 0, length); + + return true; +} + +bool CJSONVariantParserHandler::EndObject(rapidjson::SizeType memberCount) +{ + PopObject(); + + return true; +} + +bool CJSONVariantParserHandler::StartArray() +{ + PushObject(CVariant::VariantTypeArray); + + return true; +} + +bool CJSONVariantParserHandler::EndArray(rapidjson::SizeType elementCount) +{ + PopObject(); + + return true; +} + +void CJSONVariantParserHandler::PushObject(CVariant variant) +{ + if (m_status == PARSE_STATUS::Object) + { + (*m_parse[m_parse.size() - 1])[m_key] = variant; + m_parse.push_back(&(*m_parse[m_parse.size() - 1])[m_key]); + } + else if (m_status == PARSE_STATUS::Array) + { + CVariant *temp = m_parse[m_parse.size() - 1]; + temp->push_back(variant); + m_parse.push_back(&(*temp)[temp->size() - 1]); + } + else if (m_parse.empty()) + m_parse.push_back(new CVariant(variant)); + + if (variant.isObject()) + m_status = PARSE_STATUS::Object; + else if (variant.isArray()) + m_status = PARSE_STATUS::Array; + else + m_status = PARSE_STATUS::Variable; +} + +void CJSONVariantParserHandler::PopObject() +{ + CVariant *variant = m_parse[m_parse.size() - 1]; + m_parse.pop_back(); + + if (!m_parse.empty()) + { + variant = m_parse[m_parse.size() - 1]; + if (variant->isObject()) + m_status = PARSE_STATUS::Object; + else if (variant->isArray()) + m_status = PARSE_STATUS::Array; + else + m_status = PARSE_STATUS::Variable; + } + else + { + m_parsedObject = *variant; + delete variant; + + m_status = PARSE_STATUS::Variable; + } +} + +bool CJSONVariantParser::Parse(const char* json, CVariant& data) +{ + if (json == nullptr) + return false; + + rapidjson::Reader reader; + rapidjson::StringStream stringStream(json); + + CJSONVariantParserHandler handler(data); + // use kParseIterativeFlag to eliminate possible stack overflow + // from json parsing via reentrant calls + if (reader.Parse(stringStream, handler)) + return true; + + return false; +} + +bool CJSONVariantParser::Parse(const std::string& json, CVariant& data) +{ + return Parse(json.c_str(), data); +} -- cgit v1.2.3