]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap: Add imap_seq_set_ordered_parse()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 2 Dec 2025 21:39:23 +0000 (23:39 +0200)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 3 Dec 2025 20:02:34 +0000 (22:02 +0200)
src/lib-imap/imap-seqset.c
src/lib-imap/imap-seqset.h
src/lib-imap/test-imap-seqset.c

index b1f616d9f1be4c4cab2a42318f0dbf679a0e2384..d2a1f0801a95096c1405a49b11b93e7b9adb8cb9 100644 (file)
@@ -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)
index a7e1ffd93d02c4901b55d3a4a149ea928f3f04c0..930bd01f5c0f56b3156fcc871863f64a4f63af0e 100644 (file)
@@ -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);
index 39b03d419f16b10442200a3ced69e4a1c35847f1..8252144a977704b0ac14a57d0aaa760c6681b409 100644 (file)
@@ -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);