From: Timo Sirainen Date: Tue, 2 Dec 2025 21:39:23 +0000 (+0200) Subject: lib-imap: Add imap_seq_set_ordered_parse() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e18d39c4ec71ddc75eb8854cbc21cad2afcc41bf;p=thirdparty%2Fdovecot%2Fcore.git lib-imap: Add imap_seq_set_ordered_parse() --- diff --git a/src/lib-imap/imap-seqset.c b/src/lib-imap/imap-seqset.c index b1f616d9f1..d2a1f0801a 100644 --- a/src/lib-imap/imap-seqset.c +++ b/src/lib-imap/imap-seqset.c @@ -1,6 +1,7 @@ /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "array.h" #include "imap-seqset.h" static uint32_t get_next_number(const char **str) @@ -95,6 +96,37 @@ int imap_seq_set_nostar_parse(const char *str, ARRAY_TYPE(seq_range) *dest) return 0; } +int imap_seq_set_ordered_parse(const char *str, ARRAY_TYPE(uint32_t) *dest) +{ + uint32_t seq1, seq2; + + for (;;) { + seq1 = get_next_number(&str); + if (seq1 == 0) + return -1; + if (*str != ':') + seq2 = seq1; + else { + str++; + seq2 = get_next_number(&str); + if (seq2 == 0) + return -1; + } + if (seq1 > seq2) + return -1; + + for (uint32_t seq = seq1; seq <= seq2; seq++) + array_push_back(dest, &seq); + + if (*str == '\0') + break; + if (*str != ',') + return -1; + str++; + } + return 0; +} + int imap_seq_range_parse(const char *str, uint32_t *seq1_r, uint32_t *seq2_r) { if (get_next_seq_range(&str, seq1_r, seq2_r) < 0) diff --git a/src/lib-imap/imap-seqset.h b/src/lib-imap/imap-seqset.h index a7e1ffd93d..930bd01f5c 100644 --- a/src/lib-imap/imap-seqset.h +++ b/src/lib-imap/imap-seqset.h @@ -8,6 +8,9 @@ int imap_seq_set_parse(const char *str, ARRAY_TYPE(seq_range) *dest); /* Like imap_seq_set_parse(), but fail if '*' is used. */ int imap_seq_set_nostar_parse(const char *str, ARRAY_TYPE(seq_range) *dest); +/* Parse IMAP sequence-set where the order of the sequences matter, such as + ESORT response. */ +int imap_seq_set_ordered_parse(const char *str, ARRAY_TYPE(uint32_t) *dest); /* Parse IMAP seq-number / seq-range. */ int imap_seq_range_parse(const char *str, uint32_t *seq1_r, uint32_t *seq2_r); diff --git a/src/lib-imap/test-imap-seqset.c b/src/lib-imap/test-imap-seqset.c index 39b03d419f..8252144a97 100644 --- a/src/lib-imap/test-imap-seqset.c +++ b/src/lib-imap/test-imap-seqset.c @@ -156,12 +156,52 @@ static void test_imap_seq_range_parse(void) test_end(); } +static void test_imap_seq_set_ordered_parse(void) +{ + static const struct { + const char *input; + const char *output; + int ret; + } tests[] = { + { "", "", -1 }, + { "0", "", -1 }, + { "1,", "", -1 }, + { "1:", "", -1 }, + { ":1", "", -1 }, + { "0:1", "", -1 }, + { "*", "", -1 }, + { "1:*", "", -1 }, + { "1", "1", 0 }, + { "3:4,1:2,5,700,500:503", "3 4 1 2 5 700 500 501 502 503", 0 }, + }; + ARRAY_TYPE(uint32_t) dest; + string_t *str = t_str_new(64); + + test_begin("imap_seq_set_ordered_parse()"); + + t_array_init(&dest, 8); + for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) { + array_clear(&dest); + int ret = imap_seq_set_ordered_parse(tests[i].input, &dest); + test_assert_idx(ret == tests[i].ret, i); + if (ret == 0) { + str_truncate(str, 0); + const uint32_t *seqp; + array_foreach(&dest, seqp) + str_printfa(str, " %u", *seqp); + test_assert_strcmp_idx(str_c(str) + 1, tests[i].output, i); + } + } + test_end(); +} + int main(void) { static void (*const test_functions[])(void) = { test_imap_seq_set_parse, test_imap_seq_set_nostar_parse, test_imap_seq_range_parse, + test_imap_seq_set_ordered_parse, NULL }; return test_run(test_functions);