summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e597f78)
raw | patch | inline | side by side (parent: e597f78)
author | Sebastian Harl <sh@tokkee.org> | |
Mon, 20 Oct 2014 07:44:16 +0000 (09:44 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Mon, 20 Oct 2014 07:44:16 +0000 (09:44 +0200) |
Array comparison works element-by-element, returning how the first non-equal
elements compare to each other.
Added tests for array comparison and concatenation.
elements compare to each other.
Added tests for array comparison and concatenation.
src/core/data.c | patch | blob | history | |
t/unit/core/data_test.c | patch | blob | history |
diff --git a/src/core/data.c b/src/core/data.c
index 1baeadafc2dfb79e65c933964e3111f157f36cca..22d9ba36bb80e12b0a0870446573075c09999bd3 100644 (file)
--- a/src/core/data.c
+++ b/src/core/data.c
}
} /* free_array_values */
+/* compare two arrays element-by-element returning how the first non-equal
+ * elements compare to each other */
+static int
+array_cmp(const sdb_data_t *a1, const sdb_data_t *a2)
+{
+ int type = a1->type & 0xff;
+ size_t len, i;
+
+ assert((a1->type == a2->type) && (a1->type & SDB_TYPE_ARRAY));
+
+ len = SDB_MIN(a1->data.array.length, a2->data.array.length);
+
+ if (type == SDB_TYPE_INTEGER) {
+ int64_t *v1 = a1->data.array.values;
+ int64_t *v2 = a2->data.array.values;
+
+ for (i = 0; i < len; ++i)
+ if (v1[i] != v2[i])
+ return SDB_CMP(v1[i], v2[i]);
+ }
+ else if (type == SDB_TYPE_DECIMAL) {
+ double *v1 = a1->data.array.values;
+ double *v2 = a2->data.array.values;
+
+ for (i = 0; i < len; ++i)
+ if (v1[i] != v2[i])
+ return SDB_CMP(v1[i], v2[i]);
+ }
+ else if (type == SDB_TYPE_STRING) {
+ char **v1 = a1->data.array.values;
+ char **v2 = a2->data.array.values;
+
+ for (i = 0; i < len; ++i) {
+ int diff = strcasecmp(v1[i], v2[i]);
+ if (diff)
+ return diff;
+ }
+ }
+ else {
+ /* TODO */
+ errno = ENOTSUP;
+ /* but fall through to ensure stable sorting: */
+ }
+ return SDB_CMP(a1->data.array.length, a2->data.array.length);
+} /* array_cmp */
+
/* Calculate the linear function 'd1 + n * d2'. */
static int
data_lin(const sdb_data_t *d1, int n, const sdb_data_t *d2, sdb_data_t *res)
return strcmp(d1->data.re.raw, d2->data.re.raw);
}
else if (d1->type & SDB_TYPE_ARRAY) {
- /* TODO */
- errno = ENOTSUP;
- return -1;
+ CMP_NULL(d1->data.array.values, d2->data.array.values);
+ return array_cmp(d1, d2);
}
return -1;
} /* sdb_data_cmp */
index 56c6649afd7fd13d779bdbcd1050c8d768ea4f01..a41a3c2a5c584f0eaca5911e6dae1ecd7ac616e8 100644 (file)
--- a/t/unit/core/data_test.c
+++ b/t/unit/core/data_test.c
START_TEST(test_cmp)
{
+ int64_t int_values1[] = { 1, 2, 3 };
+ int64_t int_values2[] = { 1, 3, 2 };
+ char *string_values1[] = { "a", "b", "c" };
+ char *string_values2[] = { "a", "c", "b" };
+
struct {
sdb_data_t d1;
sdb_data_t d2;
{ SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
1,
},
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
+ },
+ 0,
+ },
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
+ },
+ -1,
+ },
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
+ },
+ 1,
+ },
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
+ },
+ 0,
+ },
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
+ },
+ -1,
+ },
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
+ },
+ 1,
+ },
};
size_t i;
{
sdb_data_t err = { -1, { .integer = 0 } };
+ int64_t int_values[] = { 47, 11, 23 };
+ int64_t expected_int_concat[] = { 47, 11, 23, 47, 11, 23 };
+ char *string_values[] = { "foo", "bar", "qux" "baz" };
+ char *expected_string_concat[] =
+ { "foo", "bar", "qux" "baz", "foo", "bar", "qux" "baz" };
+
struct {
sdb_data_t d1;
sdb_data_t d2;
err,
err,
},
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
+ },
+ err,
+ err,
+ err,
+ err,
+ err,
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
+ { .array = {
+ SDB_STATIC_ARRAY_LEN(expected_int_concat),
+ expected_int_concat
+ } },
+ },
+ },
+ {
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
+ },
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
+ },
+ err,
+ err,
+ err,
+ err,
+ err,
+ {
+ SDB_TYPE_ARRAY | SDB_TYPE_STRING,
+ { .array = {
+ SDB_STATIC_ARRAY_LEN(expected_string_concat),
+ expected_string_concat
+ } },
+ },
+ },
{
{ SDB_TYPE_NULL, { .integer = 0 } },
{ SDB_TYPE_NULL, { .integer = 0 } },