]> git.ipfire.org Git - thirdparty/json-c.git/commitdiff
PR#394: don't always append the ".0" if the double value rounds to zero because some...
authorEric Haszlakiewicz <erh+git@nimenees.com>
Sun, 24 Dec 2017 18:45:52 +0000 (13:45 -0500)
committerEric Haszlakiewicz <erh+git@nimenees.com>
Sun, 24 Dec 2017 18:45:52 +0000 (13:45 -0500)
Also try to accomodate formats to explicitly exclude the decimal (e.g. %.0f).

json_object.c
tests/test_double_serializer.c
tests/test_double_serializer.expected

index 4d6e2e79df90a48f90abca2bb14b470cd8e11d94..52e8b76a7c59d37a6f8c0b99fc3ac0ec0c8f7f81 100644 (file)
@@ -15,6 +15,7 @@
 #include "strerror_override.h"
 
 #include <assert.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
@@ -790,7 +791,6 @@ static int json_object_double_to_json_string_format(struct json_object* jso,
 {
        char buf[128], *p, *q;
        int size;
-       double dummy; /* needed for modf() */
        /* Although JSON RFC does not support
        NaN or Infinity as numeric values
        ECMA 262 section 9.8.1 defines
@@ -810,44 +810,60 @@ static int json_object_double_to_json_string_format(struct json_object* jso,
        {
                const char *std_format = "%.17g";
 
+               if (!format)
+               {
 #if defined(HAVE___THREAD)
-               if (tls_serialization_float_format)
-                       std_format = tls_serialization_float_format;
-               else
+                       if (tls_serialization_float_format)
+                               format = tls_serialization_float_format;
+                       else
 #endif
-               if (global_serialization_float_format)
-                       std_format = global_serialization_float_format;
-               if (!format)
-                       format = std_format;
+                       if (global_serialization_float_format)
+                               format = global_serialization_float_format;
+                       else
+                               format = std_format;
+               }
                size = snprintf(buf, sizeof(buf), format, jso->o.c_double);
-               if (modf(jso->o.c_double, &dummy) == 0  && size >= 0 && size < (int)sizeof(buf) - 2)
+
+               if (size < 0)
+                       return -1;
+
+               p = strchr(buf, ',');
+               if (p)
+                       *p = '.';
+               else
+                       p = strchr(buf, '.');
+
+               int format_drops_decimals = 0;
+               if (format == std_format || strstr(format, ".0f") == NULL)
+                       format_drops_decimals = 1;
+
+               if (size < (int)sizeof(buf) - 2 &&
+                   isdigit((int)buf[0]) && /* Looks like *some* kind of number */
+                       !p && /* Has no decimal point */
+                   strchr(buf, 'e') == NULL && /* Not scientific notation */
+                       format_drops_decimals)
                {
-                       // Ensure it looks like a float, even if snprintf didn't.
+                       // Ensure it looks like a float, even if snprintf didn't,
+                       //  unless a custom format is set to omit the decimal.
                        strcat(buf, ".0");
                        size += 2;
                }
+               if (p && (flags & JSON_C_TO_STRING_NOZERO))
+               {
+                       /* last useful digit, always keep 1 zero */
+                       p++;
+                       for (q=p ; *q ; q++) {
+                               if (*q!='0') p=q;
+                       }
+                       /* drop trailing zeroes */
+                       *(++p) = 0;
+                       size = p-buf;
+               }
        }
        // although unlikely, snprintf can fail
        if (size < 0)
                return -1;
 
-       p = strchr(buf, ',');
-       if (p)
-               *p = '.';
-       else
-               p = strchr(buf, '.');
-       if (p && (flags & JSON_C_TO_STRING_NOZERO))
-       {
-               /* last useful digit, always keep 1 zero */
-               p++;
-               for (q=p ; *q ; q++) {
-                       if (*q!='0') p=q;
-               }
-               /* drop trailing zeroes */
-               *(++p) = 0;
-               size = p-buf;
-       }
-
        if (size >= (int)sizeof(buf))
                // The standard formats are guaranteed not to overrun the buffer,
                // but if a custom one happens to do so, just silently truncate.
index c7b229ebdc955c2eb320c398ec2b02e1f4b8397f..0f7a60ea742e50f68ec641094237462baff8818a 100644 (file)
@@ -54,4 +54,24 @@ int main()
        printf("obj.to_string(back to default format)=%s\n", json_object_to_json_string(obj));
 
        json_object_put(obj);
+
+       obj = json_object_new_double(12.0);
+       printf("obj(12.0).to_string(default format)=%s\n", json_object_to_json_string(obj));
+       if (json_c_set_serialization_double_format("%.0f", JSON_C_OPTION_GLOBAL) < 0)
+               printf("ERROR: json_c_set_serialization_double_format() failed");
+       printf("obj(12.0).to_string(%%.0f)=%s\n", json_object_to_json_string(obj));
+
+       if (json_c_set_serialization_double_format("%.0g", JSON_C_OPTION_GLOBAL) < 0)
+               printf("ERROR: json_c_set_serialization_double_format() failed");
+       printf("obj(12.0).to_string(%%.0g)=%s\n", json_object_to_json_string(obj));
+
+       if (json_c_set_serialization_double_format("%.2g", JSON_C_OPTION_GLOBAL) < 0)
+               printf("ERROR: json_c_set_serialization_double_format() failed");
+       printf("obj(12.0).to_string(%%.1g)=%s\n", json_object_to_json_string(obj));
+
+       // Reset to default to free memory
+       if (json_c_set_serialization_double_format(NULL, JSON_C_OPTION_GLOBAL) < 0)
+               printf("ERROR: json_c_set_serialization_double_format() failed");
+
+       json_object_put(obj);
 }
index cd5f02b8736f4a822ce181cbfd10bc556abfa89e..98eea1e13b9021db72157a837932d4a2dcf33f26 100644 (file)
@@ -12,3 +12,7 @@ obj.to_string(with thread format)=T0.52X
 obj.to_string(long thread format)=Ttttttttttttt0.52xxxxxxxxxxxxxxxxxxX
 obj.to_string(back to global format)=x0.524y
 obj.to_string(back to default format)=0.52381
+obj(12.0).to_string(default format)=12.0
+obj(12.0).to_string(%.0f)=12
+obj(12.0).to_string(%.0g)=1e+01
+obj(12.0).to_string(%.1g)=12.0