Project
Loading...
Searching...
No Matches
Variant.cxx
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#include "Framework/Variant.h"
14#include <cstdlib>
15#include <cstring>
16#include <iostream>
17#include <memory>
18#include <sstream>
19
20namespace o2::framework
21{
22std::ostream& operator<<(std::ostream& oss, Variant const& val)
23{
24 switch (val.type()) {
26 oss << val.get<int>();
27 break;
29 oss << (int)val.get<int8_t>();
30 break;
32 oss << (int)val.get<int16_t>();
33 break;
35 oss << (int)val.get<uint8_t>();
36 break;
38 oss << (int)val.get<uint16_t>();
39 break;
41 oss << val.get<uint32_t>();
42 break;
44 oss << val.get<uint64_t>();
45 break;
47 oss << val.get<int64_t>();
48 break;
50 oss << val.get<float>();
51 break;
53 oss << val.get<double>();
54 break;
56 oss << val.get<const char*>();
57 break;
59 oss << val.get<bool>();
60 break;
70 break;
72 break;
74 oss << "{}";
75 break;
76 default:
77 oss << "undefined";
78 break;
79 };
80 return oss;
81}
82
83std::string Variant::asString() const
84{
85 std::stringstream ss;
86 ss << *this;
87 return ss.str();
88}
89
90namespace
91{
93template <typename F>
94bool visitStoredObject(VariantType type, F&& f)
95{
96 switch (type) {
98 f.template operator()<std::vector<std::string>>();
99 return true;
101 f.template operator()<Array2D<int>>();
102 return true;
104 f.template operator()<Array2D<float>>();
105 return true;
107 f.template operator()<Array2D<double>>();
108 return true;
110 f.template operator()<LabeledArray<int>>();
111 return true;
113 f.template operator()<LabeledArray<float>>();
114 return true;
116 f.template operator()<LabeledArray<double>>();
117 return true;
119 f.template operator()<LabeledArray<std::string>>();
120 return true;
121 default:
122 return false;
123 }
124}
125
127bool holdsMallocedPointer(VariantType type)
128{
129 switch (type) {
135 return true;
136 default:
137 return false;
138 }
139}
140
141template <typename T>
142T* copyBuffer(T const* values, size_t size)
143{
144 if (values == nullptr) {
145 return nullptr;
146 }
147 return reinterpret_cast<T*>(std::memcpy(std::malloc(size * sizeof(T)), values, size * sizeof(T)));
148}
149} // namespace
150
152{
153 // Make sure that destroying a Variant created without a value is always safe
154 // by creating a default stored object upfront
155 if (!visitStoredObject(mType, [this]<typename T>() { new (&mStore) T{}; })) {
156 std::memset(&mStore, 0, sizeof(mStore));
157 switch (type) {
163 mSize = 0; // empty plain array has size 0
164 break;
165 default:
166 break;
167 }
168 }
169}
170
171void Variant::copyStore(Variant const& other)
172{
173 // Proper objects are simply copied
174 if (visitStoredObject(mType, [this, &other]<typename T>() { new (&mStore) T(*reinterpret_cast<T const*>(&other.mStore)); })) {
175 return;
176 }
177 // Manually allocated buffers have to be managed
178 switch (mType) {
179 case VariantType::String: {
180 auto const* value = *reinterpret_cast<char const* const*>(&other.mStore);
181 *reinterpret_cast<char**>(&mStore) = value != nullptr ? strdup(value) : nullptr;
182 return;
183 }
185 *reinterpret_cast<int**>(&mStore) = copyBuffer(*reinterpret_cast<int* const*>(&other.mStore), mSize);
186 return;
188 *reinterpret_cast<float**>(&mStore) = copyBuffer(*reinterpret_cast<float* const*>(&other.mStore), mSize);
189 return;
191 *reinterpret_cast<double**>(&mStore) = copyBuffer(*reinterpret_cast<double* const*>(&other.mStore), mSize);
192 return;
194 *reinterpret_cast<bool**>(&mStore) = copyBuffer(*reinterpret_cast<bool* const*>(&other.mStore), mSize);
195 return;
196 default:
197 // Trivially copyable content
198 mStore = other.mStore;
199 }
200}
201
202void Variant::moveStore(Variant& other) noexcept
203{
204 // Correct move for objects, leaving proper "moved from" state
205 if (visitStoredObject(mType, [this, &other]<typename T>() { new (&mStore) T(std::move(*reinterpret_cast<T*>(&other.mStore))); })) {
206 return;
207 }
208 mStore = other.mStore;
209 // Buffers have to change their owner
210 if (holdsMallocedPointer(mType)) {
211 *reinterpret_cast<void**>(&other.mStore) = nullptr;
212 }
213}
214
215void Variant::destroyStore() noexcept
216{
217 // destroy objects
218 if (visitStoredObject(mType, [this]<typename T>() { std::destroy_at(reinterpret_cast<T*>(&mStore)); })) {
219 return;
220 }
221 // deallocate buffers
222 if (holdsMallocedPointer(mType)) {
223 free(*reinterpret_cast<void**>(&mStore));
224 }
225}
226
227Variant::Variant(const Variant& other) : mType(other.mType), mSize(other.mSize)
228{
229 copyStore(other);
230}
231
232Variant::Variant(Variant&& other) noexcept : mType(other.mType), mSize(other.mSize)
233{
234 moveStore(other);
235}
236
238{
239 destroyStore();
240}
241
243{
244 if (this != &other) {
245 // Copy first, so that a throwing copy leaves this Variant untouched
246 Variant copy(other);
247 *this = std::move(copy);
248 }
249 return *this;
250}
251
253{
254 if (this != &other) {
255 destroyStore();
256 mType = other.mType;
257 mSize = other.mSize;
258 moveStore(other);
259 }
260 return *this;
261}
262
263std::pair<std::vector<std::string>, std::vector<std::string>> extractLabels(boost::property_tree::ptree const& tree)
264{
265 std::vector<std::string> labels_rows;
266 std::vector<std::string> labels_cols;
267 auto lrc = tree.get_child_optional(labels_rows_str);
268 if (lrc) {
269 labels_rows = basicVectorFromBranch<std::string>(lrc.value());
270 }
271 auto lcc = tree.get_child_optional(labels_cols_str);
272 if (lcc) {
273 labels_cols = basicVectorFromBranch<std::string>(lcc.value());
274 }
275 return std::make_pair(labels_rows, labels_cols);
276}
277
278} // namespace o2::framework
std::vector< std::string > labels_rows
std::vector< std::string > labels_cols
Variant for configuration parameter storage. Owns stored data.
Definition Variant.h:319
std::string asString() const
Definition Variant.cxx:83
Variant & operator=(const Variant &other)
Definition Variant.cxx:242
Variant(VariantType type=VariantType::Unknown)
Definition Variant.cxx:151
GLsizeiptr size
Definition glcorearb.h:659
GLdouble f
Definition glcorearb.h:310
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
std::ostream & operator<<(std::ostream &s, ChannelType const &type)
Stream operators so that we can use ChannelType with Boost.Test.
std::pair< std::vector< std::string >, std::vector< std::string > > extractLabels(boost::property_tree::ptree const &tree)
Definition Variant.cxx:263
size_t copyBuffer(const std::vector< uint64_t > &b64, std::vector< std::byte > &b8, uint64_t prefix=0)
Definition MoveBuffer.h:24
static void write(std::ostream &o, Variant const &v)
VectorOfTObjectPtrs other
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))