rikitiki  v0.1.67
Build C++ web server modules that allow easy routing and deployment.
reflected_conversion.h
1 #include <mxcomp/reflection.h>
2 #include <tuple>
3 
4 namespace rikitiki {
5  using namespace mxcomp;
6 
7  template <typename T> struct json_value {
8  template <typename S>
9  static auto set(Json::Value& jv, T& t, const mxcomp::Field_<T, S>& field) -> decltype( jv[field.name] << field.get(t), void()) {
10  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
11  jv[field.name] << field.get(t);
12  }
13 
14  template <typename S>
15  static auto set(Json::Value& jv, T& t, const Field_<T, S>& field) -> decltype(jv[field.name] = field.get(t), void()) {
16  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
17  jv[field.name] = field.get(t);
18  }
19 
20  template <typename S>
21  static void get(Json::Value& jv, T& t, const Field_<T, S>& field){
22  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
23  jv[field.name] >> (&t)->*(field.field);
24  }
25  static void get(Json::Value& jv, T& t, const Field_<T, bool>& field){
26  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
27  field.set(t, jv[field.name].asBool());
28  }
29  static void get(Json::Value& jv, T& t, const Field_<T, double>& field){
30  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
31  field.set(t, jv[field.name].asDouble());
32  }
33  static void get(Json::Value& jv, T& t, const Field_<T, unsigned int>& field){
34  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
35  field.set(t, jv[field.name].asUInt());
36  }
37  static void get(Json::Value& jv, T& t, const Field_<T, int>& field){
38  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
39  field.set(t, jv[field.name].asInt());
40  }
41  static void get(Json::Value& jv, T& t, const Field_<T, std::string>& field){
42  if(!jv.isObject()) throw std::runtime_error("Expected an object in " + field.name);
43  field.set(t, jv[field.name].asString());
44  }
45  };
46 
47  template <typename T>
48  struct SetJsonValues {
49  Json::Value& jv; T& t;
50 
51  SetJsonValues(Json::Value& _jv, T& _t) : jv(_jv), t(_t) {}
52  template <typename S>
53  inline void operator()( const Field_<T, S>& field) {
54  try {
55  json_value<T>::set(jv, t, field);
56  } catch(std::exception& ex){
57  throw std::runtime_error("Error in setting field '" + std::string(field.name) + "': " + ex.what());
58  }
59  }
60  };
61 
62  template <typename T>
63  struct GetJsonValues {
64 
65  Json::Value& jv; T& t;
66  GetJsonValues(Json::Value& _jv, T& _t) : jv(_jv), t(_t) {}
67 
68  template <typename S>
69  inline void operator()( const Field_<T, S>& field) {
70  try {
71  json_value<T>::get(jv, t, field);
72  } catch(std::exception& ex){
73  throw std::runtime_error("Error in getting field '" + std::string(field.name) + "': " + ex.what());
74  }
75  }
76  };
77 
78  template <typename T>
79  static auto operator>>(Json::Value& jv, T& t) -> decltype(MetaClass_<T>::fields(), jv) {
80  mxcomp::tuples::iterate(GetJsonValues<T>(jv, t), MetaClass_<T>::fields() );
81  return jv;
82  }
83 
84  template <typename T>
85  static auto operator<<(Json::Value& jv, T& t) -> decltype(MetaClass_<T>::fields(), jv) {
86  mxcomp::tuples::iterate(SetJsonValues<T>(jv, t), MetaClass_<T>::fields());
87  return jv;
88  };
89 }