source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Simplify by not pre-filtering the result vector for satisfied
@ 2012-03-24  0:31 kristaps
  0 siblings, 0 replies; only message in thread
From: kristaps @ 2012-03-24  0:31 UTC (permalink / raw)
  To: source

Log Message:
-----------
Simplify by not pre-filtering the result vector for satisfied matches:
we can do this in the frontend.

Modified Files:
--------------
    mdocml:
        apropos.c
        apropos_db.c
        cgi.c
        apropos_db.h

Revision Data
-------------
Index: apropos_db.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos_db.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -Lapropos_db.c -Lapropos_db.c -u -p -r1.29 -r1.30
--- apropos_db.c
+++ apropos_db.c
@@ -42,19 +42,15 @@
 #include "apropos_db.h"
 #include "mandoc.h"
 
-struct	rec {
-	struct res	 res; /* resulting record info */
-	/*
-	 * 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;
-	int		 matched; /* expression is true */
-	int		*matches; /* partial truth evaluations */
-};
+#define	RESFREE(_x) \
+	do { \
+		free((_x)->file); \
+		free((_x)->cat); \
+		free((_x)->title); \
+		free((_x)->arch); \
+		free((_x)->desc); \
+		free((_x)->matches); \
+	} while (/*CONSTCOND*/0)
 
 struct	expr {
 	int		 regex; /* is regex? */
@@ -73,7 +69,7 @@ struct	type {
 };
 
 struct	rectree {
-	struct rec	*node; /* record array for dir tree */
+	struct res	*node; /* record array for dir tree */
 	int		 len; /* length of record array */
 };
 
@@ -127,18 +123,17 @@ static	int	 btree_read(const DBT *, cons
 			uint64_t *, recno_t *, char **);
 static	int	 expreval(const struct expr *, int *);
 static	void	 exprexec(const struct expr *,
-			const char *, uint64_t, struct rec *);
+			const char *, uint64_t, struct res *);
 static	int	 exprmark(const struct expr *,
 			const char *, uint64_t, int *);
 static	struct expr *exprexpr(int, char *[], int *, int *, size_t *);
 static	struct expr *exprterm(char *, int);
 static	DB	*index_open(void);
 static	int	 index_read(const DBT *, const DBT *, int,
-			const struct mchars *, struct rec *);
+			const struct mchars *, struct res *);
 static	void	 norm_string(const char *,
 			const struct mchars *, char **);
 static	size_t	 norm_utf8(unsigned int, char[7]);
-static	void	 recfree(struct rec *);
 static	int	 single_search(struct rectree *, const struct opts *,
 			const struct expr *, size_t terms,
 			struct mchars *, int);
@@ -361,7 +356,7 @@ index_open(void)
  */
 static int
 index_read(const DBT *key, const DBT *val, int index,
-		const struct mchars *mc, struct rec *rec)
+		const struct mchars *mc, struct res *rec)
 {
 	size_t		 left;
 	char		*np, *cp;
@@ -381,24 +376,24 @@ index_read(const DBT *key, const DBT *va
 
 	cp = val->data;
 	assert(sizeof(recno_t) == key->size);
-	memcpy(&rec->res.rec, key->data, key->size);
-	rec->res.volume = index;
+	memcpy(&rec->rec, key->data, key->size);
+	rec->volume = index;
 
 	if ('d' == (type = *cp++))
-		rec->res.type = RESTYPE_MDOC;
+		rec->type = RESTYPE_MDOC;
 	else if ('a' == type)
-		rec->res.type = RESTYPE_MAN;
+		rec->type = RESTYPE_MAN;
 	else if ('c' == type)
-		rec->res.type = RESTYPE_CAT;
+		rec->type = RESTYPE_CAT;
 	else
 		return(0);
 
 	left--;
-	INDEX_BREAD(rec->res.file);
-	INDEX_BREAD(rec->res.cat);
-	INDEX_BREAD(rec->res.title);
-	INDEX_BREAD(rec->res.arch);
-	INDEX_BREAD(rec->res.desc);
+	INDEX_BREAD(rec->file);
+	INDEX_BREAD(rec->cat);
+	INDEX_BREAD(rec->title);
+	INDEX_BREAD(rec->arch);
+	INDEX_BREAD(rec->desc);
 	return(1);
 }
 
@@ -411,17 +406,19 @@ index_read(const DBT *key, const DBT *va
 int
 apropos_search(int pathsz, char **paths, const struct opts *opts,
 		const struct expr *expr, size_t terms, void *arg,
+		size_t *sz, struct res **resp,
 		void (*res)(struct res *, size_t, void *))
 {
 	struct rectree	 tree;
 	struct mchars	*mc;
-	struct res	*ress;
-	int		 i, mlen, rc;
+	int		 i, rc;
 
 	memset(&tree, 0, sizeof(struct rectree));
 
 	rc = 0;
 	mc = mchars_alloc();
+	*sz = 0;
+	*resp = NULL;
 
 	/*
 	 * Main loop.  Change into the directory containing manpage
@@ -431,37 +428,19 @@ apropos_search(int pathsz, char **paths,
 	for (i = 0; i < pathsz; i++) {
 		if (chdir(paths[i]))
 			continue;
-		if ( ! single_search(&tree, opts, expr, terms, mc, i))
-			goto out;
-	}
-
-	/*
-	 * Count matching files, transfer to a "clean" array, then feed
-	 * them to the output handler.
-	 */
+		if (single_search(&tree, opts, expr, terms, mc, i))
+			continue;
 
-	for (mlen = i = 0; i < tree.len; i++)
-		if (tree.node[i].matched)
-			mlen++;
-
-	ress = mandoc_malloc(mlen * sizeof(struct res));
-
-	for (mlen = i = 0; i < tree.len; i++)
-		if (tree.node[i].matched)
-			memcpy(&ress[mlen++], &tree.node[i].res,
-					sizeof(struct res));
-
-	(*res)(ress, mlen, arg);
-	free(ress);
-
-	rc = 1;
-out:
-	for (i = 0; i < tree.len; i++)
-		recfree(&tree.node[i]);
+		resfree(tree.node, tree.len);
+		mchars_free(mc);
+		return(0);
+	}
 
-	free(tree.node);
+	(*res)(tree.node, tree.len, arg);
+	*sz = tree.len;
+	*resp = tree.node;
 	mchars_free(mc);
-	return(rc);
+	return(1);
 }
 
 static int
@@ -473,8 +452,8 @@ single_search(struct rectree *tree, cons
 	DBT		 key, val;
 	DB		*btree, *idx;
 	char		*buf;
-	struct rec	*rs;
-	struct rec	 r;
+	struct res	*rs;
+	struct res	 r;
 	uint64_t	 mask;
 	recno_t		 rec;
 
@@ -485,7 +464,7 @@ single_search(struct rectree *tree, cons
 	buf	= NULL;
 	rs	= tree->node;
 
-	memset(&r, 0, sizeof(struct rec));
+	memset(&r, 0, sizeof(struct res));
 
 	if (NULL == (btree = btree_open()))
 		return(1);
@@ -513,10 +492,10 @@ single_search(struct rectree *tree, cons
 		 */
 
 		for (leaf = root; leaf >= 0; )
-			if (rec > rs[leaf].res.rec &&
+			if (rec > rs[leaf].rec &&
 					rs[leaf].rhs >= 0)
 				leaf = rs[leaf].rhs;
-			else if (rec < rs[leaf].res.rec &&
+			else if (rec < rs[leaf].rec &&
 					rs[leaf].lhs >= 0)
 				leaf = rs[leaf].lhs;
 			else
@@ -528,7 +507,7 @@ single_search(struct rectree *tree, cons
 		 * try to evaluate it now and continue anyway.
 		 */
 
-		if (leaf >= 0 && rs[leaf].res.rec == rec) {
+		if (leaf >= 0 && rs[leaf].rec == rec) {
 			if (0 == rs[leaf].matched)
 				exprexec(expr, buf, mask, &rs[leaf]);
 			continue;
@@ -552,18 +531,18 @@ single_search(struct rectree *tree, cons
 
 		/* XXX: this should be elsewhere, I guess? */
 
-		if (opts->cat && strcasecmp(opts->cat, r.res.cat))
+		if (opts->cat && strcasecmp(opts->cat, r.cat))
 			continue;
 
-		if (opts->arch && *r.res.arch)
-			if (strcasecmp(opts->arch, r.res.arch))
+		if (opts->arch && *r.arch)
+			if (strcasecmp(opts->arch, r.arch))
 				continue;
 
 		tree->node = rs = mandoc_realloc
-			(rs, (tree->len + 1) * sizeof(struct rec));
+			(rs, (tree->len + 1) * sizeof(struct res));
 
-		memcpy(&rs[tree->len], &r, sizeof(struct rec));
-		memset(&r, 0, sizeof(struct rec));
+		memcpy(&rs[tree->len], &r, sizeof(struct res));
+		memset(&r, 0, sizeof(struct res));
 		rs[tree->len].matches =
 			mandoc_calloc(terms, sizeof(int));
 
@@ -572,7 +551,7 @@ single_search(struct rectree *tree, cons
 		/* Append to our tree. */
 
 		if (leaf >= 0) {
-			if (rec > rs[leaf].res.rec)
+			if (rec > rs[leaf].rec)
 				rs[leaf].rhs = tree->len;
 			else
 				rs[leaf].lhs = tree->len;
@@ -586,21 +565,18 @@ single_search(struct rectree *tree, cons
 	(*idx->close)(idx);
 
 	free(buf);
-	recfree(&r);
+	RESFREE(&r);
 	return(1 == ch);
 }
 
-static void
-recfree(struct rec *rec)
+void
+resfree(struct res *rec, size_t sz)
 {
+	size_t		 i;
 
-	free(rec->res.file);
-	free(rec->res.cat);
-	free(rec->res.title);
-	free(rec->res.arch);
-	free(rec->res.desc);
-
-	free(rec->matches);
+	for (i = 0; i < sz; i++)
+		RESFREE(&rec[i]);
+	free(rec);
 }
 
 /*
@@ -891,7 +867,7 @@ expreval(const struct expr *p, int *ms)
  */
 static void
 exprexec(const struct expr *e, const char *cp,
-		uint64_t mask, struct rec *r)
+		uint64_t mask, struct res *r)
 {
 
 	assert(0 == r->matched);
Index: apropos_db.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos_db.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -Lapropos_db.h -Lapropos_db.h -u -p -r1.11 -r1.12
--- apropos_db.h
+++ apropos_db.h
@@ -36,6 +36,18 @@ struct	res {
 	 * searched for manual page databases.
 	 */
 	unsigned int	 volume;
+	/*
+	 * The following fields are used internally.
+	 *
+	 * 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;
+	int		 matched; /* expression is true */
+	int		*matches; /* partial truth evaluations */
 };
 
 struct	opts {
@@ -47,11 +59,13 @@ __BEGIN_DECLS
 
 struct	expr;
 
-int	 	 apropos_search(int, char **, const struct opts *,
-			const struct expr *, size_t, void *,
+int		 apropos_search(int, char **, const struct opts *,
+			const struct expr *, size_t, 
+			void *, size_t *, struct res **,
 			void (*)(struct res *, size_t, void *));
 struct	expr	*exprcomp(int, char *[], size_t *);
 void		 exprfree(struct expr *);
+void	 	 resfree(struct res *, size_t);
 struct	expr	*termcomp(int, char *[], size_t *);
 
 __END_DECLS
Index: cgi.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/cgi.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -Lcgi.c -Lcgi.c -u -p -r1.40 -r1.41
--- cgi.c
+++ cgi.c
@@ -495,15 +495,22 @@ resp_baddb(void)
 static void
 resp_search(struct res *r, size_t sz, void *arg)
 {
-	int		  i;
+	size_t		 i, matched;
 	const struct req *req;
 
 	req = (const struct req *)arg;
 
 	if (sz > 0)
 		assert(req->q.manroot >= 0);
+
+	for (matched = i = 0; i < sz; i++)
+		if (r[i].matched)
+			matched++;
 	
-	if (1 == sz) {
+	if (1 == matched) {
+		for (i = 0; i < sz; i++)
+			if (r[i].matched)
+				break;
 		/*
 		 * If we have just one result, then jump there now
 		 * without any delay.
@@ -511,21 +518,19 @@ resp_search(struct res *r, size_t sz, vo
 		puts("Status: 303 See Other");
 		printf("Location: http://%s%s/show/%d/%u/%u.html?",
 				host, progname, req->q.manroot,
-				r[0].volume, r[0].rec);
+				r[i].volume, r[i].rec);
 		http_printquery(req);
 		puts("\n"
 		     "Content-Type: text/html; charset=utf-8\n");
 		return;
 	}
 
-	qsort(r, sz, sizeof(struct res), cmp);
-
 	resp_begin_html(200, NULL);
 	resp_searchform(req);
 
 	puts("<DIV CLASS=\"results\">");
 
-	if (0 == sz) {
+	if (0 == matched) {
 		puts("<P>\n"
 		     "No results found.\n"
 		     "</P>\n"
@@ -534,9 +539,13 @@ resp_search(struct res *r, size_t sz, vo
 		return;
 	}
 
+	qsort(r, sz, sizeof(struct res), cmp);
+
 	puts("<TABLE>");
 
-	for (i = 0; i < (int)sz; i++) {
+	for (i = 0; i < sz; i++) {
+		if ( ! r[i].matched)
+			continue;
 		printf("<TR>\n"
 		       "<TD CLASS=\"title\">\n"
 		       "<A HREF=\"%s/show/%d/%u/%u.html?", 
@@ -870,10 +879,11 @@ out:
 static void
 pg_search(const struct req *req, char *path)
 {
-	size_t		  tt;
+	size_t		  tt, ressz;
 	struct manpaths	  ps;
 	int		  i, sz, rc;
 	const char	 *ep, *start;
+	struct res	*res;
 	char		**cp;
 	struct opts	  opt;
 	struct expr	 *expr;
@@ -891,6 +901,8 @@ pg_search(const struct req *req, char *p
 	rc 	 = -1;
 	sz 	 = 0;
 	cp	 = NULL;
+	ressz	 = 0;
+	res	 = NULL;
 
 	/*
 	 * Begin by chdir()ing into the root of the manpath.
@@ -938,20 +950,21 @@ pg_search(const struct req *req, char *p
 
 	if (NULL != expr)
 		rc = apropos_search
-			(ps.sz, ps.paths, &opt,
-			 expr, tt, (void *)req, resp_search);
+			(ps.sz, ps.paths, &opt, expr, tt, 
+			 (void *)req, &ressz, &res, resp_search);
 
 	/* ...unless errors occured. */
 
 	if (0 == rc)
 		resp_baddb();
 	else if (-1 == rc)
-		resp_search(NULL, 0, (void *)req);
+		resp_search(NULL, 0, NULL);
 
 	for (i = 0; i < sz; i++)
 		free(cp[i]);
 
 	free(cp);
+	resfree(res, ressz);
 	exprfree(expr);
 	manpath_free(&ps);
 }
Index: apropos.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -Lapropos.c -Lapropos.c -u -p -r1.26 -r1.27
--- apropos.c
+++ apropos.c
@@ -18,6 +18,7 @@
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+#include <sys/param.h>
 
 #include <assert.h>
 #include <getopt.h>
@@ -39,8 +40,9 @@ int
 main(int argc, char *argv[])
 {
 	int		 ch, rc, whatis;
+	struct res	*res;
 	struct manpaths	 paths;
-	size_t		 terms;
+	size_t		 terms, ressz;
 	struct opts	 opts;
 	struct expr	*e;
 	char		*defpaths, *auxpaths;
@@ -59,6 +61,8 @@ main(int argc, char *argv[])
 	memset(&paths, 0, sizeof(struct manpaths));
 	memset(&opts, 0, sizeof(struct opts));
 
+	ressz = 0;
+	res = NULL;
 	auxpaths = defpaths = NULL;
 	conf_file = NULL;
 	e = NULL;
@@ -104,17 +108,17 @@ main(int argc, char *argv[])
 	}
 
 	rc = apropos_search
-		(paths.sz, paths.paths,
-		 &opts, e, terms, NULL, list);
-
-	if (0 == rc)
-		fprintf(stderr, "%s: Error reading "
-				"manual database\n", progname);
+		(paths.sz, paths.paths, &opts, 
+		 e, terms, NULL, &ressz, &res, list);
 
+	if (0 == rc) {
+		fprintf(stderr, "%s: Bad database\n", progname);
+		goto out;
+	}
 out:
 	manpath_free(&paths);
+	resfree(res, ressz);
 	exprfree(e);
-
 	return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
@@ -126,13 +130,16 @@ list(struct res *res, size_t sz, void *a
 
 	qsort(res, sz, sizeof(struct res), cmp);
 
-	for (i = 0; i < sz; i++)
+	for (i = 0; i < sz; i++) {
+		if ( ! res[i].matched)
+			continue;
 		printf("%s(%s%s%s) - %.70s\n", 
 				res[i].title,
 				res[i].cat,
 				*res[i].arch ? "/" : "",
 				*res[i].arch ? res[i].arch : "",
 				res[i].desc);
+	}
 }
 
 static int
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2012-03-24  0:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-24  0:31 mdocml: Simplify by not pre-filtering the result vector for satisfied kristaps

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).