Exiv2
Toggle main menu visibility
Loading...
Searching...
No Matches
src
safe_op.hpp
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
#ifndef SAFE_OP_HPP_
4
#define SAFE_OP_HPP_
5
6
#include <limits>
7
#include <stdexcept>
8
#include <type_traits>
9
10
#ifdef _MSC_VER
11
#include <Intsafe.h>
12
#endif
13
17
namespace
Safe
{
40
namespace
Internal
{
61
template
<
typename
T>
62
bool
fallback_add_overflow
(T summand_1, T summand_2, T& result) {
63
if
constexpr
(std::is_signed_v<T> &&
sizeof
(T) >=
sizeof
(int)) {
64
if
(((summand_2 >= 0) && (summand_1 > std::numeric_limits<T>::max() - summand_2)) ||
65
((summand_2 < 0) && (summand_1 < std::numeric_limits<T>::min() - summand_2)))
66
return
true
;
67
result = summand_1 + summand_2;
68
return
false
;
69
}
else
if
constexpr
(std::is_signed_v<T> &&
sizeof
(T) <
sizeof
(int)) {
70
const
int
res = summand_1 + summand_2;
71
if
((res > std::numeric_limits<T>::max()) || (res < std::numeric_limits<T>::min())) {
72
return
true
;
73
}
74
result =
static_cast<
T
>
(res);
75
return
false
;
76
}
else
{
77
result = summand_1 + summand_2;
78
return
result < summand_1;
79
}
80
}
81
95
template
<
typename
T>
96
bool
builtin_add_overflow
(T summand_1, T summand_2, T& result) {
97
return
fallback_add_overflow
(summand_1, summand_2, result);
98
}
99
100
#if defined(__GNUC__) || defined(__clang__)
101
#if __GNUC__ >= 5 || __clang_major__ >= 3
102
113
#define SPECIALIZE_builtin_add_overflow(type, builtin_name) \
114
/* Full specialization of builtin_add_overflow for type using the */
\
115
/* builtin_name intrinsic */
\
116
template <> \
117
constexpr bool builtin_add_overflow<type>(type summand_1, type summand_2, type & result) { \
118
return builtin_name(summand_1, summand_2, &result); \
119
}
120
121
SPECIALIZE_builtin_add_overflow(
int
, __builtin_sadd_overflow);
122
SPECIALIZE_builtin_add_overflow(
long
, __builtin_saddl_overflow);
123
SPECIALIZE_builtin_add_overflow(
long
long
, __builtin_saddll_overflow);
124
125
SPECIALIZE_builtin_add_overflow(
unsigned
int
, __builtin_uadd_overflow);
126
SPECIALIZE_builtin_add_overflow(
unsigned
long
, __builtin_uaddl_overflow);
127
SPECIALIZE_builtin_add_overflow(
unsigned
long
long
, __builtin_uaddll_overflow);
128
129
#undef SPECIALIZE_builtin_add_overflow
130
#endif
// __GNUC__ >= 5 || __clang_major >= 3
131
132
#endif
133
134
}
// namespace Internal
135
156
template
<
typename
T>
157
T
add
(T summand_1, T summand_2) {
158
T res = 0;
159
if
(
Internal::builtin_add_overflow
(summand_1, summand_2, res)) {
160
throw
std::overflow_error(
"Overflow in addition"
);
161
}
162
return
res;
163
}
164
187
template
<
typename
T>
188
T
abs
(T num)
noexcept
{
189
if
constexpr
(std::is_signed_v<T>) {
190
if
(num == std::numeric_limits<T>::min())
191
return
std::numeric_limits<T>::max();
192
return
num < 0 ? -num : num;
193
}
194
return
num;
195
}
196
197
}
// namespace Safe
198
199
#endif
// SAFE_OP_HPP_
Safe::Internal
Helper functions for providing integer overflow checks.
Definition
safe_op.hpp:40
Safe::Internal::builtin_add_overflow
bool builtin_add_overflow(T summand_1, T summand_2, T &result)
Overflow addition check using compiler intrinsics.
Definition
safe_op.hpp:96
Safe::Internal::fallback_add_overflow
bool fallback_add_overflow(T summand_1, T summand_2, T &result)
Check the addition of two numbers for overflows for signed integer types larger than int or with the ...
Definition
safe_op.hpp:62
Safe
Arithmetic operations with overflow checks.
Definition
safe_op.hpp:17
Safe::add
T add(T summand_1, T summand_2)
Safe addition, throws an exception on overflow.
Definition
safe_op.hpp:157
Safe::abs
T abs(T num) noexcept
Calculates the absolute value of a number without producing negative values.
Definition
safe_op.hpp:188
Generated on
for Exiv2 by
1.17.0