X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fcore%2Fdata.c;h=4e0fd779580f9dd734bf1211dc2769ca326a179f;hp=1bb5400028223c89eca2f9a10e7ee3e81cc5cb03;hb=39a45905e0b237e458b1826ff9b4fad1c4a59550;hpb=3cc3e3c36239c902263678100180c95c8263f7f8 diff --git a/src/core/data.c b/src/core/data.c index 1bb5400..4e0fd77 100644 --- a/src/core/data.c +++ b/src/core/data.c @@ -25,10 +25,15 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + #include "core/data.h" #include +#include #include #include @@ -85,48 +90,112 @@ sdb_data_free_datum(sdb_data_t *datum) } } /* sdb_data_free_datum */ +size_t +sdb_data_strlen(sdb_data_t *datum) +{ + if (! datum) + return 0; + + switch (datum->type) { + case SDB_TYPE_INTEGER: + /* log(64) */ + return 20; + case SDB_TYPE_DECIMAL: + /* XXX: -0xN.NNNNNNp+NNN */ + return 42; + case SDB_TYPE_STRING: + if (! datum->data.string) + return 6; /* "NULL" */ + /* in the worst case, each character needs to be escaped */ + return 2 * strlen(datum->data.string) + 2; + case SDB_TYPE_DATETIME: + /* "YYYY-MM-DD HH:MM:SS +zzzz" */ + return 27; + case SDB_TYPE_BINARY: + /* "\xNN" */ + return 4 * datum->data.binary.length + 2; + } + return 0; +} /* sdb_data_strlen */ + int -sdb_data_format(sdb_data_t *datum, sdb_strbuf_t *buf) +sdb_data_format(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: - sdb_strbuf_append(buf, "%"PRIi64, datum->data.integer); + ret = snprintf(buf, buflen, "%"PRIi64, datum->data.integer); break; case SDB_TYPE_DECIMAL: - sdb_strbuf_append(buf, "%a", datum->data.decimal); + ret = snprintf(buf, buflen, "%a", datum->data.decimal); break; case SDB_TYPE_STRING: - /* TODO: escape special characters */ - sdb_strbuf_append(buf, "\"%s\"", datum->data.string); + if (! datum->data.string) + data = "NULL"; + else { + pos = 0; + for (i = 0; i < strlen(datum->data.string); ++i) { + char byte = datum->data.string[i]; + + if ((byte == '\\') || (byte == '"')) { + tmp[pos] = '\\'; + ++pos; + } + tmp[pos] = byte; + ++pos; + } + tmp[pos] = '\0'; + 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'; - sdb_strbuf_append(buf, "%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: - { - size_t i; - /* TODO: improve this! */ - sdb_strbuf_append(buf, "%s", "\""); - for (i = 0; i < datum->data.binary.length; ++i) - sdb_strbuf_append(buf, "\\%x", - (int)datum->data.binary.datum[i]); - sdb_strbuf_append(buf, "%s", "\""); + 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; + + if (byte > 0xf) { + tmp[pos] = hex[byte >> 4]; + ++pos; + } + tmp[pos] = hex[byte & 0xf]; + ++pos; } + tmp[pos] = '\0'; + data = tmp; break; - default: - return -1; } - return 0; + + 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 ret; } /* sdb_data_format */ /* vim: set tw=78 sw=4 ts=4 noexpandtab : */