From 2d048a0c5a7be72038d70e7473b84f19cacc85fa Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sun, 13 Jun 2021 11:17:21 -0400 Subject: Sort and compress export fetch UIDs --- archive.h | 29 +++++++++++++++++++++++++++++ concat.c | 32 ++------------------------------ export.c | 11 ++++++++--- 3 files changed, 39 insertions(+), 33 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); diff --git a/concat.c b/concat.c index a3b4bac..8da5a7a 100644 --- a/concat.c +++ b/concat.c @@ -37,37 +37,9 @@ #include "archive.h" #include "imap.h" -static 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 void compressRoots(FILE *imap, struct List threads) { - uint32_t base = 0; - uint32_t prev = 0; - for (size_t i = 0; i < threads.len; ++i) { - uint32_t root = threadRoot(dataCheck(threads.ptr[i], List).list); - if (!base) { - fprintf(imap, "%" PRIu32, root); - base = prev = root; - } else if (root == prev + 1) { - prev = root; - } else { - if (prev > base) fprintf(imap, ":%" PRIu32, prev); - fprintf(imap, ",%" PRIu32, root); - base = prev = root; - } - } - if (prev > base) fprintf(imap, ":%" PRIu32, prev); -} - void concatFetch(FILE *imap, enum Atom tag, struct List threads) { fprintf(imap, "%s UID FETCH ", Atoms[tag]); - compressRoots(imap, threads); + compressUIDs(imap, threads); fprintf(imap, " (UID ENVELOPE)\r\n"); } @@ -75,7 +47,7 @@ void concatSearch( FILE *imap, enum Atom tag, struct List threads, const char *expr ) { fprintf(imap, "%s UID SEARCH CHARSET UTF-8 UID ", Atoms[tag]); - compressRoots(imap, threads); + compressUIDs(imap, threads); fprintf(imap, " %s\r\n", expr); } diff --git a/export.c b/export.c index bebd524..b7420fb 100644 --- a/export.c +++ b/export.c @@ -48,6 +48,12 @@ static char *exportPath(uint32_t uid, const char *type) { return templateString(PATH_UID, vars, escapePath); } +static int numberCompare(const void *_a, const void *_b) { + const struct Data *a = _a; + const struct Data *b = _b; + return (a->number > b->number) - (a->number < b->number); +} + bool exportFetch(FILE *imap, enum Atom tag, struct List threads) { struct List uids = {0}; listFlatten(&uids, threads); @@ -69,11 +75,10 @@ bool exportFetch(FILE *imap, enum Atom tag, struct List threads) { listFree(uids); return false; } + qsort(uids.ptr, uids.len, sizeof(*uids.ptr), numberCompare); fprintf(imap, "%s UID FETCH ", Atoms[tag]); - for (size_t i = 0; i < uids.len; ++i) { - fprintf(imap, "%s%" PRIu32, (i ? "," : ""), uids.ptr[i].number); - } + compressUIDs(imap, uids); listFree(uids); fprintf( imap, -- cgit 1.4.1