dte test coverage


Directory: ./
File: src/util/arith.h
Date: 2025-05-08 15:05:54
Exec Total Coverage
Lines: 19 19 100.0%
Functions: 7 7 100.0%
Branches: 6 6 100.0%

Line Branch Exec Source
1 #ifndef UTIL_ARITH_H
2 #define UTIL_ARITH_H
3
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 #include "debug.h"
8 #include "macros.h"
9
10 // Calculate the maximum representable value for __typeof__(x), where x
11 // is an unsigned integer and sizeof(x) >= sizeof(int)
12 #define UNSIGNED_MAX_VALUE(x) (~((x) ^ (x)))
13
14 #if GNUC_AT_LEAST(5, 0) || HAS_BUILTIN(__builtin_mul_overflow)
15 #define CHECKED_ADD(a, b, res) return __builtin_add_overflow(a, b, res)
16 #define CHECKED_MUL(a, b, res) return __builtin_mul_overflow(a, b, res)
17 #elif __STDC_VERSION__ >= 202311L
18 #include <stdckdint.h>
19 #define CHECKED_ADD(a, b, res) return ckd_add(res, a, b)
20 #define CHECKED_MUL(a, b, res) return ckd_mul(res, a, b)
21 #else
22 #define CHECKED_ADD(a, b, res) \
23 if (unlikely(b > UNSIGNED_MAX_VALUE(a) - a)) return true; else {*res = a + b; return false;}
24 #define CHECKED_MUL(a, b, res) \
25 if (unlikely(a > 0 && b > UNSIGNED_MAX_VALUE(a) / a)) return true; else {*res = a * b; return false;}
26 #endif
27
28 470 static inline bool umax_multiply_overflows(uintmax_t a, uintmax_t b, uintmax_t *result)
29 {
30 470 CHECKED_MUL(a, b, result);
31 }
32
33 14024 static inline bool size_multiply_overflows(size_t a, size_t b, size_t *result)
34 {
35 14024 CHECKED_MUL(a, b, result);
36 }
37
38 464 static inline bool umax_add_overflows(uintmax_t a, uintmax_t b, uintmax_t *result)
39 {
40 464 CHECKED_ADD(a, b, result);
41 }
42
43 206090 static inline bool size_add_overflows(size_t a, size_t b, size_t *result)
44 {
45 206090 CHECKED_ADD(a, b, result);
46 }
47
48 // Saturating subtract
49 12 static inline size_t size_ssub(size_t a, size_t b)
50 {
51 12 size_t r = a - b;
52
2/2
✓ Branch 0 (2→3) taken 4 times.
✓ Branch 1 (2→4) taken 8 times.
12 return (r > a) ? 0 : r;
53 }
54
55 // This is equivalent to `(x + 1) % modulus`, given the constraints
56 // imposed by BUG_ON(), but avoids expensive divisions by a non-constant
57 65 static inline size_t size_increment_wrapped(size_t x, size_t modulus)
58 {
59 65 BUG_ON(modulus == 0);
60 65 BUG_ON(x >= modulus);
61
2/2
✓ Branch 0 (6→7) taken 49 times.
✓ Branch 1 (6→8) taken 16 times.
65 return (x + 1 < modulus) ? x + 1 : 0;
62 }
63
64 // As above, but for decrementing `x` instead of incrementing it
65 51 static inline size_t size_decrement_wrapped(size_t x, size_t modulus)
66 {
67 51 BUG_ON(modulus == 0);
68 51 BUG_ON(x >= modulus);
69
2/2
✓ Branch 0 (6→7) taken 37 times.
✓ Branch 1 (6→8) taken 14 times.
51 return (x ? x : modulus) - 1;
70 }
71
72 #endif
73