stack_u64

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

commit 2aee4b6107c7b2579cb9d3c27ad61aed4bcd781e
Author: olikru <olikru@tkruger.se>
Date:   Fri,  5 Jan 2024 22:30:42 +0100

initial

Diffstat:
AMakefile | 40++++++++++++++++++++++++++++++++++++++++
AREADME | 13+++++++++++++
Astack_u64.c | 40++++++++++++++++++++++++++++++++++++++++
Astack_u64.h | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest_stack_u64.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 240 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_u64.c +HEADER=stack_u64.h +OBJS=stack_u64.o +SHARED=stack_u64.so +LIBSHARED=libstack_u64.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,13 @@ +stack_u64 +========= + +Small library for stacks of uint64_t's. This stack is only capable of +increasing it's allocated size, and never shrinking. Do not use it if +shrinking is neccessary. + + typedef struct { + size_t nmemb; // number of entries in stack + size_t alloc; // number of entries currently allocated for + + uint64_t *data; // array of entries + } stack_u64_t; diff --git a/stack_u64.c b/stack_u64.c @@ -0,0 +1,40 @@ +#include "stack_u64.h" + +void stack_u64_init(stack_u64_t *d) { + d->nmemb = 0; + d->alloc = BASE_STACK_SIZE; + + d->data = calloc(d->alloc, sizeof(*(d->data))); +} + +void stack_u64_clear(stack_u64_t *d) { + d->nmemb = 0; + free(d->data); + d->data = NULL; +} + +void stack_u64_push(stack_u64_t *d, const uint64_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++; +} + +uint64_t stack_u64_get(const stack_u64_t *d, const size_t i) { + return d->data[i]; +} + +uint64_t stack_u64_getlast(const stack_u64_t *d) { + return stack_u64_get(d, d->nmemb - 1); +} + +uint64_t stack_u64_pop(stack_u64_t *d) { + if (d->nmemb == 0) + return STACK_U64_EMPTY_POP; + uint64_t r = stack_u64_getlast(d); + d->nmemb--; + return r; +} diff --git a/stack_u64.h b/stack_u64.h @@ -0,0 +1,67 @@ +#ifndef STACK_U64_H +#define STACK_U64_H + +#include <stdint.h> +#include <stdlib.h> + +#define BASE_STACK_SIZE 256 +#define STACK_U64_EMPTY_POP UINT64_MAX + +typedef struct { + size_t nmemb; + size_t alloc; + + uint64_t *data; +} stack_u64_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_u64_init(stack_u64_t *d); + +/** + * Clear a stack + * + * @param d pointer to the stack to clear + */ +void stack_u64_clear(stack_u64_t *d); + +/** + * Pushes a uint64_t onto the stack. + * + * @param d pointer to the stack + * @param x the uint64_t to push + */ +void stack_u64_push(stack_u64_t *d, const uint64_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 element at index i + */ +uint64_t stack_u64_get(const stack_u64_t *d, const size_t i); + +/** + * Get the last (top) element of a stack. + * + * @param d pointer to the stack + */ +uint64_t stack_u64_getlast(const stack_u64_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. + * + * @param d pointer to the stack + */ +uint64_t stack_u64_pop(stack_u64_t *d); + +#endif diff --git a/test_stack_u64.c b/test_stack_u64.c @@ -0,0 +1,80 @@ +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include "stack_u64.h" + +static void test_stack_u64_init() { + stack_u64_t t; + stack_u64_init(&t); + + assert(t.nmemb == 0); + assert(t.alloc > 0); + assert(t.data != NULL); + + stack_u64_clear(&t); +} + +static void test_stack_u64_push() { + stack_u64_t t; + stack_u64_init(&t); + + uint64_t i; + for (i = 0; i < 2 * BASE_STACK_SIZE; i++) { + stack_u64_push(&t, i); + } + + assert(t.alloc == 2 * BASE_STACK_SIZE); + assert(t.nmemb == 2 * BASE_STACK_SIZE); + for (i = 0; i < 2 * BASE_STACK_SIZE; i++) { + assert(t.data[i] == i); + } + + stack_u64_clear(&t); +} + +static void test_stack_u64_get_getlast() { + stack_u64_t t; + stack_u64_init(&t); + + uint64_t i; + for (i = 0; i < 2 * BASE_STACK_SIZE; i++) { + stack_u64_push(&t, i); + } + + for (i = 0; i < t.nmemb; i++) { + assert(stack_u64_get(&t, i) == i); + } + assert(stack_u64_getlast(&t) == 2 * BASE_STACK_SIZE - 1); + + stack_u64_clear(&t); +} + +static void test_stack_u64_pop() { + stack_u64_t t; + stack_u64_init(&t); + + stack_u64_push(&t, 13); + stack_u64_push(&t, 16); + stack_u64_push(&t, 17); + + assert(t.nmemb == 3); + assert(stack_u64_pop(&t) == 17); + assert(t.nmemb == 2); + assert(stack_u64_pop(&t) == 16); + assert(t.nmemb == 1); + assert(stack_u64_pop(&t) == 13); + assert(t.nmemb == 0); + assert(stack_u64_pop(&t) == STACK_U64_EMPTY_POP); + assert(t.nmemb == 0); + + stack_u64_clear(&t); +} + +int main() { + test_stack_u64_init(); + test_stack_u64_push(); + test_stack_u64_pop(); + test_stack_u64_get_getlast(); + + printf("test ok\n"); +}