From 30b45eeb6c56e6ffca79910c9dd67977e2a41c6d Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Wed, 12 Nov 2014 20:55:10 +0100 Subject: [PATCH] data: Let inarray() support IN checks. This check returns true if all elements of the first array are included in the second array where order does not matter. --- src/core/data.c | 67 ++++++++++++++++++++++++++--------------- src/include/core/data.h | 5 ++- t/unit/core/data_test.c | 48 +++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 27 deletions(-) diff --git a/src/core/data.c b/src/core/data.c index 27c7aa1..88c7f82 100644 --- a/src/core/data.c +++ b/src/core/data.c @@ -631,39 +631,58 @@ sdb_data_isnull(const sdb_data_t *datum) _Bool sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array) { - size_t i; + const void *values; + size_t length, i; + int type = value->type & 0xff; if (sdb_data_isnull(value) || sdb_data_isnull(array)) return 0; - if ((value->type & SDB_TYPE_ARRAY) || (! (array->type & SDB_TYPE_ARRAY))) + if (! (array->type & SDB_TYPE_ARRAY)) return 0; - if (value->type != (array->type & 0xff)) + if ((value->type & 0xff) != (array->type & 0xff)) return 0; - if (value->type == SDB_TYPE_INTEGER) { - int64_t *v = array->data.array.values; - for (i = 0; i < array->data.array.length; ++i) - if (value->data.integer == v[i]) - return 1; - } - else if (value->type == SDB_TYPE_DECIMAL) { - double *v = array->data.array.values; - for (i = 0; i < array->data.array.length; ++i) - if (value->data.decimal == v[i]) - return 1; - } - else if (value->type == SDB_TYPE_STRING) { - char **v = array->data.array.values; - for (i = 0; i < array->data.array.length; ++i) - if (!strcasecmp(value->data.string, v[i])) - return 1; + if (value->type & SDB_TYPE_ARRAY) { + values = value->data.array.values; + length = value->data.array.length; } else { - /* TODO */ - errno = ENOTSUP; - return 0; + values = &value->data; + length = 1; } - return 0; + + for (i = 0; i < length; ++i) { + size_t j; + + if (type == SDB_TYPE_INTEGER) { + int64_t *v = array->data.array.values; + for (j = 0; j < array->data.array.length; ++j) + if (((const int64_t *)values)[i] == v[j]) + break; + } + else if (type == SDB_TYPE_DECIMAL) { + double *v = array->data.array.values; + for (j = 0; j < array->data.array.length; ++j) + if (((const double *)values)[i] == v[j]) + break; + } + else if (type == SDB_TYPE_STRING) { + char **v = array->data.array.values; + for (j = 0; j < array->data.array.length; ++j) + if (!strcasecmp(((const char * const*)values)[i], v[j])) + break; + } + else { + /* TODO */ + errno = ENOTSUP; + return 0; + } + + if (j >= array->data.array.length) + /* value not found */ + return 0; + } + return 1; } /* sdb_data_inarray */ int diff --git a/src/include/core/data.h b/src/include/core/data.h index c03c0c1..997cf9f 100644 --- a/src/include/core/data.h +++ b/src/include/core/data.h @@ -168,7 +168,10 @@ sdb_data_isnull(const sdb_data_t *datum); * sdb_data_inarray: * Determine whether a datum is included in an array based on the usual * comparison function of the value's type. The element type of the array has - * to match the type of the value. + * to match the type of the value. The value may be another array. In that + * case, the element types have to match and the function returns true if all + * elements of the first array are included in the second where order does not + * matter. */ _Bool sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array); diff --git a/t/unit/core/data_test.c b/t/unit/core/data_test.c index 2baa6a1..956cf31 100644 --- a/t/unit/core/data_test.c +++ b/t/unit/core/data_test.c @@ -730,21 +730,51 @@ END_TEST START_TEST(test_inarray) { int64_t int_values[] = { 47, 11, 64 }; + int64_t int_values2[] = { 64, 11 }; + int64_t int_values3[] = { 47, 11, 42 }; double dec_values[] = { 12.3, 47.11, 64.0 }; + double dec_values2[] = { 12.3, 47.11 }; + double dec_values3[] = { 2.3, 47.11 }; char *string_values[] = { "foo", "bar", "qux", "baz" }; + char *string_values2[] = { "qux", "bar" }; + char *string_values3[] = { "foo", "bar", "qux", "baz", "bay" }; sdb_data_t int_array = { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } } }; + sdb_data_t int_array2 = { + SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, + { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } } + }; + sdb_data_t int_array3 = { + SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, + { .array = { SDB_STATIC_ARRAY_LEN(int_values3), int_values3 } } + }; sdb_data_t dec_array = { SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL, { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } } }; + sdb_data_t dec_array2 = { + SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL, + { .array = { SDB_STATIC_ARRAY_LEN(dec_values2), dec_values2 } } + }; + sdb_data_t dec_array3 = { + SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL, + { .array = { SDB_STATIC_ARRAY_LEN(dec_values3), dec_values3 } } + }; sdb_data_t string_array = { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } } }; + sdb_data_t string_array2 = { + SDB_TYPE_ARRAY | SDB_TYPE_STRING, + { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } } + }; + sdb_data_t string_array3 = { + SDB_TYPE_ARRAY | SDB_TYPE_STRING, + { .array = { SDB_STATIC_ARRAY_LEN(string_values3), string_values3 } } + }; struct { sdb_data_t value; @@ -756,8 +786,6 @@ START_TEST(test_inarray) { { SDB_TYPE_INTEGER, { .integer = 64 } }, int_array, 1 }, { { SDB_TYPE_INTEGER, { .integer = 65 } }, int_array, 0 }, { { SDB_TYPE_NULL, { .integer = 0 } }, int_array, 0 }, - { int_array, { SDB_TYPE_INTEGER, { .integer = 47 } }, 0 }, - { int_array, int_array, 0 }, { { SDB_TYPE_DECIMAL, { .decimal = 12.3 } }, dec_array, 1 }, { { SDB_TYPE_DECIMAL, { .decimal = 47.11 } }, dec_array, 1 }, { { SDB_TYPE_DECIMAL, { .decimal = 64.0 } }, dec_array, 1 }, @@ -773,6 +801,22 @@ START_TEST(test_inarray) { { SDB_TYPE_STRING, { .string = "ba" } }, string_array, 0 }, { { SDB_TYPE_STRING, { .string = "abc" } }, string_array, 0 }, { { SDB_TYPE_NULL, { .integer = 0 } }, string_array, 0 }, + { int_array, { SDB_TYPE_INTEGER, { .integer = 47 } }, 0 }, + { int_array, int_array, 1 }, + { int_array2, int_array, 1 }, + { int_array3, int_array, 0 }, + { dec_array2, int_array, 0 }, + { string_array2, int_array, 0 }, + { dec_array, dec_array, 1 }, + { dec_array2, dec_array, 1 }, + { dec_array3, dec_array, 0 }, + { int_array2, dec_array, 0 }, + { string_array2, dec_array, 0 }, + { string_array, string_array, 1 }, + { string_array2, string_array, 1 }, + { string_array3, string_array, 0 }, + { int_array2, string_array, 0 }, + { dec_array2, string_array, 0 }, }; size_t i; -- 2.30.2