rcx

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

commit 58ec1e65dd8320654ce9ba920f6847270cddc384
parent 793139462e5134659ff54b99af7116be2e6e4dfc
Author: Robert Russell <robertrussell.72001@gmail.com>
Date:   Thu, 23 Feb 2023 22:40:11 -0800

Flatten inc directory

Diffstat:
MMakefile | 24++++++++++++------------
Ainc/all.h | 13+++++++++++++
Ainc/alloc.h | 29+++++++++++++++++++++++++++++
Ainc/bench.h | 25+++++++++++++++++++++++++
Ainc/bits.h | 8++++++++
Rinc/rcx/def.h -> inc/def.h | 0
Ainc/deque.h | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainc/error.h | 34++++++++++++++++++++++++++++++++++
Rinc/rcx/internal/util.h -> inc/internal/util.h | 0
Rinc/rcx/log.h -> inc/log.h | 0
Rinc/rcx/opt.h -> inc/opt.h | 0
Ainc/rcx.h | 16++++++++++++++++
Dinc/rcx/all.h | 13-------------
Dinc/rcx/alloc.h | 29-----------------------------
Dinc/rcx/bench.h | 25-------------------------
Dinc/rcx/bits.h | 8--------
Dinc/rcx/deque.h | 122-------------------------------------------------------------------------------
Dinc/rcx/error.h | 34----------------------------------
Dinc/rcx/rcx.h | 16----------------
Dinc/rcx/str.h | 31-------------------------------
Dinc/rcx/unicode.h | 11-----------
Dinc/rcx/unix.h | 34----------------------------------
Dinc/rcx/utf8.h | 21---------------------
Dinc/rcx/vector.h | 144-------------------------------------------------------------------------------
Ainc/str.h | 31+++++++++++++++++++++++++++++++
Ainc/unicode.h | 11+++++++++++
Ainc/unix.h | 34++++++++++++++++++++++++++++++++++
Ainc/utf8.h | 21+++++++++++++++++++++
Ainc/vector.h | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/alloc.c | 8++++----
Msrc/bench.c | 6+++---
Msrc/bits.c | 4++--
Msrc/error.c | 6+++---
Msrc/log.c | 4++--
Msrc/opt.c | 4++--
Msrc/str.c | 8++++----
Msrc/unicode.c | 2+-
Msrc/unix.c | 4++--
Msrc/utf8.c | 4++--
Mtool/ucattab.c | 8++++----
40 files changed, 529 insertions(+), 529 deletions(-)

