commit 8822860aace4bcf868c1798d8ba019fb8c700191
Author: olikru <olikru@tkruger.se>
Date: Mon, 8 Jan 2024 11:51:41 +0100
initial
Diffstat:
| A | Makefile | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
| A | README | | | 14 | ++++++++++++++ |
| A | stack_str.c | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
| A | stack_str.h | | | 70 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | test_stack_str.c | | | 87 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
5 files changed, 249 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,40 @@
+.SUFFIXES: .c .o .so
+CC=clang
+CFLAGS+=-std=c99 -pedantic -Wall -Werror -Wstrict-prototypes
+CFLAGS+=-Wmissing-prototypes -Wmissing-declarations -Wshadow
+CFLAGS+=-Wpointer-arith -Wcast-qual -Wsign-compare
+CFLAGS+=-O2 -g
+CFLAGS+=-fstack-protector-all -Wtype-limits -fno-common
+CFLAGS+=-fno-builtin
+CFLAGS+=-I/usr/local/include
+
+INSTALL_PATH=$(HOME)/.local
+BUILD=build
+
+TEST_SOURCE=test_stack_str.c
+HEADER=stack_str.h
+OBJS=stack_str.o
+SHARED=stack_str.so
+LIBSHARED=libstack_str.so
+
+all: build $(OBJS) $(SHARED) test
+
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $(BUILD)/$@
+
+.o.so:
+ $(CC) -shared -fPIC $(BUILD)/$< -o $(BUILD)/$@
+
+test: $(TEST_SOURCE)
+ $(CC) $(CFLAGS) -o $(BUILD)/test $(TEST_SOURCE) $(BUILD)/$(OBJS)
+
+build:
+ mkdir -p $(BUILD)
+
+install:
+ cp $(BUILD)/$(SHARED) $(INSTALL_PATH)/lib/$(LIBSHARED)
+ chmod 644 $(INSTALL_PATH)/lib/$(LIBSHARED)
+ cp $(HEADER) $(INSTALL_PATH)/include/
+
+clean:
+ rm -rf $(BUILD)
diff --git a/README b/README
@@ -0,0 +1,14 @@
+stack_str
+=========
+
+Small library for stacks of stringss. This stack is only capable of
+increasing it's allocated size, and never shrinking. The stack also
+contains char pointers. Make sure the strings are nice and
+null-terminated and with size implicitly known.
+
+ typedef struct {
+ size_t nmemb;
+ size_t alloc;
+
+ char **data;
+ } stack_str;
diff --git a/stack_str.c b/stack_str.c
@@ -0,0 +1,38 @@
+#include "stack_str.h"
+
+void stack_str_init(stack_str *d) {
+ d->nmemb = 0;
+ d->alloc = BASE_STACK_STR_SIZE;
+
+ d->data = calloc(d->alloc, sizeof(*(d->data)));
+}
+
+void stack_str_clear(stack_str *d) {
+ d->nmemb = 0;
+ free(d->data);
+ d->data = NULL;
+}
+
+void stack_str_push(stack_str *d, char *x) {
+ if (d->alloc <= d->nmemb) {
+ d->alloc <<= 1;
+ d->data = realloc(d->data, d->alloc * sizeof(*(d->data)));
+ }
+
+ d->data[d->nmemb] = x;
+ d->nmemb++;
+}
+
+char *stack_str_get(const stack_str *d, const size_t i) { return d->data[i]; }
+
+char *stack_str_getlast(const stack_str *d) {
+ return stack_str_get(d, d->nmemb - 1);
+}
+
+char *stack_str_pop(stack_str *d) {
+ if (d->nmemb == 0)
+ return STACK_STR_EMPTY_POP;
+ char *r = stack_str_getlast(d);
+ d->nmemb--;
+ return r;
+}
diff --git a/stack_str.h b/stack_str.h
@@ -0,0 +1,70 @@
+#ifndef STACK_STR_H
+#define STACK_STR_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define BASE_STACK_STR_SIZE 256
+#define STACK_STR_EMPTY_POP (NULL)
+
+typedef struct {
+ size_t nmemb;
+ size_t alloc;
+
+ char **data;
+} stack_str;
+
+/**
+ * Initialization of stack.
+ *
+ * Initialises memory for the stack. Use clear.
+ *
+ * @param d pointer to the address where to write the new stack
+ */
+void stack_str_init(stack_str *d);
+
+/**
+ * Clear a stack
+ *
+ * @param d pointer to the stack to clear
+ */
+void stack_str_clear(stack_str *d);
+
+/**
+ * Pushes a string (char pointer) onto the stack.
+ *
+ * Note that this does not copy the string, it just pushes the pointer to the
+ * stack.
+ *
+ * @param d pointer to the stack
+ * @param x the string (char pointer) to push
+ */
+void stack_str_push(stack_str *d, char *x);
+
+/**
+ * Gets the element at index i in the stack.
+ *
+ * @param d pointer to the stack
+ * @param i the index to get element at
+ * @return the value (the char pointer) of the element at index i
+ */
+char *stack_str_get(const stack_str *d, const size_t i);
+
+/**
+ * Get the last (top) element of a stack.
+ *
+ * @param d pointer to the stack
+ */
+char *stack_str_getlast(const stack_str *d);
+
+/**
+ * Pop an element of the stack.
+ *
+ * Note that popping never decreases the amount of memory allocated.
+ * If memory is an issue the stacks have to be destroyed and replaced.
+ *
+ * @param d pointer to the stack
+ */
+char *stack_str_pop(stack_str *d);
+
+#endif
diff --git a/test_stack_str.c b/test_stack_str.c
@@ -0,0 +1,87 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include "stack_str.h"
+
+static void test_stack_str_init() {
+ stack_str t;
+ stack_str_init(&t);
+
+ assert(t.nmemb == 0);
+ assert(t.alloc > 0);
+ assert(t.data != NULL);
+
+ stack_str_clear(&t);
+}
+
+static void test_stack_str_push() {
+ stack_str t;
+ stack_str_init(&t);
+
+ uint64_t i;
+ char buf[2 * BASE_STACK_STR_SIZE][256];
+ for (i = 0; i < 2 * BASE_STACK_STR_SIZE; i++) {
+ snprintf(buf[i], 256, "%llu", i);
+ stack_str_push(&t, buf[i]);
+ }
+
+ assert(t.alloc == 2 * BASE_STACK_STR_SIZE);
+ assert(t.nmemb == 2 * BASE_STACK_STR_SIZE);
+ for (i = 0; i < 2 * BASE_STACK_STR_SIZE; i++) {
+ assert(strncmp(buf[i], t.data[i], 256) == 0);
+ }
+
+ stack_str_clear(&t);
+}
+
+static void test_stack_str_get_getlast() {
+ stack_str t;
+ stack_str_init(&t);
+
+ uint64_t i;
+ char buf[2 * BASE_STACK_STR_SIZE][256];
+ for (i = 0; i < 2 * BASE_STACK_STR_SIZE; i++) {
+ snprintf(buf[i], 256, "%llu", i);
+ stack_str_push(&t, buf[i]);
+ }
+
+ for (i = 0; i < t.nmemb; i++) {
+ assert(stack_str_get(&t, i) == buf[i]);
+ }
+ assert(stack_str_getlast(&t) == buf[2 * BASE_STACK_STR_SIZE - 1]);
+
+ stack_str_clear(&t);
+}
+
+static void test_stack_str_pop() {
+ stack_str t;
+ stack_str_init(&t);
+
+ char *strs[3] = {"hello", "world", "this is a msg"};
+
+ stack_str_push(&t, strs[0]);
+ stack_str_push(&t, strs[1]);
+ stack_str_push(&t, strs[2]);
+
+ assert(t.nmemb == 3);
+ assert(stack_str_pop(&t) == strs[2]);
+ assert(t.nmemb == 2);
+ assert(stack_str_pop(&t) == strs[1]);
+ assert(t.nmemb == 1);
+ assert(stack_str_pop(&t) == strs[0]);
+ assert(t.nmemb == 0);
+ assert(stack_str_pop(&t) == STACK_STR_EMPTY_POP);
+ assert(t.nmemb == 0);
+
+ stack_str_clear(&t);
+}
+
+int main() {
+ test_stack_str_init();
+ test_stack_str_push();
+ test_stack_str_pop();
+ test_stack_str_get_getlast();
+
+ printf("test ok\n");
+}