Project
Loading...
Searching...
No Matches
Variant.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#ifndef FRAMEWORK_VARIANT_H
12#define FRAMEWORK_VARIANT_H
13
15#include "Framework/Array2D.h"
16#include "Framework/Traits.h"
17#include <type_traits>
18#include <cstring>
19#include <cstdint>
20#include <cstdlib>
21#include <iosfwd>
22#include <initializer_list>
23#include <string_view>
24#include <vector>
25#include <string>
26
27namespace o2::framework
28{
29
30// Do NOT insert entries in this enum, only append at the end (before "Empty"). Hyperloop depends on the order.
31enum class VariantType : int { Int = 0,
32 Int64,
33 Float,
34 Double,
35 String,
36 Bool,
45 LabeledArrayInt, // 2D array
46 LabeledArrayFloat, // 2D array
47 LabeledArrayDouble, // 2D array
48 UInt8,
49 UInt16,
50 UInt32,
51 UInt64,
52 Int8,
53 Int16,
54 LabeledArrayString, // 2D array
55 Empty,
56 Dict,
57 Unknown };
58
59template <VariantType V>
60constexpr auto isArray()
61{
62 return (V == VariantType::ArrayBool ||
67}
68
69template <VariantType V>
70constexpr auto isArray2D()
71{
72 return (V == VariantType::Array2DInt ||
75}
76
77template <VariantType V>
78constexpr auto isLabeledArrayString()
79{
81}
82
83template <VariantType V>
91
92template <VariantType V>
93constexpr auto isSimpleVariant()
94{
95 return (V == VariantType::Int) ||
96 (V == VariantType::Int8) ||
97 (V == VariantType::Int16) ||
98 (V == VariantType::Int64) ||
99 (V == VariantType::UInt8) ||
100 (V == VariantType::UInt16) ||
101 (V == VariantType::UInt32) ||
102 (V == VariantType::UInt64) ||
103 (V == VariantType::Float) ||
104 (V == VariantType::Double) ||
105 (V == VariantType::Bool);
106}
107
108template <typename T>
109struct variant_trait : std::integral_constant<VariantType, VariantType::Unknown> {
110};
111
112#define DECLARE_VARIANT_TRAIT(_Type1_, _Type2_) \
113 template <> \
114 struct variant_trait<_Type1_> : std::integral_constant<VariantType, VariantType::_Type2_> { \
115 };
116
125DECLARE_VARIANT_TRAIT(unsigned long int, UInt64);
126DECLARE_VARIANT_TRAIT(unsigned long long int, UInt64);
127
131
134DECLARE_VARIANT_TRAIT(char* const, String);
135DECLARE_VARIANT_TRAIT(const char* const, String);
136DECLARE_VARIANT_TRAIT(std::string_view, String);
138
144
147DECLARE_VARIANT_TRAIT(std::vector<double>, ArrayDouble);
149DECLARE_VARIANT_TRAIT(std::vector<std::string>, ArrayString);
150
154
159
160template <typename T>
162 constexpr static char symbol = 'u';
163};
164
165template <>
167 constexpr static char symbol = 'i';
168};
169
170template <>
171struct variant_array_symbol<float> {
172 constexpr static char symbol = 'f';
173};
174
175template <>
176struct variant_array_symbol<double> {
177 constexpr static char symbol = 'd';
178};
179
180template <>
182 constexpr static char symbol = 'b';
183};
184
185template <>
187 constexpr static char symbol = 's';
188};
189
190template <typename T>
192
193template <VariantType type>
195};
196
197#define DECLARE_VARIANT_TYPE(_Type1_, _Type2_) \
198 template <> \
199 struct variant_type<VariantType::_Type2_> { \
200 using type = _Type1_; \
201 };
202
215
221
225
230
231template <VariantType type>
234
235#define DECLARE_VARIANT_ARRAY_ELEMENT_TYPE(_Type1_, _Type2_) \
236 template <> \
237 struct variant_array_element_type<VariantType::_Type2_> { \
238 using type = _Type1_; \
239 };
240
249
254
255template <VariantType V>
257
258template <typename T>
260 static void set(void* store, T value)
261 {
262 new (reinterpret_cast<T*>(store)) T{};
263 *(reinterpret_cast<T*>(store)) = value;
264 }
265 static void set(void* store, std::remove_pointer_t<T> const* values, size_t size)
266 {
267 *reinterpret_cast<T*>(store) = reinterpret_cast<T>(std::memcpy(std::malloc(size * sizeof(std::remove_pointer_t<T>)), reinterpret_cast<void const*>(values), size * sizeof(std::remove_pointer_t<T>)));
268 }
269
270 static T get(const void* store) { return *(reinterpret_cast<const T*>(store)); }
271};
272
273template <>
274struct variant_helper<std::vector<std::string>> {
275 // Allocates a new store and copies into it.
276 static void set(void* store, std::vector<std::string> value)
277 {
278 auto ptr = reinterpret_cast<std::vector<std::string>*>(store);
279 new (ptr) std::vector<std::string>{value};
280 }
281
282 static std::vector<std::string> const& get(const void* store) { return *(reinterpret_cast<std::vector<std::string> const*>(store)); }
283};
284
285template <>
287 static void set(void* store, std::string* values, size_t size)
288 {
289 auto ptr = reinterpret_cast<std::vector<std::string>*>(store);
290 new (ptr) std::vector<std::string>{values, values + size};
291 }
292
293 static std::string const* get(const void* store) { return (*(reinterpret_cast<std::vector<std::string> const*>(store))).data(); }
294};
295
296template <>
297struct variant_helper<const char*> {
298 static const char* get(const void* store) { return *reinterpret_cast<const char* const*>(store); }
299
300 static void set(void* store, const char* value) { *reinterpret_cast<char**>(store) = strdup(value); }
301};
302
303template <>
304struct variant_helper<std::string_view> {
305 static std::string_view get(const void* store) { return std::string_view(*reinterpret_cast<const char* const*>(store)); }
306
307 static void set(void* store, std::string_view value) { *reinterpret_cast<char**>(store) = strdup(value.data()); }
308};
309
310template <>
312 static std::string get(const void* store) { return std::string(*reinterpret_cast<const char* const*>(store)); }
313
314 static void set(void* store, std::string value) { *reinterpret_cast<char**>(store) = strdup(value.data()); }
315};
316
319{
320 public:
322
323 template <typename T>
324 requires(!is_specialization_v<T, std::vector>)
325 Variant(T value) : mType{variant_trait_v<T>}
326 {
327 variant_helper<decltype(value)>::set(&mStore, value);
328 }
329
330 template <typename T>
331 Variant(T values, size_t size) : mType{variant_trait_v<T>}, mSize{size}
332 {
333 variant_helper<T>::set(&mStore, values, mSize);
334 }
335
336 // A Variant owns what it stores: the content of vectors is copied
337 template <typename T>
338 Variant(std::vector<T> const& values) : mType{variant_trait_v<T*>}, mSize{values.size()}
339 {
340 variant_helper<T*>::set(&mStore, values.data(), mSize);
341 }
342
343 Variant(std::vector<std::string> const& values) : mType{VariantType::ArrayString}, mSize{values.size()}
344 {
346 }
347
348 // Prevent constructing from a temporary vector to avoid double allocation
349 template <typename T>
350 Variant(std::vector<T>&&) = delete;
351
352 template <typename T>
353 Variant(std::initializer_list<T>)
354 {
355 static_assert(sizeof(T) == 0,
356 "brace-enclosed initializer list forbidden for Variant"
357 "\n did you accidentally put braces around the default value?");
358 }
359
360 Variant(const Variant& other);
361 Variant(Variant&& other) noexcept;
362 ~Variant();
364 Variant& operator=(Variant&& other) noexcept;
365 // Assignment from a temporary vector has to be allowed because it is used, but copies
366 // to make sure Variant owns its content
367 template <typename T>
368 Variant& operator=(std::vector<T>&& other) // not noexcept because it allocates
369 {
370 *this = Variant(other);
371 return *this;
372 }
373
374 template <typename T>
375 T get() const
376 {
377 if (mType != variant_trait_v<T>) {
378 throw runtime_error_f("Variant::get: Mismatch between types %d %d.", mType, variant_trait_v<T>);
379 }
380 return variant_helper<T>::get(&mStore);
381 }
382
383 template <typename T>
384 [[nodiscard]] std::string const* get() const
385 requires(std::same_as<std::string*, T>)
386 {
387 if (mType != VariantType::ArrayString) {
388 throw runtime_error_f("Variant::get: Mismatch between types %d %d.", mType, VariantType::ArrayString);
389 }
390 return variant_helper<T>::get(&mStore);
391 }
392
393 // The setters replace the current content, releasing it first.
394 template <typename T>
395 void set(T value)
396 {
397 *this = Variant(value);
398 }
399
400 template <typename T>
401 void set(T value, size_t size)
402 {
403 *this = Variant(value, size);
404 }
405
406 template <typename T>
407 void set(std::vector<T>& values)
408 requires(std::is_pod_v<T> || std::is_same_v<T, std::string>)
409 {
410 *this = Variant(values);
411 }
412
413 [[nodiscard]] VariantType type() const { return mType; }
414 [[nodiscard]] size_t size() const { return mSize; }
415 [[nodiscard]] std::string asString() const;
416
417 private:
418 friend std::ostream& operator<<(std::ostream& oss, Variant const& val);
419 // Helpers to manage the store depending on the actual content
420 void copyStore(Variant const& other);
421 void moveStore(Variant& other) noexcept;
422 void destroyStore() noexcept;
423 using storage_t = std::aligned_union<8, int, int8_t, int16_t, int64_t,
424 uint8_t, uint16_t, uint32_t, uint64_t,
425 const char*, float, double, bool,
426 int*, float*, double*, bool*, std::string*,
427 Array2D<int>, Array2D<float>, Array2D<double>, Array2D<std::string>,
428 LabeledArray<int>, LabeledArray<float>, LabeledArray<double>, LabeledArray<std::string>>::type;
429 storage_t mStore;
431 size_t mSize = 1;
432};
433
435
436} // namespace o2::framework
437
438#endif
TBranch * ptr
#define DECLARE_VARIANT_TYPE(_Type1_, _Type2_)
Definition Variant.h:197
#define DECLARE_VARIANT_TRAIT(_Type1_, _Type2_)
Definition Variant.h:112
#define DECLARE_VARIANT_ARRAY_ELEMENT_TYPE(_Type1_, _Type2_)
Definition Variant.h:235
Variant for configuration parameter storage. Owns stored data.
Definition Variant.h:319
Variant(T values, size_t size)
Definition Variant.h:331
void set(std::vector< T > &values)
Definition Variant.h:407
std::string asString() const
Definition Variant.cxx:83
Variant(std::vector< std::string > const &values)
Definition Variant.h:343
Variant & operator=(std::vector< T > &&other)
Definition Variant.h:368
Variant(std::vector< T > const &values)
Definition Variant.h:338
Variant(std::vector< T > &&)=delete
void set(T value)
Definition Variant.h:395
Variant & operator=(const Variant &other)
Definition Variant.cxx:242
friend std::ostream & operator<<(std::ostream &oss, Variant const &val)
Definition Variant.cxx:22
void set(T value, size_t size)
Definition Variant.h:401
Variant(std::initializer_list< T >)
Definition Variant.h:353
size_t size() const
Definition Variant.h:414
VariantType type() const
Definition Variant.h:413
std::string const * get() const
Definition Variant.h:384
GLsizei const GLchar *const * string
Definition glcorearb.h:809
GLsizeiptr size
Definition glcorearb.h:659
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum GLsizei GLsizei GLint * values
Definition glcorearb.h:1576
GLuint GLfloat * val
Definition glcorearb.h:1582
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
constexpr auto isArray()
Definition Variant.h:60
constexpr auto isSimpleVariant()
Definition Variant.h:93
constexpr auto isLabeledArrayString()
Definition Variant.h:78
constexpr auto isLabeledArray()
Definition Variant.h:84
constexpr auto isArray2D()
Definition Variant.h:70
typename variant_array_element_type< V >::type variant_array_element_type_t
Definition Variant.h:256
constexpr VariantType variant_trait_v
Definition Variant.h:191
RuntimeErrorRef runtime_error_f(const char *,...)
Variant emptyDict()
Definition Variant.h:434
static constexpr char symbol
Definition Variant.h:162
static const char * get(const void *store)
Definition Variant.h:298
static void set(void *store, const char *value)
Definition Variant.h:300
static void set(void *store, std::string value)
Definition Variant.h:314
static std::string get(const void *store)
Definition Variant.h:312
static std::string const * get(const void *store)
Definition Variant.h:293
static void set(void *store, std::string *values, size_t size)
Definition Variant.h:287
static void set(void *store, std::string_view value)
Definition Variant.h:307
static std::string_view get(const void *store)
Definition Variant.h:305
static std::vector< std::string > const & get(const void *store)
Definition Variant.h:282
static void set(void *store, std::vector< std::string > value)
Definition Variant.h:276
static T get(const void *store)
Definition Variant.h:270
static void set(void *store, std::remove_pointer_t< T > const *values, size_t size)
Definition Variant.h:265
static void set(void *store, T value)
Definition Variant.h:260
VectorOfTObjectPtrs other