diff --git a/src/core/data.c b/src/core/data.c
index 27c7aa1452de6aaaeb09f47c5ccd4ea1ee018415..d34a4dd711250041cd26d463575535bd70522f4a 100644 (file)
--- a/src/core/data.c
+++ b/src/core/data.c
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
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);
else
return -1;
- assert(s1 && s2);
-
new = malloc(len1 + len2 + 1);
if (! new)
return -1;
#undef CMP_NULL
} /* sdb_data_strcmp */
-_Bool
+bool
sdb_data_isnull(const sdb_data_t *datum)
{
if (! datum)
return 0;
} /* sdb_data_isnull */
-_Bool
+bool
sdb_data_inarray(const sdb_data_t *value, const sdb_data_t *array)
{
- size_t i;
+ const void *values;
+ size_t length, i;
+ int type = value->type & 0xff;
if (sdb_data_isnull(value) || sdb_data_isnull(array))
return 0;
- if ((value->type & SDB_TYPE_ARRAY) || (! (array->type & SDB_TYPE_ARRAY)))
+ if (! (array->type & SDB_TYPE_ARRAY))
return 0;
- if (value->type != (array->type & 0xff))
+ if ((value->type & 0xff) != (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;
+ if (value->type & SDB_TYPE_ARRAY) {
+ values = value->data.array.values;
+ length = value->data.array.length;
}
else {
- /* TODO */
- errno = ENOTSUP;
- return 0;
+ values = &value->data;
+ length = 1;
}
- return 0;
+
+ for (i = 0; i < length; ++i) {
+ size_t j;
+
+ if (type == SDB_TYPE_INTEGER) {
+ int64_t *v = array->data.array.values;
+ for (j = 0; j < array->data.array.length; ++j)
+ if (((const int64_t *)values)[i] == v[j])
+ break;
+ }
+ else if (type == SDB_TYPE_DECIMAL) {
+ double *v = array->data.array.values;
+ for (j = 0; j < array->data.array.length; ++j)
+ if (((const double *)values)[i] == v[j])
+ break;
+ }
+ else if (type == SDB_TYPE_STRING) {
+ char **v = array->data.array.values;
+ for (j = 0; j < array->data.array.length; ++j)
+ if (!strcasecmp(((const char * const*)values)[i], v[j]))
+ break;
+ }
+ else {
+ /* TODO */
+ errno = ENOTSUP;
+ return 0;
+ }
+
+ if (j >= array->data.array.length)
+ /* value not found */
+ return 0;
+ }
+ return 1;
} /* sdb_data_inarray */
int
{
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;
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)
@@ -942,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);
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);