static inline void cb_print_key(struct string_builder *, const cb_key); |
static inline size_t _low_cb_check_node(cb_node_t node, const char *, int); |
|
#ifdef DEBUG_CHECKS |
# define cb_check_node(node) do { _low_cb_check_node(node, \ |
__FILE__, __LINE__); } while (0) |
#else |
# define cb_check_node(node) do {} while(0) |
#endif |
|
#define CB_FATAL(x) Pike_error x |
|
#include "tree_low.c" |
|
static inline void cb_debug_print_key(struct string_builder * buf, cb_key key) { |
cb_size i; |
|
for (i.chars = 0; i.chars < key.len.chars; i.chars++) { |
#ifdef CB_PRINT_CHAR |
CB_PRINT_CHAR(buf, key.str, i.chars); |
#else |
string_builder_sprintf(buf, "(%d, %d) b: ", i.chars, CB_WIDTH(s)); |
|
for (i.bits = 0; i.bits < CB_WIDTH(s); i.bits++) { |
string_builder_sprintf(buf, "%d", CB_GET_BIT(key.str, i)); |
} |
string_builder_putchar(buf, ' '); |
#endif |
} |
|
|
|
if (key.len.bits) { |
i.chars = key.len.chars; |
i.bits = 0; |
|
string_builder_sprintf(buf, "(%d, %d) b: ", key.len.chars, key.len.bits); |
|
for (; CB_LT(i, key.len); CB_INC(i, 0, 1)) { |
string_builder_sprintf(buf, "%d", CB_GET_BIT(key.str, i)); |
} |
string_builder_sprintf(buf, " %d", CB_GET_BIT(key.str, key.len)); |
} |
} |
|
static inline void cb_print_key(struct string_builder * buf, cb_key key) { |
cb_size i; |
|
for (i.chars = 0; i.chars < key.len.chars; i.chars++) { |
for (i.bits = 0; i.bits < CB_WIDTH(s); i.bits++) { |
string_builder_putchar(buf, CB_GET_BIT(key.str, i) ? '1' : '0'); |
} |
} |
|
|
|
if (key.len.bits) { |
i.chars = key.len.chars; |
i.bits = 0; |
|
for (; CB_LT(i, key.len); CB_INC(i, 0, 1)) { |
string_builder_putchar(buf, CB_GET_BIT(key.str, i) ? '1' : '0'); |
} |
} |
} |
|
static inline void cb_print_node(struct string_builder * buf, |
cb_node_t node, int depth) { |
string_builder_putchars(buf, ' ', depth); |
string_builder_sprintf(buf, "%x #%lu (%d) --> ", node, |
node->size, node->value.type); |
string_builder_putchars(buf, ' ', MAXIMUM(0, 15-depth)); |
cb_debug_print_key(buf, node->key); |
if (CB_HAS_VALUE(node)) CB_PRINT_KEY(buf, node->key); |
string_builder_putchar(buf, '\n'); |
} |
|
static inline void cb_print_tree(struct string_builder *buf, |
cb_node_t tree, int depth) { |
cb_print_node(buf, tree, depth); |
#if 0 |
char *spaces = (char*)malloc(depth+1); |
char fmt[4096] = "%s %"; |
cb_size i; |
int binary = 0; |
memset(spaces, ' ', depth); |
spaces[depth] = 0; |
if (tree->key.len.bits) { |
sprintf(fmt, "%%s-> %%.%ds %%0%dd \n", |
tree->key.len.chars, tree->key.len.bits); |
i.chars = tree->key.len.chars; |
i.bits = 0; |
|
for (; CB_LT(i, tree->key.len); CB_INC(i, 0, 1)) { |
binary *= 10; |
binary += CB_GET_BIT(tree->key.str, i); |
} |
printf(fmt, spaces, tree->key->str, binary); |
} else { |
sprintf(fmt, "%%s-> %%.%ds \n", tree->key.len.chars); |
printf(fmt, spaces, tree->key->str); |
} |
free(spaces); |
#endif |
if (CB_HAS_CHILD(tree, 0)) { |
string_builder_putchar(buf, 'l'); |
cb_print_tree(buf, CB_CHILD(tree, 0), depth + 1); |
} |
if (CB_HAS_CHILD(tree, 1)) { |
string_builder_putchar(buf, 'r'); |
cb_print_tree(buf, CB_CHILD(tree, 1), depth + 1); |
} |
} |
|
static inline int cb_print_path(struct string_builder *buf, cb_node_t node, |
cb_key key, cb_size size, int depth, |
cb_node_t end) { |
cb_print_node(buf, node, depth); |
|
if (node == end) return 0; |
|
size = cb_prefix_count(node->key.str, key.str, |
CB_MIN(node->key.len, key.len), size); |
|
if (CB_S_EQ(size, key.len)) { |
if (CB_S_EQ(size, node->key.len)) { |
return 1; |
} else return 0; |
} |
|
if (CB_S_EQ(size, node->key.len)) { |
size_t bit = CB_GET_BIT(key.str, size); |
if (CB_HAS_CHILD(node, bit)) |
return cb_print_path(buf, CB_CHILD(node, bit), key, size, depth+1, |
end); |
} |
|
return 0; |
} |
|
static inline void cb_check(cb_node_t node, cb_node_t last, char *issue) { |
#ifdef DEBUG_CHECKS |
if (CB_LT(node->key.len, last->key.len)) { |
printf("ERROR AT %s\n", issue); |
cb_print_tree(last, 0); |
printf("[%d, %d] is shorter than [%d, %d]\n", node->key.len.chars, |
node->key.len.bits, last->key.len.chars, last->key.len.bits); |
return; |
} |
#endif /* DEBUG_CHECKS */ |
|
if (CB_HAS_CHILD(node, 0)) cb_check(CB_CHILD(node, 0), node, issue); |
if (CB_HAS_CHILD(node, 1)) cb_check(CB_CHILD(node, 1), node, issue); |
} |
|
static inline int cb_rec_check_parents(cb_node_t node) { |
if (node == NULL) return 0; |
if (CB_HAS_CHILD(node, 0)) { |
if (CB_CHILD(node, 0)->parent != node) { |
printf("Damaged 0.\n"); |
return 1; |
} |
if (cb_rec_check_parents(CB_CHILD(node, 0))) return 1; |
} |
if (CB_HAS_CHILD(node, 1)) { |
if (CB_CHILD(node, 1)->parent != node) { |
printf("Damaged 1.\n"); |
return 1; |
} |
if (cb_rec_check_parents(CB_CHILD(node, 1))) return 1; |
} |
return 0; |
} |
|
static inline void cb_aggregate_values(cb_node_t node, |
struct array * a, size_t start, |
size_t len) { |
if (CB_HAS_VALUE(node)) |
CB_GET_VALUE(node, ITEM(a)+start++); |
WALK_FORWARD(node, { |
if (CB_HAS_VALUE(_)) CB_GET_VALUE(_, ITEM(a)+start++); |
}); |
} |
|
static inline size_t _low_cb_check_node(cb_node_t node, |
const char *file, int line) { |
size_t len = 0; |
if (CB_HAS_CHILD(node, 0)) { |
if (CB_GET_BIT(CB_CHILD(node, 0)->key.str, node->key.len) != 0) { |
Pike_error("%s:%d EVIL DOER FOUND.\n", file, line); |
} |
if (CB_LE(CB_CHILD(node, 0)->key.len, node->key.len)) { |
Pike_error("%s:%d Child is shorter than parent.\n", file, line); |
} |
len += _low_cb_check_node(CB_CHILD(node, 0), file, line); |
} |
if (CB_HAS_CHILD(node, 1)) { |
if (CB_GET_BIT(CB_CHILD(node, 1)->key.str, node->key.len) != 1) { |
Pike_error("%s:%d It was the gardener! \n", file, line); |
} |
if (CB_LE(CB_CHILD(node, 1)->key.len, node->key.len)) { |
Pike_error("%s:%d Child is shorter than parent.\n", file, line); |
} |
len += _low_cb_check_node(CB_CHILD(node, 1), file, line); |
} |
|
if (len + CB_HAS_VALUE(node) != node->size) { |
|
Pike_error("%s:%d Found node with wrong size. is: 0x%08X\n", |
file, line, node); |
} |
|
return node->size; |
} |
|
|
|