Riyyi
2 years ago
4 changed files with 193 additions and 65 deletions
@ -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.
|
Loading…
Reference in new issue