DigitalCurling3  1.0.0
A curling simulation system for curling AIs
polymorphic_json.hpp
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2022 UEC Takeshi Ito Laboratory
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
25 
26 #ifndef DIGITALCURLING3_JSON_POLYMORPHIC_JSON_HPP
27 #define DIGITALCURLING3_JSON_POLYMORPHIC_JSON_HPP
28 
29 #include <memory>
30 #include <unordered_map>
31 #include <string>
32 #include <typeindex>
33 #include <type_traits>
34 #include <sstream>
35 #include "nlohmann/json.hpp"
36 
38 
40 namespace detail {
41 
42 template <class BaseT>
43 using ToJsonFunc = void (*)(nlohmann::json &, BaseT const&);
44 
45 template <class BaseT>
46 using ToJsonRegistry = std::map<std::type_index, ToJsonFunc<BaseT>>;
47 
48 template <class BaseT>
49 using FromJsonFunc = std::unique_ptr<BaseT>(*)(nlohmann::json const&);
50 
51 template <class BaseT>
52 using FromJsonRegistry = std::map<std::string, FromJsonFunc<BaseT>>;
53 
54 template <class BaseT>
55 ToJsonRegistry<BaseT> & GetToJsonRegistry()
56 {
57  static ToJsonRegistry<BaseT> map;
58  return map;
59 }
60 
61 template <class BaseT>
62 FromJsonRegistry<BaseT> & GetFromJsonRegistry()
63 {
64  static FromJsonRegistry<BaseT> map;
65  return map;
66 }
67 
68 template <class BaseT, class T>
69 void ToJsonFuncTemplate(nlohmann::json & j, BaseT const& v)
70 {
71  static_assert(std::is_base_of_v<BaseT, T>);
72  j = static_cast<T const&>(v);
73 }
74 
75 template <class BaseT, class T>
76 std::unique_ptr<BaseT> FromJsonFuncTemplate(nlohmann::json const& j)
77 {
78  static_assert(std::is_base_of_v<BaseT, T>);
79  return std::make_unique<T>(j.get<T>());
80 }
81 
82 
83 template <class BaseT>
84 struct Serializer {
85 
86  static void to_json(nlohmann::json & j, BaseT const& v)
87  {
88  auto const& registry = ::digitalcurling3::polymorphic_json::detail::GetToJsonRegistry<BaseT>();
89  auto it = registry.find(typeid(v));
90  if (it != registry.end()) {
91  it->second(j, v);
92  } else {
93  std::ostringstream buf;
94  buf << "polymorphic json: type \"" << typeid(v).name() << "\" is not registered to \"" << typeid(BaseT).name() << "\"";
95  throw std::runtime_error(buf.str());
96  }
97  }
98 };
99 
100 template <class BaseT>
101 struct Serializer<std::unique_ptr<BaseT>> {
102 
103  static void to_json(nlohmann::json & j, std::unique_ptr<BaseT> const& v)
104  {
105  if (v) {
106  Serializer<BaseT>::to_json(j, *v);
107  } else {
108  j = nullptr;
109  }
110  }
111 
112  static void from_json(nlohmann::json const& j, std::unique_ptr<BaseT> & v)
113  {
114  if (j.is_null()) {
115  v = nullptr;
116  return;
117  }
118 
119  auto const name = j.at("type").get<std::string>();
120  auto const& registry = ::digitalcurling3::polymorphic_json::detail::GetFromJsonRegistry<BaseT>();
121  auto it = registry.find(name);
122  if (it != registry.end()) {
123  v = it->second(j);
124  } else {
125  std::ostringstream buf;
126  buf << "polymorphic json: type name \"" << name << "\" is not registered to \"" << typeid(BaseT).name() << "\"";
127  throw std::runtime_error(buf.str());
128  }
129  }
130 };
131 
132 } // namespace detail
134 
135 
136 
141 template <class BaseT, class T>
142 void Register(std::string_view name)
143 {
144  static_assert(std::is_base_of_v<BaseT, T>);
145  ::digitalcurling3::polymorphic_json::detail::GetToJsonRegistry<BaseT>().emplace(typeid(T), ::digitalcurling3::polymorphic_json::detail::ToJsonFuncTemplate<BaseT, T>);
146  ::digitalcurling3::polymorphic_json::detail::GetFromJsonRegistry<BaseT>().emplace(std::string(name), ::digitalcurling3::polymorphic_json::detail::FromJsonFuncTemplate<BaseT, T>);
147 }
148 
149 
150 } // namespace digitalcurling3::polymorphic_json
151 
152 #endif // DIGITALCURLING3_JSON_POLYMORPHIC_JSON_HPP
digitalcurling3::polymorphic_json
インターフェースを介したJSON変換を行うためのものを定義する名前空間
Definition: polymorphic_json.hpp:37
digitalcurling3::polymorphic_json::Register
void Register(std::string_view name)
多態性を考慮したJSON変換の登録をします
Definition: polymorphic_json.hpp:142