Commit f664eab8 authored by Dominik Charousset's avatar Dominik Charousset

Add simple integer bounds checker

parent 8bc6aa1c
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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 <limits>
#include <type_traits>
namespace caf {
namespace detail {
template <class To, bool LargeUnsigned = sizeof(To) >= sizeof(int64_t)
&& std::is_unsigned<To>::value>
struct bounds_checker {
static inline bool check(int64_t x) {
return x >= std::numeric_limits<To>::min()
&& x <= std::numeric_limits<To>::max();
}
};
template <class To>
struct bounds_checker<To, true> {
static inline bool check(int64_t x) {
return x >= 0;
}
};
} // 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. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE bounds_checker
#include "caf/test/dsl.hpp"
#include "caf/detail/bounds_checker.hpp"
namespace {
template <class T>
bool check(int64_t x) {
return caf::detail::bounds_checker<T>::check(x);
}
} // namespace <anonymous>
CAF_TEST(small integers) {
CAF_CHECK_EQUAL(check<int8_t>(128), false);
CAF_CHECK_EQUAL(check<int8_t>(127), true);
CAF_CHECK_EQUAL(check<int8_t>(-128), true);
CAF_CHECK_EQUAL(check<int8_t>(-129), false);
CAF_CHECK_EQUAL(check<uint8_t>(-1), false);
CAF_CHECK_EQUAL(check<uint8_t>(0), true);
CAF_CHECK_EQUAL(check<uint8_t>(255), true);
CAF_CHECK_EQUAL(check<uint8_t>(256), false);
CAF_CHECK_EQUAL(check<int16_t>(-32769), false);
CAF_CHECK_EQUAL(check<int16_t>(-32768), true);
CAF_CHECK_EQUAL(check<int16_t>(32767), true);
CAF_CHECK_EQUAL(check<int16_t>(32768), false);
CAF_CHECK_EQUAL(check<uint16_t>(-1), false);
CAF_CHECK_EQUAL(check<uint16_t>(0), true);
CAF_CHECK_EQUAL(check<uint16_t>(65535), true);
CAF_CHECK_EQUAL(check<uint16_t>(65536), false);
}
CAF_TEST(large unsigned integers) {
CAF_CHECK_EQUAL(check<uint64_t>(-1), false);
CAF_CHECK_EQUAL(check<uint64_t>(0), true);
CAF_CHECK_EQUAL(check<uint64_t>(std::numeric_limits<int64_t>::max()), true);
}
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "caf/actor_system_config.hpp" #include "caf/actor_system_config.hpp"
#include "caf/atom.hpp" #include "caf/atom.hpp"
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
#include "caf/detail/bounds_checker.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
...@@ -66,6 +67,37 @@ config_value cfg_lst(Ts&&... xs) { ...@@ -66,6 +67,37 @@ config_value cfg_lst(Ts&&... xs) {
return config_value{std::move(lst)}; return config_value{std::move(lst)};
} }
template <class T>
detail::enable_if_t<std::is_integral<T>::value
&& !std::is_same<T, typename config_value::integer>::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 && detail::bounds_checker<T>::check(*ptr))
return static_cast<T>(*ptr);
return none;
}
template <>
optional<uint64_t> get_if<uint64_t>(const config_value* x) {
auto ptr = get_if<typename config_value::integer>(x);
if (ptr && *ptr >= 0)
return static_cast<uint64_t>(*ptr);
return none;
}
template <class T>
detail::enable_if_t<std::is_integral<T>::value
&& !std::is_same<T, typename config_value::integer>::value,
T>
get(const config_value& x) {
auto res = get_if<T>(&x);
if (res)
return *res;
CAF_RAISE_ERROR("invalid type found");
}
} // namespace <anonymous> } // namespace <anonymous>
CAF_TEST(default_constructed) { CAF_TEST(default_constructed) {
...@@ -75,6 +107,13 @@ CAF_TEST(default_constructed) { ...@@ -75,6 +107,13 @@ CAF_TEST(default_constructed) {
CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<int64_t>()); CAF_CHECK_EQUAL(x.type_name(), config_value::type_name_of<int64_t>());
} }
CAF_TEST(integer) {
config_value x{4200};
CAF_CHECK_EQUAL(get<int64_t>(x), 4200);
CAF_CHECK_EQUAL(get<size_t>(x), 4200u);
CAF_CHECK_EQUAL(get_if<uint8_t>(&x), caf::none);
}
CAF_TEST(list) { CAF_TEST(list) {
using integer_list = std::vector<int64_t>; using integer_list = std::vector<int64_t>;
auto xs = make_config_value_list(1, 2, 3); auto xs = make_config_value_list(1, 2, 3);
......
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