blob: bf3e286be8add7aa6fab700b06b34a4462eb8d1a [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_COMMON_CHECKED_MATH_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_COMMON_CHECKED_MATH_H_
#include <optional>
namespace zxdb {
// Returns the result of adding |lhs| and |rhs|. If the result overflows, then std::nullopt is
// returned. The sizes of the types for |lhs| and |rhs| may differ. The returned value will be
// stored in the larger of the two and is the type that must overflow for this function to return
// std::nullopt.
//
// Use it like:
//
// uint64_t some_number = 0;
// if (auto checked_sum = CheckedAdd(1, 2)) {
// some_number = *checked_sum;
// } else {
// return Err("Overflow!");
// }
template <typename T, typename U, typename R = std::conditional_t<sizeof(T) >= sizeof(U), T, U>>
constexpr std::optional<R> CheckedAdd(T lhs, U rhs) {
#if __has_builtin(__builtin_add_overflow)
T res = 0;
if (__builtin_add_overflow(lhs, rhs, &res)) {
return std::nullopt;
}
return std::optional<T>(res);
#else
#error "No overflow intrinsic available!"
#endif
}
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_COMMON_CHECKED_MATH_H_