20#ifndef SCRIPT_INTERFACE_GET_VALUE_HPP
21#define SCRIPT_INTERFACE_GET_VALUE_HPP
29#include <boost/algorithm/string/join.hpp>
53inline std::string simplify_symbol_variant(
Variant const &v);
56template <
typename T>
auto simplify_symbol(T
const *) {
57 auto constexpr is_string = std::is_same_v<T, std::string>;
60 auto name = (
is_string) ? std::string{
"std::string"} : Utils::demangle<T>();
61 for (std::string::size_type pos{};
70template <
typename T, std::
size_t N>
72 auto const name_val = simplify_symbol(
static_cast<T *
>(
nullptr));
73 return "Utils::Vector<" + Utils::demangle<T>() +
", " + std::to_string(
N) +
78template <
typename T>
auto simplify_symbol(std::vector<T>
const *
vec) {
79 auto const name_val = simplify_symbol(
static_cast<T *
>(
nullptr));
82 metadata +=
"{.size=" + std::to_string(
vec->size()) +
"}";
88inline auto simplify_symbol(std::vector<Variant>
const *
vec) {
92 std::set<std::string>
types = {};
93 for (
auto const &v : *
vec) {
94 types.insert(simplify_symbol_variant(v));
97 metadata +=
"{.size=" + std::to_string(
vec->size()) +
"}";
103template <
typename K,
typename V>
104auto simplify_symbol(std::unordered_map<K, V>
const *) {
105 auto const name_key = simplify_symbol(
static_cast<K *
>(
nullptr));
106 auto const name_val = simplify_symbol(
static_cast<V *
>(
nullptr));
112auto simplify_symbol(std::unordered_map<K, Variant>
const *map) {
113 auto const name_key = simplify_symbol(
static_cast<K *
>(
nullptr));
116 std::set<std::string>
types = {};
117 for (
auto const &kv : *map) {
118 types.insert(simplify_symbol_variant(kv.second));
125struct simplify_symbol_visitor : boost::static_visitor<std::string> {
126 template <
class T> std::string operator()(T
const &t)
const {
127 return simplify_symbol(&t);
132inline std::string simplify_symbol_variant(
Variant const &v) {
133 return boost::apply_visitor(simplify_symbol_visitor(), v);
137template <
typename T>
auto simplify_symbol_containee(T
const *) {
138 return std::string(
"");
142template <
typename T>
auto simplify_symbol_containee(std::vector<T>
const *) {
143 auto const name_val = simplify_symbol(
static_cast<T *
>(
nullptr));
148template <
typename K,
typename V>
149auto simplify_symbol_containee(std::unordered_map<K, V>
const *) {
150 auto const name_key = simplify_symbol(
static_cast<K *
>(
nullptr));
151 auto const name_val = simplify_symbol(
static_cast<V *
>(
nullptr));
155struct simplify_symbol_containee_visitor : boost::static_visitor<std::string> {
156 template <
class T> std::string operator()(
const T &)
const {
157 return simplify_symbol_containee(
static_cast<T *
>(
nullptr));
165inline auto simplify_symbol_containee_variant(
Variant const &v) {
166 return boost::apply_visitor(simplify_symbol_containee_visitor(), v);
177template <
class To,
class From>
178using allow_conversion =
179 std::integral_constant<bool, std::is_same_v<To, From> ||
180 (std::is_convertible_v<To, From> &&
181 std::is_floating_point_v<To> &&
182 std::is_arithmetic_v<From>)>;
184template <
class To>
struct conversion_visitor : boost::static_visitor<To> {
185 template <
class From>
186 std::enable_if_t<allow_conversion<To, From>::value,
To>
187 operator()(
const From &value)
const {
191 template <
class From>
192 std::enable_if_t<!allow_conversion<To, From>::value,
To>
193 operator()(
const From &)
const {
194 throw boost::bad_get{};
204template <
typename T,
typename =
void>
struct get_value_helper {
205 T operator()(
Variant const &v)
const {
206 return boost::apply_visitor(detail::conversion_visitor<T>(), v);
210template <
class T, std::
size_t N>
211struct vector_conversion_visitor : boost::static_visitor<Utils::Vector<T, N>> {
218 auto operator()(std::vector<Variant>
const &
vv)
const {
219 if (
N !=
vv.size()) {
220 throw boost::bad_get{};
229 template <
typename U>
231 operator()(std::vector<
U, std::allocator<U>>
const &v)
const {
233 throw boost::bad_get{};
239 throw boost::bad_get{};
244template <
typename T, std::
size_t N>
245struct get_value_helper<
Utils::Vector<T, N>> {
247 return boost::apply_visitor(detail::vector_conversion_visitor<T, N>(), v);
252struct GetVectorOrEmpty : boost::static_visitor<std::vector<T>> {
254 template <
typename U> std::vector<T> operator()(
U const &)
const {
255 throw boost::bad_get{};
259 std::vector<T> operator()(std::vector<T>
const &v)
const {
return v; }
261 template <
typename V = T,
262 std::enable_if_t<!std::is_same_v<V, Variant>,
bool> =
true>
263 std::vector<T> operator()(std::vector<Variant>
const &
vv)
const {
264 std::vector<T>
ret(
vv.size());
273template <
typename T>
struct get_value_helper<std::
vector<T>,
void> {
274 std::vector<T> operator()(
Variant const &v)
const {
279template <
typename K,
typename T>
280struct GetMapOrEmpty : boost::static_visitor<std::unordered_map<K, T>> {
282 template <
typename U> std::unordered_map<K, T> operator()(
U const &)
const {
283 throw boost::bad_get{};
287 std::unordered_map<K, T> operator()(std::unordered_map<K, T>
const &v)
const {
291 template <
typename V = T,
292 std::enable_if_t<!std::is_same_v<V, Variant>,
bool> =
true>
293 std::unordered_map<K, T>
294 operator()(std::unordered_map<K, Variant>
const &v)
const {
295 std::unordered_map<K, T>
ret;
296 for (
auto it = v.begin();
it != v.end(); ++
it) {
305struct get_value_helper<std::unordered_map<int, T>,
void> {
306 std::unordered_map<int, T> operator()(
Variant const &v)
const {
311struct get_value_helper<std::unordered_map<std::string, T>,
void> {
312 std::unordered_map<std::string, T> operator()(
Variant const &v)
const {
318class bad_get_nullptr :
public boost::bad_get {};
325struct get_value_helper<
327 typename std::enable_if_t<std::is_base_of_v<ObjectHandle, T>, void>> {
328 std::shared_ptr<T> operator()(
Variant const &v)
const {
329 auto so_ptr = boost::get<ObjectRef>(v);
331 throw bad_get_nullptr{};
340 throw boost::bad_get{};
352inline void handle_bad_get(
Variant const &v, std::string
const &name) {
354 auto const containee_name = demangle::simplify_symbol_containee_variant(v);
356 demangle::simplify_symbol_containee(
static_cast<T *
>(
nullptr));
360 if (
not name.empty()) {
361 what +=
" for parameter '" + name +
"'";
365 }
catch (bad_get_nullptr
const &) {
367 throw Exception(what +
item_error +
" is a null pointer");
368 }
catch (boost::bad_get
const &) {
372 item_error +=
" because it contains a value that";
375 auto const target = demangle::simplify_symbol(
static_cast<T *
>(
nullptr));
380template <
typename T> T get_value(
Variant const &v, std::string
const &name) {
382 return detail::get_value_helper<T>{}(v);
384 detail::handle_bad_get<T>(v, name);
401 return detail::get_value<T>(v,
"");
411 if (
vals.count(name) == 0
ul) {
412 throw Exception(
"Parameter '" + name +
"' is missing.");
414 return detail::get_value<T>(
vals.at(name), name);
424 if (
vals.count(name)) {
434template <
typename T,
typename...
Types,
typename...
ArgNames>
437 return std::make_shared<T>(
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
std::unordered_map< std::string, Variant > VariantMap
T get_value_or(VariantMap const &vals, std::string const &name, T const &default_)
Get a value from a VariantMap by name, or return a default value if it does not exist.
std::shared_ptr< T > make_shared_from_args(VariantMap const &vals, ArgNames &&...args)
Make a new std::shared_ptr<T> with arguments extracted from a VariantMap.
boost::make_recursive_variant< None, bool, int, std::size_t, double, std::string, ObjectRef, Utils::Vector3b, Utils::Vector3i, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d, std::vector< int >, std::vector< double >, std::vector< boost::recursive_variant_ >, std::unordered_map< int, boost::recursive_variant_ >, std::unordered_map< std::string, boost::recursive_variant_ > >::type Variant
Possible types for parameters.
void set_from_args(T &dst, VariantMap const &vals, const char *name)
std::string demangle()
Get a human-readable name for a type.
std::vector< T, allocator< T > > vector