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 | |
| parent | 110b99563e127abe1439fffb0084400b47eea5b3 (diff) | |
| download | libstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.tar.gz libstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.zip | |
Add initial version
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | Makefile | 13 | ||||
| -rw-r--r-- | include/strvec.h | 60 | ||||
| m--------- | lib/liballoc | 0 | ||||
| m--------- | lib/libdvec | 0 | ||||
| -rw-r--r-- | libstrvec.api | 13 | ||||
| -rw-r--r-- | libstrvec.lds | 36 | ||||
| -rw-r--r-- | src/strvec.c | 218 | ||||
| -rw-r--r-- | src/test.c | 32 |
11 files changed, 360 insertions, 38 deletions
@@ -1,3 +1,5 @@ build .cache compile_commands.json +vgcore* +.gdb_history diff --git a/.gitmodules b/.gitmodules index b2dc357..c145865 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +[submodule "lib/libdvec"] + path = lib/libdvec + url = git@sinitax.com:sinitax/libdvec [submodule "lib/liballoc"] path = lib/liballoc url = git@sinitax.com:sinitax/liballoc @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Louis Burda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. @@ -25,6 +25,10 @@ all: build/libstrvec.so build/libstrvec.a build/test clean: rm -rf build +cleanall: clean + make -C lib/liballoc cleanall + make -C lib/libdvec cleanall + build: mkdir build @@ -34,8 +38,9 @@ lib/liballoc/build/liballoc.a: lib/libdvec/build/libdvec.a: make -C lib/libdvec build/libdvec.a -build/libstrvec.a: src/strvec.c include/strvec.h libstrvec.api | build - $(CC) -o build/tmp.o src/strvec.c $(CFLAGS) -r +build/libstrvec.a: src/strvec.c lib/libdvec/build/libdvec.a \ + include/strvec.h libstrvec.api | build + $(CC) -o build/tmp.o src/strvec.c lib/libdvec/build/libdvec.a $(CFLAGS) -r objcopy --keep-global-symbols=libstrvec.api build/tmp.o build/fixed.o ar rcs $@ build/fixed.o @@ -44,7 +49,7 @@ build/libstrvec.so: src/strvec.c include/strvec.h libstrvec.lds | build -shared -Wl,-version-script libstrvec.lds build/test: src/test.c build/libstrvec.a lib/liballoc/build/liballoc.a - $(CC) -o $@ $^ $(CFLAGS) + $(CC) -o $@ $^ -g -I include -I lib/libdvec/include -I lib/liballoc/include install: install -m644 include/strvec.h -t "$(DESTDIR)$(PREFIX)$(INCLDIR)" @@ -56,4 +61,4 @@ uninstall: rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/libstrvec.so" rm -f "$(DESTDIR)$(PREFIX)$(LIBDIR)/libstrvec.a" -.PHONY: all clean install uninstall +.PHONY: all clean cleanall install uninstall diff --git a/include/strvec.h b/include/strvec.h index 21624e9..a88931b 100644 --- a/include/strvec.h +++ b/include/strvec.h @@ -2,14 +2,64 @@ #include "allocator.h" -#include <stdlib.h> +#define STRVEC_ITER(strvec, p) (p) = NULL; ((p) = strvec_iter_fwd((strvec), (p))); +#define STRVEC_ITER_BWD(strvec, p) (p) = NULL; ((p) = strvec_iter_bwd((strvec), (p))); + + +#ifdef LIBSTRVEC_ASSERT_ARGS +#include "stdlib.h" +#define LIBSTRVEC_ABORT_ON_ARGS(cond) do { if (cond) abort(); } while (0) +#else +#define LIBSTRVEC_ABORT_ON_ARGS(cond) +#endif + +#ifdef LIBSTRVEC_ASSERT_ALLOC +#include "stdlib.h" +#define LIBSTRVEC_ABORT_ON_ALLOC(cond) do { if (cond) abort(); } while (0) +#else +#define LIBSTRVEC_ABORT_ON_ALLOC(cond) +#endif struct strvec; -void strvec_init(struct strvec *strvec, size_t cap, struct allocator *allocator); -void strvec_deinit(struct strvec *strvec); +int strvec_init(struct strvec *strvec, size_t cap, struct allocator *allocator); +int strvec_deinit(struct strvec *strvec); + +struct strvec *strvec_alloc(size_t reserved, struct allocator *allocator, int *rc); +int strvec_free(struct strvec *strvec); + +int strvec_copy(struct strvec *dst, struct strvec *src, + const struct allocator *allocator); +void strvec_move(struct strvec *dst, struct strvec *src); +void strvec_swap(struct strvec *dst, struct strvec *src); + +void strvec_clear(struct strvec *strvec); +int strvec_reserve(struct strvec *strvec, size_t cap); +int strvec_shrink(struct strvec *strvec); + +const char **strvec_stra(struct strvec *strvec); +size_t strvec_len(struct strvec *strvec); + +int strvec_pushn(struct strvec *strvec, const char **str, size_t n); +static inline int strvec_push(struct strvec *strvec, const char *str); +const char **strvec_popn(struct strvec *strvec, size_t n); +static inline const char *strvec_pop(struct strvec *strvec); +void strvec_replace(struct strvec *strvec, size_t index, const char *str); +void strvec_remove(struct strvec *strvec, size_t index, size_t n); + +const char **strvec_iter_fwd(const struct strvec *strvec, const char **p); +const char **strvec_iter_bwd(const struct strvec *strvec, const char **p); -struct strvec *strvec_alloc(size_t reserved, struct allocator *allocator); -void strvec_free(struct strvec *strvec); +static inline int +strvec_push(struct strvec *strvec, const char *str) +{ + return strvec_pushn(strvec, &str, 1); +} +static inline const char * +strvec_pop(struct strvec *strvec) +{ + return *strvec_popn(strvec, 1); +} +extern const size_t strvec_dsize; diff --git a/lib/liballoc b/lib/liballoc -Subproject 7bb4bd65d7a11bbf4ad4e085aa2a32d5028585d +Subproject 52903c46d996b927ff304bae66c522d317a218f diff --git a/lib/libdvec b/lib/libdvec new file mode 160000 +Subproject 93bafd206267f9a0f26b03d60f5b52b0571bef5 diff --git a/libstrvec.api b/libstrvec.api index 803fd35..616ba3c 100644 --- a/libstrvec.api +++ b/libstrvec.api @@ -11,12 +11,15 @@ strvec_clear strvec_reserve strvec_shrink -strvec_push -strvec_pop -strvec_replace +strvec_stra +strvec_len -strvec_append -strvec_delete +strvec_pushn +strvec_popn +strvec_replace +strvec_remove strvec_iter_fwd strvec_iter_bwd + +strvec_dsize diff --git a/libstrvec.lds b/libstrvec.lds index bcc3132..15033b8 100644 --- a/libstrvec.lds +++ b/libstrvec.lds @@ -1,23 +1,29 @@ -LIBDVEC_1.1.2 { +LIBSTRVEC_1.0.0 { global: - dvec_init; - dvec_deinit; + strvec_init; + strvec_deinit; - dvec_alloc; - dvec_free; + strvec_alloc; + strvec_free; - dvec_copy; - dvec_swap; + strvec_copy; + strvec_swap; - dvec_clear; - dvec_reserve; - dvec_shrink; + strvec_clear; + strvec_reserve; + strvec_shrink; - dvec_add; - dvec_rm; - dvec_replace; + strvec_stra; + strvec_len; - dvec_iter_fwd; - dvec_iter_bwd; + strvec_pushn; + strvec_popn; + strvec_replace; + strvec_remove; + + strvec_iter_fwd; + strvec_iter_bwd; + + strvec_dsize; local: *; }; 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); +} |
