]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add seq_range_array_merge_n()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 23 Jan 2020 16:31:01 +0000 (18:31 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 6 Feb 2020 16:14:32 +0000 (16:14 +0000)
src/lib/seq-range-array.c
src/lib/seq-range-array.h
src/lib/test-seq-range-array.c

index 66b7e101cbfe1eac5c8d82c50d334cd6b8358faf..8633608a2c724c627ea03d0a58926517ea96a266 100644 (file)
@@ -215,6 +215,30 @@ void seq_range_array_merge(ARRAY_TYPE(seq_range) *dest,
                seq_range_array_add_range(dest, range->seq1, range->seq2);
 }
 
+void seq_range_array_merge_n(ARRAY_TYPE(seq_range) *dest,
+                            const ARRAY_TYPE(seq_range) *src,
+                            unsigned int count)
+{
+       const struct seq_range *src_range;
+       unsigned int src_idx, src_count;
+       unsigned int merge_count = count;
+
+       src_range = array_get(src, &src_count);
+       for (src_idx = 0; src_idx < src_count && merge_count > 0; src_idx++) {
+               uint32_t first_seq = src_range[src_idx].seq1;
+               uint32_t last_seq = src_range[src_idx].seq2;
+               unsigned int idx_count = last_seq - first_seq + 1;
+
+               if (idx_count > merge_count) {
+                       last_seq = first_seq + merge_count - 1;
+                       merge_count = 0;
+               } else {
+                       merge_count -= idx_count;
+               }
+               seq_range_array_add_range(dest, first_seq, last_seq);
+       }
+}
+
 bool seq_range_array_remove(ARRAY_TYPE(seq_range) *array, uint32_t seq)
 {
        struct seq_range *data, value;
index cdb1febba7da5f5991e599d9117f23984e917ab6..fb668ed31e4e3aa1180a0a761e17f4ef4a5e5380 100644 (file)
@@ -31,6 +31,10 @@ unsigned int seq_range_array_add_range_count(ARRAY_TYPE(seq_range) *array,
                                             uint32_t seq1, uint32_t seq2);
 void seq_range_array_merge(ARRAY_TYPE(seq_range) *dest,
                           const ARRAY_TYPE(seq_range) *src);
+/* Merge the first n sequences from src into dest. */
+void seq_range_array_merge_n(ARRAY_TYPE(seq_range) *dest,
+                            const ARRAY_TYPE(seq_range) *src,
+                            unsigned int count);
 /* Remove the given sequence from range. Returns TRUE if it was found. */
 bool ATTR_NOWARN_UNUSED_RESULT
 seq_range_array_remove(ARRAY_TYPE(seq_range) *array, uint32_t seq);
index 8ba6ba03a96ad48b32149bc6366ac9a5331bd49b..f30d57ac4e3436bc58b558a18f947f58aade7032 100644 (file)
@@ -58,6 +58,38 @@ static void test_seq_range_array_add_merge(void)
        test_end();
 }
 
+static void test_seq_range_array_merge_n(void)
+{
+       ARRAY_TYPE(seq_range) src, dest, dest2;
+       struct seq_range_iter iter;
+       const uint32_t seqs[] = { 4, 5, 7, 8, 9, 11 };
+       uint32_t seq;
+
+       test_begin("seq_range_array_merge_n()");
+       t_array_init(&src, 16);
+       t_array_init(&dest, 16);
+       t_array_init(&dest2, 16);
+       for (unsigned int i = 0; i < N_ELEMENTS(seqs); i++)
+               seq_range_array_add(&src, seqs[i]);
+
+       for (unsigned int i = 0; i <= N_ELEMENTS(seqs); i++) {
+               array_clear(&dest);
+               array_clear(&dest2);
+               seq_range_array_merge_n(&dest, &src, i);
+               test_assert_idx(seq_range_count(&dest) == I_MIN(i, N_ELEMENTS(seqs)), i);
+
+               seq_range_array_iter_init(&iter, &src);
+               for (unsigned int j = 0; j < i; j++) {
+                       test_assert_idx(seq_range_array_iter_nth(&iter, j, &seq), i);
+                       seq_range_array_add(&dest2, seq);
+               }
+               seq_range_array_invert(&dest2, 1, UINT32_MAX);
+               seq_range_array_intersect(&dest2, &dest);
+               test_assert_idx(array_count(&dest2) == 0, i);
+       }
+       test_end();
+}
+
 static void test_seq_range_array_remove_nth(void)
 {
        ARRAY_TYPE(seq_range) range;
@@ -298,6 +330,7 @@ void test_seq_range_array(void)
 {
        test_seq_range_array_add_boundaries();
        test_seq_range_array_add_merge();
+       test_seq_range_array_merge_n();
        test_seq_range_array_remove_nth();
        test_seq_range_array_invert();
        test_seq_range_array_invert_edges();