diff --git a/Makefile b/Makefile @@ -20,16 +20,16 @@ librcx.a: $(SRC:.c=.o) .c.o: $(CC) -c -o $@ $(CFLAGS) $< -src/alloc.o: src/alloc.c inc/rcx/alloc.h inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h inc/rcx/internal/util.h config.mk -src/bench.o: src/bench.c inc/rcx/bench.h inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h config.mk -src/bits.o: src/bits.c inc/rcx/bits.h inc/rcx/def.h inc/rcx/rcx.h config.mk -src/error.o: src/error.c inc/rcx/def.h inc/rcx/error.h inc/rcx/log.h inc/rcx/rcx.h config.mk -src/log.o: src/log.c inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h config.mk -src/opt.o: src/opt.c inc/rcx/def.h inc/rcx/opt.h inc/rcx/rcx.h config.mk -src/str.o: src/str.c inc/rcx/alloc.h inc/rcx/def.h inc/rcx/log.h inc/rcx/rcx.h inc/rcx/str.h config.mk -src/unicode.o: src/unicode.c inc/rcx/def.h inc/rcx/rcx.h gen/ucattab.inc config.mk -src/unix.o: src/unix.c inc/rcx/def.h inc/rcx/rcx.h inc/rcx/unix.h config.mk -src/utf8.o: src/utf8.c inc/rcx/def.h inc/rcx/rcx.h inc/rcx/utf8.h config.mk +src/alloc.o: src/alloc.c inc/alloc.h inc/def.h inc/log.h inc/rcx.h inc/internal/util.h config.mk +src/bench.o: src/bench.c inc/bench.h inc/def.h inc/log.h inc/rcx.h config.mk +src/bits.o: src/bits.c inc/bits.h inc/def.h inc/rcx.h config.mk +src/error.o: src/error.c inc/def.h inc/error.h inc/log.h inc/rcx.h config.mk +src/log.o: src/log.c inc/def.h inc/log.h inc/rcx.h config.mk +src/opt.o: src/opt.c inc/def.h inc/opt.h inc/rcx.h config.mk +src/str.o: src/str.c inc/alloc.h inc/def.h inc/log.h inc/rcx.h inc/str.h config.mk +src/unicode.o: src/unicode.c inc/def.h inc/rcx.h gen/ucattab.inc config.mk +src/unix.o: src/unix.c inc/def.h inc/rcx.h inc/unix.h config.mk +src/utf8.o: src/utf8.c inc/def.h inc/rcx.h inc/utf8.h config.mk gen/ucattab.inc: gen tool/ucattab gen/UnicodeData.txt tool/ucattab gen/UnicodeData.txt > $@ @@ -43,9 +43,9 @@ gen: tool/ucattab: tool/ucattab.c src/alloc.o src/log.o src/str.o $(CC) -o $@ $(CFLAGS) $^ -install: librcx.a +install: librcx.a uninstall mkdir -p $(DESTDIR)$(INCPREFIX) - cp -rf inc/rcx $(DESTDIR)$(INCPREFIX)/ + cp -rf inc $(DESTDIR)$(INCPREFIX)/rcx mkdir -p $(DESTDIR)$(LIBPREFIX) cp -f librcx.a $(DESTDIR)$(LIBPREFIX)/ diff --git a/inc/all.h b/inc/all.h @@ -0,0 +1,13 @@ +/* Everything except bench.h */ +#include "alloc.h" +#include "bits.h" +#include "deque.h" +#include "error.h" +#include "log.h" +#include "opt.h" +#include "rcx.h" +#include "str.h" +#include "unicode.h" +#include "unix.h" +#include "utf8.h" +#include "vector.h" diff --git a/inc/alloc.h b/inc/alloc.h @@ -0,0 +1,29 @@ +#pragma once + +#include "def.h" + +/* A consistently-named set of memory allocators: r_{,e}{,re}alloc{,n}{,z} + * e- => allocation failures are fatal + * re- => realloc-style allocator + * -n => array allocator (with overflow check) + * -z => new memory initialized to 0. + * All these allocators are interoperable with the stdlib allocators. The + * non-e variants all set errno to ENOMEM on failure. */ +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 */ +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); +int r_erealloc(void *p, usize size); +int r_ereallocz(void *p, usize osize, usize nsize); +int r_ereallocn(void *p, usize len, usize size); +int r_ereallocnz(void *p, usize olen, usize nlen, usize size); + +void free(void *p); diff --git a/inc/bench.h b/inc/bench.h @@ -0,0 +1,25 @@ +#pragma once + +#include "def.h" + +/* +Usage: + void my_benchmark(u64 N) { + <initialization (not timed)> + r_bench_start(); + for (u64 i = 0; i < N; i++) { + <code to benchmark> + } + r_bench_stop(); + <cleanup (not timed)> + } + int main(void) { + r_bench("my benchmark", my_benchmark, 3000); + } +Note that <code to benchmark> can contain calls to r_bench_stop and +r_bench_start to pause and restart timing. +*/ + +void r_bench(char *name, void (*fn)(u64 N), u32 goalms); +void r_bench_start(void); +void r_bench_stop(void); diff --git a/inc/bits.h b/inc/bits.h @@ -0,0 +1,8 @@ +#pragma once + +#include "def.h" + +int r_popcnt_8(u8 n); +int r_popcnt_16(u16 n); +int r_popcnt_32(u32 n); +int r_popcnt_64(u64 n); diff --git a/inc/rcx/def.h b/inc/def.h diff --git a/inc/deque.h b/inc/deque.h @@ -0,0 +1,122 @@ +#pragma once + +#include <string.h> + +#include "alloc.h" +#include "def.h" + +/* Defaults */ +#define R_DEQUE_STATIC +#define R_DEQUE_METHOD(name, prefix) JOIN(JOIN(prefix,_),name) +#define R_DEQUE_MIN_BITS 3 /* 1<<3 = 8 elements */ +#define R_DEQUE_REALLOCN r_ereallocn +#define R_DEQUE_FREE free + +#define R_DEQUE_TYPEDEF(D, T)\ +typedef struct D { \ + T *arr; \ + usize cap; /* Always a power of 2 for fast mod */ \ + usize l; /* Left end of active region */ \ + usize r; /* 1 past right end of active region */ \ +} D; + +/* Invariants: + * Empty iff l == cap && r == 0 + * Full iff l == r */ + +#define R_DEQUE_DECLARE(D, T, ...)\ +R_DEQUE_STATIC UNUSED void R_DEQUE_METHOD(free,##__VA_ARGS__)(D *d); \ +R_DEQUE_STATIC UNUSED usize R_DEQUE_METHOD(len,##__VA_ARGS__)(D *d); \ +R_DEQUE_STATIC UNUSED usize R_DEQUE_METHOD(cap,##__VA_ARGS__)(D *d); \ +R_DEQUE_STATIC UNUSED int R_DEQUE_METHOD(reserve,##__VA_ARGS__)(D *d, usize n); \ +R_DEQUE_STATIC UNUSED int R_DEQUE_METHOD(pushl,##__VA_ARGS__)(D *d, T e); \ +R_DEQUE_STATIC UNUSED int R_DEQUE_METHOD(pushr,##__VA_ARGS__)(D *d, T e); \ +R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(popl,##__VA_ARGS__)(D *d); \ +R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(popr,##__VA_ARGS__)(D *d); \ +R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(peekl,##__VA_ARGS__)(D *d); \ +R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(peekr,##__VA_ARGS__)(D *d); \ +R_DEQUE_STATIC UNUSED T *R_DEQUE_METHOD(idx,##__VA_ARGS__)(D *d, usize i); + +#define R_DEQUE_DEFINE(D, T, ...)\ +void R_DEQUE_METHOD(free,##__VA_ARGS__)(D *d) { \ + R_DEQUE_FREE(d->arr); \ + *d = (D){0}; \ +} \ +usize R_DEQUE_METHOD(len,##__VA_ARGS__)(D *d) { \ + return d->l == d->r ? d->cap : (d->r - d->l) & (d->cap - 1); \ +} \ +usize R_DEQUE_METHOD(cap,##__VA_ARGS__)(D *d) { \ + return d->cap; \ +} \ +int R_DEQUE_METHOD(reserve,##__VA_ARGS__)(D *d, usize n) { \ + usize rem = d->cap - R_DEQUE_METHOD(len,##__VA_ARGS__)(d); \ + if (n <= rem) \ + return 0; \ + usize need = n - rem; \ + usize ncap = MAX(d->cap, 1<<R_DEQUE_MIN_BITS); \ + while (need > ncap - d->cap) { \ + ncap <<= 1; \ + if (ncap == 0) \ + return -1; /* Overflow */ \ + } \ + 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(&d->arr[d->cap], &d->arr[0], d->r * sizeof *d->arr); \ + d->r += d->cap; \ + } else { \ + usize m = d->cap - d->l; \ + memcpy(&d->arr[ncap-m], &d->arr[d->l], m * sizeof *d->arr); \ + d->l = ncap - m; \ + } \ + } \ + d->cap = ncap; \ + return 0; \ +} \ +int R_DEQUE_METHOD(pushl,##__VA_ARGS__)(D *d, T e) { \ + if (R_DEQUE_METHOD(reserve,##__VA_ARGS__)(d, 1) < 0) \ + return -1; \ + d->l = (d->l - 1) & (d->cap - 1); \ + d->arr[d->l] = e; \ + return 0; \ +} \ +int R_DEQUE_METHOD(pushr,##__VA_ARGS__)(D *d, T e) { \ + if (R_DEQUE_METHOD(reserve,##__VA_ARGS__)(d, 1) < 0) \ + return -1; \ + d->arr[d->r] = e; \ + d->r = (d->r + 1) & (d->cap - 1); \ + if (d->l == d->cap) \ + d->l = 0; \ + return 0; \ +} \ +T R_DEQUE_METHOD(popl,##__VA_ARGS__)(D *d) { \ + T e = d->arr[d->l]; \ + d->l = (d->l + 1) & (d->cap - 1); \ + if (d->l == d->r) { \ + d->l = d->cap; \ + d->r = 0; \ + } \ + return e; \ +} \ +T R_DEQUE_METHOD(popr,##__VA_ARGS__)(D *d) { \ + d->r = (d->r - 1) & (d->cap - 1); \ + T e = d->arr[d->r]; \ + if (d->l == d->r) { \ + d->l = d->cap; \ + d->r = 0; \ + } \ + return e; \ +} \ +T R_DEQUE_METHOD(peekl,##__VA_ARGS__)(D *d) { \ + return d->arr[d->l]; \ +} \ +T R_DEQUE_METHOD(peekr,##__VA_ARGS__)(D *d) { \ + return d->arr[(d->r - 1) & (d->cap - 1)]; \ +} \ +T *R_DEQUE_METHOD(idx,##__VA_ARGS__)(D *d, usize i) { \ + return &d->arr[(d->l + i) & (d->cap - 1)]; \ +} diff --git a/inc/error.h b/inc/error.h @@ -0,0 +1,34 @@ +#pragma once + +#include "def.h" + +#define R_ERR(e) ((e).code != 0) + +typedef struct RError RError; +typedef struct RErrorSource RErrorSource; + +struct RErrorSource { + char *name; + /* Convert err to a string and write the result to buf, which must have + * length len >= 128. If the string does not fit in the given buffer, + * truncate in a source-specific manner (e.g., append an ellipsis). */ + void (*to_string)(char *buf, usize len, RError err); + /* Free any data associated with err. This field can be NULL. */ + void (*free)(RError err); +}; + +struct RError { + int code; /* 0 iff success */ + RErrorSource *src; + union { + i64 i; + u64 u; + double f; + char *s; + void *p; + } u; /* Subject to source-specific semantics. */ +}; + +void r_error_string(char *buf, usize len, RError err); +void r_error_fatal(RError err); +void r_error_drop(RError err); diff --git a/inc/rcx/internal/util.h b/inc/internal/util.h diff --git a/inc/rcx/log.h b/inc/log.h diff --git a/inc/rcx/opt.h b/inc/opt.h diff --git a/inc/rcx.h b/inc/rcx.h @@ -0,0 +1,16 @@ +#pragma once + +/* TODO: consistency check: cast style: (void*) vs (void *) */ + +#include <inttypes.h> +#include <stddef.h> + +/* Standard headers that should be part of the language proper */ +#include <stdarg.h> +#include <stdbool.h> +#if __STDC_VERSION__ >= 201100L +#include <stdalign.h> +#include <stdnoreturn.h> +#endif + +#include "def.h" diff --git a/inc/rcx/all.h b/inc/rcx/all.h @@ -1,13 +0,0 @@ -/* Everything except bench.h */ -#include "rcx/alloc.h" -#include "rcx/bits.h" -#include "rcx/deque.h" -#include "rcx/error.h" -#include "rcx/log.h" -#include "rcx/opt.h" -#include "rcx/rcx.h" -#include "rcx/str.h" -#include "rcx/unicode.h" -#include "rcx/unix.h" -#include "rcx/utf8.h" -#include "rcx/vector.h" diff --git a/inc/rcx/alloc.h b/inc/rcx/alloc.h @@ -1,29 +0,0 @@ -#pragma once - -#include "rcx/def.h" - -/* A consistently-named set of memory allocators: r_{,e}{,re}alloc{,n}{,z} - * e- => allocation failures are fatal - * re- => realloc-style allocator - * -n => array allocator (with overflow check) - * -z => new memory initialized to 0. - * All these allocators are interoperable with the stdlib allocators. The - * non-e variants all set errno to ENOMEM on failure. */ -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 */ -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); -int r_erealloc(void *p, usize size); -int r_ereallocz(void *p, usize osize, usize nsize); -int r_ereallocn(void *p, usize len, usize size); -int r_ereallocnz(void *p, usize olen, usize nlen, usize size); - -void free(void *p); diff --git a/inc/rcx/bench.h b/inc/rcx/bench.h @@ -1,25 +0,0 @@ -#pragma once - -#include "rcx/def.h" - -/* -Usage: - void my_benchmark(u64 N) { - <initialization (not timed)> - r_bench_start(); - for (u64 i = 0; i < N; i++) { - <code to benchmark> - } - r_bench_stop(); - <cleanup (not timed)> - } - int main(void) { - r_bench("my benchmark", my_benchmark, 3000); - } -Note that <code to benchmark> can contain calls to r_bench_stop and -r_bench_start to pause and restart timing. -*/ - -void r_bench(char *name, void (*fn)(u64 N), u32 goalms); -void r_bench_start(void); -void r_bench_stop(void); diff --git a/inc/rcx/bits.h b/inc/rcx/bits.h @@ -1,8 +0,0 @@ -#pragma once - -#include "rcx/def.h" - -int r_popcnt_8(u8 n); -int r_popcnt_16(u16 n); -int r_popcnt_32(u32 n); -int r_popcnt_64(u64 n); diff --git a/inc/rcx/deque.h b/inc/rcx/deque.h @@ -1,122 +0,0 @@ -#pragma once - -#include <string.h> - -#include "rcx/alloc.h" -#include "rcx/def.h" - -/* Defaults */ -#define R_DEQUE_STATIC -#define R_DEQUE_METHOD(name, prefix) JOIN(JOIN(prefix,_),name) -#define R_DEQUE_MIN_BITS 3 /* 1<<3 = 8 elements */ -#define R_DEQUE_REALLOCN r_ereallocn -#define R_DEQUE_FREE free - -#define R_DEQUE_TYPEDEF(D, T)\ -typedef struct D { \ - T *arr; \ - usize cap; /* Always a power of 2 for fast mod */ \ - usize l; /* Left end of active region */ \ - usize r; /* 1 past right end of active region */ \ -} D; - -/* Invariants: - * Empty iff l == cap && r == 0 - * Full iff l == r */ - -#define R_DEQUE_DECLARE(D, T, ...)\ -R_DEQUE_STATIC UNUSED void R_DEQUE_METHOD(free,##__VA_ARGS__)(D *d); \ -R_DEQUE_STATIC UNUSED usize R_DEQUE_METHOD(len,##__VA_ARGS__)(D *d); \ -R_DEQUE_STATIC UNUSED usize R_DEQUE_METHOD(cap,##__VA_ARGS__)(D *d); \ -R_DEQUE_STATIC UNUSED int R_DEQUE_METHOD(reserve,##__VA_ARGS__)(D *d, usize n); \ -R_DEQUE_STATIC UNUSED int R_DEQUE_METHOD(pushl,##__VA_ARGS__)(D *d, T e); \ -R_DEQUE_STATIC UNUSED int R_DEQUE_METHOD(pushr,##__VA_ARGS__)(D *d, T e); \ -R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(popl,##__VA_ARGS__)(D *d); \ -R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(popr,##__VA_ARGS__)(D *d); \ -R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(peekl,##__VA_ARGS__)(D *d); \ -R_DEQUE_STATIC UNUSED T R_DEQUE_METHOD(peekr,##__VA_ARGS__)(D *d); \ -R_DEQUE_STATIC UNUSED T *R_DEQUE_METHOD(idx,##__VA_ARGS__)(D *d, usize i); - -#define R_DEQUE_DEFINE(D, T, ...)\ -void R_DEQUE_METHOD(free,##__VA_ARGS__)(D *d) { \ - R_DEQUE_FREE(d->arr); \ - *d = (D){0}; \ -} \ -usize R_DEQUE_METHOD(len,##__VA_ARGS__)(D *d) { \ - return d->l == d->r ? d->cap : (d->r - d->l) & (d->cap - 1); \ -} \ -usize R_DEQUE_METHOD(cap,##__VA_ARGS__)(D *d) { \ - return d->cap; \ -} \ -int R_DEQUE_METHOD(reserve,##__VA_ARGS__)(D *d, usize n) { \ - usize rem = d->cap - R_DEQUE_METHOD(len,##__VA_ARGS__)(d); \ - if (n <= rem) \ - return 0; \ - usize need = n - rem; \ - usize ncap = MAX(d->cap, 1<<R_DEQUE_MIN_BITS); \ - while (need > ncap - d->cap) { \ - ncap <<= 1; \ - if (ncap == 0) \ - return -1; /* Overflow */ \ - } \ - 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(&d->arr[d->cap], &d->arr[0], d->r * sizeof *d->arr); \ - d->r += d->cap; \ - } else { \ - usize m = d->cap - d->l; \ - memcpy(&d->arr[ncap-m], &d->arr[d->l], m * sizeof *d->arr); \ - d->l = ncap - m; \ - } \ - } \ - d->cap = ncap; \ - return 0; \ -} \ -int R_DEQUE_METHOD(pushl,##__VA_ARGS__)(D *d, T e) { \ - if (R_DEQUE_METHOD(reserve,##__VA_ARGS__)(d, 1) < 0) \ - return -1; \ - d->l = (d->l - 1) & (d->cap - 1); \ - d->arr[d->l] = e; \ - return 0; \ -} \ -int R_DEQUE_METHOD(pushr,##__VA_ARGS__)(D *d, T e) { \ - if (R_DEQUE_METHOD(reserve,##__VA_ARGS__)(d, 1) < 0) \ - return -1; \ - d->arr[d->r] = e; \ - d->r = (d->r + 1) & (d->cap - 1); \ - if (d->l == d->cap) \ - d->l = 0; \ - return 0; \ -} \ -T R_DEQUE_METHOD(popl,##__VA_ARGS__)(D *d) { \ - T e = d->arr[d->l]; \ - d->l = (d->l + 1) & (d->cap - 1); \ - if (d->l == d->r) { \ - d->l = d->cap; \ - d->r = 0; \ - } \ - return e; \ -} \ -T R_DEQUE_METHOD(popr,##__VA_ARGS__)(D *d) { \ - d->r = (d->r - 1) & (d->cap - 1); \ - T e = d->arr[d->r]; \ - if (d->l == d->r) { \ - d->l = d->cap; \ - d->r = 0; \ - } \ - return e; \ -} \ -T R_DEQUE_METHOD(peekl,##__VA_ARGS__)(D *d) { \ - return d->arr[d->l]; \ -} \ -T R_DEQUE_METHOD(peekr,##__VA_ARGS__)(D *d) { \ - return d->arr[(d->r - 1) & (d->cap - 1)]; \ -} \ -T *R_DEQUE_METHOD(idx,##__VA_ARGS__)(D *d, usize i) { \ - return &d->arr[(d->l + i) & (d->cap - 1)]; \ -} diff --git a/inc/rcx/error.h b/inc/rcx/error.h @@ -1,34 +0,0 @@ -#pragma once - -#include "rcx/def.h" - -#define R_ERR(e) ((e).code != 0) - -typedef struct RError RError; -typedef struct RErrorSource RErrorSource; - -struct RErrorSource { - char *name; - /* Convert err to a string and write the result to buf, which must have - * length len >= 128. If the string does not fit in the given buffer, - * truncate in a source-specific manner (e.g., append an ellipsis). */ - void (*to_string)(char *buf, usize len, RError err); - /* Free any data associated with err. This field can be NULL. */ - void (*free)(RError err); -}; - -struct RError { - int code; /* 0 iff success */ - RErrorSource *src; - union { - i64 i; - u64 u; - double f; - char *s; - void *p; - } u; /* Subject to source-specific semantics. */ -}; - -void r_error_string(char *buf, usize len, RError err); -void r_error_fatal(RError err); -void r_error_drop(RError err); diff --git a/inc/rcx/rcx.h b/inc/rcx/rcx.h @@ -1,16 +0,0 @@ -#pragma once - -/* TODO: consistency check: cast style: (void*) vs (void *) */ - -#include <inttypes.h> -#include <stddef.h> - -/* Standard headers that should be part of the language proper */ -#include <stdarg.h> -#include <stdbool.h> -#if __STDC_VERSION__ >= 201100L -#include <stdalign.h> -#include <stdnoreturn.h> -#endif - -#include "rcx/def.h" diff --git a/inc/rcx/str.h b/inc/rcx/str.h @@ -1,31 +0,0 @@ -#pragma once - -#include <stdarg.h> -#include <stdbool.h> - -#include "rcx/def.h" - -char *r_str_dup(char *s); -char *r_str_edup(char *s); - -char *r_str_cat(char *buf, usize len, ...); -char *r_str_ecat(char *buf, usize len, ...); - -bool r_str_starts_with(char *s, char *sub); -bool r_str_ends_with(char *s, char *sub); - -/* Return the number of the nonoverlapping occurences of sub in s. */ -usize r_str_count(char *s, char *sub); - -/* Split s into substrings separated by sep (which must be nonempty) and return - * the number of separated substrings found. If n > 0, then fields must point - * to an array of at least n strings; in this case, place at most n substrings - * in fields, with the last substring being the unsplit remainder. Otherwise, - * set *fields to an allocated array containing every separated substring in s. - * If there is an allocation failure, set *fields to NULL and return 0. In - * either case, the elements of *fields are pointers into s, and s will be - * modified in order to null-terminate the substrings. */ -usize r_str_split(char ***fields, char *s, char *sep, usize n); - -int r_vaprintf(char **s, const char *fmt, va_list args); -int r_aprintf(char **s, const char *fmt, ...); diff --git a/inc/rcx/unicode.h b/inc/rcx/unicode.h @@ -1,11 +0,0 @@ -#pragma once - -#include "rcx/def.h" - -/* TODO: idea: -#define r_unicode_is_letter(r) (r_unicode_category(r)[0] == 'L') -etc... -Actually, this is wrong, because r_unicode_category can return NULL -*/ - -char *r_unicode_category(rune r); diff --git a/inc/rcx/unix.h b/inc/rcx/unix.h @@ -1,34 +0,0 @@ -#pragma once - -#include <sys/uio.h> - -#include "rcx/def.h" - -/* On success, read exactly len bytes from fd into buf and return 0. On failure - * (i.e., any error except EINTR, or EOF before len bytes are read into buf), - * return -1 and set errno in the same manner as read(2), or set errno to 0 in - * the case of premature EOF. In either case, if n is not NULL, set *n to the - * number of bytes actually read (which is less than len iff an error or - * premature EOF occurred). */ -int r_read_all(usize *n, int fd, void *buf, usize len); - -/* On success, write exactly len bytes from buf to fd and return 0. On failure - * (i.e, any error except EINTR), return -1 and set errno in the same manner as - * write(2). In either case, if n is not NULL, set *n to the number of bytes - * actually written (which is less than len iff an error occurred). */ -int r_write_all(usize *n, int fd, void *buf, usize len); - -/* Copy n bytes from (*iov, *niov) to dst. Increment the base pointer and - * decrement the length in each iovec according to the number of bytes copied. - * There must be at least n bytes in (*iov, *niov). */ -void r_iovec_gather(void *dst, struct iovec **iov, usize *niov, usize n); - -/* TODO */ -/* int r_readv_all(int fd, struct iovec **iov, usize *niov); */ - -/* On success, write all bytes from (*iov, *niov) to fd and return 0. On - * failure (i.e., any error except EINTR), return -1 and set errno in the same - * manner as writev(2). In either case, increment the base pointer and - * decrement the length in each iovec according to the number of bytes actually - * written. */ -int r_writev_all(int fd, struct iovec **iov, usize *niov); diff --git a/inc/rcx/utf8.h b/inc/rcx/utf8.h @@ -1,21 +0,0 @@ -#pragma once - -#include "rcx/def.h" - -#define R_UTF8_SIZE 4 - -/* Return the number of bytes needed to encode c, or 0 if c is an invalid - * codepoint. If s is nonnull, then it must have length >= - * r_utf8_encode(0, c), which is guaranteed to be at most R_UTF8_SIZE; - * in this case, if c is a valid codepoint, then encode c into s. */ -usize r_utf8_encode(char *s, rune c); - -/* Decode the first rune in s and return the number of consumed bytes. If this - * succeeds and c is nonnull, then set *c to the decoded rune. Otherwise, no - * valid rune is legally encoded as a prefix of s; in this case, set *c to - * RUNE_BAD if c is nonnull, and return n such that - * - n = 0 iff s is null or an incomplete prefix of a valid rune; - * - n > 0 iff the first min(n+1,slen) bytes of s are not a prefix of any - * valid rune (but if n < slen, then s[n] might be the first byte of a - * valid rune). */ -usize r_utf8_decode(rune *c, char *s, usize slen); diff --git a/inc/rcx/vector.h b/inc/rcx/vector.h @@ -1,144 +0,0 @@ -#pragma once - -#include <errno.h> -#include <stdbool.h> -#include <string.h> - -#include "rcx/alloc.h" -#include "rcx/def.h" - -#include "rcx/internal/util.h" - -typedef struct { - usize len; - usize cap; - maxalign arr[]; -} r_vector_generic_hdr_; - -#define R_VECTOR_HDR_(v) ((R_VECTOR_HDR_TYPE *)(v) - 1) - -/* Defaults */ -#define R_VECTOR_STATIC -#define R_VECTOR_METHOD(name, prefix) JOIN(JOIN(prefix,_),name) -#define R_VECTOR_NULL_TERM false -#define R_VECTOR_MIN_CAP 8 -#define R_VECTOR_HDR_TYPE r_vector_generic_hdr_ -#define R_VECTOR_REALLOC r_erealloc -#define R_VECTOR_FREE free - -#define R_VECTOR_DECLARE(T, ...)\ -R_VECTOR_STATIC UNUSED usize R_VECTOR_METHOD(len,##__VA_ARGS__)(T *v); \ -R_VECTOR_STATIC UNUSED usize R_VECTOR_METHOD(cap,##__VA_ARGS__)(T *v); \ -R_VECTOR_STATIC UNUSED void R_VECTOR_METHOD(free,##__VA_ARGS__)(T **v); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(resize,##__VA_ARGS__)(T **v, usize cap); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(reserve,##__VA_ARGS__)(T **v, usize n); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(ins,##__VA_ARGS__)(T **v, usize i, T e); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(insv,##__VA_ARGS__)(T **dst, usize i, T *src); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(insn,##__VA_ARGS__)(T **dst, usize i, T *src, usize n); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(push,##__VA_ARGS__)(T **v, T e); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(cat,##__VA_ARGS__)(T **dst, T *src); \ -R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(catn,##__VA_ARGS__)(T **dst, T *src, usize n); \ -R_VECTOR_STATIC UNUSED T R_VECTOR_METHOD(del,##__VA_ARGS__)(T **v, usize i); \ -R_VECTOR_STATIC UNUSED T R_VECTOR_METHOD(pop,##__VA_ARGS__)(T **v); \ -R_VECTOR_STATIC UNUSED T R_VECTOR_METHOD(peek,##__VA_ARGS__)(T **v); - -#define R_VECTOR_DEFINE(T, ...)\ -usize R_VECTOR_METHOD(len,##__VA_ARGS__)(T *v) { \ - return v ? R_VECTOR_HDR_(v)->len : 0; \ -} \ -usize R_VECTOR_METHOD(cap,##__VA_ARGS__)(T *v) { \ - return v ? R_VECTOR_HDR_(v)->cap : 0; \ -} \ -void R_VECTOR_METHOD(free,##__VA_ARGS__)(T **v) { \ - if (*v) \ - R_VECTOR_FREE(R_VECTOR_HDR_(*v)); \ - *v = 0; \ -} \ -int R_VECTOR_METHOD(resize,##__VA_ARGS__)(T **v, usize cap) { \ - if (cap == 0) { \ - R_VECTOR_METHOD(free,##__VA_ARGS__)(v); \ - } else { \ - cap = MAX(cap, R_VECTOR_MIN_CAP); \ - R_VECTOR_HDR_TYPE *h = *v ? R_VECTOR_HDR_(*v) : 0; \ - usize len = h ? h->len : 0; \ - usize arrsize = cap * sizeof (*v)[0]; \ - if (r_mul_will_overflow_(cap, sizeof (*v)[0]) \ - || sizeof *h > USIZE_MAX - arrsize) { \ - errno = ENOMEM; \ - return -1; \ - } \ - if (R_VECTOR_REALLOC(&h, sizeof *h + arrsize) < 0) \ - return -1; \ - h->len = MIN(len, cap - !!R_VECTOR_NULL_TERM); \ - h->cap = cap; \ - *v = (void *)(h + 1); \ - if (R_VECTOR_NULL_TERM) \ - memset(&(*v)[h->len], 0, sizeof (*v)[0]); \ - } \ - return 0; \ -} \ -int R_VECTOR_METHOD(reserve,##__VA_ARGS__)(T **v, usize n) { \ - R_VECTOR_HDR_TYPE *h = *v ? R_VECTOR_HDR_(*v) : 0; \ - usize rem = h ? h->cap - h->len - !!R_VECTOR_NULL_TERM : 0; \ - if (n > rem) { \ - usize need = n - rem; \ - usize cap = h ? h->cap + MAX(h->cap, need) \ - : need + !!R_VECTOR_NULL_TERM; \ - if ((h && cap < h->cap) || (R_VECTOR_NULL_TERM && cap == 0)) { \ - errno = ENOMEM; \ - return -1; \ - } \ - return R_VECTOR_METHOD(resize,##__VA_ARGS__)(v, cap); \ - } else { \ - return 0; \ - } \ -} \ -int R_VECTOR_METHOD(ins,##__VA_ARGS__)(T **v, usize i, T e) { \ - return R_VECTOR_METHOD(insn,##__VA_ARGS__)(v, i, &e, 1); \ -} \ -int R_VECTOR_METHOD(insv,##__VA_ARGS__)(T **dst, usize i, T *src) { \ - return R_VECTOR_METHOD(insn,##__VA_ARGS__)(dst, i, src, \ - R_VECTOR_METHOD(len,##__VA_ARGS__)(src)); \ -} \ -int R_VECTOR_METHOD(insn,##__VA_ARGS__)(T **dst, usize i, T *src, usize n) { \ - if (R_VECTOR_METHOD(reserve,##__VA_ARGS__)(dst, n)) \ - return -1; \ - usize m = R_VECTOR_HDR_(*dst)->len - i + !!R_VECTOR_NULL_TERM; \ - memmove(&(*dst)[i+n], &(*dst)[i], m * sizeof (*dst)[0]); \ - memcpy(&(*dst)[i], src, n * sizeof (*dst)[0]); \ - R_VECTOR_HDR_(*dst)->len += n; \ - return 0; \ -} \ -int R_VECTOR_METHOD(push,##__VA_ARGS__)(T **v, T e) { \ - return R_VECTOR_METHOD(catn,##__VA_ARGS__)(v, &e, 1); \ -} \ -int R_VECTOR_METHOD(cat,##__VA_ARGS__)(T **dst, T *src) { \ - return R_VECTOR_METHOD(catn,##__VA_ARGS__)(dst, \ - src, R_VECTOR_METHOD(len,##__VA_ARGS__)(src)); \ -} \ -int R_VECTOR_METHOD(catn,##__VA_ARGS__)(T **dst, T *src, usize n) { \ - return R_VECTOR_METHOD(insn,##__VA_ARGS__)(dst, \ - R_VECTOR_METHOD(len,##__VA_ARGS__)(*dst), src, n); \ -} \ -T R_VECTOR_METHOD(del,##__VA_ARGS__)(T **v, usize i) { \ - T e = (*v)[i]; \ - usize m = R_VECTOR_HDR_(*v)->len - i - 1 + !!R_VECTOR_NULL_TERM; \ - memmove(&(*v)[i], &(*v)[i+1], m * sizeof (*v)[0]); \ - R_VECTOR_HDR_(*v)->len -= 1; \ - return e; \ -} \ -T R_VECTOR_METHOD(pop,##__VA_ARGS__)(T **v) { \ - return R_VECTOR_METHOD(del,##__VA_ARGS__)(v, R_VECTOR_HDR_(*v)->len - 1); \ -} \ -T R_VECTOR_METHOD(peek,##__VA_ARGS__)(T **v) { \ - return (*v)[R_VECTOR_HDR_(*v)->len - 1]; \ -} - -/* TODO? -deln -clr => set length to 0 without resizing -optionally take cmp function and define: - sort => qsort wrapper - bsearch => bsearch wrapper - lsearch => linear search on unsorted array -*/ diff --git a/inc/str.h b/inc/str.h @@ -0,0 +1,31 @@ +#pragma once + +#include <stdarg.h> +#include <stdbool.h> + +#include "def.h" + +char *r_str_dup(char *s); +char *r_str_edup(char *s); + +char *r_str_cat(char *buf, usize len, ...); +char *r_str_ecat(char *buf, usize len, ...); + +bool r_str_starts_with(char *s, char *sub); +bool r_str_ends_with(char *s, char *sub); + +/* Return the number of the nonoverlapping occurences of sub in s. */ +usize r_str_count(char *s, char *sub); + +/* Split s into substrings separated by sep (which must be nonempty) and return + * the number of separated substrings found. If n > 0, then fields must point + * to an array of at least n strings; in this case, place at most n substrings + * in fields, with the last substring being the unsplit remainder. Otherwise, + * set *fields to an allocated array containing every separated substring in s. + * If there is an allocation failure, set *fields to NULL and return 0. In + * either case, the elements of *fields are pointers into s, and s will be + * modified in order to null-terminate the substrings. */ +usize r_str_split(char ***fields, char *s, char *sep, usize n); + +int r_vaprintf(char **s, const char *fmt, va_list args); +int r_aprintf(char **s, const char *fmt, ...); diff --git a/inc/unicode.h b/inc/unicode.h @@ -0,0 +1,11 @@ +#pragma once + +#include "def.h" + +/* TODO: idea: +#define r_unicode_is_letter(r) (r_unicode_category(r)[0] == 'L') +etc... +Actually, this is wrong, because r_unicode_category can return NULL +*/ + +char *r_unicode_category(rune r); diff --git a/inc/unix.h b/inc/unix.h @@ -0,0 +1,34 @@ +#pragma once + +#include <sys/uio.h> + +#include "def.h" + +/* On success, read exactly len bytes from fd into buf and return 0. On failure + * (i.e., any error except EINTR, or EOF before len bytes are read into buf), + * return -1 and set errno in the same manner as read(2), or set errno to 0 in + * the case of premature EOF. In either case, if n is not NULL, set *n to the + * number of bytes actually read (which is less than len iff an error or + * premature EOF occurred). */ +int r_read_all(usize *n, int fd, void *buf, usize len); + +/* On success, write exactly len bytes from buf to fd and return 0. On failure + * (i.e, any error except EINTR), return -1 and set errno in the same manner as + * write(2). In either case, if n is not NULL, set *n to the number of bytes + * actually written (which is less than len iff an error occurred). */ +int r_write_all(usize *n, int fd, void *buf, usize len); + +/* Copy n bytes from (*iov, *niov) to dst. Increment the base pointer and + * decrement the length in each iovec according to the number of bytes copied. + * There must be at least n bytes in (*iov, *niov). */ +void r_iovec_gather(void *dst, struct iovec **iov, usize *niov, usize n); + +/* TODO */ +/* int r_readv_all(int fd, struct iovec **iov, usize *niov); */ + +/* On success, write all bytes from (*iov, *niov) to fd and return 0. On + * failure (i.e., any error except EINTR), return -1 and set errno in the same + * manner as writev(2). In either case, increment the base pointer and + * decrement the length in each iovec according to the number of bytes actually + * written. */ +int r_writev_all(int fd, struct iovec **iov, usize *niov); diff --git a/inc/utf8.h b/inc/utf8.h @@ -0,0 +1,21 @@ +#pragma once + +#include "def.h" + +#define R_UTF8_SIZE 4 + +/* Return the number of bytes needed to encode c, or 0 if c is an invalid + * codepoint. If s is nonnull, then it must have length >= + * r_utf8_encode(0, c), which is guaranteed to be at most R_UTF8_SIZE; + * in this case, if c is a valid codepoint, then encode c into s. */ +usize r_utf8_encode(char *s, rune c); + +/* Decode the first rune in s and return the number of consumed bytes. If this + * succeeds and c is nonnull, then set *c to the decoded rune. Otherwise, no + * valid rune is legally encoded as a prefix of s; in this case, set *c to + * RUNE_BAD if c is nonnull, and return n such that + * - n = 0 iff s is null or an incomplete prefix of a valid rune; + * - n > 0 iff the first min(n+1,slen) bytes of s are not a prefix of any + * valid rune (but if n < slen, then s[n] might be the first byte of a + * valid rune). */ +usize r_utf8_decode(rune *c, char *s, usize slen); diff --git a/inc/vector.h b/inc/vector.h @@ -0,0 +1,144 @@ +#pragma once + +#include <errno.h> +#include <stdbool.h> +#include <string.h> + +#include "alloc.h" +#include "def.h" + +#include "internal/util.h" + +typedef struct { + usize len; + usize cap; + maxalign arr[]; +} r_vector_generic_hdr_; + +#define R_VECTOR_HDR_(v) ((R_VECTOR_HDR_TYPE *)(v) - 1) + +/* Defaults */ +#define R_VECTOR_STATIC +#define R_VECTOR_METHOD(name, prefix) JOIN(JOIN(prefix,_),name) +#define R_VECTOR_NULL_TERM false +#define R_VECTOR_MIN_CAP 8 +#define R_VECTOR_HDR_TYPE r_vector_generic_hdr_ +#define R_VECTOR_REALLOC r_erealloc +#define R_VECTOR_FREE free + +#define R_VECTOR_DECLARE(T, ...)\ +R_VECTOR_STATIC UNUSED usize R_VECTOR_METHOD(len,##__VA_ARGS__)(T *v); \ +R_VECTOR_STATIC UNUSED usize R_VECTOR_METHOD(cap,##__VA_ARGS__)(T *v); \ +R_VECTOR_STATIC UNUSED void R_VECTOR_METHOD(free,##__VA_ARGS__)(T **v); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(resize,##__VA_ARGS__)(T **v, usize cap); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(reserve,##__VA_ARGS__)(T **v, usize n); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(ins,##__VA_ARGS__)(T **v, usize i, T e); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(insv,##__VA_ARGS__)(T **dst, usize i, T *src); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(insn,##__VA_ARGS__)(T **dst, usize i, T *src, usize n); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(push,##__VA_ARGS__)(T **v, T e); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(cat,##__VA_ARGS__)(T **dst, T *src); \ +R_VECTOR_STATIC UNUSED int R_VECTOR_METHOD(catn,##__VA_ARGS__)(T **dst, T *src, usize n); \ +R_VECTOR_STATIC UNUSED T R_VECTOR_METHOD(del,##__VA_ARGS__)(T **v, usize i); \ +R_VECTOR_STATIC UNUSED T R_VECTOR_METHOD(pop,##__VA_ARGS__)(T **v); \ +R_VECTOR_STATIC UNUSED T R_VECTOR_METHOD(peek,##__VA_ARGS__)(T **v); + +#define R_VECTOR_DEFINE(T, ...)\ +usize R_VECTOR_METHOD(len,##__VA_ARGS__)(T *v) { \ + return v ? R_VECTOR_HDR_(v)->len : 0; \ +} \ +usize R_VECTOR_METHOD(cap,##__VA_ARGS__)(T *v) { \ + return v ? R_VECTOR_HDR_(v)->cap : 0; \ +} \ +void R_VECTOR_METHOD(free,##__VA_ARGS__)(T **v) { \ + if (*v) \ + R_VECTOR_FREE(R_VECTOR_HDR_(*v)); \ + *v = 0; \ +} \ +int R_VECTOR_METHOD(resize,##__VA_ARGS__)(T **v, usize cap) { \ + if (cap == 0) { \ + R_VECTOR_METHOD(free,##__VA_ARGS__)(v); \ + } else { \ + cap = MAX(cap, R_VECTOR_MIN_CAP); \ + R_VECTOR_HDR_TYPE *h = *v ? R_VECTOR_HDR_(*v) : 0; \ + usize len = h ? h->len : 0; \ + usize arrsize = cap * sizeof (*v)[0]; \ + if (r_mul_will_overflow_(cap, sizeof (*v)[0]) \ + || sizeof *h > USIZE_MAX - arrsize) { \ + errno = ENOMEM; \ + return -1; \ + } \ + if (R_VECTOR_REALLOC(&h, sizeof *h + arrsize) < 0) \ + return -1; \ + h->len = MIN(len, cap - !!R_VECTOR_NULL_TERM); \ + h->cap = cap; \ + *v = (void *)(h + 1); \ + if (R_VECTOR_NULL_TERM) \ + memset(&(*v)[h->len], 0, sizeof (*v)[0]); \ + } \ + return 0; \ +} \ +int R_VECTOR_METHOD(reserve,##__VA_ARGS__)(T **v, usize n) { \ + R_VECTOR_HDR_TYPE *h = *v ? R_VECTOR_HDR_(*v) : 0; \ + usize rem = h ? h->cap - h->len - !!R_VECTOR_NULL_TERM : 0; \ + if (n > rem) { \ + usize need = n - rem; \ + usize cap = h ? h->cap + MAX(h->cap, need) \ + : need + !!R_VECTOR_NULL_TERM; \ + if ((h && cap < h->cap) || (R_VECTOR_NULL_TERM && cap == 0)) { \ + errno = ENOMEM; \ + return -1; \ + } \ + return R_VECTOR_METHOD(resize,##__VA_ARGS__)(v, cap); \ + } else { \ + return 0; \ + } \ +} \ +int R_VECTOR_METHOD(ins,##__VA_ARGS__)(T **v, usize i, T e) { \ + return R_VECTOR_METHOD(insn,##__VA_ARGS__)(v, i, &e, 1); \ +} \ +int R_VECTOR_METHOD(insv,##__VA_ARGS__)(T **dst, usize i, T *src) { \ + return R_VECTOR_METHOD(insn,##__VA_ARGS__)(dst, i, src, \ + R_VECTOR_METHOD(len,##__VA_ARGS__)(src)); \ +} \ +int R_VECTOR_METHOD(insn,##__VA_ARGS__)(T **dst, usize i, T *src, usize n) { \ + if (R_VECTOR_METHOD(reserve,##__VA_ARGS__)(dst, n)) \ + return -1; \ + usize m = R_VECTOR_HDR_(*dst)->len - i + !!R_VECTOR_NULL_TERM; \ + memmove(&(*dst)[i+n], &(*dst)[i], m * sizeof (*dst)[0]); \ + memcpy(&(*dst)[i], src, n * sizeof (*dst)[0]); \ + R_VECTOR_HDR_(*dst)->len += n; \ + return 0; \ +} \ +int R_VECTOR_METHOD(push,##__VA_ARGS__)(T **v, T e) { \ + return R_VECTOR_METHOD(catn,##__VA_ARGS__)(v, &e, 1); \ +} \ +int R_VECTOR_METHOD(cat,##__VA_ARGS__)(T **dst, T *src) { \ + return R_VECTOR_METHOD(catn,##__VA_ARGS__)(dst, \ + src, R_VECTOR_METHOD(len,##__VA_ARGS__)(src)); \ +} \ +int R_VECTOR_METHOD(catn,##__VA_ARGS__)(T **dst, T *src, usize n) { \ + return R_VECTOR_METHOD(insn,##__VA_ARGS__)(dst, \ + R_VECTOR_METHOD(len,##__VA_ARGS__)(*dst), src, n); \ +} \ +T R_VECTOR_METHOD(del,##__VA_ARGS__)(T **v, usize i) { \ + T e = (*v)[i]; \ + usize m = R_VECTOR_HDR_(*v)->len - i - 1 + !!R_VECTOR_NULL_TERM; \ + memmove(&(*v)[i], &(*v)[i+1], m * sizeof (*v)[0]); \ + R_VECTOR_HDR_(*v)->len -= 1; \ + return e; \ +} \ +T R_VECTOR_METHOD(pop,##__VA_ARGS__)(T **v) { \ + return R_VECTOR_METHOD(del,##__VA_ARGS__)(v, R_VECTOR_HDR_(*v)->len - 1); \ +} \ +T R_VECTOR_METHOD(peek,##__VA_ARGS__)(T **v) { \ + return (*v)[R_VECTOR_HDR_(*v)->len - 1]; \ +} + +/* TODO? +deln +clr => set length to 0 without resizing +optionally take cmp function and define: + sort => qsort wrapper + bsearch => bsearch wrapper + lsearch => linear search on unsorted array +*/ diff --git a/src/alloc.c b/src/alloc.c @@ -2,11 +2,11 @@ #include <stdlib.h> #include <string.h> -#include "rcx/alloc.h" -#include "rcx/log.h" -#include "rcx/rcx.h" +#include "alloc.h" +#include "log.h" +#include "rcx.h" -#include "rcx/internal/util.h" +#include "internal/util.h" void * r_alloc(usize size) { diff --git a/src/bench.c b/src/bench.c @@ -6,9 +6,9 @@ #include <time.h> #include <unistd.h> -#include "rcx/bench.h" -#include "rcx/log.h" -#include "rcx/rcx.h" +#include "bench.h" +#include "log.h" +#include "rcx.h" #ifndef _POSIX_THREAD_CPUTIME #error "Need CLOCK_PROCESS_CPUTIME_ID" diff --git a/src/bits.c b/src/bits.c @@ -1,5 +1,5 @@ -#include "rcx/bits.h" -#include "rcx/rcx.h" +#include "bits.h" +#include "rcx.h" /* popcnt functions are implemented with a divide and conquer strategy. * See Henry Warren, Hacker's Delight, 2 ed., sec. 5.1. */ diff --git a/src/error.c b/src/error.c @@ -1,8 +1,8 @@ #include <assert.h> -#include "rcx/error.h" -#include "rcx/log.h" -#include "rcx/rcx.h" +#include "error.h" +#include "log.h" +#include "rcx.h" void r_error_string(char *buf, usize len, RError err) { diff --git a/src/log.c b/src/log.c @@ -5,8 +5,8 @@ #include <time.h> #include <unistd.h> -#include "rcx/log.h" -#include "rcx/rcx.h" +#include "log.h" +#include "rcx.h" #define ISO8601_SIZE (sizeof "YYYY-MM-DDThh:mm:ssZ") #define SGR(c) (use_color ? (c) : "") diff --git a/src/opt.c b/src/opt.c @@ -1,8 +1,8 @@ #include <assert.h> #include <string.h> -#include "cext/cext.h" -#include "cext/opt.h" +#include "rcx.h" +#include "opt.h" void opt_init(opt_ctx *opt, int *argc, char **argv) { diff --git a/src/str.c b/src/str.c @@ -4,10 +4,10 @@ #include <stdio.h> #include <string.h> -#include "rcx/alloc.h" -#include "rcx/log.h" -#include "rcx/rcx.h" -#include "rcx/str.h" +#include "alloc.h" +#include "log.h" +#include "rcx.h" +#include "str.h" /* TODO: e-versions of every function that can fail */ diff --git a/src/unicode.c b/src/unicode.c @@ -1,4 +1,4 @@ -#include "rcx/rcx.h" +#include "rcx.h" #include "../gen/ucattab.inc" static char ucats[] = diff --git a/src/unix.c b/src/unix.c @@ -4,8 +4,8 @@ #include <sys/uio.h> #include <unistd.h> -#include "rcx/rcx.h" -#include "rcx/unix.h" +#include "rcx.h" +#include "unix.h" typedef isize (*IoOp)(int, void *, usize); diff --git a/src/utf8.c b/src/utf8.c @@ -1,5 +1,5 @@ -#include "rcx/rcx.h" -#include "rcx/utf8.h" +#include "rcx.h" +#include "utf8.h" #define SURROGATE_MIN 0xD800 #define SURROGATE_MAX 0xDFFF diff --git a/tool/ucattab.c b/tool/ucattab.c @@ -4,10 +4,10 @@ #include <stdlib.h> #include <string.h> -#include "rcx/alloc.h" -#include "rcx/rcx.h" -#include "rcx/log.h" -#include "rcx/str.h" +#include "alloc.h" +#include "rcx.h" +#include "log.h" +#include "str.h" #define NF 15 /* Number of fields in UnicodeData.txt */