/**
* @file common/Any.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-2019 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_ANY_HPP
#define COMMON_ANY_HPP
#include
#include
#include
#include
#include
namespace artis {
namespace common {
class Any
{
private:
struct base
{
virtual ~base()
{}
virtual base *clone() const = 0;
};
template
struct data : base
{
data(V T::* const &value)
: value_(value)
{}
base *clone() const
{ return new data(*this); }
V T::* value_;
};
base *ptr_;
public:
Any()
: ptr_(nullptr)
{}
template
Any(V T::* const &value)
: ptr_(new data(value))
{}
Any(Any const &other)
: ptr_(other.ptr_ ? other.ptr_->clone() : nullptr)
{}
virtual ~Any()
{
if (ptr_) {
delete ptr_;
}
}
void operator=(Any const &other)
{ Any(other).swap(*this); }
void swap(Any &other)
{ std::swap(ptr_, other.ptr_); }
template
V T::* get() const
{ return dynamic_cast < data * >(ptr_)->value_; }
template
void get(T *o, V &value) const
{
data *q = dynamic_cast < data * >(ptr_);
if (q) {
value = o->*(q->value_);
} else {
assert(false);
}
}
bool is_null() const
{ return ptr_ == nullptr; }
template
void put(T *o, const V &value)
{
V T::* p = dynamic_cast * >(ptr_)->value_;
o->*(p) = value;
}
template
void restore(T *o, const common::Value &value)
{
if (value.is_type()) {
double v;
value(v);
put(o, v);
} else if (value.is_type()) {
unsigned int v;
value(v);
put(o, v);
} else if (value.is_type()) {
int v;
value(v);
put(o, v);
} else if (value.is_type()) {
bool v;
value(v);
put(o, v);
} else if (value.is_type < std::vector < double > > ()) {
std::vector v;
value(v);
put(o, v);
} else if (value.is_type < std::vector < unsigned int > > ()) {
std::vector v;
value(v);
put(o, v);
} else if (value.is_type < std::vector < int > > ()) {
std::vector v;
value(v);
put(o, v);
} else if (value.is_type < std::vector < bool > > ()) {
std::vector v;
value(v);
put(o, v);
} else {
assert(false);
}
}
template
common::Value save(const T *o) const
{
if (ptr_) {
data *q_double =
dynamic_cast < data * >(ptr_);
if (q_double) {
return common::Value(o->*(q_double->value_));
} else {
data *q_uint =
dynamic_cast < data * >(ptr_);
if (q_uint) {
return common::Value(o->*(q_uint->value_));
} else {
data *q_int =
dynamic_cast < data * >(ptr_);
if (q_int) {
return common::Value(o->*(q_int->value_));
} else {
data *q_bool =
dynamic_cast < data * >(ptr_);
if (q_bool) {
return common::Value(o->*(q_bool->value_));
} else {
data > *q_double_v =
dynamic_cast < data > * > (ptr_);
if (q_double_v) {
return common::Value(o->*(q_double_v->value_));
} else {
data > *q_int_v =
dynamic_cast < data > * > (ptr_);
if (q_int_v) {
return common::Value(o->*(q_int_v->value_));
} else {
data > *q_bool_v =
dynamic_cast < data > * > (ptr_);
if (q_bool_v) {
return common::Value(o->*(q_bool_v->value_));
}
}
}
}
}
}
}
}
assert(false);
return common::Value();
}
template
std::string to_string(const T *o) const
{
if (ptr_) {
data *q_double =
dynamic_cast < data * >(ptr_);
if (q_double) {
return std::to_string(o->*(q_double->value_));
} else {
data *q_uint =
dynamic_cast < data * >(ptr_);
if (q_uint) {
return std::to_string(o->*(q_uint->value_));
} else {
data *q_int =
dynamic_cast < data * >(ptr_);
if (q_int) {
return std::to_string(o->*(q_int->value_));
} else {
data *q_bool =
dynamic_cast < data * >(ptr_);
if (q_bool) {
return o->*(q_bool->value_) ? "true" : "false";
} else {
data > *q_double_v =
dynamic_cast < data > * > (ptr_);
if (q_double_v) {
return "";
} else {
data > *q_int_v =
dynamic_cast < data > * > (ptr_);
if (q_int_v) {
return "";
} else {
data > *q_bool_v =
dynamic_cast < data > * > (ptr_);
if (q_bool_v) {
return "";
} else {
return "NA";
}
}
}
}
}
}
}
} else {
return "NA";
}
}
};
}
}
#endif