summaryrefslogtreecommitdiffstats
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
parent110b99563e127abe1439fffb0084400b47eea5b3 (diff)
downloadlibstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.tar.gz
libstrvec-c-9fe89a48bb89dc6740787c9ed8c95b5339bba905.zip
Add initial version
-rw-r--r--.gitignore2
-rw-r--r--.gitmodules3
-rw-r--r--LICENSE21
-rw-r--r--Makefile13
-rw-r--r--include/strvec.h60
m---------lib/liballoc0
m---------lib/libdvec0
-rw-r--r--libstrvec.api13
-rw-r--r--libstrvec.lds36
-rw-r--r--src/strvec.c218
-rw-r--r--src/test.c32
11 files changed, 360 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore
index c4b7ce0..def4110 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..361f116
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/Makefile b/Makefile
index 0c32d75..8fc398a 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
+}