1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 #include <sal/config.h>
14 #include <type_traits>
17 #include <o3tl/safeint.hxx>
21 // An approximation of the C++20 integer comparison functions
22 // (<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0586r2.html> "Safe integral
23 // comparisons"), still missing from LLVM 12 libc++:
24 #if defined __cpp_lib_integer_comparison_functions
27 using std::cmp_not_equal
;
29 using std::cmp_greater
;
30 using std::cmp_less_equal
;
31 using std::cmp_greater_equal
;
35 template <typename T1
, typename T2
> constexpr bool cmp_equal(T1 value1
, T2 value2
) noexcept
37 // coverity[same_on_both_sides: FALSE]
38 if constexpr (std::is_signed_v
<T1
> == std::is_signed_v
<T2
>)
40 return value1
== value2
;
42 else if constexpr (std::is_signed_v
<T1
>)
44 return value1
>= 0 && o3tl::make_unsigned(value1
) == value2
;
48 return value2
>= 0 && value1
== o3tl::make_unsigned(value2
);
52 template <typename T1
, typename T2
> constexpr bool cmp_not_equal(T1 value1
, T2 value2
) noexcept
54 return !cmp_equal(value1
, value2
);
57 template <typename T1
, typename T2
> constexpr bool cmp_less(T1 value1
, T2 value2
) noexcept
59 if constexpr (std::is_signed_v
<T1
> == std::is_signed_v
<T2
>)
61 return value1
< value2
;
63 else if constexpr (std::is_signed_v
<T1
>)
65 return value1
< 0 || o3tl::make_unsigned(value1
) < value2
;
69 return value2
>= 0 && value1
< o3tl::make_unsigned(value2
);
73 template <typename T1
, typename T2
> constexpr bool cmp_greater(T1 value1
, T2 value2
) noexcept
75 return cmp_less(value2
, value1
);
78 template <typename T1
, typename T2
> constexpr bool cmp_less_equal(T1 value1
, T2 value2
) noexcept
80 return !cmp_greater(value1
, value2
);
83 template <typename T1
, typename T2
> constexpr bool cmp_greater_equal(T1 value1
, T2 value2
) noexcept
85 return !cmp_less(value1
, value2
);
90 // A convenient operator syntax around the standard integer comparison functions:
91 template <typename T
> struct IntCmp
93 explicit constexpr IntCmp(T theValue
)
101 template <typename T1
, typename T2
> constexpr bool operator==(IntCmp
<T1
> value1
, IntCmp
<T2
> value2
)
103 return o3tl::cmp_equal(value1
.value
, value2
.value
);
106 template <typename T1
, typename T2
> constexpr bool operator!=(IntCmp
<T1
> value1
, IntCmp
<T2
> value2
)
108 return o3tl::cmp_not_equal(value1
.value
, value2
.value
);
111 template <typename T1
, typename T2
> constexpr bool operator<(IntCmp
<T1
> value1
, IntCmp
<T2
> value2
)
113 return o3tl::cmp_less(value1
.value
, value2
.value
);
116 template <typename T1
, typename T2
> constexpr bool operator>(IntCmp
<T1
> value1
, IntCmp
<T2
> value2
)
118 return o3tl::cmp_greater(value1
.value
, value2
.value
);
121 template <typename T1
, typename T2
> constexpr bool operator<=(IntCmp
<T1
> value1
, IntCmp
<T2
> value2
)
123 return o3tl::cmp_less_equal(value1
.value
, value2
.value
);
126 template <typename T1
, typename T2
> constexpr bool operator>=(IntCmp
<T1
> value1
, IntCmp
<T2
> value2
)
128 return o3tl::cmp_greater_equal(value1
.value
, value2
.value
);
132 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */