about summary refs log tree commit diff
path: root/concat.c
diff options
context:
space:
mode:
Diffstat (limited to 'concat.c')
-rw-r--r--concat.c86
1 files changed, 62 insertions, 24 deletions
diff --git a/concat.c b/concat.c
index 800a7a2..54a49a7 100644
--- a/concat.c
+++ b/concat.c
@@ -27,6 +27,7 @@
 
 #include <err.h>
 #include <inttypes.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -54,6 +55,17 @@ void concatFetch(FILE *imap, enum Atom tag, struct List threads) {
 	fprintf(imap, " (UID ENVELOPE)\r\n");
 }
 
+void concatSearch(
+	FILE *imap, enum Atom tag, struct List threads, const char *expr
+) {
+	fprintf(imap, "%s UID SEARCH CHARSET UTF-8 UID ", Atoms[tag]);
+	for (size_t i = 0; i < threads.len; ++i) {
+		uint32_t root = threadRoot(dataCheck(threads.ptr[i], List).list);
+		fprintf(imap, "%s%" PRIu32, (i ? "," : ""), root);
+	}
+	fprintf(imap, " %s\r\n", expr);
+}
+
 void concatData(
 	struct List threads, struct Envelope *envelopes, struct List items
 ) {
@@ -230,13 +242,13 @@ void concatThreads(struct List threads, const struct Envelope *envelopes) {
 	}
 }
 
-static char *searchPath(const char *name, const char *type) {
+static char *indexPath(const char *name, const char *type) {
 	struct Variable vars[] = {
 		{ "name", name },
 		{ "type", type },
 		{0},
 	};
-	return templateString(PATH_SEARCH, vars, escapePath);
+	return templateString(PATH_INDEX, vars, escapePath);
 }
 
 static int numberCompare(const void *_a, const void *_b) {
@@ -261,23 +273,43 @@ static int sortCompare(const void *_a, const void *_b) {
 	}
 }
 
-size_t concatSearchEntries = 20;
+size_t concatIndexEntries = 20;
 
-void concatSearch(
-	const char *name, struct List threads, const struct Envelope *envelopes,
-	char *searches[const], size_t len
+void concatIndex(
+	const char *name, struct List roots,
+	struct List threads, const struct Envelope *envelopes
 ) {
-	char *path = searchPath(name, "atom");
+	bool *bitmap = calloc(threads.len, sizeof(*bitmap));
+	if (!bitmap) err(EX_OSERR, "calloc");
+
+	for (size_t i = 0; i < roots.len; ++i) {
+		dataCheck(roots.ptr[i], Number);
+	}
+	for (size_t i = 0; i < threads.len; ++i) {
+		uint32_t root = threadRoot(dataCheck(threads.ptr[i], List).list);
+		for (size_t j = 0; j < roots.len; ++j) {
+			if (root == roots.ptr[j].number) {
+				bitmap[i] = true;
+				break;
+			}
+		}
+	}
+
+	char *path = indexPath(name, "atom");
 	FILE *file = fopen(path, "w");
 	if (!file) err(EX_CANTCREAT, "%s", path);
 
-	int error = atomSearchOpen(file, name);
+	int error = atomIndexOpen(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
 	struct List flat = {0};
-	listFlatten(&flat, threads);
+	for (size_t i = 0; i < threads.len; ++i) {
+		if (!bitmap[i]) continue;
+		listFlatten(&flat, threads.ptr[i].list);
+	}
 	qsort(flat.ptr, flat.len, sizeof(*flat.ptr), numberCompare);
-	for (size_t i = 0; i < flat.len && i < concatSearchEntries; ++i) {
+
+	for (size_t i = 0; i < flat.len && i < concatIndexEntries; ++i) {
 		uint32_t uid = dataCheck(flat.ptr[i], Number).number;
 		char *src = uidPath(uid, "atom");
 		error = concatFile(file, src);
@@ -286,30 +318,37 @@ void concatSearch(
 	}
 	listFree(flat);
 
-	error = atomSearchClose(file) || fclose(file);
+	error = atomIndexClose(file) || fclose(file);
 	if (error) err(EX_IOERR, "%s", path);
 	if (!quiet) printf("%s\n", path);
 	free(path);
-
-	struct Sort *order = calloc(threads.len, sizeof(*order));
+	
+	size_t len = 0;
+	struct Sort *order = calloc(roots.len, sizeof(*order));
 	if (!order) err(EX_OSERR, "calloc");
 
 	for (size_t i = 0; i < threads.len; ++i) {
-		order[i].index = i;
-		order[i].created = envelopes[i].time;
+		if (!bitmap[i]) continue;
 
 		struct stat status;
 		char *path = threadPath(envelopes[i].messageID, "html");
-		if (!stat(path, &status)) order[i].updated = status.st_mtime;
+		error = stat(path, &status);
+		if (error) err(EX_DATAERR, "%s", path);
 		free(path);
+
+		order[len].index = i;
+		order[len].created = envelopes[i].time;
+		order[len].updated = status.st_mtime;
+		len++;
 	}
-	qsort(order, threads.len, sizeof(*order), sortCompare);
+	qsort(order, len, sizeof(*order), sortCompare);
+	free(bitmap);
 
-	path = searchPath(name, "html");
+	path = indexPath(name, "html");
 	file = fopen(path, "w");
 	if (!file) err(EX_CANTCREAT, "%s", path);
 
-	error = htmlSearchHead(file, name);
+	error = htmlIndexHead(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
 	if (concatHead) {
@@ -317,19 +356,18 @@ void concatSearch(
 		if (error) err(EX_IOERR, "%s", path);
 	}
 
-	error = htmlSearchOpen(file, name, searches, len);
+	error = htmlIndexOpen(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
-	for (size_t i = threads.len - 1; i < threads.len; --i) {
-		if (!order[i].updated) continue;
+	for (size_t i = len - 1; i < len; --i) {
 		const struct Envelope *envelope = &envelopes[order[i].index];
 		struct List thread = dataCheck(threads.ptr[order[i].index], List).list;
-		error = htmlSearchThread(file, envelope, thread);
+		error = htmlIndexThread(file, envelope, thread);
 		if (error) err(EX_IOERR, "%s", path);
 	}
 	free(order);
 
-	error = htmlSearchClose(file) || fclose(file);
+	error = htmlIndexClose(file) || fclose(file);
 	if (error) err(EX_IOERR, "%s", path);
 	if (!quiet) printf("%s\n", path);
 	free(path);