commit 7520b04430cfbbb91fa1a3e7bf94995d18655caf
parent 7c1d102fb7559da3aa34e0457e68148e8f8bb8af
Author: Louis Burda <quent.burda@gmail.com>
Date: Tue, 29 Mar 2022 18:11:15 +0200
Disconnect data buf from struct and make definition public
Diffstat:
6 files changed, 168 insertions(+), 83 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS = -I include
+CFLAGS = -I include -g
LDLIBS =
DEPFLAGS = -MT $@ -MMD -MP -MF build/$*.d
@@ -34,9 +34,8 @@ build/libvec.a: $(OBJS) | build
ar rcs $@ build/fixed.o
build/libvec.so: $(PI_OBJS) | build
- $(CC) -o build/tmp.so $(PI_OBJS) $(CFLAGS) -shared
- objcopy --keep-global-symbols=libvec.abi build/tmp.so $@
+ $(CC) -o $@ $(PI_OBJS) $(CFLAGS) -shared -Wl,-version-script libvec.lds
build/test: src/test.c build/libvec.a | build
- $(CC) -o $@ $^ -I include
+ $(CC) -o $@ $^ $(CFLAGS)
diff --git a/include/vec.h b/include/vec.h
@@ -1,7 +1,29 @@
#include <stdbool.h>
#include <stdlib.h>
-struct vec;
+#define VEC_PUSH(vec, type, val) \
+ do { \
+ type tmp = (val); \
+ vec_push(vec, &tmp); } while (0)
+
+#define VEC_POP(vec, type, var) \
+ do { \
+ type *tmp = vec_pop(vec); \
+ memcpy(&var, tmp, sizeof(type); \
+ } while (0)
+
+#define VEC_AT(vec, type, idx) \
+ (*(type *)vec_at(vec, idx))
+
+struct vec {
+ size_t dsize;
+ size_t len, cap;
+
+ char *data;
+};
+
+void vec_init(struct vec *vec, size_t dsize, size_t cap);
+void vec_deinit(struct vec *vec);
struct vec *vec_alloc(size_t dsize, size_t cap);
void vec_free(struct vec *vec);
@@ -11,15 +33,18 @@ void vec_resize(struct vec *vec, size_t cap);
void vec_add(struct vec *vec, const void *data, size_t count);
void vec_rm(struct vec *vec, size_t count);
+void vec_rm_at(struct vec *vec, size_t index, size_t count);
void vec_push(struct vec *vec, const void *data);
void *vec_pop(struct vec *vec);
-void vec_pop_at(struct vec *vec, size_t index);
void *vec_at(struct vec *vec, size_t index);
bool vec_iter(struct vec *vec, void *p);
void vec_set(struct vec *vec, size_t index, const void *data);
+void vec_setbuf(struct vec *vec, void *buf);
+void *vec_popbuf(struct vec *vec);
+
int vec_empty(struct vec *vec);
int vec_len(struct vec *vec);
diff --git a/libvec.abi b/libvec.abi
@@ -1,3 +1,6 @@
+vec_init
+vec_deinit
+
vec_alloc
vec_free
diff --git a/libvec.lds b/libvec.lds
@@ -0,0 +1,24 @@
+LIBVEC_1.0 {
+ global:
+ vec_init;
+ vec_deinit;
+
+ vec_alloc;
+ vec_free;
+
+ vec_clear;
+ vec_resize;
+
+ vec_push;
+ vec_pop;
+
+ vec_at;
+ vec_iter;
+
+ vec_set;
+ vec_rm;
+
+ vec_empty;
+ vec_len;
+ local: *;
+};
diff --git a/src/test.c b/src/test.c
@@ -7,21 +7,16 @@
int
main(int argc, const char **argv)
{
- struct vec *vec;
- int *num;
- int i, val;
+ struct vec vec;
+ int *num, i;
- vec = vec_alloc(sizeof(int), 10);
-
- for (i = 1; i < argc; i++) {
- val = atoi(argv[i]);
- vec_push(vec, &val);
- }
+ vec_init(&vec, sizeof(int), 10);
- num = NULL;
- while (vec_iter(vec, &num)) {
- printf("%i\n", *num);
- }
+ for (i = 1; i < argc; i++)
+ VEC_PUSH(&vec, int, atoi(argv[i]));
- vec_free(vec);
+ for (i = 0; i < vec_len(&vec); i++)
+ printf("%i\n", VEC_AT(&vec, int, i));
+
+ vec_deinit(&vec);
}
diff --git a/src/vec.c b/src/vec.c
@@ -6,22 +6,16 @@
#include <stdarg.h>
#include <string.h>
-#define OFFSETOF(type, member) ((size_t) &((type *)0)->member)
-
+#ifdef LIBVEC_SAFE
#define ASSERT(x) assert((x), __FILE__, __LINE__, #x)
#define OOM_CHECK(x) assert((x) != NULL, __FILE__, __LINE__, "Out of Memory")
-
-struct vec {
- size_t dsize;
- size_t count, cap;
-
- char data[];
-};
+#else
+#define ASSERT(x)
+#define OOM_CHECK(x)
+#endif
static void assert(int cond, const char *file, int line, const char *condstr);
-static const size_t vec_data_offset = OFFSETOF(struct vec, data);
-
void
assert(int cond, const char *file, int line, const char *condstr)
{
@@ -32,18 +26,41 @@ assert(int cond, const char *file, int line, const char *condstr)
exit(1);
}
+void
+vec_init(struct vec *vec, size_t dsize, size_t cap)
+{
+ ASSERT(vec != NULL && dsize > 0 && cap >= 0);
+
+ vec->dsize = dsize;
+ vec->cap = cap;
+
+ vec->len = 0;
+ vec->data = NULL;
+ if (vec->cap) {
+ vec->data = malloc(dsize * cap);
+ OOM_CHECK(vec->data);
+ }
+}
+
+void
+vec_deinit(struct vec *vec)
+{
+ ASSERT(vec != NULL);
+
+ free(vec->data);
+}
+
struct vec *
vec_alloc(size_t dsize, size_t cap)
{
struct vec *vec;
- ASSERT(dsize != 0 && cap != 0);
+ ASSERT(dsize > 0 && cap > 0);
- vec = malloc(vec_data_offset + cap * dsize);
+ vec = malloc(sizeof(struct vec));
OOM_CHECK(vec);
- vec->dsize = dsize;
- vec->count = 0;
- vec->cap = cap;
+
+ vec_init(vec, dsize, cap);
return vec;
}
@@ -53,6 +70,7 @@ vec_free(struct vec *vec)
{
ASSERT(vec != NULL);
+ vec_deinit(vec);
free(vec);
}
@@ -61,50 +79,68 @@ vec_clear(struct vec *vec)
{
ASSERT(vec != NULL);
- vec->count = 0;
+ vec->len = 0;
}
void
vec_resize(struct vec *vec, size_t cap)
{
- ASSERT(vec != NULL && cap != 0 && vec->count <= cap);
+ ASSERT(vec != NULL && cap != 0 && vec->len <= cap);
vec->cap = cap;
- vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
- OOM_CHECK(vec);
+ vec->data = realloc(vec->data, vec->cap * vec->dsize);
+ OOM_CHECK(vec->data);
}
void
-vec_add(struct vec *vec, const void *data, size_t count)
+vec_add(struct vec *vec, const void *data, size_t len)
{
ASSERT(vec != NULL && data != NULL);
- if (vec->count + count > vec->cap) {
+ if (vec->len + len > vec->cap) {
vec->cap *= 2;
- if (vec->count + count > vec->cap)
- vec->cap = vec->count + count;
- vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
- OOM_CHECK(vec);
+ if (vec->len + len > vec->cap)
+ vec->cap = vec->len + len;
+ vec->data = realloc(vec->data, vec->cap * vec->dsize);
+ OOM_CHECK(vec->data);
}
- memcpy(vec->data + vec->count * vec->dsize,
- data, vec->count * vec->dsize);
- vec->count += count;
+ memcpy(vec->data + vec->len * vec->dsize, data, len * vec->dsize);
+ vec->len += len;
}
void
vec_rm(struct vec *vec, size_t count)
{
- ASSERT(vec != NULL);
+ ASSERT(vec != NULL && len >= vec->len);
- vec->count -= count;
- if (vec->count < vec->cap / 2) {
+ vec->len -= count;
+ if (vec->len < vec->cap / 2) {
vec->cap /= 2;
- vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
- OOM_CHECK(vec);
+ vec->data = realloc(vec->data, vec->cap * vec->dsize);
+ OOM_CHECK(vec->data);
+ }
+}
+
+void
+vec_rm_at(struct vec *vec, size_t index, size_t count)
+{
+ void *start, *end;
+
+ ASSERT(vec != NULL && index < vec->len
+ && count > 0 && index + count < vec->len);
+
+ if (index + count < vec->len) {
+ start = vec->data + index * vec->dsize;
+ end = vec->data + vec->len * vec->dsize;
+ memcpy(start, start + count * vec->dsize,
+ (vec->len - index - count) * vec->dsize);
}
+
+ vec_rm(vec, count);
}
+
void
vec_push(struct vec *vec, const void *data)
{
@@ -118,35 +154,13 @@ vec_pop(struct vec *vec)
vec_rm(vec, 1);
- return vec->data + vec->dsize * vec->count;
-}
-
-void
-vec_pop_at(struct vec *vec, size_t index)
-{
- void *start, *end;
-
- ASSERT(vec != NULL && index < vec->count);
-
- start = vec->data + index * vec->dsize;
- end = vec->data + vec->count * vec->dsize;
- if (start + vec->dsize < end) {
- memcpy(start, start + vec->dsize, end - start - vec->dsize);
- }
-
- vec->count--;
-
- if (vec->count < vec->cap / 2) {
- vec->cap /= 2;
- vec = realloc(vec, vec_data_offset + vec->cap * vec->dsize);
- OOM_CHECK(vec);
- }
+ return vec->data + vec->dsize * vec->len;
}
void *
vec_at(struct vec *vec, size_t index)
{
- ASSERT(vec != NULL && index < vec->count);
+ ASSERT(vec != NULL && index < vec->len);
return vec->data + vec->dsize * index;
}
@@ -156,7 +170,9 @@ vec_iter(struct vec *vec, void *_p)
{
char **iter;
- ASSERT(vec != NULL && vec != NULL);
+ ASSERT(vec != NULL && p != NULL);
+
+ if (!vec->len) return false;
iter = _p;
if (*iter == NULL) {
@@ -165,23 +181,46 @@ vec_iter(struct vec *vec, void *_p)
*iter += vec->dsize;
}
- return *iter < vec->data + vec->dsize * vec->count;
+ return *iter < vec->data + vec->dsize * vec->len;
}
void
vec_set(struct vec *vec, size_t index, const void *data)
{
- ASSERT(vec != NULL && data != NULL && index < vec->count);
+ ASSERT(vec != NULL && data != NULL && index < vec->len);
memcpy(vec->data + index * vec->dsize, data, vec->dsize);
}
+void
+vec_setbuf(struct vec *vec, void *data)
+{
+ ASSERT(vec != NULL && buf != NULL);
+
+ free(vec->data);
+ vec->data = data;
+}
+
+void *
+vec_popbuf(struct vec *vec)
+{
+ void *data;
+
+ ASSERT(vec != NULL);
+
+ data = vec->data;
+ vec->data = NULL;
+ vec->len = 0;
+
+ return data;
+}
+
int
vec_empty(struct vec *vec)
{
ASSERT(vec != NULL);
- return vec->count == 0;
+ return vec->len == 0;
}
int
@@ -189,5 +228,5 @@ vec_len(struct vec *vec)
{
ASSERT(vec != NULL);
- return vec->count;
+ return vec->len;
}