/**
* @file artis/kernel/Any.hpp
* @author See the AUTHORS file
*/
/*
* Copyright (C) 2012-2017 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 __ARTIS_KERNEL_ANY_HPP
#define __ARTIS_KERNEL_ANY_HPP
#include
#include
#include
namespace artis { namespace kernel {
enum ValueType { DOUBLE, INT, BOOL };
class Any
{
private:
struct base
{
virtual ~base() { }
virtual base* clone() const = 0;
};
template < typename T, typename V >
struct data : base
{
data(V T::* const& value) : value_(value)
{ }
base* clone() const { return new data < T, V >(*this); }
V T::* value_;
};
base* ptr_;
public:
Any() : ptr_(nullptr)
{ }
template < typename T, typename V >
Any(V T::* const& value) : ptr_(new data < T, V >(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 < typename T, typename V >
V T::* get() const
{ return dynamic_cast < data < T, V >* >(ptr_)->value_; }
bool is_null() const
{ return ptr_ == nullptr; }
template < typename T, typename V >
void put(T* o, const V& value )
{
V T::* p = dynamic_cast <
data < T, V >* >(ptr_)->value_;
o->*(p) = value;
}
template < typename T >
void restore(T* o, const context::Value& value)
{
if (value.is_double()) {
double v;
value.get_content(v);
put(o, v);
} else if (value.is_int()) {
int v;
value.get_content(v);
put(o, v);
} else if (value.is_bool()) {
bool v;
value.get_content(v);
put(o, v);
} else if (value.is_double_vector()) {
std::vector < double > v;
value.get_content(v);
put(o, v);
} else if (value.is_int_vector()) {
std::vector < int > v;
value.get_content(v);
put(o, v);
} else if (value.is_bool_vector()) {
std::vector < bool > v;
value.get_content(v);
put(o, v);
} else {
assert(false);
}
}
template < typename T >
context::Value save(const T* o) const
{
if (ptr_) {
data < T, double >* q_double =
dynamic_cast < data < T, double >* >(ptr_);
if (q_double) {
return context::Value(o->*(q_double->value_));
} else {
data < T, int >* q_int =
dynamic_cast < data < T, int >* >(ptr_);
if (q_int) {
return context::Value(o->*(q_int->value_));
} else {
data < T, bool >* q_bool =
dynamic_cast < data < T, bool >* >(ptr_);
if (q_bool) {
return context::Value(o->*(q_bool->value_));
} else {
data < T, std::vector < double > >* q_double_v =
dynamic_cast < data < T, std::vector <
double > >* >(ptr_);
if (q_double_v) {
return context::Value(o->*(q_double_v->value_));
} else {
data < T, std::vector < int > >* q_int_v =
dynamic_cast < data < T, std::vector <
int > >* >(ptr_);
if (q_int_v) {
return context::Value(o->*(q_int_v->value_));
} else {
data < T, std::vector < bool > >* q_bool_v =
dynamic_cast < data < T, std::vector <
bool > >* >(ptr_);
if (q_bool_v) {
return context::Value(
o->*(q_bool_v->value_));
}
}
}
}
}
}
}
assert(false);
}
template < typename T >
std::string to_string(const T* o) const
{
if (ptr_) {
data < T, double >* q_double =
dynamic_cast < data < T, double >* >(ptr_);
if (q_double) {
return std::to_string(o->*(q_double->value_));
} else {
data < T, int >* q_int =
dynamic_cast < data < T, int >* >(ptr_);
if (q_int) {
return std::to_string(o->*(q_int->value_));
} else {
data < T, bool >* q_bool =
dynamic_cast < data < T, bool >* >(ptr_);
if (q_bool) {
return o->*(q_bool->value_) ? "true": "false";
} else {
data < T, std::vector < double > >* q_double_v =
dynamic_cast < data < T, std::vector <
double > >* >(ptr_);
if (q_double_v) {
return "";
} else {
data < T, std::vector < int > >* q_int_v =
dynamic_cast < data < T, std::vector <
int > >* >(ptr_);
if (q_int_v) {
return "";
} else {
data < T, std::vector < bool > >* q_bool_v =
dynamic_cast < data < T, std::vector <
bool > >* >(ptr_);
if (q_bool_v) {
return "";
} else {
return "NA";
}
}
}
}
}
}
} else {
return "NA";
}
}
};
} }
#endif