liblash

A bianry tree implementation used for game development from scratch
git clone git://holbrook.no/liblash.git
Log | Files | Refs | LICENSE

commit 521e21ef44a78573a754c424c3a6e2b289eb7ee9
parent b7ac2db355af4d0d4724a969aa5044e3714d1865
Author: nolash <dev@holbrook.no>
Date:   Sun,  5 Jan 2020 21:57:22 +0100

Prune filename prefix

Diffstat:
Adebug_log.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rlash_debug_log.h -> debug_log.h | 0
Adebug_timer.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
Rlash_debug_timer.h -> debug_timer.h | 0
Aendian.c | 44++++++++++++++++++++++++++++++++++++++++++++
Rlash_endian.h -> endian.h | 0
Ahex.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rlash_hex.h -> hex.h | 0
Dlash_debug_log.c | 78------------------------------------------------------------------------------
Dlash_debug_timer.c | 47-----------------------------------------------
Dlash_endian.c | 44--------------------------------------------
Dlash_hex.c | 68--------------------------------------------------------------------
Dlash_tree3.c | 198-------------------------------------------------------------------------------
Dlash_tree3_dump.c | 66------------------------------------------------------------------
Dlash_tree3_dump.h | 79-------------------------------------------------------------------------------
Mtests/debuglog.c | 3++-
Mtests/debuglogmaster.c | 2+-
Mtests/debugtimer.c | 5++---
Mtests/tree3_console.c | 5+++--
Mtests/tree3_shifttest.c | 5+++--
Atree.c | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atree.c_intindex | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rlash_tree3.h -> tree.h | 0
Atree_dump.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atree_dump.h | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25 files changed, 766 insertions(+), 589 deletions(-)

