Util: Add flexible constructor toJson() to Json::Value
This commit is contained in:
@@ -31,6 +31,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void emplace_back(Value value);
|
void emplace_back(Value value);
|
||||||
|
void reserve(size_t size) { m_values.reserve(size); }
|
||||||
|
|
||||||
Value& operator[](size_t index);
|
Value& operator[](size_t index);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSON_TO_JSON_H
|
||||||
|
#define JSON_TO_JSON_H
|
||||||
|
|
||||||
|
#include <cassert> // assert
|
||||||
|
#include <cstddef> // nullptr_t
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility> // forward
|
||||||
|
|
||||||
|
#include "util/json/array.h"
|
||||||
|
#include "util/json/conversion.h"
|
||||||
|
#include "util/json/object.h"
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
|
struct jsonConstructor {
|
||||||
|
template<typename Json>
|
||||||
|
static void construct(Json& json, bool boolean)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Bool;
|
||||||
|
json.m_value.asBool = boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
static void construct(Json& json, int number)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Number;
|
||||||
|
json.m_value.asDouble = (double)number;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
static void construct(Json& json, double number)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Number;
|
||||||
|
json.m_value.asDouble = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
static void construct(Json& json, const char* string)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::String;
|
||||||
|
json.m_value.asString = new std::string(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
static void construct(Json& json, const std::string& string)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::String;
|
||||||
|
json.m_value.asString = new std::string(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
static void construct(Json& json, const Array& array)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Array;
|
||||||
|
json.m_value.asArray = new Array(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json, typename T>
|
||||||
|
static void construct(Json& json, const std::vector<T>& array)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Array;
|
||||||
|
json.m_value.asArray = new Array;
|
||||||
|
json.m_value.asArray->reserve(array.size());
|
||||||
|
for (const T& value : array) {
|
||||||
|
json.m_value.asArray->emplace_back(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
static void construct(Json& json, const Object& object)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Object;
|
||||||
|
json.m_value.asObject = new Object(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json, typename T>
|
||||||
|
static void construct(Json& json, const std::map<std::string, T>& object)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Object;
|
||||||
|
json.m_value.asObject = new Object;
|
||||||
|
for (const auto& [name, value] : object) {
|
||||||
|
json.m_value.asObject->emplace(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json, typename T>
|
||||||
|
static void construct(Json& json, const std::unordered_map<std::string, T>& object)
|
||||||
|
{
|
||||||
|
json.clear();
|
||||||
|
json.m_type = Json::Type::Object;
|
||||||
|
json.m_value.asObject = new Object;
|
||||||
|
for (const auto& [name, value] : object) {
|
||||||
|
json.m_value.asObject->emplace(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Json, typename T>
|
||||||
|
void toJson(Json& json, const T& value)
|
||||||
|
{
|
||||||
|
jsonConstructor::construct(json, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct toJsonFunction {
|
||||||
|
template<typename Json, typename T>
|
||||||
|
auto operator()(Json& json, T&& value) const
|
||||||
|
{
|
||||||
|
return toJson(json, std::forward<T>(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Detail
|
||||||
|
|
||||||
|
// Anonymous namespace prevents multiple definition of the reference
|
||||||
|
namespace {
|
||||||
|
// Function object
|
||||||
|
constexpr const auto& toJson = Detail::staticConst<Detail::toJsonFunction>; // NOLINT (misc-definitions-in-headers)
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#endif // JSON_TO_JSON_H
|
||||||
|
|
||||||
|
// Customization Points
|
||||||
|
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
||||||
|
|
||||||
|
// Json::fromJson is a function object, the type of which is
|
||||||
|
// Json::Detail::fromJsonFunction. In the Json::Detail namespace are the
|
||||||
|
// fromJson free functions. The function call operator of fromJsonFunction makes
|
||||||
|
// an unqualified call to fromJson which, since it shares the Detail namespace
|
||||||
|
// with the fromJson free functions, will consider those in addition to any
|
||||||
|
// overloads that are found by argument-dependent lookup.
|
||||||
|
|
||||||
|
// Variable templates are linked externally, therefor every translation unit
|
||||||
|
// will see the same address for Detail::staticConst<Detail::fromJsonFunction>.
|
||||||
|
// Since Json::fromJson is a reference to the variable template, it too will
|
||||||
|
// have the same address in all translation units.
|
||||||
+19
-54
@@ -19,19 +19,9 @@
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
Value::Value(const Value& other)
|
Value::Value(std::nullptr_t)
|
||||||
|
: Value(Type::Null)
|
||||||
{
|
{
|
||||||
copyFrom(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value& Value::operator=(const Value& other)
|
|
||||||
{
|
|
||||||
if (this != &other) {
|
|
||||||
clear();
|
|
||||||
copyFrom(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Value(Type type)
|
Value::Value(Type type)
|
||||||
@@ -40,48 +30,6 @@ Value::Value(Type type)
|
|||||||
create();
|
create();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Value(bool value)
|
|
||||||
: m_type(Type::Bool)
|
|
||||||
{
|
|
||||||
m_value.asBool = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value(int value)
|
|
||||||
: m_type(Type::Number)
|
|
||||||
{
|
|
||||||
m_value.asDouble = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value(double value)
|
|
||||||
: m_type(Type::Number)
|
|
||||||
{
|
|
||||||
m_value.asDouble = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value(const char* value)
|
|
||||||
: m_type(Type::String)
|
|
||||||
{
|
|
||||||
m_value.asString = new std::string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value(const std::string& value)
|
|
||||||
: m_type(Type::String)
|
|
||||||
{
|
|
||||||
m_value.asString = new std::string(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value(const Array& value)
|
|
||||||
: m_type(Type::Array)
|
|
||||||
{
|
|
||||||
m_value.asArray = new Array(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value(const Object& value)
|
|
||||||
: m_type(Type::Object)
|
|
||||||
{
|
|
||||||
m_value.asObject = new Object(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value(const std::initializer_list<Value>& values)
|
Value::Value(const std::initializer_list<Value>& values)
|
||||||
{
|
{
|
||||||
bool isObject = std::all_of(values.begin(), values.end(), [](const Value& value) {
|
bool isObject = std::all_of(values.begin(), values.end(), [](const Value& value) {
|
||||||
@@ -105,6 +53,23 @@ Value::Value(const std::initializer_list<Value>& values)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy constructor
|
||||||
|
Value::Value(const Value& other)
|
||||||
|
{
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignment operator
|
||||||
|
Value& Value::operator=(const Value& other)
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
clear();
|
||||||
|
copyFrom(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
|
|
||||||
Value Value::parse(const std::string& input)
|
Value Value::parse(const std::string& input)
|
||||||
|
|||||||
+17
-11
@@ -12,8 +12,10 @@
|
|||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <iostream> // istream, ostream
|
#include <iostream> // istream, ostream
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility> // forward
|
||||||
|
|
||||||
#include "util/json/fromjson.h"
|
#include "util/json/fromjson.h"
|
||||||
|
#include "util/json/tojson.h"
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
@@ -21,6 +23,9 @@ class Array;
|
|||||||
class Object;
|
class Object;
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
|
private:
|
||||||
|
friend Detail::jsonConstructor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Null, // null (case sensitive!)
|
Null, // null (case sensitive!)
|
||||||
@@ -31,24 +36,25 @@ public:
|
|||||||
Object, // {}
|
Object, // {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Value(std::nullptr_t = nullptr) {}
|
// Constructors
|
||||||
|
Value(std::nullptr_t = nullptr);
|
||||||
|
Value(Type type);
|
||||||
|
Value(const std::initializer_list<Value>& values);
|
||||||
|
template<typename T>
|
||||||
|
Value(T value)
|
||||||
|
{
|
||||||
|
toJson(*this, std::forward<T>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
virtual ~Value() { clear(); }
|
virtual ~Value() { clear(); }
|
||||||
|
|
||||||
// Copy constructor
|
// Copy constructor
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
|
|
||||||
// Assignment operator
|
// Assignment operator
|
||||||
Value& operator=(const Value& other);
|
Value& operator=(const Value& other);
|
||||||
|
|
||||||
Value(Type type);
|
|
||||||
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<Value>& values);
|
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
|
||||||
static Value parse(const std::string& input);
|
static Value parse(const std::string& input);
|
||||||
|
|||||||
Reference in New Issue
Block a user