Remove hard-coded precision for printing JSON float values
[fio.git] / json.c
diff --git a/json.c b/json.c
index 707ea141cba973e74455c41d3072b048f3b6f827..190fa9e0d73f7a6ffd23cf6c2db93d191c00b3ae 100644 (file)
--- a/json.c
+++ b/json.c
@@ -8,18 +8,12 @@
 
 struct json_object *json_create_object(void)
 {
-       struct json_object *obj = malloc(sizeof(struct json_object));
-       if (obj)
-               memset(obj, 0, sizeof(struct json_object));
-       return obj;
+       return calloc(1, sizeof(struct json_object));
 }
 
 struct json_array *json_create_array(void)
 {
-       struct json_array *array = malloc(sizeof(struct json_array));
-       if (array)
-               memset(array, 0, sizeof(struct json_array));
-       return array;
+       return calloc(1, sizeof(struct json_array));
 }
 
 static struct json_pair *json_create_pair(const char *name, struct json_value *value)
@@ -35,7 +29,7 @@ static struct json_pair *json_create_pair(const char *name, struct json_value *v
        return pair;
 }
 
-static struct json_value *json_create_value_int(long number)
+static struct json_value *json_create_value_int(long long number)
 {
        struct json_value *value = malloc(sizeof(struct json_value));
 
@@ -57,13 +51,42 @@ static struct json_value *json_create_value_float(float number)
        return value;
 }
 
+static char *strdup_escape(const char *str)
+{
+       const char *input = str;
+       char *p, *ret;
+       int escapes;
+
+       if (!strlen(str))
+               return NULL;
+
+       escapes = 0;
+       while ((input = strpbrk(input, "\\\"")) != NULL) {
+               escapes++;
+               input++;
+       }
+
+       p = ret = malloc(strlen(str) + escapes + 1);
+       while (*str) {
+               if (*str == '\\' || *str == '\"')
+                       *p++ = '\\';
+               *p++ = *str++;
+       }
+       *p = '\0';
+
+       return ret;
+}
+
+/*
+ * Valid JSON strings must escape '"' and '/' with a preceding '/'
+ */
 static struct json_value *json_create_value_string(const char *str)
 {
        struct json_value *value = malloc(sizeof(struct json_value));
 
        if (value) {
                value->type = JSON_TYPE_STRING;
-               value->string = strdup(str);
+               value->string = strdup_escape(str);
                if (!value->string) {
                        free(value);
                        value = NULL;
@@ -96,9 +119,9 @@ static struct json_value *json_create_value_array(struct json_array *array)
        return value;
 }
 
-static void json_free_array(struct json_array *array);
 static void json_free_pair(struct json_pair *pair);
 static void json_free_value(struct json_value *value);
+
 void json_free_object(struct json_object *obj)
 {
        int i;
@@ -183,7 +206,7 @@ int json_object_add_value_type(struct json_object *obj, const char *name, int ty
        if (type == JSON_TYPE_STRING)
                value = json_create_value_string(va_arg(args, char *));
        else if (type == JSON_TYPE_INTEGER)
-               value = json_create_value_int(va_arg(args, long));
+               value = json_create_value_int(va_arg(args, long long));
        else if (type == JSON_TYPE_FLOAT)
                value = json_create_value_float(va_arg(args, double));
        else if (type == JSON_TYPE_OBJECT)
@@ -208,7 +231,7 @@ int json_object_add_value_type(struct json_object *obj, const char *name, int ty
        return 0;
 }
 
-static void json_print_array(struct json_array *array);
+static void json_print_array(struct json_array *array, struct buf_output *);
 int json_array_add_value_type(struct json_array *array, int type, ...)
 {
        struct json_value *value;
@@ -219,7 +242,7 @@ int json_array_add_value_type(struct json_array *array, int type, ...)
        if (type == JSON_TYPE_STRING)
                value = json_create_value_string(va_arg(args, char *));
        else if (type == JSON_TYPE_INTEGER)
-               value = json_create_value_int(va_arg(args, long));
+               value = json_create_value_int(va_arg(args, long long));
        else if (type == JSON_TYPE_FLOAT)
                value = json_create_value_float(va_arg(args, double));
        else if (type == JSON_TYPE_OBJECT)
@@ -267,70 +290,70 @@ static int json_value_level(struct json_value *value)
                return json_array_level(value->parent_array) + 1;
 }
 
-static void json_print_level(int level)
+static void json_print_level(int level, struct buf_output *out)
 {
        while (level-- > 0)
-               log_info("  ");
+               log_buf(out, "  ");
 }
 
-static void json_print_pair(struct json_pair *pair);
-static void json_print_array(struct json_array *array);
-static void json_print_value(struct json_value *value);
-void json_print_object(struct json_object *obj)
+static void json_print_pair(struct json_pair *pair, struct buf_output *);
+static void json_print_array(struct json_array *array, struct buf_output *);
+static void json_print_value(struct json_value *value, struct buf_output *);
+void json_print_object(struct json_object *obj, struct buf_output *out)
 {
        int i;
 
-       log_info("{\n");
+       log_buf(out, "{\n");
        for (i = 0; i < obj->pair_cnt; i++) {
                if (i > 0)
-                       log_info(",\n");
-               json_print_pair(obj->pairs[i]);
+                       log_buf(out, ",\n");
+               json_print_pair(obj->pairs[i], out);
        }
-       log_info("\n");
-       json_print_level(json_object_level(obj));
-       log_info("}");
+       log_buf(out, "\n");
+       json_print_level(json_object_level(obj), out);
+       log_buf(out, "}");
 }
 
-static void json_print_pair(struct json_pair *pair)
+static void json_print_pair(struct json_pair *pair, struct buf_output *out)
 {
-       json_print_level(json_pair_level(pair));
-       log_info("\"%s\" : ", pair->name);
-       json_print_value(pair->value);
+       json_print_level(json_pair_level(pair), out);
+       log_buf(out, "\"%s\" : ", pair->name);
+       json_print_value(pair->value, out);
 }
 
-static void json_print_array(struct json_array *array)
+static void json_print_array(struct json_array *array, struct buf_output *out)
 {
        int i;
 
-       log_info("[\n");
+       log_buf(out, "[\n");
        for (i = 0; i < array->value_cnt; i++) {
                if (i > 0)
-                       log_info(",\n");
-               json_print_level(json_value_level(array->values[i]));
-               json_print_value(array->values[i]);
+                       log_buf(out, ",\n");
+               json_print_level(json_value_level(array->values[i]), out);
+               json_print_value(array->values[i], out);
        }
-       log_info("\n");
-       json_print_level(json_array_level(array));
-       log_info("]");
+       log_buf(out, "\n");
+       json_print_level(json_array_level(array), out);
+       log_buf(out, "]");
 }
 
-static void json_print_value(struct json_value *value)
+static void json_print_value(struct json_value *value, struct buf_output *out)
 {
        switch (value->type) {
        case JSON_TYPE_STRING:
-               log_info("\"%s\"", value->string);
+               log_buf(out, "\"%s\"", value->string);
                break;
        case JSON_TYPE_INTEGER:
-               log_info("%ld", value->integer_number);
+               log_buf(out, "%lld", value->integer_number);
                break;
        case JSON_TYPE_FLOAT:
-               log_info("%.2f", value->float_number);
+               log_buf(out, "%f", value->float_number);
                break;
        case JSON_TYPE_OBJECT:
-               json_print_object(value->object);
+               json_print_object(value->object, out);
                break;
        case JSON_TYPE_ARRAY:
-               json_print_array(value->array);
+               json_print_array(value->array, out);
                break;
        }
 }