X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcore%2Fdata.c;h=d34a4dd711250041cd26d463575535bd70522f4a;hb=47a1228872b3df692d8b17b7b85d1a863faf4fd7;hp=88c7f8246953d58f1af76a01a04e1919eb96f8c2;hpb=30b45eeb6c56e6ffca79910c9dd67977e2a41c6d;p=sysdb.git diff --git a/src/core/data.c b/src/core/data.c index 88c7f82..d34a4dd 100644 --- a/src/core/data.c +++ b/src/core/data.c @@ -166,6 +166,34 @@ free_array_values(sdb_data_t *datum) v[i] = NULL; } } + else if (type == SDB_TYPE_BINARY) { + struct { + size_t length; + unsigned char *datum; + } *v = datum->data.array.values; + size_t i; + + for (i = 0; i < datum->data.array.length; ++i) { + if (v[i].datum) + free(v[i].datum); + v[i].datum = NULL; + } + } + else if (type == SDB_TYPE_REGEX) { + struct { + char *raw; + regex_t regex; + } *v = datum->data.array.values; + size_t i; + + for (i = 0; i < datum->data.array.length; ++i) { + if (v[i].raw) { + free(v[i].raw); + regfree(&v[i].regex); + } + v[i].raw = NULL; + } + } } /* free_array_values */ /* compare two arrays element-by-element returning how the first non-equal @@ -206,9 +234,61 @@ array_cmp(const sdb_data_t *a1, const sdb_data_t *a2) return diff; } } + else if (type == SDB_TYPE_DATETIME) { + sdb_time_t *v1 = a1->data.array.values; + sdb_time_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_BINARY) { + struct { + size_t length; + unsigned char *datum; + } *v1 = a1->data.array.values; + struct { + size_t length; + unsigned char *datum; + } *v2 = a2->data.array.values; + + for (i = 0; i < len; ++i) { + int diff; + + /* on a common prefix, the shorter datum sorts less */ + if (v1[i].length < v2[i].length) { + diff = memcmp(v1[i].datum, v2[i].datum, v1[i].length); + diff = diff ? diff : -1; + } + else if (v1[i].length > v2[i].length) { + diff = memcmp(v1[i].datum, v2[i].datum, v2[i].length); + diff = diff ? diff : 1; + } + else + diff = memcmp(v1[i].datum, v2[i].datum, v1[i].length); + + if (diff) + return diff; + } + } + else if (type == SDB_TYPE_REGEX) { + struct { + char *raw; + regex_t regex; + } *v1 = a1->data.array.values; + struct { + char *raw; + regex_t regex; + } *v2 = a2->data.array.values; + + for (i = 0; i < len; ++i) { + int diff = strcasecmp(v1[i].raw, v2[i].raw); + if (diff) + return diff; + } + } else { - /* TODO */ - errno = ENOTSUP; + errno = EINVAL; /* but fall through to ensure stable sorting: */ } return SDB_CMP(a1->data.array.length, a2->data.array.length); @@ -390,8 +470,6 @@ data_concat(const sdb_data_t *d1, const sdb_data_t *d2, sdb_data_t *res) else return -1; - assert(s1 && s2); - new = malloc(len1 + len2 + 1); if (! new) return -1; @@ -612,7 +690,7 @@ sdb_data_strcmp(const sdb_data_t *d1, const sdb_data_t *d2) #undef CMP_NULL } /* sdb_data_strcmp */ -_Bool +bool sdb_data_isnull(const sdb_data_t *datum) { if (! datum) @@ -628,7 +706,7 @@ sdb_data_isnull(const sdb_data_t *datum) return 0; } /* sdb_data_isnull */ -_Bool +bool sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array) { const void *values; @@ -841,7 +919,7 @@ sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted) { char tmp[sdb_data_strlen(datum) + 1]; char *data = NULL; - _Bool is_null = 0; + bool is_null = 0; int ret = -1; size_t i, pos; @@ -853,7 +931,10 @@ sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted) ret = snprintf(buf, buflen, "%"PRIi64, datum->data.integer); } else if (datum->type == SDB_TYPE_DECIMAL) { - ret = snprintf(buf, buflen, "%g", datum->data.decimal); + if (isnan(datum->data.decimal)) + ret = snprintf(buf, buflen, "nan"); + else + ret = snprintf(buf, buflen, "%g", datum->data.decimal); } else if (datum->type == SDB_TYPE_STRING) { if (! datum->data.string) @@ -961,12 +1042,17 @@ sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted) } /* sdb_data_format */ int -sdb_data_parse(char *str, int type, sdb_data_t *data) +sdb_data_parse(const char *str, int type, sdb_data_t *data) { sdb_data_t tmp; char *endptr = NULL; + if (! str) { + errno = EINVAL; + return -1; + } + errno = 0; if (type == SDB_TYPE_INTEGER) { tmp.data.integer = strtoll(str, &endptr, 0); @@ -975,16 +1061,20 @@ sdb_data_parse(char *str, int type, sdb_data_t *data) tmp.data.decimal = strtod(str, &endptr); } else if (type == SDB_TYPE_STRING) { - tmp.data.string = str; + tmp.data.string = strdup(str); + if (! tmp.data.string) + return -1; } else if (type == SDB_TYPE_DATETIME) { double datetime = strtod(str, &endptr); tmp.data.datetime = DOUBLE_TO_SDB_TIME(datetime); } else if (type == SDB_TYPE_BINARY) { - /* we don't support any binary information containing 0-bytes */ + /* we don't support any binary information containing 0-bytes here */ + tmp.data.binary.datum = (unsigned char *)strdup(str); + if (! tmp.data.binary.datum) + return -1; tmp.data.binary.length = strlen(str); - tmp.data.binary.datum = (unsigned char *)str; } else if (type == SDB_TYPE_REGEX) { tmp.data.re.raw = strdup(str);