C/C++ API Reference
Loading...
Searching...
No Matches
checked_arithmetic.h
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
23#define PW_ADD_OVERFLOW(a, b, out) __builtin_add_overflow(a, b, out)
24
33#define PW_SUB_OVERFLOW(a, b, out) __builtin_sub_overflow(a, b, out)
34
41#define PW_MUL_OVERFLOW(a, b, out) __builtin_mul_overflow(a, b, out)
42
43#ifdef __cplusplus
44
45#include <cstdint>
46#include <limits>
47#include <optional>
48#include <type_traits>
49
50namespace pw {
51
53
69template <typename A, typename B, typename T>
70[[nodiscard]] constexpr bool CheckedAdd(A a, B b, T& result) {
71 T temp = 0;
72
73 if (PW_ADD_OVERFLOW(a, b, &temp)) {
74 return false;
75 }
76 result = temp;
77
78 return true;
79}
80
95template <typename T, typename A, typename B>
96[[nodiscard]] constexpr std::optional<T> CheckedAdd(A a, B b) {
97 T result{0};
98
99 if (!CheckedAdd(a, b, result)) {
100 return std::nullopt;
101 }
102
103 return result;
104}
105
117template <typename T, typename Inc>
118[[nodiscard]] constexpr bool CheckedIncrement(T& base, Inc inc) {
119 return CheckedAdd(base, inc, base);
120}
121
137template <typename A, typename B, typename T>
138[[nodiscard]] constexpr bool CheckedSub(A a, B b, T& result) {
139 T temp = 0;
140
141 if (PW_SUB_OVERFLOW(a, b, &temp)) {
142 return false;
143 }
144 result = temp;
145
146 return true;
147}
148
163template <typename T, typename A, typename B>
164[[nodiscard]] constexpr std::optional<T> CheckedSub(A a, B b) {
165 T result{0};
166
167 if (!CheckedSub(a, b, result)) {
168 return std::nullopt;
169 }
170
171 return result;
172}
173
185template <typename T, typename Dec>
186[[nodiscard]] constexpr bool CheckedDecrement(T& base, Dec dec) {
187 return CheckedSub(base, dec, base);
188}
189
205template <typename A, typename B, typename T>
206[[nodiscard]] constexpr bool CheckedMul(A a, B b, T& result) {
207 T temp = 0;
208
209 if (PW_MUL_OVERFLOW(a, b, &temp)) {
210 return false;
211 }
212 result = temp;
213
214 return true;
215}
216
231template <typename T, typename A, typename B>
232[[nodiscard]] constexpr std::optional<T> CheckedMul(A a, B b) {
233 T result{0};
234
235 if (!CheckedMul(a, b, result)) {
236 return std::nullopt;
237 }
238
239 return result;
240}
241
242} // namespace pw
243
244#endif // __cplusplus
constexpr bool CheckedDecrement(T &base, Dec dec)
Definition: checked_arithmetic.h:186
constexpr bool CheckedIncrement(T &base, Inc inc)
Definition: checked_arithmetic.h:118
constexpr bool CheckedAdd(A a, B b, T &result)
Definition: checked_arithmetic.h:70
constexpr bool CheckedMul(A a, B b, T &result)
Definition: checked_arithmetic.h:206
constexpr bool CheckedSub(A a, B b, T &result)
Definition: checked_arithmetic.h:138
The Pigweed namespace.
Definition: alignment.h:27