diff options
author | Martin Braun <martin.braun@ettus.com> | 2018-01-10 14:45:30 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2018-01-12 13:18:03 -0800 |
commit | c48c57073d618df5a023b5daec372aec5770b471 (patch) | |
tree | c736e31a4ededb430141703055f1bfa53f21b65f | |
parent | ebfd551c355cd28f720b6b77a9d0470353b2e21c (diff) | |
download | uhd-c48c57073d618df5a023b5daec372aec5770b471.tar.gz uhd-c48c57073d618df5a023b5daec372aec5770b471.tar.bz2 uhd-c48c57073d618df5a023b5daec372aec5770b471.zip |
uhd: Add narrow_cast and narrow
Reviewed-by: Ashish Chaudhari <ashish.chaudhari@ettus.com>
-rw-r--r-- | host/include/uhd/exception.hpp | 7 | ||||
-rw-r--r-- | host/lib/exception.cpp | 1 | ||||
-rw-r--r-- | host/lib/include/uhdlib/utils/narrow.hpp | 99 | ||||
-rw-r--r-- | host/tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/tests/narrow_cast_test.cpp | 21 |
5 files changed, 129 insertions, 0 deletions
diff --git a/host/include/uhd/exception.hpp b/host/include/uhd/exception.hpp index 5ae5d790e..a8cbb8134 100644 --- a/host/include/uhd/exception.hpp +++ b/host/include/uhd/exception.hpp @@ -80,6 +80,13 @@ namespace uhd{ virtual void dynamic_throw(void) const; }; + struct UHD_API narrowing_error : value_error{ + narrowing_error(const std::string &what); + virtual unsigned code(void) const; + virtual narrowing_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + struct UHD_API runtime_error : exception{ runtime_error(const std::string &what); virtual unsigned code(void) const; diff --git a/host/lib/exception.cpp b/host/lib/exception.cpp index 3d39d901d..1a1ddb0ad 100644 --- a/host/lib/exception.cpp +++ b/host/lib/exception.cpp @@ -26,6 +26,7 @@ make_exception_impl("IndexError", index_error, lookup_err make_exception_impl("KeyError", key_error, lookup_error) make_exception_impl("TypeError", type_error, exception) make_exception_impl("ValueError", value_error, exception) +make_exception_impl("NarrowingError", narrowing_error, value_error) make_exception_impl("RuntimeError", runtime_error, exception) make_exception_impl("NotImplementedError", not_implemented_error, runtime_error) make_exception_impl("EnvironmentError", environment_error, exception) diff --git a/host/lib/include/uhdlib/utils/narrow.hpp b/host/lib/include/uhdlib/utils/narrow.hpp new file mode 100644 index 000000000..feb7112f6 --- /dev/null +++ b/host/lib/include/uhdlib/utils/narrow.hpp @@ -0,0 +1,99 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0 +// + +// This narrowing code is inspired by the guidelines support library by +// Microsoft: https://github.com/Microsoft/GSL/ +// +// The C++ guidelines are published here: +// https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md +// +// There are some minor details between this implementation and the Microsoft +// implementation, but they are similar (the main difference is the exception +// type thrown). +// The original code was published under the following license: +// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// [End of GSL license] +/////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_UHDLIB_UTILS_NARROW_HPP +#define INCLUDED_UHDLIB_UTILS_NARROW_HPP + +#include <uhd/exception.hpp> +#include <utility> + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4127) // conditional expression is constant +#endif // _MSC_VER + +namespace uhd { + +/*! Static typecast which expresses intent of narrowing + * + * Use this for any conversion that narrows, e.g.: + * + * \code{.cpp} + * uint16_t x = peek16(); + * uint8_t y = narrow_cast<uint8_t>(x); + * \endcode + */ +template <class T, class U> +inline constexpr T narrow_cast(U&& u) noexcept +{ + return static_cast<T>(std::forward<U>(u)); +} + +/*! Like narrow_cast, but will throw an exception on failure. + * + * Call this if you're not sure if the cast will work as expected (e.g. when + * narrowing user input). + * + * \throws uhd::narrowing_error on failure + */ +template <class T, class U> +inline T narrow(U u) +{ + T t = narrow_cast<T>(u); + if (static_cast<U>(t) != u) { + throw narrowing_error(""); + } + if (!std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>::value + && ((t < T{}) != (u < U{}))) { + throw narrowing_error(""); + } + return t; +} + +} /* namespace uhd */ + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif // _MSC_VER + +#endif /* INCLUDED_UHDLIB_UTILS_NARROW_HPP */ diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 7fcf1652c..6f78f8d3e 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -27,6 +27,7 @@ SET(test_sources gain_group_test.cpp log_test.cpp math_test.cpp + narrow_cast_test.cpp property_test.cpp ranges_test.cpp sid_t_test.cpp diff --git a/host/tests/narrow_cast_test.cpp b/host/tests/narrow_cast_test.cpp new file mode 100644 index 000000000..2f784bfe3 --- /dev/null +++ b/host/tests/narrow_cast_test.cpp @@ -0,0 +1,21 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0 +// + +#include <uhd/exception.hpp> +#include <../lib/include/uhdlib/utils/narrow.hpp> +#include <boost/test/unit_test.hpp> +#include <iostream> + +using namespace uhd; + +BOOST_AUTO_TEST_CASE(test_narrow){ + uint16_t x = 5; + uint8_t y = narrow_cast<uint8_t>(x); + BOOST_CHECK_EQUAL(x, y); + + BOOST_CHECK_THROW(narrow<uint8_t>(uint16_t(1<<10)), narrowing_error); + BOOST_CHECK_THROW(narrow<uint8_t>(int8_t(-1)), narrowing_error); +} |