summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-05-13 21:12:17 +0200
committerLouis Burda <quent.burda@gmail.com>2023-05-13 21:12:17 +0200
commit9fe89a48bb89dc6740787c9ed8c95b5339bba905 (patch)
treebca73651945caef5e188328a538ca782470c43dd /src
parent110b99563e127abe1439fffb0084400b47eea5b3 (diff)
downloadlibstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.tar.gz
libstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.zip
Add initial version
Diffstat (limited to 'src')
-rw-r--r--src/strvec.c218
-rw-r--r--src/test.c32
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);
+}