about summary refs log tree commit diff
path: root/archive.h
diff options
context:
space:
mode:
Diffstat (limited to 'archive.h')
-rw-r--r--archive.h29
1 files changed, 29 insertions, 0 deletions
diff --git a/archive.h b/archive.h
index d6b9608..921ae06 100644
--- a/archive.h
+++ b/archive.h
@@ -218,6 +218,35 @@ char *decodeHeader(const char *header);
 char *decodeToString(const struct BodyPart *part, const char *content);
 int decodeToFile(FILE *file, const struct BodyPart *part, const char *content);
 
+static inline uint32_t threadRoot(struct List thread) {
+	if (!thread.len) errx(EX_PROTOCOL, "empty thread");
+	while (thread.ptr[0].type == List) {
+		thread = thread.ptr[0].list;
+		if (!thread.len) errx(EX_PROTOCOL, "empty subthread");
+	}
+	return dataCheck(thread.ptr[0], Number).number;
+}
+
+static inline void compressUIDs(FILE *imap, struct List uids) {
+	uint32_t base = 0, prev = 0;
+	for (size_t i = 0; i < uids.len; ++i) {
+		uint32_t uid = uids.ptr[i].type == List
+			? threadRoot(uids.ptr[i].list)
+			: dataCheck(uids.ptr[i], Number).number;
+		if (!base) {
+			fprintf(imap, "%" PRIu32, uid);
+			base = prev = uid;
+		} else if (uid == prev + 1) {
+			prev = uid;
+		} else {
+			if (prev > base) fprintf(imap, ":%" PRIu32, prev);
+			fprintf(imap, ",%" PRIu32, uid);
+			base = prev = uid;
+		}
+	}
+	if (prev > base) fprintf(imap, ":%" PRIu32, prev);
+}
+
 bool exportFetch(FILE *imap, enum Atom tag, struct List threads);
 bool exportData(FILE *imap, enum Atom tag, struct List items);