Line | Branch | Exec | Source |
---|---|---|---|
1 | #ifndef UTIL_XMALLOC_H | ||
2 | #define UTIL_XMALLOC_H | ||
3 | |||
4 | #include <stddef.h> | ||
5 | #include <string.h> | ||
6 | #include "arith.h" | ||
7 | #include "macros.h" | ||
8 | |||
9 | #define XMEMDUP(ptr) xmemdup(ptr, sizeof(*ptr)) | ||
10 | #define xnew(type, n) xmallocarray((n), sizeof(type)) | ||
11 | #define xnew0(type, n) xcalloc((n), sizeof(type)) | ||
12 | #define xrenew(mem, n) xreallocarray(mem, (n), sizeof(*mem)) | ||
13 | |||
14 | void *xmalloc(size_t size) XMALLOC ALLOC_SIZE(1); | ||
15 | void *xcalloc(size_t nmemb, size_t size) XMALLOC ALLOC_SIZE(1, 2); | ||
16 | void *xrealloc(void *ptr, size_t size) RETURNS_NONNULL WARN_UNUSED_RESULT ALLOC_SIZE(2); | ||
17 | char *xstrdup(const char *str) XSTRDUP; | ||
18 | char *xasprintf(const char *format, ...) PRINTF(1) XMALLOC; | ||
19 | size_t xmul_(size_t a, size_t b); | ||
20 | size_t xadd(size_t a, size_t b); | ||
21 | |||
22 | // Equivalent to `a * b`, but calling fatal_error() for arithmetic overflow. | ||
23 | // Note that if either operand is 2, adding 1 to the result can never | ||
24 | // overflow (often useful when doubling a buffer plus 1 extra byte). Similar | ||
25 | // observations can be made when multiplying by other powers of 2 (except 1) | ||
26 | // due to the equivalence with left shifting. | ||
27 | 16987 | static inline size_t xmul(size_t a, size_t b) | |
28 | { | ||
29 | // If either argument is known at compile-time to be 1, the multiplication | ||
30 | // can't overflow and is thus safe to be inlined without checks | ||
31 |
2/8✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 16987 times.
✗ Branch 2 (3→4) not taken.
✗ Branch 3 (3→6) not taken.
✗ Branch 4 (4→5) not taken.
✓ Branch 5 (4→7) taken 16987 times.
✗ Branch 6 (5→6) not taken.
✗ Branch 7 (5→7) not taken.
|
16987 | if ((IS_CT_CONSTANT(a) && a <= 1) || (IS_CT_CONSTANT(b) && b <= 1)) { |
32 | − | return a * b; // GCOVR_EXCL_LINE | |
33 | } | ||
34 | // Otherwise, emit a call to the checked implementation | ||
35 | 16987 | return xmul_(a, b); | |
36 | } | ||
37 | |||
38 | 4 | static inline size_t xadd3(size_t a, size_t b, size_t c) | |
39 | { | ||
40 | 4 | return xadd(a, xadd(b, c)); | |
41 | } | ||
42 | |||
43 | XMALLOC ALLOC_SIZE(1, 2) | ||
44 | 1830 | static inline void *xmallocarray(size_t nmemb, size_t size) | |
45 | { | ||
46 | 1830 | return xmalloc(xmul(nmemb, size)); | |
47 | } | ||
48 | |||
49 | RETURNS_NONNULL WARN_UNUSED_RESULT ALLOC_SIZE(2, 3) | ||
50 | 11446 | static inline void *xreallocarray(void *ptr, size_t nmemb, size_t size) | |
51 | { | ||
52 | 11446 | return xrealloc(ptr, xmul(nmemb, size)); | |
53 | } | ||
54 | |||
55 | NONNULL_ARGS_AND_RETURN ALLOC_SIZE(2) | ||
56 | 3995 | static inline void *xmemdup(const void *ptr, size_t size) | |
57 | { | ||
58 | 3995 | return memcpy(xmalloc(size), ptr, size); | |
59 | } | ||
60 | |||
61 | // Return a null-terminated copy of the first `size` bytes of `str` | ||
62 | XSTRDUP | ||
63 | 328 | static inline char *xstrcut(const char *str, size_t size) | |
64 | { | ||
65 | 328 | char *s = xmalloc(size + 1); | |
66 | 328 | s[size] = '\0'; | |
67 | 328 | return memcpy(s, str, size); | |
68 | } | ||
69 | |||
70 | // Return a null-terminated copy of the substring between `pos` and `end` | ||
71 | XSTRDUP | ||
72 | 87 | static inline char *xstrslice(const char *str, size_t pos, size_t end) | |
73 | { | ||
74 | 87 | BUG_ON(pos > end); | |
75 | 87 | return xstrcut(str + pos, end - pos); | |
76 | } | ||
77 | |||
78 | // Portable version of glibc/FreeBSD mempcpy(3) | ||
79 | 1451 | static inline void *xmempcpy(void *restrict dest, const void *restrict src, size_t n) | |
80 | { | ||
81 | 1451 | memcpy(dest, src, n); | |
82 | 1451 | return (char*)dest + n; | |
83 | } | ||
84 | |||
85 | NONNULL_ARGS_AND_RETURN | ||
86 | 1449 | static inline void *xmemjoin(const void *p1, size_t n1, const void *p2, size_t n2) | |
87 | { | ||
88 | 1449 | char *joined = xmalloc(xadd(n1, n2)); | |
89 | 1449 | memcpy(xmempcpy(joined, p1, n1), p2, n2); | |
90 | 1449 | return joined; | |
91 | } | ||
92 | |||
93 | NONNULL_ARGS_AND_RETURN | ||
94 | 1 | static inline void *xmemjoin3 ( | |
95 | const void *p1, size_t n1, | ||
96 | const void *p2, size_t n2, | ||
97 | const void *p3, size_t n3 | ||
98 | ) { | ||
99 | 1 | char *joined = xmalloc(xadd3(n1, n2, n3)); | |
100 | 1 | memcpy(xmempcpy(xmempcpy(joined, p1, n1), p2, n2), p3, n3); | |
101 | 1 | return joined; | |
102 | } | ||
103 | |||
104 | XSTRDUP | ||
105 | 1391 | static inline char *xstrjoin(const char *s1, const char *s2) | |
106 | { | ||
107 | 1391 | return xmemjoin(s1, strlen(s1), s2, strlen(s2) + 1); | |
108 | } | ||
109 | |||
110 | #endif | ||
111 |