respondd modules: Use proper formatting of doubles

Most doubles that are delivered via respondd have limited input
precision, but are converted with up to 17 digits of precision. That can
cause ugly blowups like 0.2800000000000001 in the output, which is
avoided by specifying better format strings (like "%.2f" in most cases).
This commit is contained in:
Jan-Philipp Litza 2016-05-06 16:49:00 +02:00
parent 4c09783723
commit f7eda9381f
5 changed files with 130 additions and 7 deletions

View File

@ -501,7 +501,9 @@ static struct json_object * get_batadv(void) {
struct json_object *obj = json_object_new_object();
json_object_object_add(obj, "tq", json_object_new_int(tq));
json_object_object_add(obj, "lastseen", json_object_new_double(lastseen));
struct json_object *jso = json_object_new_double(lastseen);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.3f", NULL);
json_object_object_add(obj, "lastseen", jso);
json_object_object_add(interface, mac1, obj);
}

View File

@ -192,7 +192,9 @@ static bool get_peer_connection(struct json_object **ret, struct json_object *co
int64_t established_time = json_object_get_int64(established);
*ret = json_object_new_object();
json_object_object_add(*ret, "established", json_object_new_double(established_time/1000.0));
struct json_object *jso = json_object_new_double(established_time/1000.0);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.3f", NULL);
json_object_object_add(*ret, "established", jso);
}
else {
*ret = NULL;

View File

@ -64,7 +64,9 @@ static struct json_object * get_number(struct uci_context *ctx, struct uci_secti
if (*end)
return NULL;
return json_object_new_double(d);
struct json_object *jso = json_object_new_double(d);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.8f", NULL);
return jso;
}
static struct json_object * get_location(struct uci_context *ctx, struct uci_package *p) {

View File

@ -107,13 +107,18 @@ static struct json_object * respondd_provider_nodeinfo(void) {
static void add_uptime(struct json_object *obj) {
FILE *f = fopen("/proc/uptime", "r");
struct json_object* jso;
if (!f)
return;
double uptime, idletime;
if (fscanf(f, "%lf %lf", &uptime, &idletime) == 2) {
json_object_object_add(obj, "uptime", json_object_new_double(uptime));
json_object_object_add(obj, "idletime", json_object_new_double(idletime));
jso = json_object_new_double(uptime);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
json_object_object_add(obj, "uptime", jso);
jso = json_object_new_double(idletime);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
json_object_object_add(obj, "idletime", jso);
}
fclose(f);
@ -127,7 +132,9 @@ static void add_loadavg(struct json_object *obj) {
double loadavg;
unsigned proc_running, proc_total;
if (fscanf(f, "%lf %*f %*f %u/%u", &loadavg, &proc_running, &proc_total) == 3) {
json_object_object_add(obj, "loadavg", json_object_new_double(loadavg));
struct json_object *jso = json_object_new_double(loadavg);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.2f", NULL);
json_object_object_add(obj, "loadavg", jso);
struct json_object *processes = json_object_new_object();
json_object_object_add(processes, "running", json_object_new_int(proc_running));
@ -176,7 +183,9 @@ static struct json_object * get_rootfs_usage(void) {
if (statfs("/", &s))
return NULL;
return json_object_new_double(1 - (double)s.f_bfree / s.f_blocks);
struct json_object *jso = json_object_new_double(1 - (double)s.f_bfree / s.f_blocks);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.4f", NULL);
return jso;
}
static struct json_object * respondd_provider_statistics(void) {

View File

@ -0,0 +1,108 @@
From: Jan-Philipp Litza <janphilipp@litza.de>
Date: Fri, 6 May 2016 16:44:29 +0200
Subject: libjson-c: Add support for custom format strings for doubles
diff --git a/package/libs/libjson-c/patches/002-custom-format-string.patch b/package/libs/libjson-c/patches/002-custom-format-string.patch
new file mode 100644
index 0000000..2f454c5
--- /dev/null
+++ b/package/libs/libjson-c/patches/002-custom-format-string.patch
@@ -0,0 +1,98 @@
+From 21dc5dc92bd56f5f4dc2c90b9ea6bf1e1407714e Mon Sep 17 00:00:00 2001
+From: Jan-Philipp Litza <janphilipp@litza.de>
+Date: Fri, 6 May 2016 16:12:44 +0200
+Subject: [PATCH] Export json_object_double_to_json_string() and use custom
+ format string
+BCC: janphilipp@litza.de
+
+---
+ json_object.c | 12 ++++++------
+ json_object.h | 28 ++++++++++++++++++++++++++++
+ 2 files changed, 34 insertions(+), 6 deletions(-)
+
+diff --git a/json_object.c b/json_object.c
+index 7d60884..46701e7 100644
+--- a/json_object.c
++++ b/json_object.c
+@@ -55,7 +55,6 @@ static struct json_object* json_object_new(enum json_type o_type);
+ static json_object_to_json_string_fn json_object_object_to_json_string;
+ static json_object_to_json_string_fn json_object_boolean_to_json_string;
+ static json_object_to_json_string_fn json_object_int_to_json_string;
+-static json_object_to_json_string_fn json_object_double_to_json_string;
+ static json_object_to_json_string_fn json_object_string_to_json_string;
+ static json_object_to_json_string_fn json_object_array_to_json_string;
+
+@@ -644,10 +643,10 @@ int64_t json_object_get_int64(const struct json_object *jso)
+
+ /* json_object_double */
+
+-static int json_object_double_to_json_string(struct json_object* jso,
+- struct printbuf *pb,
+- int level,
+- int flags)
++int json_object_double_to_json_string(struct json_object* jso,
++ struct printbuf *pb,
++ int level,
++ int flags)
+ {
+ char buf[128], *p, *q;
+ int size;
+@@ -663,7 +662,8 @@ static int json_object_double_to_json_string(struct json_object* jso,
+ else
+ size = snprintf(buf, sizeof(buf), "-Infinity");
+ else
+- size = snprintf(buf, sizeof(buf), "%.17g", jso->o.c_double);
++ size = snprintf(buf, sizeof(buf),
++ jso->_userdata ? (const char*) jso->_userdata : "%.17g", jso->o.c_double);
+
+ p = strchr(buf, ',');
+ if (p) {
+diff --git a/json_object.h b/json_object.h
+index 2bce454..a89de44 100644
+--- a/json_object.h
++++ b/json_object.h
+@@ -614,6 +614,9 @@ extern int64_t json_object_get_int64(const struct json_object *obj);
+ /* double type methods */
+
+ /** Create a new empty json_object of type json_type_double
++ *
++ * @see json_object_double_to_json_string() for how to set a custom format string.
++ *
+ * @param d the double
+ * @returns a json_object of type json_type_double
+ */
+@@ -642,6 +645,31 @@ extern struct json_object* json_object_new_double(double d);
+ */
+ extern struct json_object* json_object_new_double_s(double d, const char *ds);
+
++
++/** Serialize a json_object of type json_type_double to a string.
++ *
++ * This function isn't meant to be called directly. Instead, you can set a
++ * custom format string for the serialization of this double using the
++ * following call (where "%.17g" actually is the default):
++ *
++ * @code
++ * jso = json_object_new_double(d);
++ * json_object_set_serializer(jso, json_object_double_to_json_string,
++ * "%.17g", NULL);
++ * @endcode
++ *
++ * @see printf(3) man page for format strings
++ *
++ * @param jso The json_type_double object that is serialized.
++ * @param pb The destination buffer.
++ * @param level Ignored.
++ * @param flags Ignored.
++ */
++extern int json_object_double_to_json_string(struct json_object* jso,
++ struct printbuf *pb,
++ int level,
++ int flags);
++
+ /** Get the double floating point value of a json_object
+ *
+ * The type is coerced to a double if the passed object is not a double.
+--
+2.7.4
+