X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fcore%2Fdata.c;h=dc2d0ae8afde4dbb741bc2525444fddad05ed0a8;hp=a0c2be11014d7de81b6aa1e12f9e31a39871f595;hb=56b97a180a53aecbfe9f7162b8ece3faae973cf9;hpb=e990840022affb61add5682b7a60ba6dba89fbf2 diff --git a/src/core/data.c b/src/core/data.c index a0c2be1..dc2d0ae 100644 --- a/src/core/data.c +++ b/src/core/data.c @@ -25,6 +25,10 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + #include "core/data.h" #include @@ -86,8 +90,64 @@ sdb_data_free_datum(sdb_data_t *datum) } } /* sdb_data_free_datum */ +int +sdb_data_cmp(sdb_data_t *d1, 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; + +#define CMP(a, b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0) + switch (d1->type) { + case SDB_TYPE_INTEGER: + return CMP(d1->data.integer, d2->data.integer); + case SDB_TYPE_DECIMAL: + return 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 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 +#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; @@ -115,28 +175,28 @@ sdb_data_strlen(sdb_data_t *datum) } /* sdb_data_strlen */ int -sdb_data_format(sdb_data_t *datum, char *buf, size_t buflen) +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; + int ret = -1; + + size_t i, pos; + if ((! datum) || (! buf)) return -1; switch (datum->type) { case SDB_TYPE_INTEGER: - snprintf(buf, buflen, "%"PRIi64, datum->data.integer); + ret = snprintf(buf, buflen, "%"PRIi64, datum->data.integer); break; case SDB_TYPE_DECIMAL: - snprintf(buf, buflen, "%a", datum->data.decimal); + ret = snprintf(buf, buflen, "%a", datum->data.decimal); break; case SDB_TYPE_STRING: - if (! datum->data.string) { - strncpy(buf, "\"NULL\"", buflen); - buf[buflen - 1] = '\0'; - return 0; - } - { - char tmp[2 * strlen(datum->data.string) + 1]; - size_t i, pos; - + if (! datum->data.string) + data = "NULL"; + else { pos = 0; for (i = 0; i < strlen(datum->data.string); ++i) { char byte = datum->data.string[i]; @@ -149,50 +209,49 @@ sdb_data_format(sdb_data_t *datum, char *buf, size_t buflen) ++pos; } tmp[pos] = '\0'; - snprintf(buf, buflen, "\"%s\"", tmp); + data = tmp; } break; case SDB_TYPE_DATETIME: - { - char tmp[64]; - if (! sdb_strftime(tmp, sizeof(tmp), "%F %T %z", - datum->data.datetime)) - return -1; - tmp[sizeof(tmp) - 1] = '\0'; - snprintf(buf, buflen, "\"%s\"", tmp); - } + if (! sdb_strftime(tmp, sizeof(tmp), "%F %T %z", + datum->data.datetime)) + return -1; + tmp[sizeof(tmp) - 1] = '\0'; + data = tmp; break; case SDB_TYPE_BINARY: - { - char tmp[4 * datum->data.binary.length + 1]; - size_t i, pos; + pos = 0; + for (i = 0; i < datum->data.binary.length; ++i) { + int byte = (int)datum->data.binary.datum[i]; + char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - pos = 0; - for (i = 0; i < datum->data.binary.length; ++i) { - int byte = (int)datum->data.binary.datum[i]; - char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + tmp[pos] = '\\'; + tmp[pos + 1] = 'x'; + pos += 2; - tmp[pos] = '\\'; - tmp[pos + 1] = 'x'; - pos += 2; - - if (byte > 0xf) { - tmp[pos] = hex[byte >> 4]; - ++pos; - } - tmp[pos] = hex[byte & 0xf]; + if (byte > 0xf) { + tmp[pos] = hex[byte >> 4]; ++pos; } - tmp[pos] = '\0'; - snprintf(buf, buflen, "\"%s\"", tmp); + tmp[pos] = hex[byte & 0xf]; + ++pos; } + tmp[pos] = '\0'; + data = tmp; break; - default: - return -1; + } + + if (data) { + if (quoted == SDB_UNQUOTED) + ret = snprintf(buf, buflen, "%s", data); + else if (quoted == SDB_SINGLE_QUOTED) + ret = snprintf(buf, buflen, "'%s'", data); + else + ret = snprintf(buf, buflen, "\"%s\"", data); } buf[buflen - 1] = '\0'; - return 0; + return ret; } /* sdb_data_format */ /* vim: set tw=78 sw=4 ts=4 noexpandtab : */