OpenVPN 3 Core Library
Loading...
Searching...
No Matches
numeric_util.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2023- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12
13
14#pragma once
15
16#include <cstdint>
17#include <limits>
18#include <type_traits>
19#include <functional>
20
21
22namespace openvpn::numeric_util {
23
24// Evaluates true if both template args are integral.
25template <typename OutT, typename InT>
26constexpr bool is_int_conversion()
27{
28 return std::is_integral_v<InT> && std::is_integral_v<OutT>;
29}
30
31// Returns true if the in param is an unsigned integral type and out param is a signed integral type.
32template <typename OutT, typename InT>
33constexpr bool is_int_u2s()
34{
35 return is_int_conversion<OutT, InT>() && std::is_unsigned_v<InT> && std::is_signed_v<OutT>;
36}
37
38// Returns true if the in param is a signed integral type and out param is an unsigned integral type.
39template <typename OutT, typename InT>
40constexpr bool is_int_s2u()
41{
42 return is_int_conversion<OutT, InT>() && std::is_signed_v<InT> && std::is_unsigned_v<OutT>;
43}
44
45// Returns true if both args are integral and the range of OutT can contain the range of InT
46template <typename OutT, typename InT>
47constexpr bool is_int_rangesafe()
48{
49 constexpr auto out_digits = std::numeric_limits<OutT>::digits;
50 constexpr auto in_digits = std::numeric_limits<InT>::digits;
51
52 return is_int_conversion<OutT, InT>() && !is_int_s2u<OutT, InT>() && out_digits >= in_digits;
53}
54
55/* ============================================================================================================= */
56// is_safe_conversion
57/* ============================================================================================================= */
58
68template <typename OutT, typename InT>
69bool is_safe_conversion(InT inVal)
70{
71 if constexpr (!numeric_util::is_int_rangesafe<OutT, InT>())
72 {
73 if constexpr (numeric_util::is_int_u2s<OutT, InT>())
74 {
75 auto unsignedInVal = static_cast<uintmax_t>(inVal);
76 auto outMax = static_cast<uintmax_t>(std::numeric_limits<OutT>::max());
77 if (outMax < unsignedInVal)
78 return false;
79 }
80 else if constexpr (numeric_util::is_int_s2u<OutT, InT>())
81 {
82 auto lowerVal = static_cast<uintmax_t>(std::max(inVal, InT(0)));
83 auto upperLimit = static_cast<uintmax_t>(std::numeric_limits<OutT>::max());
84 if (inVal < 0 || lowerVal > upperLimit)
85 return false;
86 }
87 else
88 {
89 auto outMin = static_cast<InT>(std::numeric_limits<OutT>::min());
90 auto outMax = static_cast<InT>(std::numeric_limits<OutT>::max());
91 if (inVal < outMin || inVal > outMax)
92 return false;
93 }
94 }
95
96 return true;
97}
98
99} // namespace openvpn::numeric_util
constexpr bool is_int_s2u()
constexpr bool is_int_u2s()
constexpr bool is_int_rangesafe()
constexpr bool is_int_conversion()
bool is_safe_conversion(InT inVal)
Returns true if the given value can be contained by the out type.