#include #include "util.h" #include "id.h" #define NODE2ID(n) ((struct id *) n) static struct id *free_id = NULL; int comp_id(const struct id *a, const struct id *b) { int len = a->len < b->len ? a->len : b->len; int cmp; cmp = memcmp(a->s, b->s, len); if (cmp) return cmp; return a->len < b->len ? -1 : a->len > b->len; } struct tree *make_tree(int (*comp)(const struct id *a, const struct id *b)) { struct tree *tree; tree = alloc_type(struct tree); tree->comp = comp; tree->root = NULL; return tree; } static struct node *add_node(struct tree *tree, struct node *node) { struct node **p, *last; int cmp; p = &tree->root; last = NULL; while (*p) { last = *p; cmp = tree->comp(NODE2ID(node), NODE2ID(*p)); if (cmp < 0) p = &(*p)->left; else if (cmp > 0) p = &(*p)->right; else return *p; } *p = node; node->up = last; node->left = node->right = NULL; return NULL; } struct id *make_id(struct tree *tree, const char *s, size_t len) { struct id *id; struct node *node; if (!free_id) free_id = alloc_type(struct id); id = free_id; id->s = s; id->len = len; id->value = NULL; node = add_node(tree, &id->node); if (node) return NODE2ID(node); free_id = NULL; return id; } const struct id *find_id(const struct tree *tree, const char *s, size_t len) { struct id id = { .s = s, .len = len }; const struct node *n = tree->root; int cmp; while (n) { cmp = tree->comp(&id, NODE2ID(n)); if (cmp < 0) n = n->left; else if (cmp > 0) n = n->right; else return NODE2ID(n); } return NULL; } const struct id *first_id(const struct tree *tree) { const struct node *n = tree->root; if (!n) return NULL; while (n->left) n = n->left; return NODE2ID(n); } const struct id *next_id(const struct id *id) { const struct node *n = &id->node; if (n->right) { n = n->right; while (n->left) n = n->left; return NODE2ID(n); } while (n->up) { if (n == n->up->left) return NODE2ID(n->up); n = n->up; } return NULL; }