Util: Add get<T>() functionality with customization points to Value
This commit is contained in:
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSON_FROM_JSON_H
|
||||||
|
#define JSON_FROM_JSON_H
|
||||||
|
|
||||||
|
#include <algorithm> // transform
|
||||||
|
#include <cassert> // assert
|
||||||
|
#include <cstddef> // nullptr_t
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "util/json/array.h"
|
||||||
|
#include "util/json/object.h"
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
|
// Required for containers with Json::Value type
|
||||||
|
template<typename Json>
|
||||||
|
void fromJson(const Json& json, Json& value)
|
||||||
|
{
|
||||||
|
value = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
void fromJson(const Json& json, std::nullptr_t& null)
|
||||||
|
{
|
||||||
|
assert(json.type() == Json::Type::Null);
|
||||||
|
null = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
void fromJson(const Json& json, bool& boolean)
|
||||||
|
{
|
||||||
|
assert(json.type() == Json::Type::Bool);
|
||||||
|
boolean = json.asBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
void fromJson(const Json& json, int& number)
|
||||||
|
{
|
||||||
|
assert(json.type() == Json::Type::Number);
|
||||||
|
number = (int)json.asDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
void fromJson(const Json& json, double& number)
|
||||||
|
{
|
||||||
|
assert(json.type() == Json::Type::Number);
|
||||||
|
number = json.asDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json>
|
||||||
|
void fromJson(const Json& json, std::string& string)
|
||||||
|
{
|
||||||
|
assert(json.type() == Json::Type::String);
|
||||||
|
string = json.asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Json, typename T>
|
||||||
|
void fromJson(const Json& json, std::vector<T>& array)
|
||||||
|
{
|
||||||
|
assert(json.type() == Json::Type::Array);
|
||||||
|
array.resize(json.size());
|
||||||
|
std::transform(
|
||||||
|
json.asArray().values().begin(),
|
||||||
|
json.asArray().values().end(),
|
||||||
|
array.begin(),
|
||||||
|
[](const Json& json) {
|
||||||
|
return json.template get<T>(); // (missing-dependent-template-keyword)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fromJsonFunction {
|
||||||
|
template<typename Json, typename T>
|
||||||
|
auto operator()(const Json& json, T&& value) const
|
||||||
|
{
|
||||||
|
return fromJson(json, std::forward<T>(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Avoid ODR (One Definition Rule) violations
|
||||||
|
template<typename T>
|
||||||
|
constexpr T staticConst {};
|
||||||
|
|
||||||
|
} // namespace Detail
|
||||||
|
|
||||||
|
// Anonymous namespace prevents multiple definition of the reference
|
||||||
|
namespace {
|
||||||
|
// Function object
|
||||||
|
constexpr const auto& fromJson = Detail::staticConst<Detail::fromJsonFunction>; // NOLINT (misc-definitions-in-headers)
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
} // namespace Json
|
||||||
|
|
||||||
|
#endif // JSON_FROM_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.
|
||||||
@@ -7,8 +7,7 @@
|
|||||||
#include <algorithm> // all_of
|
#include <algorithm> // all_of
|
||||||
#include <cassert> // assert
|
#include <cassert> // assert
|
||||||
#include <cstdint> // uint32_t
|
#include <cstdint> // uint32_t
|
||||||
#include <iostream>
|
#include <iostream> // istream, ostream
|
||||||
#include <memory> // make_shared, shared_ptr
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include <iostream> // istream, ostream
|
#include <iostream> // istream, ostream
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "util/json/fromjson.h"
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
class Array;
|
class Array;
|
||||||
@@ -73,6 +75,22 @@ public:
|
|||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T get() const
|
||||||
|
{
|
||||||
|
T type;
|
||||||
|
fromJson(*this, type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void getTo(T& type) const
|
||||||
|
{
|
||||||
|
fromJson(*this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------
|
||||||
|
|
||||||
Type type() const { return m_type; }
|
Type type() const { return m_type; }
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user