Code

data: Return the number of bytes that would have been returned.
authorSebastian Harl <sh@tokkee.org>
Sat, 7 Mar 2015 13:01:17 +0000 (14:01 +0100)
committerSebastian Harl <sh@tokkee.org>
Sat, 7 Mar 2015 13:01:17 +0000 (14:01 +0100)
That is, behave as documented, even if the buffer is NULL or otherwise too
small. Return size_t instead of an integer.

src/core/data.c
src/core/store_json.c
src/core/store_lookup.c
src/include/core/data.h
t/unit/core/data_test.c
t/unit/utils/proto_test.c

index 9f2b506fbc1b76e66dd330be7879655a530871ba..914946fbec6761d3e7b4345742ddbd63668106c1 100644 (file)
@@ -681,9 +681,9 @@ sdb_data_strcmp(const sdb_data_t *d1, const sdb_data_t *d2)
 
        CMP_NULL(d1, d2);
 
-       if (sdb_data_format(d1, d1_str, sizeof(d1_str), SDB_UNQUOTED) < 0)
+       if (! sdb_data_format(d1, d1_str, sizeof(d1_str), SDB_UNQUOTED))
                return SDB_CMP(sizeof(d1_str), sizeof(d2_str));
-       if (sdb_data_format(d2, d2_str, sizeof(d2_str), SDB_UNQUOTED) < 0)
+       if (! sdb_data_format(d2, d2_str, sizeof(d2_str), SDB_UNQUOTED))
                return SDB_CMP(sizeof(d1_str), sizeof(d2_str));
 
        return strcasecmp(d1_str, d2_str);
@@ -918,18 +918,18 @@ sdb_data_strlen(const sdb_data_t *datum)
        return 0;
 } /* sdb_data_strlen */
 
-int
+size_t
 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;
-       int ret = -1;
+       size_t ret = 0;
 
        size_t i, pos;
 
-       if ((! datum) || (! buf) || (! buflen))
-               return -1;
+       if (! datum)
+               return 0;
 
        if (datum->type == SDB_TYPE_NULL) {
                strncpy(buf, "NULL", buflen);
@@ -1005,37 +1005,41 @@ sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted)
        }
        else if (datum->type & SDB_TYPE_ARRAY) {
                ret = 1;
-               buf[0] = '[';
+               if (buflen > 0)
+                       buf[0] = '[';
                for (i = 0; i < datum->data.array.length; ++i) {
                        sdb_data_t v = SDB_DATA_INIT;
-                       int n;
-                       if ((size_t)ret >= buflen - 1)
-                               break;
+                       size_t n;
 
                        if (ret > 1) {
-                               buf[ret] = ',';
-                               buf[ret + 1] = ' ';
+                               if (buflen > ret + 1) {
+                                       buf[ret] = ',';
+                                       buf[ret + 1] = ' ';
+                               }
                                ret += 2;
                        }
 
                        sdb_data_array_get(datum, i, &v);
-                       n = sdb_data_format(&v, buf + ret, buflen - ret, quoted);
+                       if (buflen > ret)
+                               n = sdb_data_format(&v, buf + ret, buflen - ret, quoted);
+                       else
+                               n = sdb_data_format(&v, NULL, 0, quoted);
                        if (n > 0)
                                ret += n;
                        else
                                break;
                }
-               if ((size_t)ret < buflen - 1) {
+               if (buflen > ret + 1) {
                        buf[ret] = ']';
                        buf[ret + 1] = '\0';
-                       ++ret;
                }
+               ++ret;
        }
 
        if (is_null) {
                /* never quote NULL */
                strncpy(buf, "NULL", buflen);
-               ret = (int)SDB_MIN(buflen, 4);
+               ret = 4;
        }
        else if (data) {
                if (quoted == SDB_UNQUOTED)
@@ -1045,7 +1049,8 @@ sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted)
                else
                        ret = snprintf(buf, buflen, "\"%s\"", data);
        }
-       buf[buflen - 1] = '\0';
+       if (buflen > 0)
+               buf[buflen - 1] = '\0';
        return ret;
 } /* sdb_data_format */
 
