#include #include #include #define PAGE_SIZE 4096 static btrie_node_t * btrie_alloc(btrie_t *tree) { btrie_node_t *p; if (tree->free) { p = tree->free; tree->free = tree->free->right; return p; } if (tree->size < sizeof(btrie_node_t)) { tree->start = (char *) calloc(sizeof(char), PAGE_SIZE); if (tree->start == NULL) { return NULL; } tree->pools[tree->len++] = tree->start; tree->size = PAGE_SIZE; } p = (btrie_node_t *) tree->start; tree->start += sizeof(btrie_node_t); tree->size -= sizeof(btrie_node_t); return p; } btrie_t * btrie_create() { btrie_t *tree = (btrie_t *) malloc(sizeof(btrie_t)); if (tree == NULL) { return NULL; } tree->free = NULL; tree->start = NULL; tree->size = 0; memset(tree->pools, 0, sizeof(btrie_t *) * BTRIE_MAX_PAGES); tree->len = 0; tree->root = btrie_alloc(tree); if (tree->root == NULL) { return NULL; } tree->root->right = NULL; tree->root->left = NULL; tree->root->parent = NULL; tree->root->value = BTRIE_NULL; return tree; } static size_t subtree_weight(btrie_node_t *node) { size_t weight = 1; if (node->left) { weight += subtree_weight(node->left); } if (node->right) { weight += subtree_weight(node->right); } return weight; } size_t btrie_count(btrie_t *tree) { if (tree->root == NULL) { return 0; } return subtree_weight(tree->root); } size_t btrie_allocated(btrie_t *tree) { return tree->len * PAGE_SIZE; } int btrie_insert(btrie_t *tree, uint32_t key, uint32_t mask, uintptr_t value) { uint32_t bit; btrie_node_t *node, *next; bit = 0x80000000; node = tree->root; next = tree->root; while (bit & mask) { if (key & bit) { next = node->right; } else { next = node->left; } if (next == NULL) { break; } bit >>= 1; node = next; } if (next) { if (node->value != BTRIE_NULL) { return -1; } node->value = value; return 0; } while (bit & mask) { next = btrie_alloc(tree); if (next == NULL) { return -1; } next->right = NULL; next->left = NULL; next->parent = node; next->value = BTRIE_NULL; if (key & bit) { node->right = next; } else { node->left = next; } bit >>= 1; node = next; } node->value = value; return 0; } int btrie_delete(btrie_t *tree, uint32_t key, uint32_t mask) { uint32_t bit; btrie_node_t *node; bit = 0x80000000; node = tree->root; while (node && (bit & mask)) { if (key & bit) { node = node->right; } else { node = node->left; } bit >>= 1; } if (node == NULL) { return -1; } if (node->right || node->left) { if (node->value != BTRIE_NULL) { node->value = BTRIE_NULL; return 0; } return -1; } for ( ;; ) { if (node->parent->right == node) { node->parent->right = NULL; } else { node->parent->left = NULL; } node->right = tree->free; tree->free = node; node = node->parent; if (node->right || node->left) { break; } if (node->value != BTRIE_NULL) { break; } if (node->parent == NULL) { break; } } return 0; } uintptr_t btrie_find(btrie_t *tree, uint32_t key) { uint32_t bit; uintptr_t value; btrie_node_t *node; bit = 0x80000000; value = BTRIE_NULL; node = tree->root; while (node) { if (node->value != BTRIE_NULL) { value = node->value; } if (key & bit) { node = node->right; } else { node = node->left; } bit >>= 1; } return value; } int btrie_insert_a6(btrie_t *tree, const uint8_t *key, const uint8_t *mask, uintptr_t value) { uint8_t bit; unsigned int i; btrie_node_t *node, *next; i = 0; bit = 0x80; node = tree->root; next = tree->root; while (bit & mask[i]) { if (key[i] & bit) { next = node->right; } else { next = node->left; } if (next == NULL) { break; } bit >>= 1; node = next; if (bit == 0) { if (++i == 16) { break; } bit = 0x80; } } if (next) { if (node->value != BTRIE_NULL) { return -1; } node->value = value; return 0; } while (bit & mask[i]) { next = btrie_alloc(tree); if (next == NULL) { return -1; } next->right = NULL; next->left = NULL; next->parent = node; next->value = BTRIE_NULL; if (key[i] & bit) { node->right = next; } else { node->left = next; } bit >>= 1; node = next; if (bit == 0) { if (++i == 16) { break; } bit = 0x80; } } node->value = value; return 0; } int btrie_delete_a6(btrie_t *tree, const uint8_t *key, const uint8_t *mask) { uint8_t bit; unsigned int i; btrie_node_t *node; i = 0; bit = 0x80; node = tree->root; while (node && (bit & mask[i])) { if (key[i] & bit) { node = node->right; } else { node = node->left; } bit >>= 1; if (bit == 0) { if (++i == 16) { break; } bit = 0x80; } } if (node == NULL) { return -1; } if (node->right || node->left) { if (node->value != BTRIE_NULL) { node->value = BTRIE_NULL; return 0; } return -1; } for ( ;; ) { if (node->parent->right == node) { node->parent->right = NULL; } else { node->parent->left = NULL; } node->right = tree->free; tree->free = node; node = node->parent; if (node->right || node->left) { break; } if (node->value != BTRIE_NULL) { break; } if (node->parent == NULL) { break; } } return 0; } uintptr_t btrie_find_a6(btrie_t *tree, const uint8_t *key) { uint8_t bit; uintptr_t value; unsigned int i; btrie_node_t *node; i = 0; bit = 0x80; value = BTRIE_NULL; node = tree->root; while (node) { if (node->value != BTRIE_NULL) { value = node->value; } if (key[i] & bit) { node = node->right; } else { node = node->left; } bit >>= 1; if (bit == 0) { i++; bit = 0x80; } } return value; } int btrie_destroy(btrie_t *tree) { size_t i; /* free memory pools */ for (i = 0; i < tree->len; i++) { free(tree->pools[i]); } free(tree); return 0; }