summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 2486840)
raw | patch | inline | side by side (parent: 2486840)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 5 Oct 2014 18:43:24 +0000 (20:43 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 5 Oct 2014 18:43:24 +0000 (20:43 +0200) |
This function compares the string values of two data points.
src/core/data.c | patch | blob | history | |
src/include/core/data.h | 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 48ca6b0bd74b9a4507c5a86b1c161d066d0f2cf7..57326fe9c00e8746c3e8e2476f780469813b87e2 100644 (file)
--- a/src/core/data.c
+++ b/src/core/data.c
return diff;
}
- default:
- return -1;
}
-#undef CMP_NULL
+ return -1;
} /* sdb_data_cmp */
+int
+sdb_data_strcmp(const sdb_data_t *d1, const sdb_data_t *d2)
+{
+ char d1_str[sdb_data_strlen(d1) + 1];
+ char d2_str[sdb_data_strlen(d2) + 1];
+
+ if (sdb_data_isnull(d1))
+ d1 = NULL;
+ if (sdb_data_isnull(d2))
+ d2 = NULL;
+
+ CMP_NULL(d1, d2);
+
+ if (sdb_data_format(d1, d1_str, sizeof(d1_str), SDB_UNQUOTED) < 0)
+ return SDB_CMP(sizeof(d1_str), sizeof(d2_str));
+ if (sdb_data_format(d2, d2_str, sizeof(d2_str), SDB_UNQUOTED) < 0)
+ return SDB_CMP(sizeof(d1_str), sizeof(d2_str));
+
+ return strcasecmp(d1_str, d2_str);
+#undef CMP_NULL
+} /* sdb_data_strcmp */
+
_Bool
sdb_data_isnull(const sdb_data_t *datum)
{
index af4ae5abb7e0d6f25c83e2d7856f90b9b17cd9ee..1bd0d5354e652656b891d0178cdf5030bf4992ec 100644 (file)
--- a/src/include/core/data.h
+++ b/src/include/core/data.h
int
sdb_data_cmp(const sdb_data_t *d1, const sdb_data_t *d2);
+/*
+ * sdb_data_strcmp:
+ * Compare the string values of two data points. A NULL datum is considered
+ * less than any non-NULL. This function works for arbitrary combination of
+ * data-types.
+ *
+ * Returns:
+ * - a value less than zero if d1 compares less than d2
+ * - zero if d1 compares equal to d2
+ * - a value greater than zero if d1 compares greater than d2
+ */
+int
+sdb_data_strcmp(const sdb_data_t *d1, const sdb_data_t *d2);
+
/*
* sdb_data_isnull:
* Determine whether a datum is NULL. A datum is considered to be NULL if
index 484d59c64f9f10920648b027bac69dfa8002954a..12944fceb147a13acfd3b7e0f073253a5cf4c89f 100644 (file)
--- a/t/unit/core/data_test.c
+++ b/t/unit/core/data_test.c
END_TEST
START_TEST(test_cmp)
+{
+ struct {
+ sdb_data_t d1;
+ sdb_data_t d2;
+ int expected;
+ } golden_data[] = {
+ /* same data as for the sdb_data_cmp test; in case the types match,
+ * both functions should behave the same (except for some loss in
+ * precision, e.g. when formatting datetime values) */
+ {
+ { SDB_TYPE_INTEGER, { .integer = 47 } },
+ { SDB_TYPE_INTEGER, { .integer = 4711 } },
+ -1,
+ },
+ {
+ { SDB_TYPE_INTEGER, { .integer = 4711 } },
+ { SDB_TYPE_INTEGER, { .integer = 4711 } },
+ 0,
+ },
+ {
+ { SDB_TYPE_INTEGER, { .integer = 4711 } },
+ { SDB_TYPE_INTEGER, { .integer = 47 } },
+ 1,
+ },
+ {
+ { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
+ { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
+ -1,
+ },
+ {
+ { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
+ { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
+ 0,
+ },
+ {
+ { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
+ { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
+ 1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = NULL } },
+ { SDB_TYPE_STRING, { .string = "" } },
+ -1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = NULL } },
+ { SDB_TYPE_STRING, { .string = NULL } },
+ 0,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "" } },
+ { SDB_TYPE_STRING, { .string = NULL } },
+ 1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "a" } },
+ { SDB_TYPE_STRING, { .string = "b" } },
+ -1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "a" } },
+ { SDB_TYPE_STRING, { .string = "ab" } },
+ -1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "a" } },
+ { SDB_TYPE_STRING, { .string = "a" } },
+ 0,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "b" } },
+ { SDB_TYPE_STRING, { .string = "a" } },
+ 1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "ab" } },
+ { SDB_TYPE_STRING, { .string = "a" } },
+ 1,
+ },
+ {
+ { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
+ { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
+ -1,
+ },
+ {
+ { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
+ { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
+ 0,
+ },
+ {
+ { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
+ { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
+ 1,
+ },
+ {
+ { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
+ { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
+ -1,
+ },
+ {
+ { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
+ { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
+ 0,
+ },
+ {
+ { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
+ { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
+ 1,
+ },
+ {
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0a" } },
+ },
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0b" } },
+ },
+ -1,
+ },
+ {
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 1, (unsigned char *)"a" } },
+ },
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0\0" } },
+ },
+ -1,
+ },
+ {
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0a" } },
+ },
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0a" } },
+ },
+ 0,
+ },
+ {
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0b" } },
+ },
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0a" } },
+ },
+ 1,
+ },
+ {
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 3, (unsigned char *)"a\0\0" } },
+ },
+ {
+ SDB_TYPE_BINARY,
+ { .binary = { 1, (unsigned char *)"a" } },
+ },
+ 1,
+ },
+ /* type mismatches */
+ {
+ { SDB_TYPE_INTEGER, { .integer = 123 } },
+ { SDB_TYPE_STRING, { .string = "123" } },
+ 0,
+ },
+ {
+ { SDB_TYPE_INTEGER, { .integer = 120 } },
+ { SDB_TYPE_STRING, { .string = "123" } },
+ -1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "123" } },
+ { SDB_TYPE_INTEGER, { .integer = 120 } },
+ 1,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "12.3" } },
+ { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
+ 0,
+ },
+ {
+ { SDB_TYPE_STRING, { .string = "12.0" } },
+ { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
+ -1,
+ },
+ {
+ { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
+ { SDB_TYPE_STRING, { .string = "12.0" } },
+ 1,
+ },
+ };
+
+ size_t i;
+
+ for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+ int check = sdb_data_strcmp(&golden_data[i].d1, &golden_data[i].d2);
+ check = check < 0 ? -1 : check > 0 ? 1 : 0;
+ if (check != golden_data[i].expected) {
+ char d1_str[64] = "", d2_str[64] = "";
+ sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
+ SDB_DOUBLE_QUOTED);
+ sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
+ SDB_DOUBLE_QUOTED);
+ fail("sdb_data_strcmp(%s, %s) = %d; expected: %d",
+ d1_str, d2_str, check, golden_data[i].expected);
+ }
+ }
+}
+END_TEST
+
+START_TEST(test_strcmp)
{
struct {
sdb_data_t d1;
tc = tcase_create("core");
tcase_add_test(tc, test_data);
tcase_add_test(tc, test_cmp);
+ tcase_add_test(tc, test_strcmp);
tcase_add_test(tc, test_expr_eval);
tcase_add_test(tc, test_format);
tcase_add_test(tc, test_parse);