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) xmalloc(xmul(sizeof(type), (n))) | ||
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 | 17479 | 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 not taken.
✓ Branch 1 taken 17479 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17479 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
17479 | 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 | 17479 | return xmul_(a, b); | |
36 | } | ||
37 | |||
38 | RETURNS_NONNULL WARN_UNUSED_RESULT ALLOC_SIZE(2, 3) | ||
39 | 11018 | static inline void *xreallocarray(void *ptr, size_t nmemb, size_t size) | |
40 | { | ||
41 | 11018 | return xrealloc(ptr, xmul(nmemb, size)); | |
42 | } | ||
43 | |||
44 | NONNULL_ARGS_AND_RETURN ALLOC_SIZE(2) | ||
45 | 3965 | static inline void *xmemdup(const void *ptr, size_t size) | |
46 | { | ||
47 | 3965 | return memcpy(xmalloc(size), ptr, size); | |
48 | } | ||
49 | |||
50 | // Return a null-terminated copy of the first `size` bytes of `str` | ||
51 | XSTRDUP | ||
52 | 325 | static inline char *xstrcut(const char *str, size_t size) | |
53 | { | ||
54 | 325 | char *s = xmalloc(size + 1); | |
55 | 325 | s[size] = '\0'; | |
56 | 325 | return memcpy(s, str, size); | |
57 | } | ||
58 | |||
59 | // Return a null-terminated copy of the substring between `pos` and `end` | ||
60 | XSTRDUP | ||
61 | 87 | static inline char *xstrslice(const char *str, size_t pos, size_t end) | |
62 | { | ||
63 | 87 | return xstrcut(str + pos, end - pos); | |
64 | } | ||
65 | |||
66 | NONNULL_ARGS_AND_RETURN | ||
67 | 1425 | static inline void *xmemjoin(const void *p1, size_t n1, const void *p2, size_t n2) | |
68 | { | ||
69 | 1425 | char *joined = xmalloc(xadd(n1, n2)); | |
70 | 1425 | memcpy(joined, p1, n1); | |
71 | 1425 | memcpy(joined + n1, p2, n2); | |
72 | 1425 | return joined; | |
73 | } | ||
74 | |||
75 | XSTRDUP | ||
76 | 1391 | static inline char *xstrjoin(const char *s1, const char *s2) | |
77 | { | ||
78 | 1391 | return xmemjoin(s1, strlen(s1), s2, strlen(s2) + 1); | |
79 | } | ||
80 | |||
81 | #endif | ||
82 |