=================================================================== RCS file: /cvs/mandoc/Attic/apropos.c,v retrieving revision 1.2 retrieving revision 1.5 diff -u -p -r1.2 -r1.5 --- mandoc/Attic/apropos.c 2011/10/07 13:22:33 1.2 +++ mandoc/Attic/apropos.c 2011/10/09 10:35:12 1.5 @@ -1,4 +1,4 @@ -/* $Id: apropos.c,v 1.2 2011/10/07 13:22:33 kristaps Exp $ */ +/* $Id: apropos.c,v 1.5 2011/10/09 10:35:12 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -103,6 +103,14 @@ struct res { char *title; /* manual section */ char *uri; /* formatted uri of file */ recno_t rec; /* unique id of underlying manual */ + /* + * Maintain a binary tree for checking the uniqueness of `rec' + * when adding elements to the results array. + * Since the results array is dynamic, use offset in the array + * instead of a pointer to the structure. + */ + int lhs; + int rhs; }; struct state { @@ -282,19 +290,21 @@ out: static void state_search(struct state *p, const struct opts *opts, char *q) { - int i, len, ch, rflags, dflag; + int leaf, root, len, ch, rflags, dflag; struct mchars *mc; char *buf; size_t bufsz; recno_t rec; uint32_t fl; DBT key, val; - struct res res[MAXRESULTS]; + struct res *res; regex_t reg; regex_t *regp; char filebuf[10]; struct rec record; + root = leaf = -1; + res = NULL; len = 0; buf = NULL; bufsz = 0; @@ -341,10 +351,7 @@ state_search(struct state *p, const struct opts *opts, * Lastly, add it to the available records. */ - while (len < MAXRESULTS) { - if ((ch = (*p->db->seq)(p->db, &key, &val, dflag))) - break; - + while (0 == (ch = (*p->db->seq)(p->db, &key, &val, dflag))) { dflag = R_NEXT; /* @@ -402,15 +409,25 @@ state_search(struct state *p, const struct opts *opts, if (opts->arch && strcasecmp(opts->arch, record.arch)) continue; - /* FIXME: this needs to be changed. Ugh. Linear. */ + /* + * Do a binary search to dedupe the results tree of the + * same record: we don't print the same file. + */ - for (i = 0; i < len; i++) - if (res[i].rec == record.rec) + for (leaf = root; leaf >= 0; ) + if (rec > res[leaf].rec && res[leaf].rhs >= 0) + leaf = res[leaf].rhs; + else if (rec < res[leaf].rec && res[leaf].lhs >= 0) + leaf = res[leaf].lhs; + else break; - if (i < len) + if (leaf >= 0 && res[leaf].rec == rec) continue; + res = mandoc_realloc + (res, (len + 1) * sizeof(struct res)); + /* * Now we have our filename, keywords, types, and all * other necessary information. @@ -423,6 +440,7 @@ state_search(struct state *p, const struct opts *opts, res[len].rec = record.rec; res[len].types = fl; + res[len].lhs = res[len].rhs = -1; buf_dup(mc, &res[len].keyword, buf); buf_dup(mc, &res[len].uri, filebuf); @@ -430,6 +448,15 @@ state_search(struct state *p, const struct opts *opts, buf_dup(mc, &res[len].arch, record.arch); buf_dup(mc, &res[len].title, record.title); buf_dup(mc, &res[len].desc, record.desc); + + if (leaf >= 0) { + if (record.rec > res[leaf].rec) + res[leaf].rhs = len; + else + res[leaf].lhs = len; + } else + root = len; + len++; } @@ -471,6 +498,7 @@ send: free(res[len].uri); } + free(res); free(buf); mchars_free(mc); @@ -489,10 +517,7 @@ buf_alloc(char **buf, size_t *bufsz, size_t sz) return; *bufsz = sz + 1024; - if (NULL == (*buf = realloc(*buf, *bufsz))) { - perror(NULL); - exit(EXIT_FAILURE); - } + *buf = mandoc_realloc(*buf, *bufsz); } /*