diff options
| author | Louis Burda <quent.burda@gmail.com> | 2023-05-13 21:12:17 +0200 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2023-05-13 21:12:17 +0200 |
| commit | 9fe89a48bb89dc6740787c9ed8c95b5339bba905 (patch) | |
| tree | bca73651945caef5e188328a538ca782470c43dd /src | |
| parent | 110b99563e127abe1439fffb0084400b47eea5b3 (diff) | |
| download | libstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.tar.gz libstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.zip | |
Add initial version
Diffstat (limited to 'src')
| -rw-r--r-- | src/strvec.c | 218 | ||||
| -rw-r--r-- | src/test.c | 32 |
2 files changed, 241 insertions, 9 deletions
diff --git a/src/strvec.c b/src/strvec.c index 343d8ba..dbc964e 100644 --- a/src/strvec.c +++ b/src/strvec.c @@ -2,35 +2,235 @@ #include "dvec.h" #include "allocator.h" +#include <string.h> + struct strvec { struct dvec vec; - const struct allocator *alloc; }; -void +const size_t strvec_dsize = sizeof(struct strvec); + +int strvec_init(struct strvec *strvec, size_t cap, struct allocator *allocator) { - strvec->alloc = allocator; - dvec_init(&strvec->vec, sizeof(char *), cap, allocator); + int rc; + + LIBSTRVEC_ABORT_ON_ARGS(!strvec || !allocator); + + rc = dvec_init(&strvec->vec, sizeof(char *), cap, allocator); + LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); + + return rc; } -void +int strvec_deinit(struct strvec *strvec) { - dvec_deinit(&strvec->vec); + int rc; + + LIBSTRVEC_ABORT_ON_ALLOC(!strvec); + + rc = dvec_deinit(&strvec->vec); + LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); + + return rc; } struct strvec * -strvec_alloc(size_t reserved, struct allocator *allocator) +strvec_alloc(size_t cap, struct allocator *allocator, int *_rc) { + struct strvec *strvec; + int *rc, stub; + + LIBSTRVEC_ABORT_ON_ARGS(!allocator); + rc = _rc ? _rc : &stub; + + strvec = allocator->alloc(sizeof(struct strvec), rc); + if (!strvec) return NULL; + + *rc = strvec_init(strvec, cap, allocator); + if (*rc) return NULL; + + return strvec; } int strvec_free(struct strvec *strvec) { - dvec_deinit(&strvec->vec); - strvec->alloc->free(strvec); + const struct allocator *allocator; + int rc; + + LIBSTRVEC_ABORT_ON_ARGS(!allocator); + + allocator = strvec->vec.allocator; + + rc = dvec_deinit(&strvec->vec); + LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); + if (rc) return rc; + + rc = allocator->free(strvec); + LIBSTRVEC_ABORT_ON_ALLOC(rc); + + return rc; } +int +strvec_copy(struct strvec *dst, struct strvec *src, + const struct allocator *allocator) +{ + char **str, *nstr; + size_t len; + int rc; + + LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); + + dvec_copy(&dst->vec, &src->vec); + for (DVEC_ITER(&dst->vec, str)) { + if (!*str) continue; + len = strlen(*str); + nstr = allocator->alloc(len + 1, &rc); + LIBSTRVEC_ABORT_ON_ALLOC(!nstr); + if (!nstr) return rc; + strncpy(nstr, *str, len + 1); + *str = nstr; + } + return 0; +} + +void +strvec_move(struct strvec *dst, struct strvec *src) +{ + LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); + + memcpy(dst, src, sizeof(struct strvec)); +} + +void +strvec_swap(struct strvec *dst, struct strvec *src) +{ + struct strvec tmp; + + LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); + + memcpy(&tmp, dst, sizeof(struct dvec)); + memcpy(dst, src, sizeof(struct dvec)); + memcpy(src, &tmp, sizeof(struct dvec)); +} + +int +strvec_reserve(struct strvec *strvec, size_t cap) +{ + int rc; + + LIBSTRVEC_ABORT_ON_ARGS(!strvec); + + rc = dvec_reserve(&strvec->vec, cap); + LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); + + return rc; +} + +void +strvec_clear(struct strvec *strvec) +{ + LIBSTRVEC_ABORT_ON_ARGS(!strvec); + + dvec_clear(&strvec->vec); +} + +int +strvec_shrink(struct strvec *strvec) +{ + int rc; + + LIBSTRVEC_ABORT_ON_ARGS(!strvec); + + rc = dvec_shrink(&strvec->vec); + LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); + + return rc; +} + +const char ** +strvec_stra(struct strvec *strvec) +{ + LIBSTRVEC_ABORT_ON_ARGS(!strvec && !strvec->vec.data); + + return strvec->vec.data; +} + +size_t +strvec_len(struct strvec *strvec) +{ + LIBSTRVEC_ABORT_ON_ARGS(!strvec); + + return strvec->vec.len; +} + +int +strvec_pushn(struct strvec *strvec, const char **str, size_t count) +{ + const char **dst; + int rc; + + LIBSTRVEC_ABORT_ON_ARGS(!strvec || !str || !count); + + rc = dvec_add_back(&strvec->vec, count); + LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); + if (rc) return rc; + + dst = dvec_at_back(&strvec->vec, count - 1); + memcpy(dst, str, count * sizeof(char *)); + + return 0; +} + +const char ** +strvec_popn(struct strvec *strvec, size_t count) +{ + const char **pos; + + LIBSTRVEC_ABORT_ON_ARGS(!strvec || !count); + + pos = dvec_at_back(&strvec->vec, count); + dvec_rm_back(&strvec->vec, count); + + return pos; +} + +void +strvec_replace(struct strvec *strvec, size_t index, const char *str) +{ + const char **pos; + + LIBSTRVEC_ABORT_ON_ARGS(!strvec || index >= dvec_len(&strvec->vec)) + + pos = dvec_at(&strvec->vec, index); + *pos = str; +} + +void +strvec_remove(struct strvec *strvec, size_t index, size_t count) +{ + LIBSTRVEC_ABORT_ON_ARGS(!strvec); + + dvec_rm(&strvec->vec, index, count); +} + +const char ** +strvec_iter_fwd(const struct strvec *strvec, const char **p) +{ + LIBSTRVEC_ABORT_ON_ARGS(!strvec); + + return dvec_iter_fwd(&strvec->vec, p); +} + +const char ** +strvec_iter_bwd(const struct strvec *strvec, const char **p) +{ + LIBSTRVEC_ABORT_ON_ARGS(!strvec); + + return dvec_iter_bwd(&strvec->vec, p); +} diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000..40e1828 --- /dev/null +++ b/src/test.c @@ -0,0 +1,32 @@ +#include "strvec.h" +#include "allocator.h" + +#include <err.h> +#include <string.h> +#include <stdio.h> + +#define LIBSTRVEC_ERR(rc) errx(1, "libstrvec: %s", strerror(-rc)) + +int +main(int argc, const char **argv) +{ + struct strvec *strvec; + const char **arg; + + strvec = strvec_alloc(0, &stdlib_strict_heap_allocator, NULL); + + if (!argc) return 1; + for (arg = &argv[1]; *arg; arg++) { + strvec_push(strvec, *arg); + } + + strvec_push(strvec, "--"); + strvec_push(strvec, "end"); + strvec_push(strvec, NULL); + + for (arg = strvec_stra(strvec); *arg; arg++) { + printf("%s\n", *arg); + } + + strvec_free(strvec); +} |
