mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
spa: add locale independent spa_dtoa
And use this in spa_json_format_float() where we also avoid invalid json floats. Use json float format in some places where we serialize json floats. Add a unit test. See #2223
This commit is contained in:
parent
5f4d031db0
commit
2b16df4e89
6 changed files with 40 additions and 13 deletions
|
|
@ -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);
|
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;
|
if (SPA_UNLIKELY(!isnormal(val))) {
|
||||||
l = snprintf(str, size, "%f", val);
|
if (val == INFINITY)
|
||||||
for (i = 0; i < l; i++)
|
val = FLT_MAX;
|
||||||
if (str[i] == ',')
|
else if (val == -INFINITY)
|
||||||
str[i] = '.';
|
val = FLT_MIN;
|
||||||
return str;
|
else
|
||||||
|
val = 0.0f;
|
||||||
|
}
|
||||||
|
return spa_dtoa(str, size, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* int */
|
/* int */
|
||||||
|
|
|
||||||
|
|
@ -354,6 +354,16 @@ static inline bool spa_atod(const char *str, double *val)
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \}
|
* \}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -695,7 +695,7 @@ static int parse_prop_params(struct impl *this, struct spa_pod *params)
|
||||||
while (true) {
|
while (true) {
|
||||||
const char *name;
|
const char *name;
|
||||||
struct spa_pod *pod;
|
struct spa_pod *pod;
|
||||||
char value[512];
|
char value[512], buf[128];
|
||||||
|
|
||||||
if (spa_pod_parser_get_string(&prs, &name) < 0)
|
if (spa_pod_parser_get_string(&prs, &name) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
@ -706,8 +706,9 @@ static int parse_prop_params(struct impl *this, struct spa_pod *params)
|
||||||
if (spa_pod_is_string(pod)) {
|
if (spa_pod_is_string(pod)) {
|
||||||
spa_pod_copy_string(pod, sizeof(value), value);
|
spa_pod_copy_string(pod, sizeof(value), value);
|
||||||
} else if (spa_pod_is_float(pod)) {
|
} else if (spa_pod_is_float(pod)) {
|
||||||
snprintf(value, sizeof(value), "%f",
|
snprintf(value, sizeof(value), "%s",
|
||||||
SPA_POD_VALUE(struct spa_pod_float, pod));
|
spa_json_format_float(buf, sizeof(buf),
|
||||||
|
SPA_POD_VALUE(struct spa_pod_float, pod)));
|
||||||
} else if (spa_pod_is_int(pod)) {
|
} else if (spa_pod_is_int(pod)) {
|
||||||
snprintf(value, sizeof(value), "%d",
|
snprintf(value, sizeof(value), "%d",
|
||||||
SPA_POD_VALUE(struct spa_pod_int, pod));
|
SPA_POD_VALUE(struct spa_pod_int, pod));
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
size_t size;
|
size_t size;
|
||||||
char key[1024];
|
char key[1024], buf[128];
|
||||||
|
|
||||||
spa_zero(map);
|
spa_zero(map);
|
||||||
spa_zero(vol);
|
spa_zero(vol);
|
||||||
|
|
@ -260,7 +260,8 @@ static int do_extension_stream_restore_write(struct client *client, uint32_t com
|
||||||
if (vol.channels > 0) {
|
if (vol.channels > 0) {
|
||||||
fprintf(f, ", \"volumes\": [");
|
fprintf(f, ", \"volumes\": [");
|
||||||
for (i = 0; i < vol.channels; i++)
|
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, " ]");
|
fprintf(f, " ]");
|
||||||
}
|
}
|
||||||
if (map.channels > 0) {
|
if (map.channels > 0) {
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,7 @@ static void put_double(struct data *d, const char *key, double val)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
put_fmt(d, key, "%s%s%s", NUMBER,
|
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)
|
static void put_value(struct data *d, const char *key, const char *val)
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,7 @@ PWTEST(json_float)
|
||||||
};
|
};
|
||||||
float v;
|
float v;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
char buf1[128], buf2[128], *b1 = buf1, *b2 = buf2;
|
||||||
|
|
||||||
pwtest_int_eq(spa_json_parse_float("", 0, &v), 0);
|
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_int_gt(spa_json_parse_float(val[i].str, strlen(val[i].str), &v), 0);
|
||||||
pwtest_double_eq(v, val[i].val);
|
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;
|
return PWTEST_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue