14#include <rapidjson/reader.h>
15#include <rapidjson/prettywriter.h>
16#include <rapidjson/istreamwrapper.h>
17#include <rapidjson/ostreamwrapper.h>
18#include <rapidjson/error/en.h>
28template <VariantType V>
29struct VariantReader :
public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, VariantReader<V>> {
30 using Ch = rapidjson::UTF8<>::Ch;
31 using SizeType = rapidjson::SizeType;
48 debug <<
"Start" << std::endl;
49 states.push(State::IN_START);
54 debug <<
"Null value encountered" << std::endl;
60 debug <<
"Int(" <<
i <<
")" << std::endl;
61 if (
states.top() == State::IN_ERROR) {
62 debug <<
"In ERROR state" << std::endl;
65 if constexpr (!std::is_same_v<int, variant_array_element_type_t<V>>) {
66 states.push(State::IN_ERROR);
69 if (
states.top() == State::IN_ARRAY ||
states.top() == State::IN_ROW) {
70 debug <<
"added to array" << std::endl;
75 states.push(State::IN_ERROR);
81 debug <<
"Uint -> Int" << std::endl;
82 return Int(
static_cast<int>(
i));
87 debug <<
"Int64 -> Int" << std::endl;
88 return Int(
static_cast<int>(
i));
93 debug <<
"Uint64 -> Int" << std::endl;
94 return Int(
static_cast<int>(
i));
99 debug <<
"Double(" << d <<
")" << std::endl;
100 if (
states.top() == State::IN_ERROR) {
101 debug <<
"In ERROR state" << std::endl;
104 if constexpr (!(std::is_same_v<float, variant_array_element_type_t<V>> || std::is_same_v<double, variant_array_element_type_t<V>>)) {
105 states.push(State::IN_ERROR);
108 if (
states.top() == State::IN_ARRAY ||
states.top() == State::IN_ROW) {
109 if constexpr (std::is_same_v<double, variant_array_element_type_t<V>>) {
110 debug <<
"added to array as double" << std::endl;
113 }
else if constexpr (std::is_same_v<float, variant_array_element_type_t<V>>) {
114 debug <<
"added to array as float" << std::endl;
119 states.push(State::IN_ERROR);
125 debug <<
"Bool(" <<
b <<
")" << std::endl;
126 if (
states.top() == State::IN_ERROR) {
127 debug <<
"In ERROR state" << std::endl;
130 if constexpr (!std::is_same_v<bool, variant_array_element_type_t<V>>) {
131 states.push(State::IN_ERROR);
134 if (
states.top() == State::IN_ARRAY) {
135 debug <<
"added to array" << std::endl;
139 states.push(State::IN_ERROR);
144 bool String(
const Ch*
str, SizeType,
bool)
146 debug <<
"String(" <<
str <<
")" << std::endl;
147 if (
states.top() == State::IN_ERROR) {
148 debug <<
"In ERROR state" << std::endl;
152 states.push(State::IN_ERROR);
155 if (
states.top() == State::IN_ARRAY ||
states.top() == State::IN_ROW) {
156 debug <<
"added to array" << std::endl;
157 if constexpr (isLabeledArray<V>()) {
158 if (currentKey == labels_rows_str) {
162 if (currentKey == labels_cols_str) {
167 if (currentKey ==
"values") {
168 if constexpr (std::is_same_v<std::string, variant_array_element_type_t<V>>) {
171 states.push(State::IN_ERROR);
177 states.push(State::IN_ERROR);
184 debug <<
"StartObject()" << std::endl;
185 if (
states.top() == State::IN_ERROR) {
186 debug <<
"In ERROR state" << std::endl;
189 if (
states.top() == State::IN_START) {
190 states.push(State::IN_DATA);
193 states.push(State::IN_ERROR);
197 bool Key(
const Ch*
str, SizeType,
bool)
199 debug <<
"Key(" <<
str <<
")" << std::endl;
200 if (
states.top() == State::IN_ERROR) {
201 debug <<
"In ERROR state" << std::endl;
205 if (
states.top() == State::IN_DATA) {
207 states.push(State::IN_KEY);
211 if (
states.top() == State::IN_KEY) {
213 if constexpr (!isLabeledArray<V>()) {
214 debug <<
"extra keys in a single-key variant" << std::endl;
215 states.push(State::IN_ERROR);
221 states.push(State::IN_ERROR);
225 bool EndObject(SizeType)
227 debug <<
"EndObject()" << std::endl;
228 if (
states.top() == State::IN_ERROR) {
229 debug <<
"In ERROR state" << std::endl;
232 if (
states.top() == State::IN_KEY) {
233 if constexpr (isArray<V>()) {
234 debug <<
"creating 1d-array variant" << std::endl;
235 result = Variant(accumulatedData);
236 }
else if constexpr (isArray2D<V>()) {
237 debug <<
"creating 2d-array variant" << std::endl;
240 }
else if constexpr (isLabeledArray<V>()) {
241 debug <<
"creating labeled array variant" << std::endl;
251 states.push(State::IN_STOP);
254 states.push(State::IN_ERROR);
260 debug <<
"StartArray()" << std::endl;
261 if (
states.top() == State::IN_ERROR) {
262 debug <<
"In ERROR state" << std::endl;
265 if (
states.top() == State::IN_KEY) {
266 states.push(State::IN_ARRAY);
268 }
else if (
states.top() == State::IN_ARRAY) {
269 if constexpr (isArray2D<V>() || isLabeledArray<V>()) {
270 states.push(State::IN_ROW);
274 states.push(State::IN_ERROR);
278 bool EndArray(SizeType elementCount)
280 debug <<
"EndArray()" << std::endl;
281 if (
states.top() == State::IN_ERROR) {
282 debug <<
"In ERROR state" << std::endl;
285 if (
states.top() == State::IN_ARRAY) {
288 if constexpr (isArray2D<V>() || isLabeledArray<V>()) {
292 }
else if (
states.top() == State::IN_ROW) {
295 if constexpr (isArray2D<V>() || isLabeledArray<V>()) {
300 states.push(State::IN_ERROR);
317template <VariantType V>
320 rapidjson::Reader reader;
321 rapidjson::IStreamWrapper isw(s);
322 VariantReader<V> vreader;
323 bool ok = reader.Parse(isw, vreader);
326 std::stringstream error;
327 error <<
"Cannot parse serialized Variant, error: " << rapidjson::GetParseError_En(reader.GetParseErrorCode()) <<
" at offset: " << reader.GetErrorOffset();
328 throw std::runtime_error(error.str());
330 return vreader.result;
333template <VariantType V>
336 if constexpr (isArray<V>() || isArray2D<V>() || isLabeledArray<V>()) {
338 rapidjson::OStreamWrapper osw(
o);
339 rapidjson::Writer<rapidjson::OStreamWrapper>
w(osw);
341 auto writeArray = [&](
auto*
values,
size_t size) {
342 using T = std::remove_pointer_t<
decltype(
values)>;
344 for (
auto i = 0u;
i <
size; ++
i) {
345 if constexpr (std::is_same_v<int, T>) {
347 }
else if constexpr (std::is_same_v<float, T> || std::is_same_v<double, T>) {
349 }
else if constexpr (std::is_same_v<bool, T>) {
351 }
else if constexpr (std::is_same_v<std::string, T>) {
358 auto writeVector = [&](
auto&& vector) {
359 return writeArray(vector.data(), vector.size());
362 auto writeArray2D = [&](
auto&& array2d) {
363 using T =
typename std::decay_t<
decltype(array2d)>::element_t;
365 for (
auto i = 0u;
i < array2d.rows; ++
i) {
367 for (
auto j = 0u;
j < array2d.cols; ++
j) {
368 if constexpr (std::is_same_v<int, T>) {
369 w.Int(array2d(
i,
j));
370 }
else if constexpr (std::is_same_v<float, T> || std::is_same_v<double, T>) {
371 w.Double(array2d(
i,
j));
372 }
else if constexpr (std::is_same_v<std::string, T>) {
373 w.String(array2d(
i,
j).c_str());
381 auto writeLabeledArray = [&](
auto&&
array) {
382 w.Key(labels_rows_str);
383 writeVector(
array.getLabelsRows());
384 w.Key(labels_cols_str);
385 writeVector(
array.getLabelsCols());
387 writeArray2D(
array.getData());
391 if constexpr (isArray<V>()) {
393 writeArray(
v.get<
type*>(),
v.size());
394 }
else if constexpr (isArray2D<V>()) {
397 }
else if constexpr (isLabeledArray<V>()) {
406template Variant VariantJSONHelpers::read<VariantType::ArrayInt>(std::istream& s);
407template Variant VariantJSONHelpers::read<VariantType::ArrayFloat>(std::istream& s);
408template Variant VariantJSONHelpers::read<VariantType::ArrayDouble>(std::istream& s);
409template Variant VariantJSONHelpers::read<VariantType::ArrayString>(std::istream& s);
410template Variant VariantJSONHelpers::read<VariantType::Array2DInt>(std::istream& s);
411template Variant VariantJSONHelpers::read<VariantType::Array2DFloat>(std::istream& s);
412template Variant VariantJSONHelpers::read<VariantType::Array2DDouble>(std::istream& s);
413template Variant VariantJSONHelpers::read<VariantType::LabeledArrayInt>(std::istream& s);
414template Variant VariantJSONHelpers::read<VariantType::LabeledArrayFloat>(std::istream& s);
415template Variant VariantJSONHelpers::read<VariantType::LabeledArrayDouble>(std::istream& s);
416template Variant VariantJSONHelpers::read<VariantType::LabeledArrayString>(std::istream& s);
422 writeVariant<VariantType::ArrayInt>(
o,
v);
425 writeVariant<VariantType::ArrayFloat>(
o,
v);
428 writeVariant<VariantType::ArrayDouble>(
o,
v);
431 throw std::runtime_error(
"Bool vectors not implemented yet");
435 writeVariant<VariantType::ArrayString>(
o,
v);
438 writeVariant<VariantType::Array2DInt>(
o,
v);
441 writeVariant<VariantType::Array2DFloat>(
o,
v);
444 writeVariant<VariantType::Array2DDouble>(
o,
v);
447 writeVariant<VariantType::LabeledArrayInt>(
o,
v);
450 writeVariant<VariantType::LabeledArrayFloat>(
o,
v);
453 writeVariant<VariantType::LabeledArrayDouble>(
o,
v);
456 writeVariant<VariantType::LabeledArrayString>(
o,
v);
459 writeVariant<VariantType::Dict>(
o,
v);
o2::monitoring::tags::Key Key
std::vector< variant_array_element_type_t< V > > accumulatedData
std::vector< std::string > labels_rows
std::vector< std::string > labels_cols
Variant for configuration parameter storage. Owns stored data.
GLboolean GLboolean GLboolean b
GLint GLint GLsizei GLint GLenum GLenum type
GLenum GLsizei GLsizei GLint * values
GLubyte GLubyte GLubyte GLubyte w
Defining PrimaryVertex explicitly as messageable.
void writeVariant(std::ostream &o, Variant const &v)
typename variant_array_element_type< V >::type variant_array_element_type_t
static Variant read(std::istream &s)
static void write(std::ostream &o, Variant const &v)
std::vector< ReadoutWindowData > rows