X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fcore%2Fdata.c;h=2381636092ceb03b7d4ef25ae8c9935ec3300583;hb=863ebc4bdd91758a2f7d20e846f10f61df2ad409;hp=4e0fd779580f9dd734bf1211dc2769ca326a179f;hpb=39a45905e0b237e458b1826ff9b4fad1c4a59550;p=sysdb.git diff --git a/src/core/data.c b/src/core/data.c index 4e0fd77..2381636 100644 --- a/src/core/data.c +++ b/src/core/data.c @@ -29,7 +29,12 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include "sysdb.h" + #include "core/data.h" +#include "utils/error.h" + +#include #include @@ -65,6 +70,7 @@ sdb_data_copy(sdb_data_t *dst, const sdb_data_t *src) break; } + sdb_data_free_datum(dst); *dst = tmp; return 0; } /* sdb_data_copy */ @@ -90,8 +96,62 @@ sdb_data_free_datum(sdb_data_t *datum) } } /* sdb_data_free_datum */ +int +sdb_data_cmp(const sdb_data_t *d1, const sdb_data_t *d2) +{ +#define CMP_NULL(a, b) \ + do { \ + if (!(a) && !(b)) return 0; \ + if (!(a)) return -1; \ + if (!(b)) return 1; \ + } while (0) + + CMP_NULL(d1, d2); + + if (d1->type != d2->type) + return -1; + + switch (d1->type) { + case SDB_TYPE_INTEGER: + return SDB_CMP(d1->data.integer, d2->data.integer); + case SDB_TYPE_DECIMAL: + return SDB_CMP(d1->data.decimal, d2->data.decimal); + case SDB_TYPE_STRING: + CMP_NULL(d1->data.string, d2->data.string); + return strcasecmp(d1->data.string, d2->data.string); + case SDB_TYPE_DATETIME: + return SDB_CMP(d1->data.datetime, d2->data.datetime); + case SDB_TYPE_BINARY: + { + int diff; + + CMP_NULL(d1->data.binary.datum, d2->data.binary.datum); + + /* on a common prefix, the shorter datum sorts less */ + if (d1->data.binary.length < d2->data.binary.length) { + diff = memcmp(d1->data.binary.datum, d2->data.binary.datum, + d1->data.binary.length); + diff = diff ? diff : -1; + } + else if (d1->data.binary.length > d2->data.binary.length) { + diff = memcmp(d1->data.binary.datum, d2->data.binary.datum, + d2->data.binary.length); + diff = diff ? diff : 1; + } + else + diff = memcmp(d1->data.binary.datum, d2->data.binary.datum, + d1->data.binary.length); + + return diff; + } + default: + return -1; + } +#undef CMP_NULL +} /* sdb_data_cmp */ + size_t -sdb_data_strlen(sdb_data_t *datum) +sdb_data_strlen(const sdb_data_t *datum) { if (! datum) return 0; @@ -119,7 +179,7 @@ sdb_data_strlen(sdb_data_t *datum) } /* sdb_data_strlen */ int -sdb_data_format(sdb_data_t *datum, char *buf, size_t buflen, int quoted) +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; @@ -198,5 +258,61 @@ sdb_data_format(sdb_data_t *datum, char *buf, size_t buflen, int quoted) return ret; } /* sdb_data_format */ +int +sdb_data_parse(char *str, int type, sdb_data_t *data) +{ + sdb_data_t tmp; + + char *endptr = NULL; + + errno = 0; + switch (type) { + case SDB_TYPE_INTEGER: + tmp.data.integer = strtoll(str, &endptr, 0); + break; + case SDB_TYPE_DECIMAL: + tmp.data.decimal = strtod(str, &endptr); + break; + case SDB_TYPE_STRING: + tmp.data.string = str; + break; + case SDB_TYPE_DATETIME: + { + double datetime = strtod(str, &endptr); + tmp.data.datetime = DOUBLE_TO_SDB_TIME(datetime); + } + break; + case SDB_TYPE_BINARY: + /* we don't support any binary information containing 0-bytes */ + tmp.data.binary.length = strlen(str); + tmp.data.binary.datum = (unsigned char *)str; + break; + default: + errno = EINVAL; + return -1; + } + + if ((type == SDB_TYPE_INTEGER) || (type == SDB_TYPE_DECIMAL) + || (type == SDB_TYPE_DATETIME)) { + if (errno || (str == endptr)) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "core: Failed to parse string " + "'%s' as numeric value (type %i): %s", str, type, + sdb_strerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + else if (endptr && (*endptr != '\0')) + sdb_log(SDB_LOG_WARNING, "core: Ignoring garbage after " + "number while parsing numeric value (type %i): %s.", + type, endptr); + } + + if (data) { + *data = tmp; + data->type = type; + } + return 0; +} /* sdb_data_parse */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */