From 8bfae9b4833ccbf14526fac357d4d8efd5e2821b Mon Sep 17 00:00:00 2001 From: Riyyi Date: Thu, 23 Jun 2022 13:47:07 +0200 Subject: [PATCH] Util: Add more ways of accessing and creating Json::Value objects --- src/util/json/array.h | 19 +++++++++++++- src/util/json/object.h | 12 +++++++++ src/util/json/value.cpp | 58 ++++++++++++++++++++++++++++++++++++++--- src/util/json/value.h | 14 ++++++++-- 4 files changed, 96 insertions(+), 7 deletions(-) diff --git a/src/util/json/array.h b/src/util/json/array.h index a879102..4af9e56 100644 --- a/src/util/json/array.h +++ b/src/util/json/array.h @@ -7,6 +7,7 @@ #ifndef JSON_ARRAY_H #define JSON_ARRAY_H +#include #include // move #include @@ -19,6 +20,10 @@ public: Array() {} virtual ~Array() {} + Array(const std::initializer_list& values) + : m_values(values) + {} + Array(const Array& other) : m_values(other.m_values) { @@ -29,6 +34,19 @@ public: m_values.emplace_back(std::move(value)); } + Value& at(size_t index) + { + if (index + 1 > m_values.size()) { + m_values.resize(index + 1); + } + + return m_values.at(index); + } + Value& operator[](size_t index) { return at(index); } + const Value& at(size_t index) const { return m_values.at(index); } + const Value& operator[](size_t index) const { return m_values.at(index); } + + size_t size() const { return m_values.size(); } const std::vector& values() const { return m_values; } private: @@ -37,5 +55,4 @@ private: } // namespace Json - #endif // JSON_ARRAY_H diff --git a/src/util/json/object.h b/src/util/json/object.h index 52d79ca..24554fa 100644 --- a/src/util/json/object.h +++ b/src/util/json/object.h @@ -30,6 +30,18 @@ public: m_members.emplace(key, std::move(value)); } + Value& at(const std::string& key) + { + if (m_members.find(key) == m_members.end()) { + emplace(key, {}); + } + + return m_members.at(key); + } + Value& operator[](const std::string& key) { return at(key); } + const Value& at(const std::string& key) const { return m_members.at(key); } + const Value& operator[](const std::string& key) const { return m_members.at(key); } + const std::map& members() const { return m_members; } private: diff --git a/src/util/json/value.cpp b/src/util/json/value.cpp index f5c7265..1f56fd5 100644 --- a/src/util/json/value.cpp +++ b/src/util/json/value.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: MIT */ +#include // all_of #include // assert #include // uint32_t #include @@ -38,6 +39,12 @@ Value::Value(bool value) m_value.asBool = value; } +Value::Value(int value) + : m_type(Type::Number) +{ + m_value.asDouble = value; +} + Value::Value(double value) : m_type(Type::Number) { @@ -68,7 +75,29 @@ Value::Value(const Object& value) m_value.asObject = new Object(value); } -Value Value::operator[](size_t index) +Value::Value(const std::initializer_list& values) +{ + bool isObject = std::all_of(values.begin(), values.end(), [](const Value& value) { + return value.type() == Type::Array + && value.m_value.asArray->size() == 2 + && value[0].m_type == Type::String; + }); + + if (!isObject) { + m_type = Type::Array; + m_value.asArray = new Array(values); + } + else { + m_type = Type::Object; + m_value.asObject = new Object; + + for (auto& value : values) { + m_value.asObject->emplace(std::move(*value[0].m_value.asString), + std::move(value[1])); + } + } +} + // ------------------------------------------ Value Value::parse(const std::string& input) @@ -87,15 +116,36 @@ std::string Value::dump(const uint32_t indent, const char indentCharacter) const return stringify.dump(); } +// ------------------------------------------ + +Value& Value::operator[](size_t index) +{ + assert(m_type == Type::Array); + return m_value.asArray->at(index); +} + +Value& Value::operator[](const std::string& key) +{ + // Implicit conversion to an object + if (m_type == Type::Null) { + m_type = Type::Object; + m_value.asObject = new Object; + } + + assert(m_type == Type::Object); + return m_value.asObject->at(key); +} + +const Value& Value::operator[](size_t index) const { assert(m_type == Type::Array); - return m_value.asArray->values().at(index); + return m_value.asArray->at(index); } -Value Value::operator[](const std::string& key) +const Value& Value::operator[](const std::string& key) const { assert(m_type == Type::Object); - return m_value.asObject->members().at(key); + return m_value.asObject->at(key); } // ------------------------------------------ diff --git a/src/util/json/value.h b/src/util/json/value.h index 8fa1a45..f564496 100644 --- a/src/util/json/value.h +++ b/src/util/json/value.h @@ -7,7 +7,9 @@ #ifndef JSON_VALUE_H #define JSON_VALUE_H +#include // nullptr_t #include // uint32_t +#include #include // istream, ostream #include @@ -36,20 +38,28 @@ public: Value& operator=(const Value& other); Value(bool value); + Value(int value); Value(double value); Value(const char* value); Value(const std::string& value); Value(const Array& value); Value(const Object& value); + Value(const std::initializer_list& values); // ------------------------------------------ static Value parse(const std::string& input); std::string dump(const uint32_t indent = 0, const char indentCharacter = ' ') const; + // ------------------------------------------ + // Array index operator - Value operator[](size_t index); - Value operator[](const std::string& key); + Value& operator[](size_t index); + Value& operator[](const std::string& key); + const Value& operator[](size_t index) const; + const Value& operator[](const std::string& key) const; + + // ------------------------------------------ Type type() const { return m_type; }