/**
* @file common/event/Value.hpp
* @author The ARTIS Development Team
* See the AUTHORS or Authors.txt file
*/
/*
* ARTIS - the multimodeling and simulation environment
* This file is a part of the ARTIS environment
*
* Copyright (C) 2013-2022 ULCO http://www.univ-littoral.fr
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef COMMON_EVENT_VALUE
#define COMMON_EVENT_VALUE
#include
#include
#include
#include
#include
#include
#include
#include
namespace artis::common::event {
template
struct HasToString {
template
struct SFINAE {
};
template
static char Test(SFINAE *);
template
static int Test(...);
static const bool Has = sizeof(Test(0)) == sizeof(char);
};
class Value {
class Base {
public:
virtual ~Base() = default;
virtual bool operator==(const Base &other) const = 0;
virtual size_t size() const = 0;
virtual std::string to_string() const = 0;
virtual const std::type_info &type() const noexcept = 0;
};
template
class Data : public Base, public std::any {
public:
template, bool> = true>
Data(const U &value) : std::any(value) {}
Data(const std::string &value) : std::any(value) {}
Data(const std::valarray &value) : std::any(value) {}
Data(const std::vector &value) : std::any(value) {}
bool operator==(const Base &other) const override {
return type() == other.type() and
std::any_cast(*this) == std::any_cast(*dynamic_cast *>(&other));
}
template
void operator()(U &value) const {
value = std::any_cast(*this);
}
std::string to_string() const override {
std::stringstream ss;
if constexpr (HasToString::Has) {
if (type() == typeid(std::vector)) {
const std::vector &values = std::any_cast &>(*this);
for (const auto &e: values) {
ss << std::boolalpha << e.to_string() << " ";
}
} else if (type() == typeid(std::vector>)) {
const std::vector> &lines = std::any_cast> &>(*this);
for (const auto &values: lines) {
for (const auto &e: values) {
ss << std::boolalpha << e.to_string() << " ";
}
ss << "| ";
}
} else {
ss << std::any_cast(*this).to_string();
}
} else {
if (type() == typeid(std::string)) {
ss << std::any_cast(*this);
} else if (type() == typeid(std::valarray)) {
const std::valarray &values = std::any_cast &>(*this);
for (const auto &e: values) {
ss << std::boolalpha << e << " ";
}
} else if (type() == typeid(std::vector)) {
const std::vector &values = std::any_cast &>(*this);
for (const auto &e: values) {
ss << std::boolalpha << e << " ";
}
} else if (type() == typeid(std::vector>)) {
const std::vector> &lines = std::any_cast> &>(*this);
for (const auto &values: lines) {
for (const auto &e: values) {
ss << std::boolalpha << e << " ";
}
ss << "| ";
}
} else {
ss << std::boolalpha << std::any_cast(*this);
}
}
return ss.str();
}
size_t size() const override {
if (type() == typeid(std::vector)) {
return std::any_cast &>(*this).size();
} else if (type() == typeid(std::string)) {
return std::any_cast(*this).size();
} else if (type() == typeid(std::valarray)) {
return std::any_cast &>(*this).size();
} else { return 1; }
}
const std::type_info &type() const noexcept override { return std::any::type(); }
private:
using _type = T;
};
public:
Value() : _data(nullptr) {}
Value(const Value &value) : _data(value._data) {}
template
Value(const std::vector> &value) : _data(new Data(value)) {}
template
Value(const std::vector &value) : _data(new Data(value)) {}
template
Value(const T &value) : _data(new Data(value)) {}
template::value, bool> = true>
Value(const T (&value)[size]) : _data(new Data(std::string(value, size))) {}
template
Value(const T *value, size_t size) : _data(new Data(std::valarray(value, size))) {}
bool is_null() const { return _data.get() == nullptr; }
template
bool is_type() const { return _data->type() == typeid(Z); }
Value &operator=(const Value &other) {
_data = other._data;
return *this;
}
bool operator==(const Value &other) const {
return _data->operator==(*other._data);
}
template
void operator()(T &value) const {
dynamic_cast *>(_data.get())->operator()(value);
}
template
void operator()(T *&value) const {
const std::valarray& array = std::any_cast&>(*dynamic_cast *>(_data.get()));
unsigned int index = 0;
value = new T[size()];
for (const auto& e: array) {
value[index++] = e;
}
}
template
void operator()(std::vector &value) const {
dynamic_cast *>(_data.get())->operator()(value);
}
template
void operator()(std::valarray &value) const {
dynamic_cast *>(_data.get())->operator()(value);
}
size_t size() const { return _data->size(); }
std::string to_string() const { return _data->to_string(); }
private:
friend class boost::serialization::access;
template
void serialize(Archive & /* ar */, const unsigned int /* version */) {
// TODO
}
std::shared_ptr _data;
};
std::ostream &operator<<(std::ostream &o, const artis::common::event::Value &value);
} // namespace artis common event
#endif