commit 71c633f4798c7554f3889071b85800522595029a Author: Daniel Knüttel Date: Wed Sep 26 13:18:37 2018 +0200 added method dispatcher diff --git a/method_dispatcher.c b/method_dispatcher.c new file mode 100644 index 0000000..90e4fed --- /dev/null +++ b/method_dispatcher.c @@ -0,0 +1,120 @@ +#include +#include "method_dispatcher.h" + + +dispatch_tree_t dispatch_tree_t_new(void) +{ + dispatch_tree_t tree = malloc(sizeof(struct dispatch_tree_s)); + tree->root = NULL; + return tree; +} + +void dispatch_tree_t_del(dispatch_tree_t tree) +{ + dispatch_tree_node_t_del(tree->root); + free(tree); +} + +dispatch_tree_node_t dispatch_tree_node_t_new(uint16_t word + , bci_core_method_t method) +{ + dispatch_tree_node_t node = malloc(sizeof(struct dispatch_tree_node_s)); + node->higher = NULL; + node->lower = 0; + node->method = method; + node->word = word; + return node; +} + +void dispatch_tree_node_t_del(dispatch_tree_node_t node) +{ + if(node->higher) + { + dispatch_tree_node_t_del(node->higher); + } + if(node->lower) + { + dispatch_tree_node_t_del(node->lower); + } + free(node); +} + +char dispatch_tree_t_insert(dispatch_tree_t tree + , uint16_t word + , bci_core_method_t method) +{ + dispatch_tree_node_t new_node = dispatch_tree_node_t_new(word, method); + if(!new_node) + { + return 1; + } + // explicitly handle empty tree + if(!tree->root) + { + tree->root = new_node; + return 0; + } + + // non-empty tree + dispatch_tree_node_t this_node = tree->root; + dispatch_tree_node_t parent_node = NULL; + // search for place + do + { + parent_node = this_node; + if(parent_node->word < word) + { + this_node = parent_node->higher; + continue; + } + if(parent_node->word > word) + { + this_node = parent_node->lower; + continue; + } + if(parent_node->word == word) + { + // we already have that key. + return 2; + } + + } + while(this_node); + if(parent_node->word < word) + { + parent_node->higher = new_node; + } + if(parent_node->word > word) + { + parent_node->lower = new_node; + } + + return 0; + +} + + +bci_core_method_t dispatch_tree_t_dispatch(dispatch_tree_t tree + , uint16_t word) +{ + dispatch_tree_node_t this_node = tree->root; + while(this_node) + { + if(this_node->word < word) + { + this_node = this_node->higher; + continue; + } + if(this_node->word > word) + { + this_node = this_node->lower; + continue; + } + if(this_node->word == word) + { + return this_node->method; + } + } + return NULL; +} + diff --git a/method_dispatcher.h b/method_dispatcher.h new file mode 100644 index 0000000..96a04f6 --- /dev/null +++ b/method_dispatcher.h @@ -0,0 +1,61 @@ +#ifndef bci_method_dispatcher_h__ +#define bci_method_dispatcher_h__ + +#include +#include "base.h" + +typedef struct dispatch_tree_node_s +{ + struct dispatch_tree_node_s * higher; + struct dispatch_tree_node_s * lower; + uint16_t word; + bci_core_method_t method; +} * dispatch_tree_node_t; + +typedef struct dispatch_tree_s +{ + dispatch_tree_node_t root; +} * dispatch_tree_t; + +dispatch_tree_t dispatch_tree_t_new(void); +/* + * This deletes the tree and will invoke dispatch_tree_node_t_del on + * tree->root (which will delete all the other nodes recursively). + * If you want to keep nodes you have to explicityl remove the reference to + * them by setting them to NULL. + * */ +void dispatch_tree_t_del(dispatch_tree_t tree); + + +dispatch_tree_node_t dispatch_tree_node_t_new(uint16_t word + , bci_core_method_t method); +/* + * This deletes the node an will invoke dispatch_tree_node_t_del on + * node->higher and node->lower. If you want to keep those nodes + * you have to explicitly clear the reference by setting them to NULL. + * */ +void dispatch_tree_node_t_del(dispatch_tree_node_t node); + + +/* + * Insert a new key-value-pair into the tree. + * + * Return codes: + * 0: OK + * 1: out of memory + * 2: key already in tree + * */ +char dispatch_tree_t_insert(dispatch_tree_t tree + , uint16_t word + , bci_core_method_t method); + +// TODO: +// Figure out if that function is actually useful. +// Maybe manually inserting the methods in a good order +// is better. +// +//dispatch_tree_t optimize(dispatch_tree_t tree); + +bci_core_method_t dispatch_tree_t_dispatch(dispatch_tree_t tree + , uint16_t word); +#endif diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..7997126 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,14 @@ +CC=gcc + +all: test_method_dispatcher + +method_dispatcher: clean + $(CC) ../method_dispatcher.c test_method_dispatcher.c -o method_dispatcher + +test_method_dispatcher: method_dispatcher + valgrind ./method_dispatcher + + + +clean: + -rm method_dispatcher diff --git a/test/method_dispatcher b/test/method_dispatcher new file mode 100755 index 0000000..722927d Binary files /dev/null and b/test/method_dispatcher differ diff --git a/test/test_method_dispatcher.c b/test/test_method_dispatcher.c new file mode 100644 index 0000000..563d888 --- /dev/null +++ b/test/test_method_dispatcher.c @@ -0,0 +1,51 @@ +#include +#include "../method_dispatcher.h" + +char m1(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m2(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m3(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m4(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); +char m5(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_reg, uint16_t * reg[10], bci_stack_t * stack); + +int main(void) +{ + printf("sizeof struct dispatch_tree_node_s: %zd\n", sizeof(struct dispatch_tree_node_s)); + dispatch_tree_t tree = dispatch_tree_t_new(); + + dispatch_tree_t_insert(tree, 3 << 6, m3); + dispatch_tree_t_insert(tree, 2 << 6, m2); + dispatch_tree_t_insert(tree, 1 << 6, m1); + dispatch_tree_t_insert(tree, 4 << 6, m4); + dispatch_tree_t_insert(tree, 5 << 6, m5); + + int i; + for(i = 1; i < 6; i++) + { + dispatch_tree_t_dispatch(tree, i << 6)(i, i << 6, NULL, NULL, NULL, NULL); + } + dispatch_tree_t_del(tree); + return 0; +} + + + +char m1(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m1: %d, %d\n", small_arg, arg); +} +char m2(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m2: %d, %d\n", small_arg, arg); +} +char m3(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m3: %d, %d\n", small_arg, arg); +} +char m4(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m4: %d, %d\n", small_arg, arg); +} +char m5(uint8_t small_arg, uint16_t arg, uint16_t * s_reg, uint16_t * shutdown_register, uint16_t * reg[10], bci_stack_t * stack) +{ + printf("m5: %d, %d\n", small_arg, arg); +}