rcx

library of miscellaneous bits of C code
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

commit 10821efb8b7d9688408de07f4dbd0078ed6ec2fa
parent 18f833e9a6f8aae2b678ff9a749e9ec0c75eca3f
Author: Robert Russell <robertrussell.72001@gmail.com>
Date:   Wed,  7 Sep 2022 14:44:22 -0700

Change realloc function signatures

On allocation failure, realloc returns NULL and does not touch
the given memory block. Thus, writing simply
	p = realloc(p, newsize);
is wrong, because we lose the pointer to the memory block on
failure. Instead, we must write
	void *q = realloc(p, newsize);
	if (!q)
		handle_error();
	p = q;
which is a bit cumbersome. With the new function signatures,
we simply write
	if (r_realloc(&p, newsize) < 0)
		handle_error();
or
	r_erealloc(&p, newsize);

Diffstat:
Minc/rcx/alloc.h | 16++++++++--------
Minc/rcx/deque.h | 8+++-----
Minc/rcx/vector.h | 4++--
Msrc/alloc.c | 64++++++++++++++++++++++++++++++++++++++--------------------------
4 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/inc/rcx/alloc.h b/inc/rcx/alloc.h @@ -14,17 +14,17 @@ void *r_alloc(usize size); /* aka malloc */ void *r_allocz(usize size); void *r_allocn(usize len, usize size); void *r_allocnz(usize len, usize size); /* aka calloc */ -void *r_realloc(void *p, usize size); -void *r_reallocz(void *p, usize osize, usize nsize); -void *r_reallocn(void *p, usize len, usize size); -void *r_reallocnz(void *p, usize olen, usize nlen, usize size); +int r_realloc(void **p, usize size); +int r_reallocz(void **p, usize osize, usize nsize); +int r_reallocn(void **p, usize len, usize size); +int r_reallocnz(void **p, usize olen, usize nlen, usize size); void *r_ealloc(usize size); void *r_eallocz(usize size); void *r_eallocn(usize len, usize size); void *r_eallocnz(usize len, usize size); -void *r_erealloc(void *p, usize size); -void *r_ereallocz(void *p, usize osize, usize nsize); -void *r_ereallocn(void *p, usize len, usize size); -void *r_ereallocnz(void *p, usize olen, usize nlen, usize size); +void r_erealloc(void **p, usize size); +void r_ereallocz(void **p, usize osize, usize nsize); +void r_ereallocn(void **p, usize len, usize size); +void r_ereallocnz(void **p, usize olen, usize nlen, usize size); void free(void *p); diff --git a/inc/rcx/deque.h b/inc/rcx/deque.h @@ -59,23 +59,21 @@ int R_DEQUE_METHOD(reserve,##__VA_ARGS__)(D *d, usize n) { \ if (ncap == 0) \ return -1; /* Overflow */ \ } \ - T *narr = R_DEQUE_REALLOCN(d->arr, ncap, sizeof *narr); \ - if (!narr) \ + if (R_DEQUE_REALLOCN(&d->arr, ncap, sizeof *d->arr) < 0) \ return -1; \ if (d->l == d->cap) { \ d->l = ncap; /* Maintain invariant for empty deques */ \ } else if (d->r <= d->l) { \ /* Move as little as possible */ \ if (d->r <= d->cap - d->l) { \ - memcpy(&narr[d->cap], &narr[0], d->r * sizeof *narr); \ + memcpy(&d->arr[d->cap], &d->arr[0], d->r * sizeof *d->arr); \ d->r += d->cap; \ } else { \ usize m = d->cap - d->l; \ - memcpy(&narr[ncap-m], &narr[d->l], m * sizeof *narr); \ + memcpy(&d->arr[ncap-m], &d->arr[d->l], m * sizeof *d->arr); \ d->l = ncap - m; \ } \ } \ - d->arr = narr; \ d->cap = ncap; \ return 0; \ } \ diff --git a/inc/rcx/vector.h b/inc/rcx/vector.h @@ -59,8 +59,8 @@ int R_VECTOR_METHOD(resize,##__VA_ARGS__)(T **v, usize cap) { \ errno = ENOMEM; \ return -1; \ } \ - h = R_VECTOR_REALLOC(h, sizeof *h + arrsize); \ - if (!h) return -1; \ + if (R_VECTOR_REALLOC(&h, sizeof *h + arrsize) < 0) \ + return -1; \ h->len = MIN(len, cap); \ h->cap = cap; \ *v = (void *)(h + 1); \ diff --git a/src/alloc.c b/src/alloc.c @@ -32,51 +32,63 @@ r_allocnz(usize len, usize size) { return calloc(len, size); } -void * -r_realloc(void *p, usize size) { - return realloc(p, size); +int +r_realloc(void **p, usize size) { + void *q = realloc(*p, size); + if (!q) return -1; + *p = q; + return 0; } -void * -r_reallocz(void *p, usize osize, usize nsize) { - p = r_realloc(p, nsize); - if (p && nsize > osize) - memset((char *) p + osize, 0, nsize - osize); - return p; +int +r_reallocz(void **p, usize osize, usize nsize) { + int ret = r_realloc(p, nsize); + if (ret == 0 && nsize > osize) + memset((char *)*p + osize, 0, nsize - osize); + return ret; } -void * -r_reallocn(void *p, usize len, usize size) { +int +r_reallocn(void **p, usize len, usize size) { if (r_mul_will_overflow_(len, size)) { errno = ENOMEM; - return 0; + return -1; } return r_realloc(p, len * size); } -void * -r_reallocnz(void *p, usize olen, usize nlen, usize size) { +int +r_reallocnz(void **p, usize olen, usize nlen, usize size) { if (r_mul_will_overflow_(nlen, size)) { errno = ENOMEM; - return 0; + return -1; } return r_reallocz(p, olen * size, nlen * size); } -#define EALLOC(name, ...)\ - void *r_e##name(__VA_ARGS__) {\ - void *q = r_##name(EALLOC_AUX +#define EALLOC(mods, ...)\ + void *r_ealloc##mods(__VA_ARGS__) {\ + void *q = r_alloc##mods(EALLOC_AUX #define EALLOC_AUX(...)\ __VA_ARGS__);\ if (!q) r_fatalf("allocation failure");\ return q;\ } -EALLOC(alloc, usize size)(size) -EALLOC(allocz, usize size)(size) -EALLOC(allocn, usize len, usize size)(len, size) -EALLOC(allocnz, usize len, usize size)(len, size) -EALLOC(realloc, void *p, usize size)(p, size) -EALLOC(reallocz, void *p, usize osize, usize nsize)(p, osize, nsize) -EALLOC(reallocn, void *p, usize len, usize size)(p, len, size) -EALLOC(reallocnz, void *p, usize olen, usize nlen, usize size)(p, olen, nlen, size) +EALLOC(, usize size)(size) +EALLOC(z, usize size)(size) +EALLOC(n, usize len, usize size)(len, size) +EALLOC(nz, usize len, usize size)(len, size) + +#define EREALLOC(mods, ...)\ + void r_erealloc##mods(void **p, __VA_ARGS__) {\ + int ret = r_realloc##mods(p, EREALLOC_AUX +#define EREALLOC_AUX(...)\ + __VA_ARGS__);\ + if (ret < 0) r_fatalf("allocation failure");\ + } + +EREALLOC(, usize size)(size) +EREALLOC(z, usize osize, usize nsize)(osize, nsize) +EREALLOC(n, usize len, usize size)(len, size) +EREALLOC(nz, usize olen, usize nlen, usize size)(olen, nlen, size)