Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/woip/c/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'woip/c/search.c')
-rw-r--r--woip/c/search.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/woip/c/search.c b/woip/c/search.c
new file mode 100644
index 0000000..e440d5a
--- /dev/null
+++ b/woip/c/search.c
@@ -0,0 +1,174 @@
+#include "search.h"
+
+#define NODES(n) ((n) * sizeof(struct node))
+
+static uint32_t storepos = 0;
+static char needle[MAXLINE];
+static char so_far[MAXLINE];
+static struct node *root;
+static bool done;
+static bool csen = true;
+static char cmd[MAXLINE];
+
+struct node *load_index(char *file) {
+ void *ptr;
+ struct index_hdr h;
+ FILE *fp = xfopen(file, "r");
+
+ fread(&h, sizeof(struct index_hdr), 1, fp);
+ storepos = h.nodes;
+ strncpy(cmd, h.cmd, MAXLINE);
+
+ if(h.node_size != sizeof(struct node))
+ fatal("Couldn't read index: conflicting node sizes. %s expects %d, " \
+ "I've been compiled to expect %d. Did you use -fpack-struct?", \
+ file, h.node_size, sizeof(struct node));
+
+ ptr = xmmap(NULL, NODES(storepos), PROT_READ, MAP_PRIVATE, fileno(fp), 0);
+
+ return ptr + sizeof(struct index_hdr);
+}
+
+void print_cmd() {
+ printf("%s\n", cmd);
+}
+
+void load_root(char *file) {
+ root = load_index(file);
+}
+
+char *matchstr(int depth, struct node *n, char *match) {
+ debug("matchstr(%d, 0x%x)", depth, n);
+
+ int i, j = 0;
+ bool compressed;
+
+ compressed = n->block & CMASK;
+
+ for(i = 0; i < depth; i++)
+ if(so_far[i])
+ match[j++] = so_far[i];
+
+ match[j] = '\0';
+ debug("so_far: %s", match);
+
+ if(compressed) {
+ char *s = ((struct cnode *) n)->str;
+ debug("compressed str: %s", s);
+ strncpy(match + j, s, strlen(s));
+ j += strlen(s);
+ } else {
+ match[j++] = n->c;
+ }
+
+ match[j] = '\0';
+
+ debug(" -> %s", match);
+
+ return match;
+}
+
+bool handle_matches(int startdepth, int depth, struct node *n, resultf r) {
+ debug("handle_matches(%d, %d, 0x%x %d %c)", startdepth, depth, n, n - root, n->c);
+
+ bool compressed = n->block & CMASK;
+ char match[MAXLINE];
+
+ if(BLOCK_DEMASK(n->block)) {
+ if(!r(matchstr(depth, n, match), BLOCK_DEMASK(n->block))) {
+ done = true;
+ return false;
+ }
+ }
+
+ if(compressed) return true;
+
+ if(depth == startdepth && n->eq)
+ handle_matches(startdepth, depth + 1, root + n->eq, r);
+ else {
+ if(n->lt)
+ if(!handle_matches(startdepth, depth, root + n->lt, r))
+ return false;
+ if(n->eq) {
+ debug("following eq...");
+ so_far[depth] = n->c;
+ if(!handle_matches(startdepth, depth + 1, root + n->eq, r))
+ return false;
+ }
+ if(n->gt)
+ if(!handle_matches(startdepth, depth, root + n->gt, r))
+ return false;
+ }
+
+ return true;
+}
+
+void csen_set(bool b) {
+ csen = b;
+}
+
+void csearch(char *prefix, struct cnode *n, resultf r, int depth) {
+ debug("csearch(%s, (0x%x, %s), %d)", prefix, n, n->str, depth);
+ if(!strncmp(prefix, n->str, strlen(prefix)))
+ handle_matches(depth, depth, (struct node *) n, r);
+}
+
+void search(char *prefix, struct node *n, resultf r, int depth) {
+ debug("0x%x search(%s, (%d, %c), %d)", n, prefix, n - root, n->c, depth);
+
+ if(n->block & CMASK) {
+ csearch(prefix, (struct cnode *) n, r, depth);
+ return;
+ }
+
+ if(((!csen && tolower(n->c) == tolower(prefix[0])) || \
+ (csen && n->c == prefix[0])) && !done) {
+ so_far[depth] = n->c;
+ debug("0x%x match", n);
+ if(prefix[1]) {
+ if(n->eq)
+ search(prefix + 1, root + n->eq, r, depth + 1);
+ } else
+ handle_matches(depth, depth, n, r);
+
+ }
+
+ if(!done) {
+ if((n->c > prefix[0] || (isascii(prefix[0]) && !csen && n->c > (prefix[0]^0x20))) \
+ && n->lt)
+ search(prefix, root + n->lt, r, depth);
+
+ if((n->c < prefix[0] || (isascii(prefix[0]) && !csen && n->c < (prefix[0]^0x20))) \
+ && n->gt)
+ search(prefix, root + n->gt, r, depth);
+ }
+}
+
+void root_search(char *prefix, resultf r) {
+ done = false;
+ strcpy(needle, prefix);
+ search(prefix, root, r, 0);
+}
+
+void print_tree() {
+ int i;
+ for(i = 0; i < storepos; i++) {
+ struct node *n = root + i;
+
+ debug("--");
+ debug("%d", i);
+
+ if(n->block == -1) {
+ debug("obsolete");
+ continue;
+ }
+
+ debug("block: %d", BLOCK_DEMASK(n->block));
+ if(n->block & CMASK)
+ debug("COMPRESSED: %s", ((struct cnode *) n)->str);
+ else {
+ debug("c: %c", n->c);
+ debug("lt: %d | eq: %d | gt: %d", n->lt, n->eq, n->gt);
+ }
+ }
+}