Code

data: Added sdb_data_inarray().
authorSebastian Harl <sh@tokkee.org>
Tue, 21 Oct 2014 05:25:37 +0000 (07:25 +0200)
committerSebastian Harl <sh@tokkee.org>
Tue, 21 Oct 2014 05:25:37 +0000 (07:25 +0200)
The function determines whether a value is included in an array.

src/core/data.c
src/include/core/data.h
t/unit/core/data_test.c

index 22d9ba36bb80e12b0a0870446573075c09999bd3..1f3aa82a42a641fad531c6b682363c51813af168 100644 (file)
@@ -541,6 +541,44 @@ sdb_data_isnull(const sdb_data_t *datum)
        return 0;
 } /* sdb_data_isnull */
 
        return 0;
 } /* sdb_data_isnull */
 
+_Bool
+sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array)
+{
+       size_t i;
+
+       if (sdb_data_isnull(value) || sdb_data_isnull(array))
+               return 0;
+       if ((value->type & SDB_TYPE_ARRAY) || (! (array->type & SDB_TYPE_ARRAY)))
+               return 0;
+       if (value->type != (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;
+       }
+       else {
+               /* TODO */
+               errno = ENOTSUP;
+               return 0;
+       }
+       return 0;
+} /* sdb_data_inarray */
+
 int
 sdb_data_parse_op(const char *op)
 {
 int
 sdb_data_parse_op(const char *op)
 {
index cfdf48db8ea7d63fd1c2ef718901706bd10ca2e0..7ff111c1f17395218874a5d954b554cc39d02628 100644 (file)
@@ -157,6 +157,15 @@ sdb_data_strcmp(const sdb_data_t *d1, const sdb_data_t *d2);
 _Bool
 sdb_data_isnull(const sdb_data_t *datum);
 
 _Bool
 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.
+ */
+_Bool
+sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array);
+
 /*
  * Operators supported by sdb_data_eval_expr.
  */
 /*
  * Operators supported by sdb_data_eval_expr.
  */
index a41a3c2a5c584f0eaca5911e6dae1ecd7ac616e8..5c10c59f7693c465b49db2ae5544568f8566634b 100644 (file)
@@ -727,6 +727,73 @@ START_TEST(test_strcmp)
 }
 END_TEST
 
 }
 END_TEST
 
+START_TEST(test_inarray)
+{
+       int64_t int_values[] = { 47, 11, 64 };
+       double dec_values[] = { 12.3, 47.11, 64.0 };
+       char *string_values[] = { "foo", "bar", "qux", "baz" };
+
+       sdb_data_t int_array = {
+               SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+               { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } }
+       };
+       sdb_data_t dec_array = {
+               SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
+               { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } }
+       };
+       sdb_data_t string_array = {
+               SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+               { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } }
+       };
+
+       struct {
+               sdb_data_t value;
+               sdb_data_t array;
+               _Bool expected;
+       } golden_data[] = {
+               { { SDB_TYPE_INTEGER, { .integer = 47    } }, int_array,    1 },
+               { { SDB_TYPE_INTEGER, { .integer = 11    } }, int_array,    1 },
+               { { 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 },
+               { { SDB_TYPE_DECIMAL, { .decimal = 60.0  } }, dec_array,    0 },
+               { { SDB_TYPE_INTEGER, { .integer = 64    } }, dec_array,    0 },
+               { { SDB_TYPE_NULL,    { .integer = 0     } }, dec_array,    0 },
+               { { SDB_TYPE_STRING,  { .string  = "Foo" } }, string_array, 1 },
+               { { SDB_TYPE_STRING,  { .string  = "FOO" } }, string_array, 1 },
+               { { SDB_TYPE_STRING,  { .string  = "foo" } }, string_array, 1 },
+               { { SDB_TYPE_STRING,  { .string  = "bar" } }, string_array, 1 },
+               { { SDB_TYPE_STRING,  { .string  = "qux" } }, string_array, 1 },
+               { { SDB_TYPE_STRING,  { .string  = "baz" } }, string_array, 1 },
+               { { SDB_TYPE_STRING,  { .string  = "ba"  } }, string_array, 0 },
+               { { SDB_TYPE_STRING,  { .string  = "abc" } }, string_array, 0 },
+               { { SDB_TYPE_NULL,    { .integer = 0     } }, string_array, 0 },
+       };
+
+       size_t i;
+
+       for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+               char v_str[1024] = "", a_str[1024] = "";
+               _Bool check;
+
+               sdb_data_format(&golden_data[i].value,
+                               v_str, sizeof(v_str), SDB_UNQUOTED);
+               sdb_data_format(&golden_data[i].array,
+                               a_str, sizeof(a_str), SDB_UNQUOTED);
+
+               check = sdb_data_inarray(&golden_data[i].value, &golden_data[i].array);
+               fail_unless(check == golden_data[i].expected,
+                               "sdb_data_inarray(%s, %s) = %d; expected: %d",
+                               v_str, a_str, check, golden_data[i].expected);
+       }
+}
+END_TEST
+
 START_TEST(test_parse_op)
 {
        struct {
 START_TEST(test_parse_op)
 {
        struct {
@@ -1353,6 +1420,7 @@ core_data_suite(void)
        tcase_add_test(tc, test_data);
        tcase_add_test(tc, test_cmp);
        tcase_add_test(tc, test_strcmp);
        tcase_add_test(tc, test_data);
        tcase_add_test(tc, test_cmp);
        tcase_add_test(tc, test_strcmp);
+       tcase_add_test(tc, test_inarray);
        tcase_add_test(tc, test_parse_op);
        tcase_add_test(tc, test_expr_eval);
        tcase_add_test(tc, test_format);
        tcase_add_test(tc, test_parse_op);
        tcase_add_test(tc, test_expr_eval);
        tcase_add_test(tc, test_format);