Chi-Tech
varying.h
Go to the documentation of this file.
1#ifndef CHI_DATA_TYPES_VARYING_H
2#define CHI_DATA_TYPES_VARYING_H
3
4#include "chi_data_types.h"
5
6#include <cstddef>
7#include <iostream>
8#include <vector>
9#include <memory>
10
11namespace chi_data_types
12{
14{
15private:
16 // Helpers
17 template <typename T>
19 {
20 static constexpr bool value = std::is_same_v<T, std::vector<std::byte>>;
21 };
22 template <typename T>
23 struct IsBool
24 {
25 static constexpr bool value = std::is_same_v<T, bool>;
26 };
27 template <typename T>
28 struct IsString
29 {
30 static constexpr bool value =
31 std::is_same_v<T, std::string> or std::is_same_v<T, char*>;
32 };
33 template <typename T>
34 struct IsFloat
35 {
36 static constexpr bool value = std::is_floating_point_v<T>;
37 };
38 template <typename T>
39 struct IsInteger
40 {
41 static constexpr bool value =
42 std::is_integral_v<T> and not std::is_same_v<T, bool>;
43 };
44
45 template <typename T>
46 using BoolType = typename std::enable_if_t<IsBool<T>::value, T>;
47 template <typename T>
48 using FloatType = typename std::enable_if_t<IsFloat<T>::value, T>;
49 template <typename T>
50 using IntegerType = typename std::enable_if_t<IsInteger<T>::value, T>;
51
52 template <typename T>
53 using BoolStorageType = typename std::enable_if_t<IsBool<T>::value, bool>;
54 template <typename T>
55 using FloatStorageType = typename std::enable_if_t<IsFloat<T>::value, double>;
56 template <typename T>
58 typename std::enable_if_t<IsInteger<T>::value, int64_t>;
59
60 template <typename T>
62 {
63 return value;
64 }
65
66 template <typename T>
68 {
69 return static_cast<double>(value);
70 }
71
72 template <typename T>
74 {
75 return static_cast<int64_t>(value);
76 }
77
78 /**This acts as a base class for templated child arbitrary types*/
80 {
81 public:
82 virtual std::string StringValue() const;
83 virtual bool BoolValue() const;
84 virtual int64_t IntegerValue() const;
85 virtual double FloatValue() const;
86 virtual std::vector<std::byte> BytesValue() const;
87
88 virtual std::unique_ptr<VaryingType> Clone() const = 0;
89 virtual size_t Size() const = 0;
90
91 virtual bool operator==(const VaryingType& that) const = 0;
92 virtual bool operator!=(const VaryingType& that) const = 0;
93 virtual bool operator>(const VaryingType& that) const = 0;
94 virtual bool operator<(const VaryingType& that) const = 0;
95 virtual bool operator>=(const VaryingType& that) const = 0;
96 virtual bool operator<=(const VaryingType& that) const = 0;
97
98 VaryingDataType Type() const { return type_; }
99
100 virtual ~VaryingType() = default;
101
102 protected:
104 explicit VaryingType(VaryingDataType type) : type_(type) {}
105 };
106
107 template <typename T>
109 {
110 public:
111 // clang-format off
112 explicit VaryingArbitraryType(T value)
114 IsString<T>::value ? VaryingDataType::STRING :
115 IsBool<T>::value ? VaryingDataType::BOOL :
116 IsInteger<T>::value ? VaryingDataType::INTEGER :
117 IsFloat<T>::value ? VaryingDataType::FLOAT :
119 value_(value)
120 {
121 }
122 // clang-format on
123 std::string StringValue() const override;
124 bool BoolValue() const override;
125 int64_t IntegerValue() const override;
126 double FloatValue() const override;
127
128 std::unique_ptr<VaryingType> Clone() const override
129 {
130 return std::make_unique<VaryingArbitraryType<T>>(value_);
131 }
132 size_t Size() const override { return sizeof(T); }
133
134 bool operator==(const VaryingType& that) const override
135 {
136 if (type_ != that.Type()) return false;
137
138 switch (this->Type())
139 {
141 return BytesValue() == that.BytesValue();
143 return StringValue() == that.StringValue();
145 return BoolValue() == that.BoolValue();
147 return IntegerValue() == that.IntegerValue();
149 return FloatValue() == that.FloatValue();
151 default:
152 return false;
153 }
154 }
155
156 bool operator!=(const VaryingType& that) const override
157 {
158 return not(*this == that);
159 }
160 bool operator>(const VaryingType& that) const override
161 {
162 if (type_ != that.Type()) return false;
163
164 switch (this->Type())
165 {
167 return BytesValue() > that.BytesValue();
169 return StringValue() > that.StringValue();
171 return BoolValue() > that.BoolValue();
173 return IntegerValue() > that.IntegerValue();
175 return FloatValue() > that.FloatValue();
177 default:
178 return false;
179 }
180 }
181 bool operator<(const VaryingType& that) const override
182 {
183 if (type_ != that.Type()) return false;
184
185 switch (this->Type())
186 {
188 return BytesValue() < that.BytesValue();
190 return StringValue() < that.StringValue();
192 return BoolValue() < that.BoolValue();
194 return IntegerValue() < that.IntegerValue();
196 return FloatValue() < that.FloatValue();
198 default:
199 return false;
200 }
201 }
202 bool operator>=(const VaryingType& that) const override
203 {
204 return (*this > that) or (*this == that);
205 }
206 bool operator<=(const VaryingType& that) const override
207 {
208 return (*this < that) or (*this == that);
209 }
210
211 private:
213 };
214
215 /**Type specification*/
217 std::unique_ptr<VaryingType> data_ = nullptr;
218
219private:
220 /**Checks if two VaryingDataType values match.
221 * Type A is matched against type B.*/
223 VaryingDataType type_B_required) const;
224
225private:
226public:
227 // Constructors
228 /**Generalized constructor for bool, integral- and float-types. This
229 * constructor has been specialized for std::string and
230 * std::vector<std::byte>.*/
231 template <typename T>
232 explicit Varying(const T& value)
233 {
234 constexpr bool is_supported_type =
236 static_assert(is_supported_type,
237 "Constructor called with unsupported type");
238
240 {
242 }
243 else if (IsFloat<T>::value)
244 {
246 }
247 else if (IsInteger<T>::value)
248 {
250 }
251
252 data_ = Helper(CastValue(value));
253 }
254
255 static std::unique_ptr<VaryingType> Helper(const bool& value)
256 {
257 return std::make_unique<VaryingArbitraryType<bool>>(value);
258 }
259
260 static std::unique_ptr<VaryingType> Helper(const int64_t& value)
261 {
262 return std::make_unique<VaryingArbitraryType<int64_t>>(value);
263 }
264
265 static std::unique_ptr<VaryingType> Helper(const double& value)
266 {
267 return std::make_unique<VaryingArbitraryType<double>>(value);
268 }
269
270
271
272 // template <typename T>
273 // explicit Varying(const BoolType<T>& value)
274 //{
275 // constexpr bool is_supported_type = IsBool<T>::value;
276 // static_assert(is_supported_type,
277 // "Constructor called with unsupported type");
278 //
279 // type_ = VaryingDataType::BOOL;
280 // data_ = std::make_unique<VaryingArbitraryType<BoolStorageType<T>>>(
281 // CastValue(value));
282 // }
283 //
284 // template <typename T>
285 // explicit Varying(const IntegerType<T>& value)
286 //{
287 // constexpr bool is_supported_type = IsInteger<T>::value;
288 // static_assert(is_supported_type,
289 // "Constructor called with unsupported type");
290 //
291 // type_ = VaryingDataType::INTEGER;
292 // data_ = std::make_unique<VaryingArbitraryType<IntegerStorageType<T>>>(
293 // CastValue(value));
294 // }
295 //
296 // template <typename T>
297 // explicit Varying(const FloatType<T>& value)
298 //{
299 // constexpr bool is_supported_type = IsFloat<T>::value;
300 // static_assert(is_supported_type,
301 // "Constructor called with unsupported type");
302 //
303 // type_ = VaryingDataType::FLOAT;
304 // data_ = std::make_unique<VaryingArbitraryType<FloatStorageType<T>>>(
305 // CastValue(value));
306 // }
307
308 /**Constructor for an arbitrary sequence of bytes value.*/
309 explicit Varying(const std::vector<std::byte>& value);
310 /**Constructor for a string value.*/
311 explicit Varying(const std::string& value);
312 /**Constructor for a string literal value.*/
313 // explicit Varying(const char*& value) : Varying(std::string(value)) {}
314 explicit Varying(const char* value)
315 : Varying((not value) ? std::string() : std::string(value))
316 {
317 }
318 // template <std::size_t N>
319 // explicit Varying(const char (&value)[N])
320 // : Varying(static_cast<const char*>(value))
321 //{
322 // }
323
324 /**Copy constructor.*/
325 Varying(const Varying& other);
326
327 /**Move constructor.*/
328 Varying(Varying&& other) noexcept;
329
330public:
331 // Copy assignment operator
332 /**Assignment operator. i.e., type_A = type_B*/
333 Varying& operator=(const Varying& other);
334
335 // Assignment operators
336 /**Assigns an arbitrary sequence of bytes value.*/
337 Varying& operator=(const std::vector<std::byte>& value);
338 /**Assigns a string value.*/
339 Varying& operator=(const std::string& value);
340
341 /**Assigns a bool value.*/
342 template <typename T, std::enable_if_t<IsBool<T>::value, bool> = true>
343 Varying& operator=(const T& value)
344 {
346 data_ = std::make_unique<VaryingArbitraryType<bool>>(value);
347
348 return *this;
349 }
350
351 /**Assigns an integer value.*/
352 template <typename T, std::enable_if_t<IsInteger<T>::value, bool> = true>
353 Varying& operator=(const T& value)
354 {
356 data_ = std::make_unique<VaryingArbitraryType<int64_t>>(value);
357
358 return *this;
359 }
360
361 /**Assign a floating point value.*/
362 template <typename T, std::enable_if_t<IsFloat<T>::value, bool> = true>
363 Varying& operator=(const T& value)
364 {
366 data_ = std::make_unique<VaryingArbitraryType<double>>(value);
367
368 return *this;
369 }
370
371 /**Equality operator*/
372 bool operator==(const Varying& that) const { return *data_ == *that.data_; }
373
374 /**Inequality operator*/
375 bool operator!=(const Varying& that) const { return not(*this == that); }
376
377 /**Relation operators*/
378 bool operator>(const Varying& that) const { return *data_ > *that.data_; }
379 /**Relation operators*/
380 bool operator>=(const Varying& that) const
381 {
382 return (*this > that) or (*this == that);
383 }
384 /**Relation operators*/
385 bool operator<(const Varying& that) const { return *data_ < *that.data_; }
386 /**Relation operators*/
387 bool operator<=(const Varying& that) const
388 {
389 return (*this < that) or (*this == that);
390 }
391
392 /**Returns a default value for the type required.*/
393 template <typename T>
394 static T DefaultValue()
395 {
396 return {};
397 }
398
399public:
400 // More Helpers
401 template <typename T>
403 {
404 static constexpr bool value = std::is_integral_v<T> and
405 std::is_signed_v<T> and
406 not std::is_same_v<T, bool>;
407 };
408 template <typename T>
410 {
411 static constexpr bool value = std::is_integral_v<T> and
412 std::is_unsigned_v<T> and
413 not std::is_same_v<T, bool>;
414 };
415
416 template <typename T>
417 using StringType = typename std::enable_if_t<IsString<T>::value, T>;
418 template <typename T>
420 typename std::enable_if_t<IsSignedInteger<T>::value, T>;
421 template <typename T>
423 typename std::enable_if_t<IsUnsignedInteger<T>::value, T>;
424
425 /**Returns values of type bool if able.*/
426 template <typename T>
428 {
430
431 return data_->BoolValue();
432 }
433
434 /**Returns floating point values if able.*/
435 template <typename T>
437 {
439
440 const double value = data_->FloatValue();
441
442 return static_cast<T>(value);
443 }
444
445 /**Returns a string if able.*/
446 template <typename T>
448 {
450
451 return data_->StringValue();
452 }
453
454 /**Returns a signed integer if able.*/
455 template <typename T>
457 {
459
460 const int64_t value = data_->IntegerValue();
461
462 return static_cast<T>(value);
463 }
464
465 /**Returns an unsigned integer if able.*/
466 template <typename T>
468 {
470
471 const int64_t value = data_->IntegerValue();
472
473 if (value < 0)
474 throw std::logic_error(std::string(__PRETTY_FUNCTION__) +
475 ": Attempt to cast negative number to unsigned.");
476
477 return static_cast<T>(value);
478 }
479
480 /**Returns the string value if valid. Otherwise throws std::logic_error.*/
481 std::string StringValue() const;
482 /**Returns the bool value if valid. Otherwise throws std::logic_error.*/
483 bool BoolValue() const;
484 /**Returns the integer value if valid. Otherwise throws std::logic_error.*/
485 int64_t IntegerValue() const;
486 /**Returns the float value if valid. Otherwise throws std::logic_error.*/
487 double FloatValue() const;
488
489 /**Returns the raw byte size associated with the type.*/
490 size_t ByteSize() const;
491
492public:
493 /**Returns the current-type of the variable.*/
494 VaryingDataType Type() const { return type_; }
495 /**Returns the string type name of the type.*/
496 std::string TypeName() const { return VaryingDataTypeStringName(type_); }
497
498 /**Returns a string value for the value.*/
499 std::string PrintStr(bool with_type = true) const;
500
501public:
502 ~Varying() = default;
503}; // class Varying
504
505} // namespace chi_data_types
506
507/**Stream operator*/
508std::ostream& operator<<(std::ostream& outstr,
509 const chi_data_types::Varying& value);
510
511#endif // CHI_DATA_TYPES_VARYING_H
bool operator<(const VaryingType &that) const override
Definition: varying.h:181
bool operator>=(const VaryingType &that) const override
Definition: varying.h:202
bool operator!=(const VaryingType &that) const override
Definition: varying.h:156
bool operator>(const VaryingType &that) const override
Definition: varying.h:160
bool operator==(const VaryingType &that) const override
Definition: varying.h:134
bool operator<=(const VaryingType &that) const override
Definition: varying.h:206
std::unique_ptr< VaryingType > Clone() const override
Definition: varying.h:128
std::string StringValue() const override
virtual bool operator==(const VaryingType &that) const =0
virtual double FloatValue() const
Definition: varying.cc:46
virtual std::unique_ptr< VaryingType > Clone() const =0
VaryingDataType Type() const
Definition: varying.h:98
VaryingType(VaryingDataType type)
Definition: varying.h:104
virtual int64_t IntegerValue() const
Definition: varying.cc:42
virtual bool operator!=(const VaryingType &that) const =0
virtual bool operator>(const VaryingType &that) const =0
virtual std::vector< std::byte > BytesValue() const
Definition: varying.cc:50
virtual bool operator<(const VaryingType &that) const =0
virtual std::string StringValue() const
Definition: varying.cc:34
virtual size_t Size() const =0
virtual bool operator<=(const VaryingType &that) const =0
virtual bool operator>=(const VaryingType &that) const =0
virtual bool BoolValue() const
Definition: varying.cc:38
VaryingDataType type_
Definition: varying.h:216
BoolStorageType< T > CastValue(const T &value)
Definition: varying.h:61
std::string PrintStr(bool with_type=true) const
Definition: varying.cc:285
typename std::enable_if_t< IsString< T >::value, T > StringType
Definition: varying.h:417
typename std::enable_if_t< IsInteger< T >::value, int64_t > IntegerStorageType
Definition: varying.h:58
bool operator<(const Varying &that) const
Definition: varying.h:385
UnsignedIntegerType< T > GetValue() const
Definition: varying.h:467
static std::unique_ptr< VaryingType > Helper(const double &value)
Definition: varying.h:265
typename std::enable_if_t< IsFloat< T >::value, double > FloatStorageType
Definition: varying.h:55
static std::unique_ptr< VaryingType > Helper(const int64_t &value)
Definition: varying.h:260
typename std::enable_if_t< IsInteger< T >::value, T > IntegerType
Definition: varying.h:50
Varying & operator=(const T &value)
Definition: varying.h:343
VaryingDataType Type() const
Definition: varying.h:494
bool operator>=(const Varying &that) const
Definition: varying.h:380
typename std::enable_if_t< IsFloat< T >::value, T > FloatType
Definition: varying.h:48
typename std::enable_if_t< IsUnsignedInteger< T >::value, T > UnsignedIntegerType
Definition: varying.h:423
bool operator>(const Varying &that) const
Definition: varying.h:378
FloatType< T > GetValue() const
Definition: varying.h:436
IntegerStorageType< T > CastValue(const T &value)
Definition: varying.h:73
typename std::enable_if_t< IsBool< T >::value, bool > BoolStorageType
Definition: varying.h:53
bool operator==(const Varying &that) const
Definition: varying.h:372
typename std::enable_if_t< IsSignedInteger< T >::value, T > SignedIntegerType
Definition: varying.h:420
double FloatValue() const
Definition: varying.cc:272
std::string StringValue() const
Definition: varying.cc:248
Varying & operator=(const Varying &other)
Definition: varying.cc:215
static std::unique_ptr< VaryingType > Helper(const bool &value)
Definition: varying.h:255
StringType< T > GetValue() const
Definition: varying.h:447
int64_t IntegerValue() const
Definition: varying.cc:264
BoolType< T > GetValue() const
Definition: varying.h:427
static T DefaultValue()
Definition: varying.h:394
bool operator<=(const Varying &that) const
Definition: varying.h:387
void CheckTypeMatch(VaryingDataType type_A, VaryingDataType type_B_required) const
Definition: varying.cc:171
std::unique_ptr< VaryingType > data_
Definition: varying.h:217
SignedIntegerType< T > GetValue() const
Definition: varying.h:456
bool operator!=(const Varying &that) const
Definition: varying.h:375
size_t ByteSize() const
Definition: varying.cc:281
Varying(const T &value)
Definition: varying.h:232
typename std::enable_if_t< IsBool< T >::value, T > BoolType
Definition: varying.h:46
bool BoolValue() const
Definition: varying.cc:256
FloatStorageType< T > CastValue(const T &value)
Definition: varying.h:67
std::string TypeName() const
Definition: varying.h:496
Varying(const char *value)
Definition: varying.h:314
@ INTEGER
Datatype mapping to int64_t.
@ STRING
Datatype mapping to std::string.
@ VOID
Basically undefined or null.
@ BOOL
Datatype mapping to bool.
@ ARBITRARY_BYTES
Basic sequence of bytes.
@ FLOAT
Datatype mapping to double.
std::string VaryingDataTypeStringName(VaryingDataType type)
Definition: varying.cc:10
static constexpr bool value
Definition: varying.h:25
static constexpr bool value
Definition: varying.h:20
static constexpr bool value
Definition: varying.h:36
static constexpr bool value
Definition: varying.h:41
static constexpr bool value
Definition: varying.h:30
std::ostream & operator<<(std::ostream &outstr, const chi_data_types::Varying &value)
Definition: varying.cc:303