diff --git a/debug_log.c b/debug_log.c @@ -0,0 +1,78 @@ +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#include "debug_log.h" + +struct timespec _timecontainer; + +int lash_debugLogInit(lash_debug_log_t *log, int autoflush) { + + log->capacity = 0; + log->items = (lash_debug_log_item_t*)malloc(sizeof(lash_debug_log_item_t) * LASH_DEBUG_LOG_CAPACITY_CHUNK); + + if (log->items == NULL) { + log = NULL; + return 1; + } + + log->error_string_buffer = (char*)calloc(LASH_DEBUG_LOG_CAPACITY_DESCRIPTION, sizeof(char)); + + if (log->error_string_buffer == NULL) { + log = NULL; + return 1; + } + + log->capacity = LASH_DEBUG_LOG_CAPACITY_CHUNK; + log->count = 0; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &_timecontainer); + log->ns_start = _timecontainer.tv_nsec; + log->autoflush = autoflush != 0 ? 1 : 0; + + return 0; +} + +/** + * TODO Auto extend memory for log if capacity runs out + */ + +int lash_debugLogAdd(lash_debug_log_t *log, char *origin, char level, char *description) { + if (log->count == log->capacity || log->capacity == 0) + return 1; + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &_timecontainer); + (log->items+log->count)->ns = _timecontainer.tv_nsec; + (log->items+log->count)->level = level; + + if (description == NULL) + (log->items+log->count)->description = log->error_string_buffer; + else + (log->items+log->count)->description = description; + + + if (origin == NULL) + (log->items+log->count)->origin = log->origin_string_buffer; + else + (log->items+log->count)->origin = origin; + + + if (log->autoflush > 0) + fprintf(stderr, "%s: %s\n", (log->items+log->count)->origin, (log->items+log->count)->description); + + //*(log->error_string_buffer) = NULL; + //*(log->origin_string_buffer) = NULL; + log->error_string_buffer = NULL; + log->origin_string_buffer = NULL; + + log->count++; + + return 0; +} + +int lash_debugLogSetDescription(lash_debug_log_t *log, const char *d) { + log->error_string_buffer = d; +} + +int lash_debugLogSetOrigin(lash_debug_log_t *log, const char *o) { + log->origin_string_buffer = o; +} diff --git a/lash_debug_log.h b/debug_log.h diff --git a/debug_timer.c b/debug_timer.c @@ -0,0 +1,48 @@ +#include <time.h> + +#include "debug_timer.h" + +void lash_debugTimerReset(lash_debug_timer_t *time) { + time->running = 0; + time->paused = 0; + time->count = 0; + time->total = 0; +} + +void lash_debugTimerStart(lash_debug_timer_t *time) { + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_start)); + time->running = 1; +} + +long lash_debugTimerPause(lash_debug_timer_t *time) { + if (!time->running) + return 0; + + if (time->paused) { + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_tmp)); + time->snap_start.tv_nsec += time->snap_tmp.tv_nsec - time->snap_end.tv_nsec; + time->paused = 0; + return time->snap_tmp.tv_nsec; + } else { + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_end)); + time->paused = 1; + return time->snap_end.tv_nsec; + } +} + +void lash_debugTimerStop(lash_debug_timer_t * time) { + if (time->running == 0) + return; + + if (!time->paused) + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_end)); + + time->total = time->snap_end.tv_nsec - time->snap_start.tv_nsec; + time->count++; + time->running = 0; + time->paused = 0; +} + +float lash_debugTimerGetAverage(lash_debug_timer_t *time) { + return time->total / (float)time->count; +} diff --git a/lash_debug_timer.h b/debug_timer.h diff --git a/endian.c b/endian.c @@ -0,0 +1,44 @@ +#include "endian.h" + +int is_le() { + short s = 42; + return *((unsigned char*)&s) == 42; +} + +// convert unsigned integer to little-endian representation +int to_endian(char direction, int l, void *n) { + union le un; + + if (l == 1 || is_le() == direction) { + return 0; + } + switch(l) { + case sizeof(long long): + un.ll = (long long*)n; + break; + case sizeof(int): + un.i = (int*)n; + break; + case sizeof(short): + un.s = (short*)n; + break; + default: + return 1; + } + flip_endian(l, &un); + + return 0; +} + +void flip_endian(int l, union le *n) { + int i; + char t; + char *ne; + + ne = (n->c)+(l-1); + for (i = 0; i < l/2; i++) { + t = *(n->c+i); + *((n->c)+i) = *(ne-i); + *(ne-i) = t; + } +} diff --git a/lash_endian.h b/endian.h diff --git a/hex.c b/hex.c @@ -0,0 +1,68 @@ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include "hex.h" + +/** +* \todo improve +*/ +int toHex(const unsigned char *data, size_t l, unsigned char *zHex, size_t *z) { + int i; + + if (*z < (l*2)+1) { + return 1; + } + + for (i = 0; i < l; i++) { + sprintf(zHex+(i*2), "%02x", *(data+i)); + } + *z = (i*2); + *(zHex+(*z)) = 0x0; + *z++; + return 0; +} + + +// cheekily stolen from https://nachtimwald.com/2017/09/24/hex-encode-and-decode-in-c/ +int hexchr2bin(const char hex, char *out) { + if (out == NULL) + return 0; + + if (hex >= '0' && hex <= '9') { + *out = hex - '0'; + } else if (hex >= 'A' && hex <= 'F') { + *out = hex - 'A' + 10; + } else if (hex >= 'a' && hex <= 'f') { + *out = hex - 'a' + 10; + } else { + return 0; + } + + return 1; +} + +size_t hex2bin(const char *hex, unsigned char **out) { + size_t len; + char b1; + char b2; + size_t i; + + if (hex == NULL || *hex == '\0' || out == NULL) + return 0; + + len = strlen(hex); + if (len % 2 != 0) + return 0; + len /= 2; + + *out = malloc(len); + memset(*out, 'A', len); + for (i=0; i<len; i++) { + if (!hexchr2bin(hex[i*2], &b1) || !hexchr2bin(hex[i*2+1], &b2)) { + return 0; + } + (*out)[i] = (b1 << 4) | b2; + } + return len; +} diff --git a/lash_hex.h b/hex.h diff --git a/lash_debug_log.c b/lash_debug_log.c @@ -1,78 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <time.h> - -#include "lash_debug_log.h" - -struct timespec _timecontainer; - -int lash_debugLogInit(lash_debug_log_t *log, int autoflush) { - - log->capacity = 0; - log->items = (lash_debug_log_item_t*)malloc(sizeof(lash_debug_log_item_t) * LASH_DEBUG_LOG_CAPACITY_CHUNK); - - if (log->items == NULL) { - log = NULL; - return 1; - } - - log->error_string_buffer = (char*)calloc(LASH_DEBUG_LOG_CAPACITY_DESCRIPTION, sizeof(char)); - - if (log->error_string_buffer == NULL) { - log = NULL; - return 1; - } - - log->capacity = LASH_DEBUG_LOG_CAPACITY_CHUNK; - log->count = 0; - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &_timecontainer); - log->ns_start = _timecontainer.tv_nsec; - log->autoflush = autoflush != 0 ? 1 : 0; - - return 0; -} - -/** - * TODO Auto extend memory for log if capacity runs out - */ - -int lash_debugLogAdd(lash_debug_log_t *log, char *origin, char level, char *description) { - if (log->count == log->capacity || log->capacity == 0) - return 1; - - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &_timecontainer); - (log->items+log->count)->ns = _timecontainer.tv_nsec; - (log->items+log->count)->level = level; - - if (description == NULL) - (log->items+log->count)->description = log->error_string_buffer; - else - (log->items+log->count)->description = description; - - - if (origin == NULL) - (log->items+log->count)->origin = log->origin_string_buffer; - else - (log->items+log->count)->origin = origin; - - - if (log->autoflush > 0) - fprintf(stderr, "%s: %s\n", (log->items+log->count)->origin, (log->items+log->count)->description); - - //*(log->error_string_buffer) = NULL; - //*(log->origin_string_buffer) = NULL; - log->error_string_buffer = NULL; - log->origin_string_buffer = NULL; - - log->count++; - - return 0; -} - -int lash_debugLogSetDescription(lash_debug_log_t *log, const char *d) { - log->error_string_buffer = d; -} - -int lash_debugLogSetOrigin(lash_debug_log_t *log, const char *o) { - log->origin_string_buffer = o; -} diff --git a/lash_debug_timer.c b/lash_debug_timer.c @@ -1,47 +0,0 @@ -#include "lash_debug_timer.h" -#include <time.h> - -void lash_debugTimerReset(lash_debug_timer_t *time) { - time->running = 0; - time->paused = 0; - time->count = 0; - time->total = 0; -} - -void lash_debugTimerStart(lash_debug_timer_t *time) { - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_start)); - time->running = 1; -} - -long lash_debugTimerPause(lash_debug_timer_t *time) { - if (!time->running) - return 0; - - if (time->paused) { - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_tmp)); - time->snap_start.tv_nsec += time->snap_tmp.tv_nsec - time->snap_end.tv_nsec; - time->paused = 0; - return time->snap_tmp.tv_nsec; - } else { - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_end)); - time->paused = 1; - return time->snap_end.tv_nsec; - } -} - -void lash_debugTimerStop(lash_debug_timer_t * time) { - if (time->running == 0) - return; - - if (!time->paused) - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(time->snap_end)); - - time->total = time->snap_end.tv_nsec - time->snap_start.tv_nsec; - time->count++; - time->running = 0; - time->paused = 0; -} - -float lash_debugTimerGetAverage(lash_debug_timer_t *time) { - return time->total / (float)time->count; -} diff --git a/lash_endian.c b/lash_endian.c @@ -1,44 +0,0 @@ -#include "liblash/lash_endian.h" - -int is_le() { - short s = 42; - return *((unsigned char*)&s) == 42; -} - -// convert unsigned integer to little-endian representation -int to_endian(char direction, int l, void *n) { - union le un; - - if (l == 1 || is_le() == direction) { - return 0; - } - switch(l) { - case sizeof(long long): - un.ll = (long long*)n; - break; - case sizeof(int): - un.i = (int*)n; - break; - case sizeof(short): - un.s = (short*)n; - break; - default: - return 1; - } - flip_endian(l, &un); - - return 0; -} - -void flip_endian(int l, union le *n) { - int i; - char t; - char *ne; - - ne = (n->c)+(l-1); - for (i = 0; i < l/2; i++) { - t = *(n->c+i); - *((n->c)+i) = *(ne-i); - *(ne-i) = t; - } -} diff --git a/lash_hex.c b/lash_hex.c @@ -1,68 +0,0 @@ -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#include "liblash/lash_hex.h" - -/** -* \todo improve -*/ -int toHex(const unsigned char *data, size_t l, unsigned char *zHex, size_t *z) { - int i; - - if (*z < (l*2)+1) { - return 1; - } - - for (i = 0; i < l; i++) { - sprintf(zHex+(i*2), "%02x", *(data+i)); - } - *z = (i*2); - *(zHex+(*z)) = 0x0; - *z++; - return 0; -} - - -// cheekily stolen from https://nachtimwald.com/2017/09/24/hex-encode-and-decode-in-c/ -int hexchr2bin(const char hex, char *out) { - if (out == NULL) - return 0; - - if (hex >= '0' && hex <= '9') { - *out = hex - '0'; - } else if (hex >= 'A' && hex <= 'F') { - *out = hex - 'A' + 10; - } else if (hex >= 'a' && hex <= 'f') { - *out = hex - 'a' + 10; - } else { - return 0; - } - - return 1; -} - -size_t hex2bin(const char *hex, unsigned char **out) { - size_t len; - char b1; - char b2; - size_t i; - - if (hex == NULL || *hex == '\0' || out == NULL) - return 0; - - len = strlen(hex); - if (len % 2 != 0) - return 0; - len /= 2; - - *out = malloc(len); - memset(*out, 'A', len); - for (i=0; i<len; i++) { - if (!hexchr2bin(hex[i*2], &b1) || !hexchr2bin(hex[i*2+1], &b2)) { - return 0; - } - (*out)[i] = (b1 << 4) | b2; - } - return len; -} diff --git a/lash_tree3.c b/lash_tree3.c @@ -1,198 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "liblash/lash_tree3.h" - - -lash_tree_t *lash_treeInit(lash_tree_t *tree, const unsigned int size) { - tree = (lash_tree_t*)malloc(sizeof(lash_tree_t)); - tree->key = (lash_tree_key_t**)malloc(sizeof(lash_tree_key_t*) * size + 1); - tree->item = (void*)malloc(sizeof(void*) * size + 1); - - if (tree->key == NULL || tree->item == NULL) - return NULL; - - tree->count = 0; - //tree->shiftpos = 0; - tree->capacity = size; - //tree->foldbackthreshold = tree->capacity / 2; - - return tree; -} - -void lash_treeFree(lash_tree_t *tree) { - if (tree == NULL) - return; - - if (tree->key != NULL) - free(tree->key); - - if (tree->item != NULL) - free(tree->item); - - free(tree); -} - -// key is optional, if NULL is passed, then tree assumes a lash_tree_key_t at first address of item pointer -int lash_treePush(lash_tree_t *tree, void *item, lash_tree_key_t *key) { - //printf("%p", item); - - if (tree->count == tree->capacity) - return -1; - - tree->count++; - - if (key != NULL) - *(tree->key + tree->count - 1) = key; - else - *(tree->key + tree->count - 1) = (lash_tree_key_t*)item; - - *(tree->item + tree->count - 1) = item; - - _lash_treeProcess(tree, tree->count, -1); - - return tree->count; -} - -int lash_treeShift(lash_tree_t *tree, void **item) { - return lash_treeRemove(tree, 0, item); -} - -int lash_treeRemove(lash_tree_t *tree, unsigned int position, void **item) { - - if (tree->count == 0) - return -1; - - // retrieve the values from the position from the argument - *item = *(tree->item + position); - - // move the values from the end of the tree to the position from the argument - *(tree->key + position) = *(tree->key + tree->count - 1); - *(tree->item + position) = *(tree->item + tree->count - 1); - - // reduce the count of the tree - tree->count--; - - // iterate the new value down the tree to its proper place - _lash_treeProcess(tree, position + 1, 1); - - return tree->count; -} - -int _lash_treeProcess(lash_tree_t *tree, unsigned int currentposition, int direction) { - - // towards end of pointer is downwards in the tree - // the direction to sort, -1 is from end towards start, 1 is from startposition towards end - - while (direction != 0) { - - lash_tree_key_t *currentkey = *(tree->key + currentposition - 1); - lash_tree_key_t *nextkey = NULL; - lash_tree_key_t *swapkey; - //lash_tree_key_t swapkey; - void *swapitem;; - void *currentitem; - void *nextitem; - - unsigned int nextposition; - - switch(direction) { - - // if there is still room to ascend in the tree, that is if the current position isn't 0 already. - case -1: - if (currentposition == 1) { - direction = 0; - } else { - nextposition = currentposition >> 1; - nextkey = *(tree->key + nextposition - 1); - if (*currentkey < *nextkey) { - /*swapkey = *currentkey; - *currentkey = *nextkey; - *nextkey = swapkey;*/ - - currentitem = *(tree->item + currentposition - 1); - nextitem = *(tree->item + nextposition - 1); - - swapkey = currentkey; - *(tree->key + currentposition - 1) = nextkey; - *(tree->key + nextposition - 1) = swapkey; - - // ORIGINALLY IT SEEMED LIKE WHEN THE ADDRESS WAS THE SAME THAT THIS WOULD SHIFT THINGS AROUND TWICE - // NOW IT WORKS IF THE ADDRESS OF THE KEY AND THE FIRST ADDRESS OF THE ITEM ARE THE SAME - // if the position of the key is not in the first address of the item we need to move it separately - // note that swapkey now holds the original currentkey - //if ((lash_tree_key_t *)currentitem != swapkey) { - swapitem = currentitem; - *(tree->item + currentposition - 1) = nextitem; - *(tree->item + nextposition - 1) = swapitem; - //} - - currentposition = nextposition; - } else { - direction = 0; - } - } - break; - - // if there is still room from the current position to descend one level in the tree): - // level 0 has 2^0 = entry 1 - // level 1 has 2^1 = entries 2-3 - // level 2 has 2^2 = entries 4-7 - // if we're at position 3, the check will be 3*2 = 6, which is within bounds of level 2, and points to elements 6 and 7 (the children of 3) - // If we're at position 4, the check will be 4*2 = 8, which is out of bounds of level 2. - - case 1: - nextposition = currentposition << 1; - - if (nextposition <= tree->count) { - - // compare both the child values, to pick the higher one - nextkey = *(tree->key + nextposition - 1); - if (*nextkey > **(tree->key + nextposition)) { - nextkey = *(tree->key + nextposition); - nextposition++; - } - - // compare the values, set nextkey back to null to stop the swapping if the value is not higher - if (*currentkey <= *nextkey) { - nextkey = NULL; - } - - if (nextkey != NULL) { - /*swapkey = *currentkey; - *currentkey = *nextkey; - *nextkey = swapkey;*/ - - currentitem = *(tree->item + currentposition - 1); - nextitem = *(tree->item + nextposition - 1); - - swapkey = currentkey; - *(tree->key + currentposition - 1) = nextkey; - *(tree->key + nextposition - 1) = swapkey; - - // ORIGINALLY IT SEEMED LIKE WHEN THE ADDRESS WAS THE SAME THAT THIS WOULD SHIFT THINGS AROUND TWICE - // NOW IT WORKS IF THE ADDRESS OF THE KEY AND THE FIRST ADDRESS OF THE ITEM ARE THE SAME - // if the position of the key is not in the first address of the item we need to move it separately - // note that swapkey holds the original currentkey value - //if ((lash_tree_key_t *)currentitem != swapkey) { - swapitem = currentitem; - *(tree->item + currentposition - 1) = nextitem; - *(tree->item + nextposition - 1) = swapitem; - //} - - currentposition = nextposition; - } else { - direction = 0; - } - } else { - direction = 0; - } - break; - default: - direction = 0; - } - } - - return currentposition; -} diff --git a/lash_tree3_dump.c b/lash_tree3_dump.c @@ -1,66 +0,0 @@ -#include "liblash/lash_tree3_dump.h" -#include "liblash/lash_tree3.h" -#include <stdio.h> -#include <stdlib.h> - -unsigned int lash_tree_dump_monitor_capacity; -unsigned int lash_tree_dump_monitor_count; - -void lash_treeDump(lash_tree_t *tree, char *comment) { - int i; - int j; - - lash_tree_t *currenttree; - - for (i = 0; i < lash_tree_dump_monitor_count; i++) { - currenttree = *(lash_tree_dump_monitor.tree + i); - if (tree != NULL) - if (tree != currenttree) - continue; - - printf("'%s' size %d", *(lash_tree_dump_monitor.name + i), currenttree->count); - if (comment != NULL) - printf(" (%s)", comment); - printf(":\n"); - - for (j = 0; j < currenttree->count; j++) { - printf("i:%2d v:%3li\n", j, (long int)**(currenttree->key + j)); - } - } -} - -int lash_treeDumpInit(unsigned int count) { - - lash_tree_dump_monitor.tree = (lash_tree_t**)malloc(sizeof(lash_tree_t*) * count); - if (lash_tree_dump_monitor.tree == NULL) - return 1; - - lash_tree_dump_monitor.name = (char**)malloc(sizeof(char) * 128 * count); - if (lash_tree_dump_monitor.name == NULL) - return 1; - - lash_tree_dump_monitor_capacity = count; - lash_tree_dump_monitor_count = 0; - - return 0; -} - -int lash_treeDumpAdd(lash_tree_t *tree, char *name) { - if (lash_tree_dump_monitor_count == lash_tree_dump_monitor_capacity) - return 1; - - *(lash_tree_dump_monitor.tree + lash_tree_dump_monitor_count) = tree; - *(lash_tree_dump_monitor.name + lash_tree_dump_monitor_count) = name; - - lash_tree_dump_monitor_count++; - - return 0; -} - -void lash_treeDumpFree() { - if (lash_tree_dump_monitor.tree != NULL) - free(lash_tree_dump_monitor.tree); - - if (lash_tree_dump_monitor.name != NULL) - free(lash_tree_dump_monitor.name); -} diff --git a/lash_tree3_dump.h b/lash_tree3_dump.h @@ -1,79 +0,0 @@ -#ifndef LASH_TREE_DUMP_H_ -#define LASH_TREE_DUMP_H_ - -#include "liblash/lash_tree3.h" - -struct lash_tree_dump_monitor { - lash_tree_t **tree; - char **name; -} lash_tree_dump_monitor; - -#ifdef __cplusplus -extern "C" { -#endif -void lash_treeDump(lash_tree_t *tree, char *comment); -int lash_treeDumpInit(unsigned int count); -int lash_treeDumpAdd(lash_tree_t *tree, char *name); -void lash_treeDumpFree(); - -#ifdef __cplusplus -} -#endif - -#endif // LASH_TREE_DUMP_H_ - -/** - * \file lash_tree3_dump.h - * \brief Dump contents of `lash_tree3` objects - * - * \author Louis Holbrook - * \version 0.2 - * - */ - -/** - * - * \struct lash_tree_dump_monitor - * \brief Container pointing to trees elegible for dumping - * \var **tree Pointers to trees - * \var **name Name of tree to display when dumping - * - */ - -/** - * \fn lash_treeDump(lash_tree_t *tree, char *comment) - * \brief Dumps content of tree in sort order to **STDOUT** - * - * \param *tree Tree to dump. - * \param *comment Optional text string to display in front of dump - * - * If `*tree` is specified, only this tree will be dumped. - * Note that trees have to be added to `lash_tree_dump_monitor` by `lash_treeDumpAdd` or they will be skipped. - * - * \todo Parametric output formatting - */ - -/** - * \fn lash_treeDumpInit(unsigned int count) - * \brief Memory allocation - * - * \param count number of trees to allocate - * \return 1 if allocation failed, 0 if no error. - */ - -/** - * \fn lash_treeDumpAdd(lash_tree_t *tree, char *name) - * \brief Add tree to the list of trees for dumping - * - * \param *tree Tree to add - * \param *name Name to display in front of output - * \return 1 if capacity is exceeded, 0 otherwise - * - */ - -/** - * \fn lash_treeDumpFree() - * \brief Free memory from `lash_tree_dump_monitor` - * - * \param *tree Tree to free - */ diff --git a/tests/debuglog.c b/tests/debuglog.c @@ -1,6 +1,7 @@ -#include "../lash_debug_log.h" #include <stdio.h> +#include "../debug_log.h" + int main() { lash_debug_log_t log; lash_debug_log_t log2; diff --git a/tests/debuglogmaster.c b/tests/debuglogmaster.c @@ -1,6 +1,6 @@ #define LASH_DEBUG_LOG_GLOBAL 1 -#include "../lash_debug_log.h" +#include "../debug_log.h" int main() { lash_debugLogInit(&lash_log_global, 1); diff --git a/tests/debugtimer.c b/tests/debugtimer.c @@ -1,8 +1,7 @@ -// debugtimer - -#include "../lash_debug_timer.h" #include <stdio.h> +#include "../debug_timer.h" + int main() { int i; lash_debug_timer_t time; diff --git a/tests/tree3_console.c b/tests/tree3_console.c @@ -1,8 +1,9 @@ -#include "../lash_tree3.h" -#include "../lash_tree3_dump.h" #include <stdlib.h> #include <stdio.h> +#include "../tree.h" +#include "../tree_dump.h" + typedef struct teststructure { lash_tree_key_t val; char *nothing; diff --git a/tests/tree3_shifttest.c b/tests/tree3_shifttest.c @@ -1,10 +1,11 @@ -#include "../lash_tree3.h" -#include "../lash_tree3_dump.h" #include <stdlib.h> #include <stdio.h> #include <limits.h> #include <time.h> +#include "../tree.h" +#include "../tree_dump.h" + #define TREE_CAPACITY 100 #define HEAP_RANGE 1000 diff --git a/tree.c b/tree.c @@ -0,0 +1,198 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "tree.h" + + +lash_tree_t *lash_treeInit(lash_tree_t *tree, const unsigned int size) { + tree = (lash_tree_t*)malloc(sizeof(lash_tree_t)); + tree->key = (lash_tree_key_t**)malloc(sizeof(lash_tree_key_t*) * size + 1); + tree->item = (void*)malloc(sizeof(void*) * size + 1); + + if (tree->key == NULL || tree->item == NULL) + return NULL; + + tree->count = 0; + //tree->shiftpos = 0; + tree->capacity = size; + //tree->foldbackthreshold = tree->capacity / 2; + + return tree; +} + +void lash_treeFree(lash_tree_t *tree) { + if (tree == NULL) + return; + + if (tree->key != NULL) + free(tree->key); + + if (tree->item != NULL) + free(tree->item); + + free(tree); +} + +// key is optional, if NULL is passed, then tree assumes a lash_tree_key_t at first address of item pointer +int lash_treePush(lash_tree_t *tree, void *item, lash_tree_key_t *key) { + //printf("%p", item); + + if (tree->count == tree->capacity) + return -1; + + tree->count++; + + if (key != NULL) + *(tree->key + tree->count - 1) = key; + else + *(tree->key + tree->count - 1) = (lash_tree_key_t*)item; + + *(tree->item + tree->count - 1) = item; + + _lash_treeProcess(tree, tree->count, -1); + + return tree->count; +} + +int lash_treeShift(lash_tree_t *tree, void **item) { + return lash_treeRemove(tree, 0, item); +} + +int lash_treeRemove(lash_tree_t *tree, unsigned int position, void **item) { + + if (tree->count == 0) + return -1; + + // retrieve the values from the position from the argument + *item = *(tree->item + position); + + // move the values from the end of the tree to the position from the argument + *(tree->key + position) = *(tree->key + tree->count - 1); + *(tree->item + position) = *(tree->item + tree->count - 1); + + // reduce the count of the tree + tree->count--; + + // iterate the new value down the tree to its proper place + _lash_treeProcess(tree, position + 1, 1); + + return tree->count; +} + +int _lash_treeProcess(lash_tree_t *tree, unsigned int currentposition, int direction) { + + // towards end of pointer is downwards in the tree + // the direction to sort, -1 is from end towards start, 1 is from startposition towards end + + while (direction != 0) { + + lash_tree_key_t *currentkey = *(tree->key + currentposition - 1); + lash_tree_key_t *nextkey = NULL; + lash_tree_key_t *swapkey; + //lash_tree_key_t swapkey; + void *swapitem;; + void *currentitem; + void *nextitem; + + unsigned int nextposition; + + switch(direction) { + + // if there is still room to ascend in the tree, that is if the current position isn't 0 already. + case -1: + if (currentposition == 1) { + direction = 0; + } else { + nextposition = currentposition >> 1; + nextkey = *(tree->key + nextposition - 1); + if (*currentkey < *nextkey) { + /*swapkey = *currentkey; + *currentkey = *nextkey; + *nextkey = swapkey;*/ + + currentitem = *(tree->item + currentposition - 1); + nextitem = *(tree->item + nextposition - 1); + + swapkey = currentkey; + *(tree->key + currentposition - 1) = nextkey; + *(tree->key + nextposition - 1) = swapkey; + + // ORIGINALLY IT SEEMED LIKE WHEN THE ADDRESS WAS THE SAME THAT THIS WOULD SHIFT THINGS AROUND TWICE + // NOW IT WORKS IF THE ADDRESS OF THE KEY AND THE FIRST ADDRESS OF THE ITEM ARE THE SAME + // if the position of the key is not in the first address of the item we need to move it separately + // note that swapkey now holds the original currentkey + //if ((lash_tree_key_t *)currentitem != swapkey) { + swapitem = currentitem; + *(tree->item + currentposition - 1) = nextitem; + *(tree->item + nextposition - 1) = swapitem; + //} + + currentposition = nextposition; + } else { + direction = 0; + } + } + break; + + // if there is still room from the current position to descend one level in the tree): + // level 0 has 2^0 = entry 1 + // level 1 has 2^1 = entries 2-3 + // level 2 has 2^2 = entries 4-7 + // if we're at position 3, the check will be 3*2 = 6, which is within bounds of level 2, and points to elements 6 and 7 (the children of 3) + // If we're at position 4, the check will be 4*2 = 8, which is out of bounds of level 2. + + case 1: + nextposition = currentposition << 1; + + if (nextposition <= tree->count) { + + // compare both the child values, to pick the higher one + nextkey = *(tree->key + nextposition - 1); + if (*nextkey > **(tree->key + nextposition)) { + nextkey = *(tree->key + nextposition); + nextposition++; + } + + // compare the values, set nextkey back to null to stop the swapping if the value is not higher + if (*currentkey <= *nextkey) { + nextkey = NULL; + } + + if (nextkey != NULL) { + /*swapkey = *currentkey; + *currentkey = *nextkey; + *nextkey = swapkey;*/ + + currentitem = *(tree->item + currentposition - 1); + nextitem = *(tree->item + nextposition - 1); + + swapkey = currentkey; + *(tree->key + currentposition - 1) = nextkey; + *(tree->key + nextposition - 1) = swapkey; + + // ORIGINALLY IT SEEMED LIKE WHEN THE ADDRESS WAS THE SAME THAT THIS WOULD SHIFT THINGS AROUND TWICE + // NOW IT WORKS IF THE ADDRESS OF THE KEY AND THE FIRST ADDRESS OF THE ITEM ARE THE SAME + // if the position of the key is not in the first address of the item we need to move it separately + // note that swapkey holds the original currentkey value + //if ((lash_tree_key_t *)currentitem != swapkey) { + swapitem = currentitem; + *(tree->item + currentposition - 1) = nextitem; + *(tree->item + nextposition - 1) = swapitem; + //} + + currentposition = nextposition; + } else { + direction = 0; + } + } else { + direction = 0; + } + break; + default: + direction = 0; + } + } + + return currentposition; +} diff --git a/tree.c_intindex b/tree.c_intindex @@ -0,0 +1,173 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "tree.h" + +lash_tree_t *lashTreeInit(lash_tree_t *tree, const unsigned int size) { + tree = (lash_tree_t*)malloc(sizeof(lash_tree_t)); + tree->key = (lash_tree_key_t*)malloc(sizeof(lash_tree_key_t*) * size + 1); + tree->item = (void*)malloc(sizeof(void*) * size + 1); + + if (tree->key == NULL || tree->item == NULL) + return NULL; + + tree->count = 0; + tree->shiftpos = 0; + tree->capacity = size; + tree->foldbackthreshold = tree->capacity / 2; + + return tree; +} + +void lashTreeFree(lash_tree_t *tree) { + if (tree == NULL) + return; + + if (tree->key != NULL) + free(tree->key); + + if (tree->item != NULL) + free(tree->item); + + free(tree); +} + +int lashTreePush(lash_tree_t *tree, lash_tree_key_t *key, void *item) { + //printf("%p", item); + + if (tree->count == tree->capacity) + return 0; + + tree->count++; + + *(tree->key + tree->shiftpos + tree->count - 1) = key; + *(tree->item + tree->shiftpos + tree->count - 1) = item; + + lashTreeProcess(tree, tree->count, -1); + + return tree->count; +} + +int lashTreeShift(lash_tree_t *tree, void **item) { + return lashTreeRemove(tree, 0, item); +} + +int lashTreeRemove(lash_tree_t *tree, unsigned int position, void **item) { + + if (tree->count == 0) + return 0; + + // retrieve the values from the position from the argument + *item = *(tree->item + tree->shiftpos + position); + + // move the values from the end of the tree to the position from the argument + *(tree->key + tree->shiftpos + position) = *(tree->key + tree->shiftpos + tree->count - 1); + *(tree->item + tree->shiftpos + position) = *(tree->item + tree->shiftpos + tree->count - 1); + + // reduce the count of the tree + tree->count--; + + // iterate the new value down the tree to its proper place + lashTreeProcess(tree, position + 1, 1); + + return tree->count; +} +int lashTreeProcess(lash_tree_t *tree, unsigned int currentposition, int direction) { + + // towards end of pointer is downwards in the tree + // the direction to sort, -1 is from end towards start, 1 is from startposition towards end + + while (direction != 0) { + + lash_tree_key_t *currentkey = *(tree->key + tree->shiftpos + currentposition - 1); + lash_tree_key_t *nextkey = NULL; + lash_tree_key_t *swapkey; + //lash_tree_key_t swapkey; + void *swapitem;; + void *currentitem; + void *nextitem; + + unsigned int nextposition; + + switch(direction) { + + // if there is still room to ascend in the tree, that is if the current position isn't 0 already. + case -1: + if (currentposition == 1) { + direction = 0; + } else { + nextposition = currentposition >> 1; + nextkey = *(tree->key + tree->shiftpos + nextposition - 1); + if (*currentkey < *nextkey) { + /*swapkey = *currentkey; + *currentkey = *nextkey; + *nextkey = swapkey;*/ + + currentitem = *(tree->item + tree->shiftpos + currentposition - 1); + nextitem = *(tree->item + tree->shiftpos + nextposition - 1); + + // if the position of the key is not in the first address of the item we need to move it separately + if ((lash_tree_key_t *)currentitem != currentkey) { + swapkey = currentkey; + *(tree->key + tree->shiftpos + currentposition - 1) = nextkey; + *(tree->key + tree->shiftpos + nextposition - 1) = swapkey; + } + + swapitem = currentitem; + *(tree->item + tree->shiftpos + currentposition - 1) = nextitem; + *(tree->item + tree->shiftpos + nextposition - 1) = swapitem; + + currentposition = nextposition; + } else { + direction = 0; + } + } + break; + + // if there is still room from the current position to descend one level in the tree): + // level 0 has 2^0 = entry 1 + // level 1 has 2^1 = entries 2-3 + // level 2 has 2^2 = entries 4-7 + // if we're at position 3, the check will be 3*2 = 6, which is within bounds of level 2, and points to elements 6 and 7 (the children of 3) + // If we're at position 4, the check will be 4*2 = 8, which is out of bounds of level 2. + + case 1: + nextposition = currentposition << 1; + + if (nextposition <= tree->count) { + + // compare both the child values, to pick the higher one + nextkey = *(tree->key + tree->shiftpos + nextposition - 1); + if (*nextkey > *(nextkey + 1)) { + nextkey = (nextkey + 1); + nextposition++; + } + + // compare the values, set nextkey back to null to stop the swapping if the value is not higher + if (*currentkey <= *nextkey) { + nextkey = NULL; + } + + if (nextkey != NULL) { + /*swapkey = *currentkey; + *currentkey = *nextkey; + *nextkey = swapkey;*/ + swapkey = currentkey; + currentkey = nextkey; + nextkey = swapkey; + currentposition = nextposition; + } else { + direction = 0; + } + } else { + direction = 0; + } + break; + default: + direction = 0; + } + } + + return currentposition; +} diff --git a/lash_tree3.h b/tree.h diff --git a/tree_dump.c b/tree_dump.c @@ -0,0 +1,67 @@ +#include <stdio.h> +#include <stdlib.h> + +#include "tree.h" +#include "tree_dump.h" + +unsigned int lash_tree_dump_monitor_capacity; +unsigned int lash_tree_dump_monitor_count; + +void lash_treeDump(lash_tree_t *tree, char *comment) { + int i; + int j; + + lash_tree_t *currenttree; + + for (i = 0; i < lash_tree_dump_monitor_count; i++) { + currenttree = *(lash_tree_dump_monitor.tree + i); + if (tree != NULL) + if (tree != currenttree) + continue; + + printf("'%s' size %d", *(lash_tree_dump_monitor.name + i), currenttree->count); + if (comment != NULL) + printf(" (%s)", comment); + printf(":\n"); + + for (j = 0; j < currenttree->count; j++) { + printf("i:%2d v:%3li\n", j, (long int)**(currenttree->key + j)); + } + } +} + +int lash_treeDumpInit(unsigned int count) { + + lash_tree_dump_monitor.tree = (lash_tree_t**)malloc(sizeof(lash_tree_t*) * count); + if (lash_tree_dump_monitor.tree == NULL) + return 1; + + lash_tree_dump_monitor.name = (char**)malloc(sizeof(char) * 128 * count); + if (lash_tree_dump_monitor.name == NULL) + return 1; + + lash_tree_dump_monitor_capacity = count; + lash_tree_dump_monitor_count = 0; + + return 0; +} + +int lash_treeDumpAdd(lash_tree_t *tree, char *name) { + if (lash_tree_dump_monitor_count == lash_tree_dump_monitor_capacity) + return 1; + + *(lash_tree_dump_monitor.tree + lash_tree_dump_monitor_count) = tree; + *(lash_tree_dump_monitor.name + lash_tree_dump_monitor_count) = name; + + lash_tree_dump_monitor_count++; + + return 0; +} + +void lash_treeDumpFree() { + if (lash_tree_dump_monitor.tree != NULL) + free(lash_tree_dump_monitor.tree); + + if (lash_tree_dump_monitor.name != NULL) + free(lash_tree_dump_monitor.name); +} diff --git a/tree_dump.h b/tree_dump.h @@ -0,0 +1,79 @@ +#ifndef LASH_TREE_DUMP_H_ +#define LASH_TREE_DUMP_H_ + +#include "tree.h" + +struct lash_tree_dump_monitor { + lash_tree_t **tree; + char **name; +} lash_tree_dump_monitor; + +#ifdef __cplusplus +extern "C" { +#endif +void lash_treeDump(lash_tree_t *tree, char *comment); +int lash_treeDumpInit(unsigned int count); +int lash_treeDumpAdd(lash_tree_t *tree, char *name); +void lash_treeDumpFree(); + +#ifdef __cplusplus +} +#endif + +#endif // LASH_TREE_DUMP_H_ + +/** + * \file lash_tree3_dump.h + * \brief Dump contents of `lash_tree3` objects + * + * \author Louis Holbrook + * \version 0.2 + * + */ + +/** + * + * \struct lash_tree_dump_monitor + * \brief Container pointing to trees elegible for dumping + * \var **tree Pointers to trees + * \var **name Name of tree to display when dumping + * + */ + +/** + * \fn lash_treeDump(lash_tree_t *tree, char *comment) + * \brief Dumps content of tree in sort order to **STDOUT** + * + * \param *tree Tree to dump. + * \param *comment Optional text string to display in front of dump + * + * If `*tree` is specified, only this tree will be dumped. + * Note that trees have to be added to `lash_tree_dump_monitor` by `lash_treeDumpAdd` or they will be skipped. + * + * \todo Parametric output formatting + */ + +/** + * \fn lash_treeDumpInit(unsigned int count) + * \brief Memory allocation + * + * \param count number of trees to allocate + * \return 1 if allocation failed, 0 if no error. + */ + +/** + * \fn lash_treeDumpAdd(lash_tree_t *tree, char *name) + * \brief Add tree to the list of trees for dumping + * + * \param *tree Tree to add + * \param *name Name to display in front of output + * \return 1 if capacity is exceeded, 0 otherwise + * + */ + +/** + * \fn lash_treeDumpFree() + * \brief Free memory from `lash_tree_dump_monitor` + * + * \param *tree Tree to free + */