stack_sd

Stack for sd_t's
git clone git://www.tkruger.se/stack_sd.git
Log | Files | Refs | README

commit 80b2c917096e504561dc6471d93dc52be66651a3
Author: olikru <olikru@tkruger.se>
Date:   Mon,  8 Jan 2024 13:33:30 +0100

initial

Diffstat:
AMakefile | 43+++++++++++++++++++++++++++++++++++++++++++
AREADME | 8++++++++
Astack_sd.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Astack_sd.h | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest_stack_sd.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 355 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,43 @@ +.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 + +CFLAGS+=-I$(HOME)/.local/include +LFLAGS+=-L$(HOME)/.local/lib -lsd + +INSTALL_PATH=$(HOME)/.local +BUILD=build + +TEST_SOURCE=test_stack_sd.c +HEADER=stack_sd.h +OBJS=stack_sd.o +SHARED=stack_sd.so +LIBSHARED=libstack_sd.so + +all: build $(OBJS) $(SHARED) test + +.c.o: + $(CC) $(CFLAGS) -c $< -o $(BUILD)/$@ + +.o.so: + $(CC) -shared -fPIC $(BUILD)/$< -o $(BUILD)/$@ $(LFLAGS) + +test: $(TEST_SOURCE) + $(CC) $(CFLAGS) -o $(BUILD)/test $(TEST_SOURCE) $(BUILD)/$(OBJS) $(LFLAGS) + +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,8 @@ +stack_sd +======== + +Small library for stacks of sd_t's. This stack is only capable of +increasing it's allocated size, and never shrinking. Do not use it if +shrinking is neccessary. + + diff --git a/stack_sd.c b/stack_sd.c @@ -0,0 +1,53 @@ +#include "stack_sd.h" + +void stack_sd_init(stack_sd_t *d) { + d->nmemb = 0; + d->alloc = BASE_STACK_SD_SIZE; + + d->data = calloc(d->alloc, sizeof(*(d->data))); +} + +void stack_sd_init_size(stack_sd_t *d, const size_t size) { + d->nmemb = 0; + d->alloc = size; + + d->data = calloc(d->alloc, sizeof(*(d->data))); +} + +void stack_sd_clear(stack_sd_t *d) { + d->nmemb = 0; + free(d->data); + d->data = NULL; +} + +void stack_sd_push(stack_sd_t *d, sd_t 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++; +} + +sd_t stack_sd_get(const stack_sd_t *d, const size_t i) { return d->data[i]; } + +sd_t stack_sd_getlast(const stack_sd_t *d) { return stack_sd_get(d, d->nmemb - 1); } + +sd_t stack_sd_pop(stack_sd_t *d) { + if (d->nmemb == 0) + return STACK_SD_EMPTY_POP; + + sd_t r = stack_sd_getlast(d); + d->nmemb--; + return r; +} + +int stack_sd_lookup(stack_sd_t *d, sd_t s) { + size_t i; + for (i = 0; i < d->nmemb; i++) { + if (sd_cmp(&d->data[i], &s) == 0) + return i; + } + return STACK_SD_LOOKUP_NOT_FOUND; +} diff --git a/stack_sd.h b/stack_sd.h @@ -0,0 +1,97 @@ +#ifndef STACK_SD_H +#define STACK_SD_H + +#include <sd.h> +#include <stdint.h> +#include <stdlib.h> + +#define BASE_STACK_SD_SIZE 256 +#define STACK_SD_LOOKUP_NOT_FOUND (-1) +#define STACK_SD_EMPTY_POP ((sd_t){.size = 0, .data = NULL}) + +typedef struct { + size_t nmemb; + size_t alloc; + + sd_t *data; +} stack_sd_t; + +/** + * Initialization of stack. + * + * Initialises memory for the stack. Use clear. + * + * @param d pointer to the address where to write the new stack + */ +void stack_sd_init(stack_sd_t *d); + +/** + * Initialization of stack, with size. + * + * Initialises memory for the stack. Use clear. + * + * @param d pointer to the address where to write the new stack + * @param size initial size of stack alloc + */ +void stack_sd_init_size(stack_sd_t *d, const size_t size); + +/** + * Clear a stack + * + * @param d pointer to the stack to clear + */ +void stack_sd_clear(stack_sd_t *d); + +/** + * Pushes a sd_t pointer onto the stack. + * + * Note that this does not copy the sd_t data, it just pushes the sd + * struct including the pointer to the stack. + * + * @param d pointer to the stack + * @param x the sd_t to push + */ +void stack_sd_push(stack_sd_t *d, sd_t 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 of the sd_t at index i + */ +sd_t stack_sd_get(const stack_sd_t *d, const size_t i); + +/** + * Get the last (top) element of a stack. + * + * @param d pointer to the stack + * @return the value of the sd_t at the top + */ +sd_t stack_sd_getlast(const stack_sd_t *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. + * Returns STACK_SD_POP_EMPY if stack is empty. + * + * @param d pointer to the stack + * @return the value of the popped sd + */ +sd_t stack_sd_pop(stack_sd_t *d); + +/** + * Lookup a sd_t on a stack. + * + * Returns the first index on the stack at which a sd_t appears. Returns + * STACK_SD_LOOKUP_NOT_FOUND (== -1) if element is not in stack. It + * compares the sd_t elements (i.e. not only the pointers). + * + * @param d the stack to lookup in + * @param s the sd_t to look for in the stack + */ +int stack_sd_lookup(stack_sd_t *d, sd_t s); + +#endif diff --git a/test_stack_sd.c b/test_stack_sd.c @@ -0,0 +1,154 @@ +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include "stack_sd.h" + +static void test_stack_sd_init() { + stack_sd_t s; + stack_sd_init(&s); + + assert(s.nmemb == 0); + assert(s.alloc == BASE_STACK_SD_SIZE); + assert(s.data != NULL); + + stack_sd_clear(&s); + + stack_sd_init_size(&s, 4); + + assert(s.nmemb == 0); + assert(s.alloc == 4); + assert(s.data != NULL); + + stack_sd_clear(&s); +} + +static void test_stack_sd_push() { + stack_sd_t s; + stack_sd_init_size(&s, 4); + + sd_t topush[5]; + size_t i; + for (i = 0; i < 5; i++) { + sd_init_u64(&topush[i], i); + stack_sd_push(&s, topush[i]); + + assert(s.nmemb == i + 1); + } + assert(s.nmemb == 5); + assert(s.alloc == 8); + + assert(memcmp(s.data, topush, sizeof(*topush) * 5) == 0); + + for (i = 0; i < 5; i++) + sd_clear(&topush[i]); + stack_sd_clear(&s); +} + +static void test_stack_sd_get() { + stack_sd_t s; + stack_sd_init(&s); + + sd_t topush[20]; + size_t i; + for (i = 0; i < 20; i++) { + sd_init_u64(&topush[i], i); + stack_sd_push(&s, topush[i]); + } + + sd_t tmp; + for (i = 0; i < 20; i++) { + tmp = stack_sd_get(&s, i); + assert(tmp.size == topush[i].size); + assert(tmp.data == topush[i].data); + } + + for (i = 0; i < 5; i++) + sd_clear(&topush[i]); + stack_sd_clear(&s); +} + +static void test_stack_sd_getlast() { + stack_sd_t s; + stack_sd_init_size(&s, 8); + + sd_t topush[20]; + size_t i; + for (i = 0; i < 20; i++) { + sd_init_u64(&topush[i], i); + stack_sd_push(&s, topush[i]); + } + + sd_t tmp = stack_sd_getlast(&s); + assert(tmp.size == topush[19].size); + assert(tmp.data == topush[19].data); + + for (i = 0; i < 5; i++) + sd_clear(&topush[i]); + stack_sd_clear(&s); +} + +static void test_stack_sd_pop() { + stack_sd_t s; + stack_sd_init_size(&s, 8); + + sd_t topush[20]; + size_t i; + for (i = 0; i < 20; i++) { + sd_init_u64(&topush[i], i); + stack_sd_push(&s, topush[i]); + } + + sd_t tmp; + for (i = 0; i < 20; i++) { + tmp = stack_sd_pop(&s); + assert(tmp.size == topush[19 - i].size); + assert(tmp.data == topush[19 - i].data); + } + + tmp = stack_sd_pop(&s); + assert(tmp.size == STACK_SD_EMPTY_POP.size); + assert(tmp.data == STACK_SD_EMPTY_POP.data); + + tmp = stack_sd_pop(&s); + assert(tmp.size == STACK_SD_EMPTY_POP.size); + assert(tmp.data == STACK_SD_EMPTY_POP.data); + + for (i = 0; i < 5; i++) + sd_clear(&topush[i]); + stack_sd_clear(&s); +} + +static void test_stack_sd_lookup() { + stack_sd_t s; + stack_sd_init_size(&s, 8); + + sd_t topush[20]; + size_t i; + for (i = 0; i < 20; i++) { + sd_init_u64(&topush[i], i); + stack_sd_push(&s, topush[i]); + } + + sd_t tmp; + sd_init_u64(&tmp, 13); + assert(stack_sd_lookup(&s, tmp) == 13); + sd_clear(&tmp); + sd_init_u64(&tmp, 22); + assert(stack_sd_lookup(&s, tmp) == STACK_SD_LOOKUP_NOT_FOUND); + sd_clear(&tmp); + + for (i = 0; i < 5; i++) + sd_clear(&topush[i]); + stack_sd_clear(&s); +} + +int main() { + test_stack_sd_init(); + test_stack_sd_push(); + test_stack_sd_getlast(); + test_stack_sd_get(); + test_stack_sd_pop(); + test_stack_sd_lookup(); + + printf("test ok\n"); +}