From 69055716798ecc8fb1db3ccbbb1b059f3faf9a05 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sat, 8 Nov 2014 17:00:05 +0100 Subject: [PATCH] data: Added sdb_data_array_get(). This function retrieves an array element, returning an "alias" to its value. --- src/core/data.c | 37 ++++++++++++++++++++ src/include/core/data.h | 14 ++++++++ t/unit/core/data_test.c | 76 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/src/core/data.c b/src/core/data.c index 8754f88..a6cd092 100644 --- a/src/core/data.c +++ b/src/core/data.c @@ -650,6 +650,43 @@ sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array) return 0; } /* sdb_data_inarray */ +int +sdb_data_array_get(const sdb_data_t *array, size_t i, sdb_data_t *value) +{ + sdb_data_t tmp = SDB_DATA_INIT; + int type; + + if ((! array) || (! (array->type & SDB_TYPE_ARRAY))) + return -1; + if (i >= array->data.array.length) + return -1; + + type = array->type & 0xff; + if (type == SDB_TYPE_INTEGER) { + int64_t *v = array->data.array.values; + tmp.data.integer = v[i]; + } + else if (type == SDB_TYPE_DECIMAL) { + double *v = array->data.array.values; + tmp.data.decimal = v[i]; + } + else if (type == SDB_TYPE_STRING) { + char **v = array->data.array.values; + tmp.data.string = v[i]; + } + else { + /* TODO */ + errno = ENOTSUP; + return -1; + } + + if (value) { + *value = tmp; + value->type = type; + } + return 0; +} /* sdb_data_array_get */ + int sdb_data_parse_op(const char *op) { diff --git a/src/include/core/data.h b/src/include/core/data.h index cf4e27e..c03c0c1 100644 --- a/src/include/core/data.h +++ b/src/include/core/data.h @@ -173,6 +173,20 @@ sdb_data_isnull(const sdb_data_t *datum); _Bool sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array); +/* + * sdb_data_array_get: + * Get the i-th value stored in the specified array and store an alias in + * 'value'. Storing an alias means that the value points to the actual array + * element. Do *not* free the value after using it (i.e., don't use + * sdb_data_free_datum). + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_data_array_get(const sdb_data_t *array, size_t i, sdb_data_t *value); + /* * Operators supported by sdb_data_eval_expr. */ diff --git a/t/unit/core/data_test.c b/t/unit/core/data_test.c index a647e02..704ebdd 100644 --- a/t/unit/core/data_test.c +++ b/t/unit/core/data_test.c @@ -794,6 +794,81 @@ START_TEST(test_inarray) } END_TEST +START_TEST(test_array_get) +{ + 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 array; + size_t i; + sdb_data_t expected; + } golden_data[] = { + { int_array, 0, { SDB_TYPE_INTEGER, { .integer = 47 } } }, + { int_array, 1, { SDB_TYPE_INTEGER, { .integer = 11 } } }, + { int_array, 2, { SDB_TYPE_INTEGER, { .integer = 64 } } }, + { int_array, 3, { -1, { .integer = 0 } } }, + { dec_array, 0, { SDB_TYPE_DECIMAL, { .decimal = 12.3 } } }, + { dec_array, 1, { SDB_TYPE_DECIMAL, { .decimal = 47.11 } } }, + { dec_array, 2, { SDB_TYPE_DECIMAL, { .decimal = 64.0 } } }, + { dec_array, 3, { -1, { .integer = 0 } } }, + { string_array, 0, { SDB_TYPE_STRING, { .string = "foo" } } }, + { string_array, 1, { SDB_TYPE_STRING, { .string = "bar" } } }, + { string_array, 2, { SDB_TYPE_STRING, { .string = "qux" } } }, + { string_array, 3, { SDB_TYPE_STRING, { .string = "baz" } } }, + { string_array, 4, { -1, { .integer = 0 } } }, + { { SDB_TYPE_INTEGER, { .integer = 666 } }, 0, { -1, { .integer = 0 } } }, + { { SDB_TYPE_INTEGER, { .integer = 666 } }, 1, { -1, { .integer = 0 } } }, + }; + + size_t i; + + for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { + char a_str[1024] = "", v_str[1024] = "", exp_str[1024] = ""; + sdb_data_t value = SDB_DATA_INIT; + int check; + + sdb_data_format(&golden_data[i].array, + a_str, sizeof(a_str), SDB_UNQUOTED); + sdb_data_format(&golden_data[i].expected, + exp_str, sizeof(exp_str), SDB_UNQUOTED); + + check = sdb_data_array_get(&golden_data[i].array, + golden_data[i].i, &value); + + sdb_data_format(&value, v_str, sizeof(v_str), SDB_UNQUOTED); + + if (golden_data[i].expected.type < 0) { + fail_unless(check < 0, + "sdb_data_array_get(%s, %zu) = %d (%s); expected: <0", + a_str, golden_data[i].i, check, v_str); + continue; + } + + fail_unless(check == 0, + "sdb_data_array_get(%s, %zu) = %d; expected: 0", + a_str, golden_data[i].i, check); + fail_unless(! sdb_data_cmp(&value, &golden_data[i].expected), + "sdb_data_array_get(%s, %zu) -> '%s'; expected: '%s'", + a_str, golden_data[i].i, v_str, exp_str); + } +} +END_TEST + START_TEST(test_parse_op) { struct { @@ -1670,6 +1745,7 @@ core_data_suite(void) tcase_add_test(tc, test_cmp); tcase_add_test(tc, test_strcmp); tcase_add_test(tc, test_inarray); + tcase_add_test(tc, test_array_get); tcase_add_test(tc, test_parse_op); tcase_add_test(tc, test_expr_eval); tcase_add_test(tc, test_format); -- 2.30.2