123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- /**
- * @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 <http://www.gnu.org/licenses/>.
- */
- #ifndef COMMON_EVENT_VALUE
- #define COMMON_EVENT_VALUE
- #include <boost/serialization/serialization.hpp>
- #include <any>
- #include <memory>
- #include <sstream>
- #include <string>
- #include <type_traits>
- #include <valarray>
- #include <vector>
- namespace artis::common::event {
- template<typename T>
- struct HasToString {
- template<typename U, std::string (U::*)() const>
- struct SFINAE {
- };
- template<typename U>
- static char Test(SFINAE<U, &U::to_string> *);
- template<typename U>
- static int Test(...);
- static const bool Has = sizeof(Test<T>(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<typename T>
- class Data : public Base, public std::any {
- public:
- template<typename U = T, std::enable_if_t<not std::is_same_v<U, std::string>, bool> = true>
- Data(const U &value) : std::any(value) {}
- Data(const std::string &value) : std::any(value) {}
- Data(const std::valarray<T> &value) : std::any(value) {}
- Data(const std::vector<T> &value) : std::any(value) {}
- bool operator==(const Base &other) const override {
- return type() == other.type() and
- std::any_cast<const T &>(*this) == std::any_cast<const T &>(*dynamic_cast<const Data<T> *>(&other));
- }
- template<typename U>
- void operator()(U &value) const {
- value = std::any_cast<const U &>(*this);
- }
- std::string to_string() const override {
- std::stringstream ss;
- if constexpr (HasToString<T>::Has) {
- if (type() == typeid(std::vector<T>)) {
- const std::vector<T> &values = std::any_cast<const std::vector<T> &>(*this);
- for (const auto &e: values) {
- ss << std::boolalpha << e.to_string() << " ";
- }
- } else if (type() == typeid(std::vector<std::vector<T>>)) {
- const std::vector<std::vector<T>> &lines = std::any_cast<const std::vector<std::vector<T>> &>(*this);
- for (const auto &values: lines) {
- for (const auto &e: values) {
- ss << std::boolalpha << e.to_string() << " ";
- }
- ss << "| ";
- }
- } else {
- ss << std::any_cast<const T &>(*this).to_string();
- }
- } else {
- if (type() == typeid(std::string)) {
- ss << std::any_cast<const std::string &>(*this);
- } else if (type() == typeid(std::valarray<T>)) {
- const std::valarray<T> &values = std::any_cast<const std::valarray<T> &>(*this);
- for (const auto &e: values) {
- ss << std::boolalpha << e << " ";
- }
- } else if (type() == typeid(std::vector<T>)) {
- const std::vector<T> &values = std::any_cast<const std::vector<T> &>(*this);
- for (const auto &e: values) {
- ss << std::boolalpha << e << " ";
- }
- } else if (type() == typeid(std::vector<std::vector<T>>)) {
- const std::vector<std::vector<T>> &lines = std::any_cast<const std::vector<std::vector<T>> &>(*this);
- for (const auto &values: lines) {
- for (const auto &e: values) {
- ss << std::boolalpha << e << " ";
- }
- ss << "| ";
- }
- } else {
- ss << std::boolalpha << std::any_cast<const T &>(*this);
- }
- }
- return ss.str();
- }
- size_t size() const override {
- if (type() == typeid(std::vector<T>)) {
- return std::any_cast<const std::vector<T> &>(*this).size();
- } else if (type() == typeid(std::string)) {
- return std::any_cast<const std::string &>(*this).size();
- } else if (type() == typeid(std::valarray<T>)) {
- return std::any_cast<const std::valarray<T> &>(*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<typename T>
- Value(const std::vector<std::vector<T>> &value) : _data(new Data<T>(value)) {}
- template<typename T>
- Value(const std::vector<T> &value) : _data(new Data<T>(value)) {}
- template<typename T>
- Value(const T &value) : _data(new Data<T>(value)) {}
- template<typename T, size_t size, std::enable_if_t<std::is_same<T, char>::value, bool> = true>
- Value(const T (&value)[size]) : _data(new Data<T>(std::string(value, size))) {}
- template<typename T>
- Value(const T *value, size_t size) : _data(new Data<T>(std::valarray<T>(value, size))) {}
- bool is_null() const { return _data.get() == nullptr; }
- template<typename Z>
- 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<typename T>
- void operator()(T &value) const {
- dynamic_cast<Data<T> *>(_data.get())->operator()(value);
- }
- template<typename T>
- void operator()(T *&value) const {
- const std::valarray<T>& array = std::any_cast<const std::valarray<T>&>(*dynamic_cast<Data<T> *>(_data.get()));
- unsigned int index = 0;
- value = new T[size()];
- for (const auto& e: array) {
- value[index++] = e;
- }
- }
- template<typename T>
- void operator()(std::vector<T> &value) const {
- dynamic_cast<Data<T> *>(_data.get())->operator()(value);
- }
- template<typename T>
- void operator()(std::valarray<T> &value) const {
- dynamic_cast<Data<T> *>(_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<typename Archive>
- void serialize(Archive & /* ar */, const unsigned int /* version */) {
- // TODO
- }
- std::shared_ptr<Base> _data;
- };
- std::ostream &operator<<(std::ostream &o, const artis::common::event::Value &value);
- } // namespace artis common event
- #endif
|