diff --git a/spa/include/spa/utils/json.h b/spa/include/spa/utils/json.h index 8303d4a3e..ef44800bb 100644 --- a/spa/include/spa/utils/json.h +++ b/spa/include/spa/utils/json.h @@ -258,14 +258,17 @@ static inline int spa_json_get_float(struct spa_json *iter, float *res) return spa_json_parse_float(value, len, res); } -static inline char *spa_json_format_double(char *str, int size, const double val) +static inline char *spa_json_format_float(char *str, int size, float val) { - int i, l; - l = snprintf(str, size, "%f", val); - for (i = 0; i < l; i++) - if (str[i] == ',') - str[i] = '.'; - return str; + if (SPA_UNLIKELY(!isnormal(val))) { + if (val == INFINITY) + val = FLT_MAX; + else if (val == -INFINITY) + val = FLT_MIN; + else + val = 0.0f; + } + return spa_dtoa(str, size, val); } /* int */ diff --git a/spa/include/spa/utils/string.h b/spa/include/spa/utils/string.h index d8d68657a..080536050 100644 --- a/spa/include/spa/utils/string.h +++ b/spa/include/spa/utils/string.h @@ -354,6 +354,16 @@ static inline bool spa_atod(const char *str, double *val) return true; } +static inline char *spa_dtoa(char *str, size_t size, double val) +{ + int i, l; + l = spa_scnprintf(str, size, "%f", val); + for (i = 0; i < l; i++) + if (str[i] == ',') + str[i] = '.'; + return str; +} + /** * \} */ diff --git a/spa/plugins/audioconvert/channelmix.c b/spa/plugins/audioconvert/channelmix.c index f49f7c353..3fb46beb9 100644 --- a/spa/plugins/audioconvert/channelmix.c +++ b/spa/plugins/audioconvert/channelmix.c @@ -695,7 +695,7 @@ static int parse_prop_params(struct impl *this, struct spa_pod *params) while (true) { const char *name; struct spa_pod *pod; - char value[512]; + char value[512], buf[128]; if (spa_pod_parser_get_string(&prs, &name) < 0) break; @@ -706,8 +706,9 @@ static int parse_prop_params(struct impl *this, struct spa_pod *params) if (spa_pod_is_string(pod)) { spa_pod_copy_string(pod, sizeof(value), value); } else if (spa_pod_is_float(pod)) { - snprintf(value, sizeof(value), "%f", - SPA_POD_VALUE(struct spa_pod_float, pod)); + snprintf(value, sizeof(value), "%s", + spa_json_format_float(buf, sizeof(buf), + SPA_POD_VALUE(struct spa_pod_float, pod))); } else if (spa_pod_is_int(pod)) { snprintf(value, sizeof(value), "%d", SPA_POD_VALUE(struct spa_pod_int, pod)); diff --git a/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c b/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c index 2524687f4..76c73325c 100644 --- a/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c +++ b/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c @@ -235,7 +235,7 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com FILE *f; char *ptr; size_t size; - char key[1024]; + char key[1024], buf[128]; spa_zero(map); spa_zero(vol); @@ -260,7 +260,8 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com if (vol.channels > 0) { fprintf(f, ", \"volumes\": ["); for (i = 0; i < vol.channels; i++) - fprintf(f, "%s%f", (i == 0 ? " ":", "), vol.values[i]); + fprintf(f, "%s%s", (i == 0 ? " ":", "), + spa_json_format_float(buf, sizeof(buf), vol.values[i])); fprintf(f, " ]"); } if (map.channels > 0) { diff --git a/src/tools/pw-dump.c b/src/tools/pw-dump.c index 659361409..b60ef49f1 100644 --- a/src/tools/pw-dump.c +++ b/src/tools/pw-dump.c @@ -280,7 +280,7 @@ static void put_double(struct data *d, const char *key, double val) { char buf[128]; put_fmt(d, key, "%s%s%s", NUMBER, - spa_json_format_double(buf, sizeof(buf), val), NORMAL); + spa_json_format_float(buf, sizeof(buf), val), NORMAL); } static void put_value(struct data *d, const char *key, const char *val) diff --git a/test/test-spa-json.c b/test/test-spa-json.c index 1fd6a83f0..b5dedf749 100644 --- a/test/test-spa-json.c +++ b/test/test-spa-json.c @@ -247,6 +247,7 @@ PWTEST(json_float) }; float v; unsigned i; + char buf1[128], buf2[128], *b1 = buf1, *b2 = buf2; pwtest_int_eq(spa_json_parse_float("", 0, &v), 0); @@ -260,6 +261,17 @@ PWTEST(json_float) pwtest_int_gt(spa_json_parse_float(val[i].str, strlen(val[i].str), &v), 0); pwtest_double_eq(v, val[i].val); } + pwtest_ptr_eq(spa_json_format_float(buf1, sizeof(buf1), 0.0f), b1); + pwtest_str_eq(buf1, "0.000000"); + pwtest_ptr_eq(spa_json_format_float(buf1, sizeof(buf1), NAN), b1); + pwtest_str_eq(buf1, "0.000000"); + pwtest_ptr_eq(spa_json_format_float(buf1, sizeof(buf1), INFINITY), b1); + pwtest_ptr_eq(spa_json_format_float(buf2, sizeof(buf2), FLT_MAX), b2); + pwtest_str_eq(buf1, buf2); + pwtest_ptr_eq(spa_json_format_float(buf1, sizeof(buf1), -INFINITY), b1); + pwtest_ptr_eq(spa_json_format_float(buf2, sizeof(buf2), FLT_MIN), b2); + pwtest_str_eq(buf1, buf2); + return PWTEST_PASS; }