BCI-base/interpreter/method_dispatcher/method_dispatcher.c

159 lines
2.9 KiB
C
Raw Normal View History

2018-09-26 11:18:37 +00:00
#include <stdlib.h>
#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;
}
dispatch_tree_autoinserter_t dispatch_tree_autoinserter_t_new(dispatch_tree_t tree)
{
dispatch_tree_autoinserter_t autoinserter = malloc(
sizeof(struct dispatch_tree_autoinserter_s));
if(!autoinserter)
{
return NULL;
}
autoinserter->mayor = 2;
autoinserter->minor = 1;
autoinserter->tree = tree;
return autoinserter;
}
void dispatch_tree_autoinserter_t_del(dispatch_tree_autoinserter_t autoinserter)
{
free(autoinserter);
}
uint16_t dispatch_tree_autoinserter_t_insert(
dispatch_tree_autoinserter_t autoinserter
, bci_core_method_t method)
{
uint16_t opcode = 0b1111111111;
opcode *= autoinserter->minor;
opcode /= autoinserter->mayor;
opcode <<= 6;
dispatch_tree_t_insert(autoinserter->tree, opcode, method);
autoinserter->minor = (autoinserter->minor + 2) % autoinserter->mayor;
if(autoinserter->minor == 1)
{
autoinserter->mayor *= 2;
}
return opcode;
}