mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-10-04 15:10:20 +00:00
json: add locale independent parse and format functions
Use them in pw-dump. Add some unit tests. See #2223
This commit is contained in:
parent
947d15a60a
commit
93b5d440bc
|
@ -34,6 +34,7 @@ extern "C" {
|
|||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <spa/utils/defs.h>
|
||||
|
||||
|
@ -237,9 +238,16 @@ static inline bool spa_json_is_null(const char *val, int len)
|
|||
static inline int spa_json_parse_float(const char *val, int len, float *result)
|
||||
{
|
||||
char *end;
|
||||
*result = strtof(val, &end);
|
||||
static locale_t locale = NULL;
|
||||
if (SPA_UNLIKELY(locale == NULL))
|
||||
locale = newlocale(LC_ALL_MASK, "C", NULL);
|
||||
if (locale != NULL)
|
||||
*result = strtof_l(val, &end, locale);
|
||||
else
|
||||
*result = strtof(val, &end);
|
||||
return len > 0 && end == val + len;
|
||||
}
|
||||
|
||||
static inline bool spa_json_is_float(const char *val, int len)
|
||||
{
|
||||
float dummy;
|
||||
|
@ -254,6 +262,16 @@ 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)
|
||||
{
|
||||
int i, l;
|
||||
l = snprintf(str, size, "%f", val);
|
||||
for (i = 0; i < l; i++)
|
||||
if (str[i] == ',')
|
||||
str[i] = '.';
|
||||
return str;
|
||||
}
|
||||
|
||||
/* int */
|
||||
static inline int spa_json_parse_int(const char *val, int len, int *result)
|
||||
{
|
||||
|
|
|
@ -278,13 +278,15 @@ static void put_int(struct data *d, const char *key, int64_t val)
|
|||
|
||||
static void put_double(struct data *d, const char *key, double val)
|
||||
{
|
||||
put_fmt(d, key, "%s%f%s", NUMBER, val, NORMAL);
|
||||
char buf[128];
|
||||
put_fmt(d, key, "%s%s%s", NUMBER,
|
||||
spa_json_format_double(buf, sizeof(buf), val), NORMAL);
|
||||
}
|
||||
|
||||
static void put_value(struct data *d, const char *key, const char *val)
|
||||
{
|
||||
int64_t li;
|
||||
double dv;
|
||||
float fv;
|
||||
|
||||
if (val == NULL)
|
||||
put_literal(d, key, "null");
|
||||
|
@ -292,8 +294,8 @@ static void put_value(struct data *d, const char *key, const char *val)
|
|||
put_literal(d, key, val);
|
||||
else if (spa_atoi64(val, &li, 10))
|
||||
put_int(d, key, li);
|
||||
else if (spa_atod(val, &dv))
|
||||
put_double(d, key, dv);
|
||||
else if (spa_json_parse_float(val, strlen(val), &fv))
|
||||
put_double(d, key, fv);
|
||||
else
|
||||
put_string(d, key, val);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "pwtest.h"
|
||||
|
||||
#include <spa/utils/defs.h>
|
||||
|
@ -225,8 +227,39 @@ PWTEST(json_overflow)
|
|||
|
||||
PWTEST(json_float)
|
||||
{
|
||||
struct {
|
||||
const char *str;
|
||||
double val;
|
||||
} val[] = {
|
||||
{ "0.0", 0.0f },
|
||||
{ ".0", 0.0f },
|
||||
{ ".0E0", 0.0E0f },
|
||||
{ "1.0", 1.0f },
|
||||
{ "1.011", 1.011f },
|
||||
{ "176543.123456", 176543.123456f },
|
||||
{ "-176543.123456", -176543.123456f },
|
||||
{ "-5678.5432E10", -5678.5432E10f },
|
||||
{ "-5678.5432e10", -5678.5432e10f },
|
||||
{ "-5678.5432e-10", -5678.5432e-10f },
|
||||
{ "5678.5432e+10", 5678.5432e+10f },
|
||||
{ "00.000100", 00.000100f },
|
||||
{ "-0.000100", -0.000100f },
|
||||
};
|
||||
float v;
|
||||
unsigned i;
|
||||
|
||||
pwtest_int_eq(spa_json_parse_float("", 0, &v), 0);
|
||||
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
for (i = 0; i < SPA_N_ELEMENTS(val); i++) {
|
||||
pwtest_int_gt(spa_json_parse_float(val[i].str, strlen(val[i].str), &v), 0);
|
||||
pwtest_double_eq(v, val[i].val);
|
||||
}
|
||||
setlocale(LC_NUMERIC, "fr_FR");
|
||||
for (i = 0; i < SPA_N_ELEMENTS(val); i++) {
|
||||
pwtest_int_gt(spa_json_parse_float(val[i].str, strlen(val[i].str), &v), 0);
|
||||
pwtest_double_eq(v, val[i].val);
|
||||
}
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue