]> git.proxmox.com Git - libgit2.git/blob - src/integer.h
Merge pull request #2885 from JIghtuse/master
[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(git_off_t p)
12 {
13 size_t r = (size_t)p;
14 return p == (git_off_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 uint32_t */
25 GIT_INLINE(int) git__is_uint32(size_t p)
26 {
27 uint32_t r = (uint32_t)p;
28 return p == (size_t)r;
29 }
30
31 /** @return true if p fits into the range of an unsigned long */
32 GIT_INLINE(int) git__is_ulong(git_off_t p)
33 {
34 unsigned long r = (unsigned long)p;
35 return p == (git_off_t)r;
36 }
37
38 /** @return true if p fits into the range of an int */
39 GIT_INLINE(int) git__is_int(long long p)
40 {
41 int r = (int)p;
42 return p == (long long)r;
43 }
44
45 /**
46 * Sets `one + two` into `out`, unless the arithmetic would overflow.
47 * @return true if the result fits in a `uint64_t`, false on overflow.
48 */
49 GIT_INLINE(bool) git__add_uint64_overflow(uint64_t *out, uint64_t one, uint64_t two)
50 {
51 if (UINT64_MAX - one < two)
52 return true;
53 *out = one + two;
54 return false;
55 }
56
57 /* Use clang/gcc compiler intrinsics whenever possible */
58 #if (SIZE_MAX == UINT_MAX) && __has_builtin(__builtin_uadd_overflow)
59 # define git__add_sizet_overflow(out, one, two) \
60 __builtin_uadd_overflow(one, two, out)
61 # define git__multiply_sizet_overflow(out, one, two) \
62 __builtin_umul_overflow(one, two, out)
63 #elif (SIZE_MAX == ULONG_MAX) && __has_builtin(__builtin_uaddl_overflow)
64 # define git__add_sizet_overflow(out, one, two) \
65 __builtin_uaddl_overflow(one, two, out)
66 # define git__multiply_sizet_overflow(out, one, two) \
67 __builtin_umull_overflow(one, two, out)
68 #else
69
70 /**
71 * Sets `one + two` into `out`, unless the arithmetic would overflow.
72 * @return true if the result fits in a `size_t`, false on overflow.
73 */
74 GIT_INLINE(bool) git__add_sizet_overflow(size_t *out, size_t one, size_t two)
75 {
76 if (SIZE_MAX - one < two)
77 return true;
78 *out = one + two;
79 return false;
80 }
81
82 /**
83 * Sets `one * two` into `out`, unless the arithmetic would overflow.
84 * @return true if the result fits in a `size_t`, false on overflow.
85 */
86 GIT_INLINE(bool) git__multiply_sizet_overflow(size_t *out, size_t one, size_t two)
87 {
88 if (one && SIZE_MAX / one < two)
89 return true;
90 *out = one * two;
91 return false;
92 }
93
94 #endif
95
96 #endif /* INCLUDE_integer_h__ */