Commit 61d13970 authored by Dominik Charousset's avatar Dominik Charousset

Bundle get functions for config_value

parent 438e0bf4
......@@ -164,58 +164,15 @@ using config_value_map = std::map<std::string, config_value::dictionary>;
/// @relates config_value
template <class T>
struct config_value_access;
/// @relates config_value
template <class T>
auto holds_alternative(const config_value& x)
-> decltype(config_value_access<T>::is(x)) {
return config_value_access<T>::is(x);
}
/// @relates config_value
template <class T>
auto get_if(config_value* x)
-> decltype(config_value_access<T>::get_if(x)) {
return config_value_access<T>::get_if(x);
}
/// @relates config_value
template <class T>
auto get_if(const config_value* x)
-> decltype(config_value_access<T>::get_if(x)) {
return config_value_access<T>::get_if(x);
}
/// @relates config_value
template <class T>
auto get(config_value& x) -> decltype(config_value_access<T>::get(x)) {
return config_value_access<T>::get(x);
}
/// @relates config_value
template <class T>
auto get(const config_value& x) -> decltype(config_value_access<T>::get(x)) {
return config_value_access<T>::get(x);
}
/// @relates config_value
template <class Visitor>
auto visit(Visitor&& f, config_value& x)
-> decltype(visit(std::forward<Visitor>(f), x.get_data())) {
return visit(std::forward<Visitor>(f), x.get_data());
}
/// @relates config_value
template <class Visitor>
auto visit(Visitor&& f, const config_value& x)
-> decltype(visit(std::forward<Visitor>(f), x.get_data())) {
return visit(std::forward<Visitor>(f), x.get_data());
}
struct config_value_access {
static constexpr bool specialized = false;
};
/// @relates config_value_access
template <class T>
struct default_config_value_access {
static constexpr bool specialized = true;
static bool is(const config_value& x) {
return holds_alternative<T>(x.get_data());
}
......@@ -252,6 +209,8 @@ CAF_CONFIG_VALUE_DEFAULT_ACCESS(dictionary);
template <>
struct config_value_access<float> {
static constexpr bool specialized = true;
static bool is(const config_value& x) {
return holds_alternative<double>(x.get_data());
}
......@@ -268,48 +227,6 @@ struct config_value_access<float> {
}
};
/// Checks whether `x` is a `config_value::integer` that can convert to `T`.
/// @relates config_value
template <class T>
detail::enable_if_t<std::is_integral<T>::value
&& !std::is_same<T, typename config_value::integer>::value
&& !std::is_same<T, bool>::value,
bool>
holds_alternative(const config_value& x) {
using cvi = typename config_value::integer;
auto ptr = config_value_access<cvi>::get_if(&x);
return ptr != nullptr && detail::bounds_checker<T>::check(*ptr);
}
/// Tries to convert the value of `x` to `T`.
/// @relates config_value
template <class T>
detail::enable_if_t<std::is_integral<T>::value
&& !std::is_same<T, typename config_value::integer>::value
&& !std::is_same<T, bool>::value,
optional<T>>
get_if(const config_value* x) {
using cvi = typename config_value::integer;
auto ptr = config_value_access<cvi>::get_if(x);
if (ptr != nullptr && detail::bounds_checker<T>::check(*ptr))
return static_cast<T>(*ptr);
return none;
}
/// Converts the value of `x` to `T`.
/// @relates config_value
template <class T>
detail::enable_if_t<std::is_integral<T>::value
&& !std::is_same<T, typename config_value::integer>::value
&& !std::is_same<T, bool>::value,
T>
get(const config_value& x) {
auto res = get_if<T>(&x);
if (res)
return *res;
CAF_RAISE_ERROR("invalid type found");
}
/// Implements automagic unboxing of `std::vector<T>` from a homogeneous
/// `config_value::list`.
/// @relates config_value
......@@ -317,6 +234,8 @@ template <class T>
struct config_value_access<std::vector<T>> {
using vector_type = std::vector<T>;
static constexpr bool specialized = true;
static bool is(const config_value& x) {
auto lst = caf::get_if<config_value::list>(&x);
if (lst != nullptr) {
......@@ -360,6 +279,8 @@ struct config_value_access<std::map<std::string, V>> {
using kvp = std::pair<const std::string, config_value>;
static constexpr bool specialized = true;
static bool is(const config_value& x) {
auto lst = caf::get_if<config_value::dictionary>(&x);
if (lst != nullptr) {
......@@ -526,6 +447,99 @@ T get_or(const actor_system_config& cfg, const std::string& name,
std::string get_or(const actor_system_config& cfg, const std::string& name,
const char* default_value);
// -- SumType-like access ------------------------------------------------------
/// Delegates to config_value_access for all specialized versions.
template <class T, bool Specialized = config_value_access<T>::specialized>
struct select_config_value_access {
using type = config_value_access<T>;
};
/// Catches all non-specialized integer types.
template <class T>
struct select_config_value_access<T, false> {
static_assert(std::is_integral<T>::value,
"T must be integral or specialize config_value_access");
struct type {
static bool is(const config_value& x) {
using cvi = typename config_value::integer;
auto ptr = config_value_access<cvi>::get_if(&x);
return ptr != nullptr && detail::bounds_checker<T>::check(*ptr);
}
static optional<T> get_if(const config_value* x) {
using cvi = typename config_value::integer;
auto ptr = config_value_access<cvi>::get_if(x);
if (ptr != nullptr && detail::bounds_checker<T>::check(*ptr))
return static_cast<T>(*ptr);
return none;
}
static T get(const config_value& x) {
auto res = get_if(&x);
CAF_ASSERT(res != none);
return *res;
}
};
};
template <class T>
using select_config_value_access_t =
typename select_config_value_access<T>::type;
/// @relates config_value
template <class T>
bool holds_alternative(const config_value& x) {
return select_config_value_access_t<T>::is(x);
}
/// @relates config_value
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, const T*,
optional<T>>::type
get_if(const config_value* x) {
return select_config_value_access_t<T>::get_if(x);
}
/// @relates config_value
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, T*,
optional<T>>::type
get_if(config_value* x) {
return select_config_value_access_t<T>::get_if(x);
}
/// @relates config_value
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, const T&,
T>::type
get(const config_value& x) {
return select_config_value_access_t<T>::get(x);
}
/// @relates config_value
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, T&,
T>::type
get(config_value& x) {
return select_config_value_access_t<T>::get(x);
}
/// @relates config_value
template <class Visitor>
auto visit(Visitor&& f, config_value& x)
-> decltype(visit(std::forward<Visitor>(f), x.get_data())) {
return visit(std::forward<Visitor>(f), x.get_data());
}
/// @relates config_value
template <class Visitor>
auto visit(Visitor&& f, const config_value& x)
-> decltype(visit(std::forward<Visitor>(f), x.get_data())) {
return visit(std::forward<Visitor>(f), x.get_data());
}
/// @relates config_value
bool operator<(const config_value& x, const config_value& y);
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <type_traits>
namespace caf {
namespace detail {
/// Checks wheter `T` is in the template parameter pack `Ts`.
template <class T, class... Ts>
struct is_one_of;
template <class T>
struct is_one_of<T> : std::false_type {};
template <class T, class... Ts>
struct is_one_of<T, T, Ts...> : std::true_type {};
template <class T, class U, class... Ts>
struct is_one_of<T, U, Ts...> : is_one_of<T, Ts...> {};
} // namespace detail
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <cstdint>
#include <map>
#include <vector>
#include "caf/detail/is_one_of.hpp"
#include "caf/timespan.hpp"
// -- forward declarations (this header cannot include fwd.hpp) ----------------
namespace caf {
class config_value;
enum class atom_value : uint64_t;
} // namespace caf
// -- trait --------------------------------------------------------------------
namespace caf {
namespace detail {
/// Checks wheter `T` is in a primitive value type in `config_value`.
template <class T>
using is_primitive_config_value =
is_one_of<T, int64_t, bool, double, atom_value, timespan, std::string,
std::vector<config_value>, std::map<std::string, config_value>>;
} // namespace detail
} // namespace caf
......@@ -29,6 +29,7 @@
#include "caf/fwd.hpp"
#include "caf/timestamp.hpp"
#include "caf/detail/is_one_of.hpp"
#include "caf/detail/type_list.hpp"
#define CAF_HAS_MEMBER_TRAIT(name) \
......@@ -125,19 +126,6 @@ struct disjunction<X, Xs...> {
static constexpr bool value = X || disjunction<Xs...>::value;
};
/// Checks wheter `X` is in the template parameter pack Ts.
template <class X, class... Ts>
struct is_one_of;
template <class X>
struct is_one_of<X> : std::false_type {};
template <class X, class... Ts>
struct is_one_of<X, X, Ts...> : std::true_type {};
template <class X, typename T0, class... Ts>
struct is_one_of<X, T0, Ts...> : is_one_of<X, Ts...> {};
/// Checks whether `T` is a `std::chrono::duration`.
template <class T>
struct is_duration : std::false_type {};
......
......@@ -23,6 +23,10 @@
#include <memory>
#include <tuple>
#include "caf/detail/is_one_of.hpp"
#include "caf/detail/is_primitive_config_value.hpp"
#include "caf/timespan.hpp"
namespace caf {
// -- 1 param templates --------------------------------------------------------
......@@ -150,17 +154,42 @@ config_option make_config_option(T& storage, const char* category,
enum class stream_priority;
enum class atom_value : uint64_t;
// -- aliases ------------------------------------------------------------------
using actor_id = uint64_t;
using stream_slot = uint16_t;
// -- free functions related to forwarded types --------------------------------
template <class T>
bool holds_alternative(const config_value&);
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, const T*,
optional<T>>::type
get_if(const config_value*);
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, T*,
optional<T>>::type
get_if(config_value*);
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, const T&,
T>::type
get(const config_value&);
template <class T>
typename std::conditional<detail::is_primitive_config_value<T>::value, T&,
T>::type
get(config_value&);
// -- functions ----------------------------------------------------------------
/// @relates actor_system_config
const std::map<std::string, std::map<std::string, config_value>>&
content(const actor_system_config&);
// -- aliases ------------------------------------------------------------------
using actor_id = uint64_t;
using stream_slot = uint16_t;
// -- intrusive containers -----------------------------------------------------
namespace intrusive {
......
......@@ -21,8 +21,9 @@
#include <memory>
#include "caf/config_option.hpp"
#include "caf/config_value.hpp"
#include "caf/detail/type_name.hpp"
#include "caf/error.hpp"
#include "caf/fwd.hpp"
#include "caf/pec.hpp"
namespace caf {
......
......@@ -20,7 +20,9 @@
#include "caf/test/unit_test.hpp"
#include "caf/config_option.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/make_config_option.hpp"
#include "caf/config_value.hpp"
#include "caf/expected.hpp"
using namespace caf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment