Bond
 
Loading...
Searching...
No Matches
checked.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include <boost/static_assert.hpp>
9#include <boost/utility/enable_if.hpp>
10
11#include <cstdint>
12#include <limits>
13#include <stdexcept>
14#include <type_traits>
15
16namespace bond
17{
18namespace detail
19{
20
21 inline const char* checked_add(const char* ptr, uint32_t offset)
22 {
23 // Numeric limit logic below requires uintptr_t to be exactly same size as a pointer
24 BOOST_STATIC_ASSERT(sizeof(const char*) == sizeof(std::uintptr_t));
25
26 std::uintptr_t uintptr = reinterpret_cast<std::uintptr_t>(ptr);
27 if (((std::numeric_limits<uintptr_t>::max)() - offset) < uintptr)
28 {
29 throw std::overflow_error("Offset caused pointer to overflow");
30 }
31 return ptr + offset;
32 }
33
34 template <typename T, typename U>
35 inline typename boost::enable_if_c<std::is_unsigned<T>::value && std::is_unsigned<U>::value, T>::type
36 checked_add(T lhs, U rhs)
37 {
38 BOOST_STATIC_ASSERT(sizeof(T) >= sizeof(U));
39
40 if (((std::numeric_limits<T>::max)() - lhs) < rhs)
41 {
42 throw std::overflow_error("Overflow on addition");
43 }
44 return lhs + rhs;
45 }
46
47 template <typename T>
48 inline typename boost::enable_if_c<std::is_unsigned<T>::value && (sizeof(T) < sizeof(uint64_t)), T>::type
49 checked_multiply(T lhs, uint8_t rhs)
50 {
51 uint64_t result = static_cast<uint64_t>(lhs) * static_cast<uint64_t>(rhs);
52
53 if (result > (std::numeric_limits<T>::max)())
54 {
55 throw std::overflow_error("Overflow on multiplication");
56 }
57
58 return static_cast<T>(result);
59 }
60
61} // namespace detail
62} // namespace bond
63
namespace bond
Definition: apply.h:17