/** * @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