Browse Source

Util: Add get<T>() functionality with customization points to Value

master
Riyyi 2 years ago
parent
commit
0c972f420c
  1. 118
      src/util/json/fromjson.h
  2. 3
      src/util/json/value.cpp
  3. 18
      src/util/json/value.h

118
src/util/json/fromjson.h

@ -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.

3
src/util/json/value.cpp

@ -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

18
src/util/json/value.h

@ -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;

Loading…
Cancel
Save