index f5be74543f32ed8bbee35b2cff6f95dba828d2e1..a772dc39c8f67549c8205a0f63527672b6edf473 100644 (file)
@@ -119,8 +119,8 @@ json_emit(sdb_store_json_formatter_t *f, sdb_store_obj_t *obj)
        if (obj->type == SDB_ATTRIBUTE) {
                char tmp[sdb_data_strlen(&ATTR(obj)->value) + 1];
                char val[2 * sizeof(tmp) + 3];
-               if (sdb_data_format(&ATTR(obj)->value, tmp, sizeof(tmp),
-                                       SDB_DOUBLE_QUOTED) < 0)
+               if (sdb_data_format(&ATTR(obj)->value, tmp, sizeof(tmp),
+                                       SDB_DOUBLE_QUOTED))
                        snprintf(tmp, sizeof(tmp), "<error>");
 
                if (tmp[0] == '"') {
index 5aa69152f237576cb4d2995e15c9a3c771b5b976..2e73780fbf8da67f51c7e040470d051668b20621 100644 (file)
@@ -142,7 +142,7 @@ match_regex_value(int op, sdb_data_t *v, sdb_data_t *re)
        else if (re->type != SDB_TYPE_REGEX)
                return 0;
 
-       if (sdb_data_format(v, value, sizeof(value), SDB_UNQUOTED) < 0)
+       if (! sdb_data_format(v, value, sizeof(value), SDB_UNQUOTED))
                status = 0;
        else if (! regexec(&re->data.re.regex, value, 0, NULL, 0))
                status = 1;
index c037fb00e2a1f8f91ea09d057b7a5064be2f91ca..e529fb9ceec24749aca3efdf8841bbc2dd073e23 100644 (file)
@@ -55,7 +55,8 @@ enum {
 };
 
 #define SDB_TYPE_TO_STRING(t) \
-       (((t) == SDB_TYPE_INTEGER) ? "INTEGER" \
+       (((t) == SDB_TYPE_NULL) ? "NULL" \
+               : ((t) == SDB_TYPE_INTEGER) ? "INTEGER" \
                : ((t) == SDB_TYPE_DECIMAL) ? "DECIMAL" \
                : ((t) == SDB_TYPE_STRING) ? "STRING" \
                : ((t) == SDB_TYPE_DATETIME) ? "DATETIME" \
@@ -289,9 +290,8 @@ enum {
  *  - the number of characters written to the buffer (excluding the terminated
  *    null byte) or the number of characters which would have been written in
  *    case the output was truncated
- *  - a negative value else
  */
-int
+size_t
 sdb_data_format(const sdb_data_t *datum, char *buf, size_t buflen, int quoted);
 
 /*
index 71dae2acbb65f673d011d935e562eba65243a495..cd76dff1c458f53994c7cff1383a9c14c5dd8115 100644 (file)
@@ -2032,6 +2032,10 @@ START_TEST(test_format)
                sdb_data_t datum;
                const char *expected;
        } golden_data[] = {
+               {
+                       { SDB_TYPE_NULL, { .integer = 0 } },
+                       "NULL",
+               },
                {
                        { SDB_TYPE_INTEGER, { .integer = 4711 } },
                        "4711",
@@ -2100,10 +2104,11 @@ START_TEST(test_format)
        for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
                sdb_data_t *datum = &golden_data[i].datum;
                char buf[sdb_data_strlen(datum) + 2];
-               int check;
+               size_t check_null, check;
 
                memset(buf, (int)'A', sizeof(buf));
 
+               check_null = sdb_data_format(datum, NULL, 0, SDB_DOUBLE_QUOTED);
                check = sdb_data_format(datum, buf, sizeof(buf) - 1,
                                SDB_DOUBLE_QUOTED);
                fail_unless(check > 0,
@@ -2113,7 +2118,17 @@ START_TEST(test_format)
                                "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
                                SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
 
-               fail_unless((size_t)check <= sizeof(buf) - 2,
+               fail_unless(check_null == check,
+                               "sdb_data_format(type=%s, NULL) = %d; "
+                               "expected %d (matching sdb_data_format(type=%s, <buf>))",
+                               SDB_TYPE_TO_STRING(datum->type), check_null,
+                               check, SDB_TYPE_TO_STRING(datum->type));
+               fail_unless(check == strlen(golden_data[i].expected),
+                               "sdb_data_format(type=%s) = %d; expected %zu (strlen)",
+                               SDB_TYPE_TO_STRING(datum->type), check,
+                               strlen(golden_data[i].expected));
+
+               fail_unless(check <= sizeof(buf) - 2,
                                "sdb_data_format(type=%s) wrote %d bytes; "
                                "expected <= %zu based on sdb_data_strlen()",
                                SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
index 01b63502bd5bab44c68cbcea7c6f5577fd63a418..e7e8d44cca4730959a5cccbf720e3298d5adc345 100644 (file)
@@ -163,7 +163,7 @@ START_TEST(test_marshal_data)
                sdb_data_t datum = SDB_DATA_INIT;
                ssize_t check;
 
-               if (sdb_data_format(&golden_data[i].datum, v1, sizeof(v1), 0) < 0)
+               if (! sdb_data_format(&golden_data[i].datum, v1, sizeof(v1), 0))
                        snprintf(v1, sizeof(v1), "<ERR>");
 
                fail_unless(len == golden_data[i].expected_len,
@@ -189,7 +189,7 @@ START_TEST(test_marshal_data)
                }
 
                check = sdb_proto_unmarshal_data(buf, len, &datum);
-               if (sdb_data_format(&datum, v2, sizeof(v2), 0) < 0)
+               if (! sdb_data_format(&datum, v2, sizeof(v2), 0))
                        snprintf(v2, sizeof(v2), "<ERR>");
 
                if (sdb_data_isnull(&golden_data[i].datum))
@@ -499,7 +499,7 @@ START_TEST(test_marshal_attribute)
                                        pos, (int)buf[pos], (int)golden_data[i].expected[pos]);
                }
 
-               if (sdb_data_format(&golden_data[i].attr.value, v1, sizeof(v1), 0) < 0)
+               if (! sdb_data_format(&golden_data[i].attr.value, v1, sizeof(v1), 0))
                        snprintf(v1, sizeof(v1), "<ERR>");
 
                check = sdb_proto_unmarshal_attribute(buf, len, &attr);
@@ -507,7 +507,7 @@ START_TEST(test_marshal_attribute)
                                "<%zu> sdb_proto_unmarshal_attribute(buf<%s>) = %zi; expected: %zi",
                                i, golden_data[i].attr.key, check, len);
 
-               if (sdb_data_format(&attr.value, v2, sizeof(v2), 0) < 0)
+               if (! sdb_data_format(&attr.value, v2, sizeof(v2), 0))
                        snprintf(v2, sizeof(v2), "<ERR>");
                fail_unless((attr.last_update == golden_data[i].attr.last_update)
                                && (attr.parent_type == golden_data[i].attr.parent_type)