]> git.proxmox.com Git - libgit2.git/blob - src/integer.h
install as examples
[libgit2.git] / src / integer.h
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7 #ifndef INCLUDE_integer_h__
8 #define INCLUDE_integer_h__
9
10 /** @return true if p fits into the range of a size_t */
11 GIT_INLINE(int) git__is_sizet(int64_t p)
12 {
13 size_t r = (size_t)p;
14 return p == (int64_t)r;
15 }
16
17 /** @return true if p fits into the range of an ssize_t */
18 GIT_INLINE(int) git__is_ssizet(size_t p)
19 {
20 ssize_t r = (ssize_t)p;
21 return p == (size_t)r;
22 }
23
24 /** @return true if p fits into the range of a uint16_t */
25 GIT_INLINE(int) git__is_uint16(size_t p)
26 {
27 uint16_t r = (uint16_t)p;
28 return p == (size_t)r;
29 }
30
31 /** @return true if p fits into the range of a uint32_t */
32 GIT_INLINE(int) git__is_uint32(size_t p)
33 {
34 uint32_t r = (uint32_t)p;
35 return p == (size_t)r;
36 }
37
38 /** @return true if p fits into the range of an unsigned long */
39 GIT_INLINE(int) git__is_ulong(int64_t p)
40 {
41 unsigned long r = (unsigned long)p;
42 return p == (int64_t)r;
43 }
44
45 /** @return true if p fits into the range of an int */
46 GIT_INLINE(int) git__is_int(long long p)
47 {
48 int r = (int)p;
49 return p == (long long)r;
50 }
51
52 /* Use clang/gcc compiler intrinsics whenever possible */
53 #if (__has_builtin(__builtin_add_overflow) || \
54 (defined(__GNUC__) && (__GNUC__ >= 5)))
55
56 # if (SIZE_MAX == UINT_MAX)
57 # define git__add_sizet_overflow(out, one, two) \
58 __builtin_uadd_overflow(one, two, out)
59 # define git__multiply_sizet_overflow(out, one, two) \
60 __builtin_umul_overflow(one, two, out)
61 # elif (SIZE_MAX == ULONG_MAX)
62 # define git__add_sizet_overflow(out, one, two) \
63 __builtin_uaddl_overflow(one, two, out)
64 # define git__multiply_sizet_overflow(out, one, two) \
65 __builtin_umull_overflow(one, two, out)
66 # elif (SIZE_MAX == ULLONG_MAX)
67 # define git__add_sizet_overflow(out, one, two) \
68 __builtin_uaddll_overflow(one, two, out)
69 # define git__multiply_sizet_overflow(out, one, two) \
70 __builtin_umulll_overflow(one, two, out)
71 # else
72 # error compiler has add with overflow intrinsics but SIZE_MAX is unknown
73 # endif
74
75 # define git__add_int_overflow(out, one, two) \
76 __builtin_sadd_overflow(one, two, out)
77 # define git__sub_int_overflow(out, one, two) \
78 __builtin_ssub_overflow(one, two, out)
79
80 /* Use Microsoft's safe integer handling functions where available */
81 #elif defined(_MSC_VER)
82
83 # define ENABLE_INTSAFE_SIGNED_FUNCTIONS
84 # include <intsafe.h>
85
86 # define git__add_sizet_overflow(out, one, two) \
87 (SizeTAdd(one, two, out) != S_OK)
88 # define git__multiply_sizet_overflow(out, one, two) \
89 (SizeTMult(one, two, out) != S_OK)
90 #define git__add_int_overflow(out, one, two) \
91 (IntAdd(one, two, out) != S_OK)
92 #define git__sub_int_overflow(out, one, two) \
93 (IntSub(one, two, out) != S_OK)
94
95 #else
96
97 /**
98 * Sets `one + two` into `out`, unless the arithmetic would overflow.
99 * @return false if the result fits in a `size_t`, true on overflow.
100 */
101 GIT_INLINE(bool) git__add_sizet_overflow(size_t *out, size_t one, size_t two)
102 {
103 if (SIZE_MAX - one < two)
104 return true;
105 *out = one + two;
106 return false;
107 }
108
109 /**
110 * Sets `one * two` into `out`, unless the arithmetic would overflow.
111 * @return false if the result fits in a `size_t`, true on overflow.
112 */
113 GIT_INLINE(bool) git__multiply_sizet_overflow(size_t *out, size_t one, size_t two)
114 {
115 if (one && SIZE_MAX / one < two)
116 return true;
117 *out = one * two;
118 return false;
119 }
120
121 GIT_INLINE(bool) git__add_int_overflow(int *out, int one, int two)
122 {
123 if ((two > 0 && one > (INT_MAX - two)) ||
124 (two < 0 && one < (INT_MIN - two)))
125 return true;
126 *out = one + two;
127 return false;
128 }
129
130 GIT_INLINE(bool) git__sub_int_overflow(int *out, int one, int two)
131 {
132 if ((two > 0 && one < (INT_MIN + two)) ||
133 (two < 0 && one > (INT_MAX + two)))
134 return true;
135 *out = one - two;
136 return false;
137 }
138
139 #endif
140
141 #endif