CppWAMP
C++11 client library for the WAMP protocol
varianttraits.hpp
1 /*------------------------------------------------------------------------------
2  Copyright Butterfly Energy Systems 2014-2015, 2022.
3  Distributed under the Boost Software License, Version 1.0.
4  http://www.boost.org/LICENSE_1_0.txt
5 ------------------------------------------------------------------------------*/
6 
7 #ifndef CPPWAMP_INTERNAL_VARIANTTRAITS_HPP
8 #define CPPWAMP_INTERNAL_VARIANTTRAITS_HPP
9 
10 #include <map>
11 #include <string>
12 #include <type_traits>
13 #include <utility>
14 #include <vector>
15 #include "../blob.hpp"
16 #include "../null.hpp"
17 #include "../traits.hpp"
18 #include "../variantdefs.hpp"
19 
20 namespace wamp
21 {
22 
23 namespace internal
24 {
25 
26 template <typename T> struct FieldTraits;
27 
28 template <typename T, typename Enable = int> struct ArgTraits;
29 
30 template <typename T> struct Access;
31 
32 //------------------------------------------------------------------------------
33 template <TypeId typeId> struct FieldTypeForId {};
34 template <> struct FieldTypeForId<TypeId::null> {using Type = Null;};
35 template <> struct FieldTypeForId<TypeId::boolean> {using Type = Bool;};
36 template <> struct FieldTypeForId<TypeId::integer> {using Type = Int;};
37 template <> struct FieldTypeForId<TypeId::uint> {using Type = UInt;};
38 template <> struct FieldTypeForId<TypeId::real> {using Type = Real;};
39 template <> struct FieldTypeForId<TypeId::string> {using Type = String;};
40 template <> struct FieldTypeForId<TypeId::blob> {using Type = Blob;};
41 template <> struct FieldTypeForId<TypeId::array> {using Type = Array;};
42 template <> struct FieldTypeForId<TypeId::object> {using Type = Object;};
43 
44 
45 //------------------------------------------------------------------------------
46 template <typename TField>
47 struct FieldTraits
48 {
49  static constexpr bool isValid = false;
50  static String typeName() {return "<unknown>";}
51 };
52 
53 template <> struct FieldTraits<Null>
54 {
55  static constexpr bool isValid = true;
56  static constexpr TypeId typeId = TypeId::null;
57  static String typeName() {return "Null";}
58 };
59 
60 template <> struct FieldTraits<Bool>
61 {
62  static constexpr bool isValid = true;
63  static constexpr TypeId typeId = TypeId::boolean;
64  static String typeName() {return "Bool";}
65 };
66 
67 template <> struct FieldTraits<Int>
68 {
69  static constexpr bool isValid = true;
70  static constexpr TypeId typeId = TypeId::integer;
71  static String typeName() {return "Int";}
72 };
73 
74 template <> struct FieldTraits<UInt>
75 {
76  static constexpr bool isValid = true;
77  static constexpr TypeId typeId = TypeId::uint;
78  static String typeName() {return "UInt";}
79 };
80 
81 template <> struct FieldTraits<Real>
82 {
83  static constexpr bool isValid = true;
84  static constexpr TypeId typeId = TypeId::real;
85  static String typeName() {return "Real";}
86 };
87 
88 template <> struct FieldTraits<String>
89 {
90  static constexpr bool isValid = true;
91  static constexpr TypeId typeId = TypeId::string;
92  static String typeName() {return "String";}
93 };
94 
95 template <> struct FieldTraits<Blob>
96 {
97  static constexpr bool isValid = true;
98  static constexpr TypeId typeId = TypeId::blob;
99  static String typeName() {return "Blob";}
100 };
101 
102 template <> struct FieldTraits<Array>
103 {
104  static constexpr bool isValid = true;
105  static constexpr TypeId typeId = TypeId::array;
106  static String typeName() {return "Array";}
107 };
108 
109 template <> struct FieldTraits<Object>
110 {
111  static constexpr bool isValid = true;
112  static constexpr TypeId typeId = TypeId::object;
113  static String typeName() {return "Object";}
114 };
115 
116 //------------------------------------------------------------------------------
117 template <typename TField, typename Enable>
118 struct ArgTraits
119 {
120  static constexpr bool isValid = false;
121  static String typeName() {return "[unknown]";}
122 };
123 
124 template <> struct ArgTraits<Null>
125 {
126  static constexpr bool isValid = true;
127  static String typeName() {return "Null";}
128  using FieldType = Null;
129 };
130 
131 template <typename TField>
132 struct ArgTraits<TField, EnableIf<isBool<TField>()>>
133 {
134  static constexpr bool isValid = true;
135  static String typeName() {return "Bool";}
136  using FieldType = Bool;
137 };
138 
139 template <typename TField>
140 struct ArgTraits<TField, EnableIf<isSignedInteger<TField>()>>
141 {
142  static constexpr bool isValid = true;
143  static String typeName() {return "[signed integer]";}
144  using FieldType = Int;
145 };
146 
147 template <typename TField>
148 struct ArgTraits<TField, EnableIf<isUnsignedInteger<TField>()>>
149 {
150  static constexpr bool isValid = true;
151  static String typeName() {return "[unsigned integer]";}
152  using FieldType = UInt;
153 };
154 
155 template <typename TField>
156 struct ArgTraits<TField, EnableIf<std::is_floating_point<TField>::value>>
157 {
158  static constexpr bool isValid = true;
159  static String typeName() {return "[floating point]";}
160  using FieldType = Real;
161 };
162 
163 template <> struct ArgTraits<String>
164 {
165  static constexpr bool isValid = true;
166  static String typeName() {return "String";}
167  using FieldType = String;
168 };
169 
170 template <> struct ArgTraits<String::value_type*>
171 {
172  static constexpr bool isValid = true;
173  static String typeName() {return "[character array]";}
174  using FieldType = String;
175 };
176 
177 template <> struct ArgTraits<const String::value_type*>
178 {
179  static constexpr bool isValid = true;
180  static String typeName() {return "[character array]";}
181  using FieldType = String;
182 };
183 
184 template <size_t N> struct ArgTraits<String::value_type[N]>
185 {
186  static constexpr bool isValid = true;
187  static String typeName() {return "[character array]";}
188  using FieldType = String;
189 };
190 
191 template <size_t N>
192 struct ArgTraits<const String::value_type[N]>
193 {
194  static constexpr bool isValid = true;
195  static String typeName() {return "[character array]";}
196  using FieldType = String;
197 };
198 
199 template <> struct ArgTraits<Blob>
200 {
201  static constexpr bool isValid = true;
202  static String typeName() {return "Blob";}
203  using FieldType = Blob;
204 };
205 
206 template <> struct ArgTraits<Array>
207 {
208  static constexpr bool isValid = true;
209  static String typeName() {return "Array";}
210  using FieldType = Array;
211 };
212 
213 template <typename TElem>
214 struct ArgTraits<std::vector<TElem>, DisableIf<isSameType<TElem,Variant>()>>
215 {
216  static constexpr bool isValid = ArgTraits<TElem>::isValid;
217  static String typeName() {return "std::vector<" +
218  ArgTraits<TElem>::typeName() + '>';}
219  using FieldType = Array;
220 };
221 
222 template <> struct ArgTraits<Object>
223 {
224  static constexpr bool isValid = true;
225  static String typeName() {return "Object";}
226  using FieldType = Object;
227 };
228 
229 template <typename TValue>
230 struct ArgTraits<std::map<String, TValue>,
231  DisableIf<isSameType<TValue, Variant>()>>
232 {
233  static constexpr bool isValid = ArgTraits<TValue>::isValid;
234  static String typeName() {return "std::map<String, "
235  + ArgTraits<TValue>::typeName() + '>';}
236  using FieldType = Object;
237 };
238 
239 
240 //------------------------------------------------------------------------------
241 template <typename TField> struct Access
242 {
243  template <typename U> static void construct(U&& value, void* field)
244  {get(field) = value;}
245 
246  static void destruct(void*) {}
247 
248  static TField& get(void* field)
249  {return *static_cast<TField*>(field);}
250 
251  static const TField& get(const void* field)
252  {return *static_cast<const TField*>(field);}
253 };
254 
255 template <> struct Access<String>
256 {
257  template <typename U> static void construct(U&& value, void* field)
258  {new (field) String(std::forward<U>(value));}
259 
260  static void destruct(void* field) {get(field).~String();}
261 
262  static String& get(void* field)
263  {return *static_cast<String*>(field);}
264 
265  static const String& get(const void* field)
266  {return *static_cast<const String*>(field);}
267 };
268 
269 template <> struct Access<Blob>
270 {
271  template <typename U> static void construct(U&& value, void* field)
272  {ptr(field) = new Blob(std::forward<U>(value));}
273 
274  static void destruct(void* field)
275  {
276  Blob*& b = ptr(field);
277  delete b;
278  b = nullptr;
279  }
280 
281  static Blob& get(void* field) {return *ptr(field);}
282 
283  static const Blob& get(const void* field)
284  {
285  const Blob* b = Access<const Blob*>::get(field);
286  return *b;
287  }
288 
289  static Blob*& ptr(void* field) {return Access<Blob*>::get(field);}
290 };
291 
292 template <> struct Access<Array>
293 {
294  template <typename U> static void construct(U&& value, void* field)
295  {ptr(field) = new Array(std::forward<U>(value));}
296 
297  static void destruct(void* field)
298  {
299  Array*& a = ptr(field);
300  delete a;
301  a = nullptr;
302  }
303 
304  static Array& get(void* field) {return *ptr(field);}
305 
306  static const Array& get(const void* field)
307  {
308  const Array* a = Access<const Array*>::get(field);
309  return *a;
310  }
311 
312  static Array*& ptr(void* field) {return Access<Array*>::get(field);}
313 };
314 
315 template <> struct Access<Object>
316 {
317  template <typename U> static void construct(U&& value, void* field)
318  {
319  ptr(field) = new Object(std::forward<U>(value));
320  }
321 
322  static void destruct(void* field)
323  {
324  Object*& o = ptr(field);
325  delete o;
326  o = nullptr;
327  }
328 
329  static Object& get(void* field) {return *ptr(field);}
330 
331  static const Object& get(const void* field)
332  {
333  const Object* o = Access<const Object*>::get(field);
334  return *o;
335  }
336 
337  static Object*& ptr(void* field) {return Access<Object*>::get(field);}
338 };
339 
340 } // namespace internal
341 
342 } // namespace wamp
343 
344 #endif // CPPWAMP_INTERNAL_VARIANTTRAITS_HPP
wamp::DisableIf
typename std::enable_if<!B, T >::type DisableIf
Metafunction used to disable overloads based on a boolean condition.
Definition: traits.hpp:43
wamp::isSignedInteger
constexpr bool isSignedInteger()
Determines if the given type is a signed integer.
Definition: traits.hpp:86
wamp::TypeId
TypeId
Integer ID used to indicate the current dynamic type of a Variant.
Definition: variantdefs.hpp:26
wamp::UInt
std::uint64_t UInt
Variant bound type for unsigned integers.
Definition: variantdefs.hpp:48
wamp::null
constexpr Null null
Constant Null object that can be assigned to, or compared with a Variant.
Definition: null.hpp:68
wamp::TypeId::array
@ array
For Variant::Array.
wamp::TypeId::string
@ string
For Variant::String.
wamp::Object
std::map< String, Variant > Object
Variant bound type for maps of variants.
Definition: variantdefs.hpp:52
wamp
Definition: anyhandler.hpp:36
wamp::isUnsignedInteger
constexpr bool isUnsignedInteger()
Determines if the given type is an unsigned integer.
Definition: traits.hpp:96
wamp::Array
std::vector< Variant > Array
Variant bound type for arrays of variants.
Definition: variantdefs.hpp:51
wamp::TypeId::uint
@ uint
For Variant::UInt.
wamp::Int
std::int64_t Int
Variant bound type for signed integers.
Definition: variantdefs.hpp:47
wamp::Bool
bool Bool
Variant bound type for boolean values.
Definition: variantdefs.hpp:46
wamp::TypeId::boolean
@ boolean
For Variant::Bool.
wamp::Real
double Real
Variant bound type for floating-point numbers.
Definition: variantdefs.hpp:49
wamp::EnableIf
typename std::enable_if< B, T >::type EnableIf
Metafunction used to enable overloads based on a boolean condition.
Definition: traits.hpp:37
wamp::TypeId::null
@ null
For Variant::Null.
wamp::TypeId::real
@ real
For Variant::Real.
wamp::isBool
constexpr bool isBool()
Determines if the given type is considered a boolean.
Definition: traits.hpp:63
wamp::TypeId::object
@ object
For Variant::Object.
wamp::String
std::string String
Variant bound type for text strings.
Definition: variantdefs.hpp:50
wamp::TypeId::integer
@ integer
For Variant::Int.
wamp::TypeId::blob
@ blob
For Variant::Blob.