dovecot-2.2: lib: array - element-wise comparison via callback
dovecot at dovecot.org
dovecot at dovecot.org
Tue Nov 25 01:53:53 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/b8ac4e5a1002
changeset: 18111:b8ac4e5a1002
user: Phil Carmody <phil at dovecot.fi>
date: Tue Nov 25 03:43:02 2014 +0200
description:
lib: array - element-wise comparison via callback
2 are provided - with and without a context pointer.
Signed-off-by: Phil Carmody <phil at dovecot.fi>
diffstat:
src/lib/array.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/lib/array.h | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+), 0 deletions(-)
diffs (118 lines):
diff -r a45ee7e221b0 -r b8ac4e5a1002 src/lib/array.c
--- a/src/lib/array.c Tue Nov 25 03:43:02 2014 +0200
+++ b/src/lib/array.c Tue Nov 25 03:43:02 2014 +0200
@@ -69,6 +69,59 @@
return buffer_cmp(array1->buffer, array2->buffer);
}
+bool array_equal_fn_i(const struct array *array1, const struct array *array2,
+ int (*cmp)(const void *, const void*))
+{
+ unsigned int count1, count2, i, size;
+
+ if (!array_is_created_i(array1) || array1->buffer->used == 0)
+ return !array_is_created_i(array2) || array2->buffer->used == 0;
+
+ if (!array_is_created_i(array2))
+ return FALSE;
+
+ count1 = array_count_i(array1); count2 = array_count_i(array2);
+ if (count1 != count2)
+ return FALSE;
+
+ size = array1->element_size;
+ i_assert(size == array2->element_size);
+
+ for (i = 0; i < count1; i++) {
+ if (cmp(CONST_PTR_OFFSET(array1->buffer->data, i * size),
+ CONST_PTR_OFFSET(array2->buffer->data, i * size)) != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool array_equal_fn_ctx_i(const struct array *array1, const struct array *array2,
+ int (*cmp)(const void *, const void *, const void *),
+ const void *context)
+{
+ unsigned int count1, count2, i, size;
+
+ if (!array_is_created_i(array1) || array1->buffer->used == 0)
+ return !array_is_created_i(array2) || array2->buffer->used == 0;
+
+ if (!array_is_created_i(array2))
+ return FALSE;
+
+ count1 = array_count_i(array1); count2 = array_count_i(array2);
+ if (count1 != count2)
+ return FALSE;
+
+ size = array1->element_size;
+ i_assert(size == array2->element_size);
+
+ for (i = 0; i < count1; i++) {
+ if (cmp(CONST_PTR_OFFSET(array1->buffer->data, i * size),
+ CONST_PTR_OFFSET(array2->buffer->data, i * size), context) != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
void array_reverse_i(struct array *array)
{
const size_t element_size = array->element_size;
diff -r a45ee7e221b0 -r b8ac4e5a1002 src/lib/array.h
--- a/src/lib/array.h Tue Nov 25 03:43:02 2014 +0200
+++ b/src/lib/array.h Tue Nov 25 03:43:02 2014 +0200
@@ -47,10 +47,15 @@
# define ARRAY_TYPE_CHECK(array, data) \
COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \
**(array)->v_modifiable, *(data))
+# define ARRAY_TYPES_CHECK(array1, array2) \
+ COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \
+ **(array1)->v_modifiable, **(array2)->v_modifiable)
+
#else
# define ARRAY_TYPE_CAST_CONST(array)
# define ARRAY_TYPE_CAST_MODIFIABLE(array)
# define ARRAY_TYPE_CHECK(array, data) 0
+# define ARRAY_TYPES_CHECK(array1, array2) 0
#endif
/* usage: struct foo *foo; array_foreach(foo_arr, foo) { .. } */
@@ -259,6 +264,35 @@
#define array_cmp(array1, array2) \
array_cmp_i(&(array1)->arr, &(array2)->arr)
+/* Test equality via a comparator */
+bool array_equal_fn_i(const struct array *array1,
+ const struct array *array2,
+ int (*cmp)(const void*, const void *)) ATTR_PURE;
+#define array_equal_fn(array1, array2, cmp) \
+ array_equal_fn_i(&(array1)->arr + \
+ ARRAY_TYPES_CHECK(array1, array2), \
+ &(array2)->arr + \
+ CALLBACK_TYPECHECK(cmp, int (*)(typeof(*(array1)->v), \
+ typeof(*(array2)->v))), \
+ (int (*)(const void *, const void *))cmp)
+bool array_equal_fn_ctx_i(const struct array *array1,
+ const struct array *array2,
+ int (*cmp)(const void*, const void *, const void *),
+ const void *context) ATTR_PURE;
+/* Same, but with a context pointer.
+ context can't be void* as ``const typeof(context)'' won't compile,
+ so ``const typeof(*context)*'' is required instead, and that requires a
+ complete type. */
+#define array_equal_fn_ctx(array1, array2, cmp, ctx) \
+ array_equal_fn_ctx_i(&(array1)->arr + \
+ ARRAY_TYPES_CHECK(array1, array2), \
+ &(array2)->arr + \
+ CALLBACK_TYPECHECK(cmp, int (*)(typeof(*(array1)->v), \
+ typeof(*(array2)->v), \
+ const typeof(*ctx)*)), \
+ (int (*)(const void *, const void *, const void *))cmp, \
+ ctx)
+
void array_reverse_i(struct array *array);
#define array_reverse(array) \
array_reverse_i(&(array)->arr)
More information about the dovecot-cvs
mailing list