From: Timo Sirainen Date: Thu, 23 Jan 2020 16:31:01 +0000 (+0200) Subject: lib: Add seq_range_array_merge_n() X-Git-Tag: 2.3.10~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=df592aadbbba0063a30085177edbcd0b8ea45f18;p=thirdparty%2Fdovecot%2Fcore.git lib: Add seq_range_array_merge_n() --- diff --git a/src/lib/seq-range-array.c b/src/lib/seq-range-array.c index 66b7e101cb..8633608a2c 100644 --- a/src/lib/seq-range-array.c +++ b/src/lib/seq-range-array.c @@ -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; diff --git a/src/lib/seq-range-array.h b/src/lib/seq-range-array.h index cdb1febba7..fb668ed31e 100644 --- a/src/lib/seq-range-array.h +++ b/src/lib/seq-range-array.h @@ -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); diff --git a/src/lib/test-seq-range-array.c b/src/lib/test-seq-range-array.c index 8ba6ba03a9..f30d57ac4e 100644 --- a/src/lib/test-seq-range-array.c +++ b/src/lib/test-seq-range-array.c @@ -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();