]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: seq-range-array - add range changes
authorPhil Carmody <phil@dovecot.fi>
Tue, 20 Jan 2015 23:44:31 +0000 (01:44 +0200)
committerPhil Carmody <phil@dovecot.fi>
Tue, 20 Jan 2015 23:44:31 +0000 (01:44 +0200)
Pull the _add_range() guts into a private helper function, and add a new
_add_range_count() helper which also returns the number of SEQs added.

Expand the tests to test this new functionality.

Signed-off-by: Phil Carmody <phil@dovecot.fi>
src/lib/seq-range-array.c
src/lib/seq-range-array.h
src/lib/test-seq-range-array.c

index c8e54081415e5a1dbe7091ee01282e42e561cb35..63134253f72f803b16fd9d783ef28e1d6a27a573 100644 (file)
@@ -110,8 +110,10 @@ void seq_range_array_add_with_init(ARRAY_TYPE(seq_range) *array,
        seq_range_array_add(array, seq);
 }
 
-void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array,
-                              uint32_t seq1, uint32_t seq2)
+static void
+seq_range_array_add_range_internal(ARRAY_TYPE(seq_range) *array,
+                                  uint32_t seq1, uint32_t seq2,
+                                  unsigned int *r_count)
 {
        struct seq_range *data, value;
        unsigned int idx1, idx2, count;
@@ -120,6 +122,43 @@ void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array,
        seq_range_lookup(array, seq2, &idx2);
 
        data = array_get_modifiable(array, &count);
+       if (r_count != NULL) {
+               /* Find number we're adding by counting the number we're
+                  not adding, and subtracting that from the nominal range. */
+               unsigned int added = seq2+1 - seq1;
+               unsigned int countidx2 = idx2;
+               unsigned int overcounted = 0u, notadded = 0u;
+               unsigned int i;
+
+               if (idx1 == count) {
+                       /* not in a range as too far right */
+               } else if (seq1 < data[idx1].seq1) {
+                       /* not in a range, to the left of a real range */
+               } else {
+                       /* count the whole of this range, which is an overcount */
+                       overcounted += seq1 - data[idx1].seq1;
+                       /* fencepost check: equality means the whole range is valid,
+                          therefore there's no overcounting. Result = 0 overcount */
+               }
+               if (idx2 == count) {
+                       /* not in a range as too far right */
+               } else  if (seq2 < data[idx2].seq1) {
+                       /* not in a range, to the left of a real range */
+               } else {
+                       /* count the whole of this range, which is an overcount */
+                       overcounted += data[idx2].seq2 - seq2;
+                       countidx2++; /* may become == count i.e. past the end */
+                       /* fencepost check: equality  means the whole range is valid,
+                          therefore there's no overcounting. Result = 0 overcount. */
+               }
+               /* Now count how many we're not adding */
+               for (i = idx1; i < countidx2; i++)
+                       notadded += data[i].seq2+1 - data[i].seq1;
+               /* Maybe the not added tally included some over-counting too */
+               added -= (notadded - overcounted);
+               *r_count = added;
+       }
+
        if (idx1 > 0 && data[idx1-1].seq2+1 == seq1)
                idx1--;
 
@@ -149,6 +188,19 @@ void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array,
        }
 }
 
+void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array,
+                              uint32_t seq1, uint32_t seq2)
+{
+       seq_range_array_add_range_internal(array, seq1, seq2, NULL);
+}
+unsigned int seq_range_array_add_range_count(ARRAY_TYPE(seq_range) *array,
+                                            uint32_t seq1, uint32_t seq2)
+{
+       unsigned int count;
+       seq_range_array_add_range_internal(array, seq1, seq2, &count);
+       return count;
+}
+
 void seq_range_array_merge(ARRAY_TYPE(seq_range) *dest,
                           const ARRAY_TYPE(seq_range) *src)
 {
index ee776b7ea7920ee671f22cf9376bdcb08f50b9b3..b9525ac471e8f77877617ba647c3909cd544790a 100644 (file)
@@ -11,7 +11,13 @@ struct seq_range_iter {
        unsigned int prev_n, prev_idx;
 };
 
-/* Add sequrence to range. If the array isn't created yet, create it with
+static inline uint32_t ATTR_PURE seq_range_length(struct seq_range *range)
+{
+       i_assert(range->seq2 >= range->seq1);
+       return range->seq2 - range->seq1 + 1;
+}
+
+/* Add sequence to range. If the array isn't created yet, create it with
    initial size of init_count. */
 bool ATTR_NOWARN_UNUSED_RESULT
 seq_range_array_add(ARRAY_TYPE(seq_range) *array, uint32_t seq);
@@ -21,6 +27,8 @@ void seq_range_array_add_with_init(ARRAY_TYPE(seq_range) *array,
                                   unsigned int init_count, uint32_t seq);
 void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array,
                               uint32_t seq1, uint32_t seq2);
+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);
 /* Remove the given sequrence from range. Returns TRUE if it was found. */
index 9d8b5e03ebef99808caf5a03d6f1de59afd5c8c8..6d4fccb168d2e74531542538aedd0db7ce50c593 100644 (file)
@@ -82,8 +82,8 @@ static void test_seq_range_array_remove_nth(void)
 
 static void test_seq_range_array_random(void)
 {
-#define SEQ_RANGE_TEST_BUFSIZE 20
-#define SEQ_RANGE_TEST_COUNT 10000
+#define SEQ_RANGE_TEST_BUFSIZE 100
+#define SEQ_RANGE_TEST_COUNT 20000
        unsigned char shadowbuf[SEQ_RANGE_TEST_BUFSIZE];
        ARRAY_TYPE(seq_range) range;
        const struct seq_range *seqs;
@@ -100,12 +100,18 @@ static void test_seq_range_array_random(void)
                test = rand() % 4;
                switch (test) {
                case 0:
-                       seq_range_array_add(&range, seq1);
+                       ret = seq_range_array_add(&range, seq1) ? 0 : 1; /* FALSE == added */
+                       ret2 = shadowbuf[seq1] == 0 ? 1 : 0;
                        shadowbuf[seq1] = 1;
                        break;
                case 1:
-                       seq_range_array_add_range(&range, seq1, seq2);
-                       memset(shadowbuf + seq1, 1, seq2 - seq1 + 1);
+                       ret = seq_range_array_add_range_count(&range, seq1, seq2);
+                       for (ret2 = 0; seq1 <= seq2; seq1++) {
+                               if (shadowbuf[seq1] == 0) {
+                                       ret2++;
+                                       shadowbuf[seq1] = 1;
+                               }
+                       }
                        break;
                case 2:
                        ret = seq_range_array_remove(&range, seq1) ? 1 : 0;