mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-10-29 05:40:27 -04: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
					
				
					 3 changed files with 58 additions and 5 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Wim Taymans
						Wim Taymans