diff options
author | Petri Lehtinen <petri@digip.org> | 2024-03-07 21:02:55 +0200 |
---|---|---|
committer | Petri Lehtinen <petri@digip.org> | 2024-03-08 21:36:21 +0200 |
commit | 2d1c13224f757e780763e205e22fdf0517db82d0 (patch) | |
tree | c663630339ba20e64c0c21b221e7ee47492cdf7e /src/strconv.c | |
parent | 9b9b5e81cf64936207c2081a123fa02dd943916f (diff) | |
download | jansson-2d1c13224f757e780763e205e22fdf0517db82d0.zip jansson-2d1c13224f757e780763e205e22fdf0517db82d0.tar.gz jansson-2d1c13224f757e780763e205e22fdf0517db82d0.tar.bz2 |
Use sprintf() to determine locale's decimal point
This should fix thread safety of encoding and decoding, since
localeconv() is not tread safe after all.
Diffstat (limited to 'src/strconv.c')
-rw-r--r-- | src/strconv.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/src/strconv.c b/src/strconv.c index c6f4fd1..7d317dd 100644 --- a/src/strconv.c +++ b/src/strconv.c @@ -11,57 +11,57 @@ #include <jansson_private_config.h> #endif -#if JSON_HAVE_LOCALECONV -#include <locale.h> - /* - This code assumes that the decimal separator is exactly one character. - If setlocale() is called by another thread between the call to - localeconv() and the call to sprintf() or strtod(), the result may - be wrong. setlocale() is not thread-safe and should not be used - this way. Multi-threaded programs should use uselocale() instead. + get_decimal_point() and the call to sprintf() or strtod(), the + result may be wrong. setlocale() is not thread-safe and should + not be used this way. Multi-threaded programs should use + uselocale() instead. */ +static char get_decimal_point() { + char buf[3]; + sprintf(buf, "%#.0f", 1.0); // "1." in the current locale + return buf[1]; +} static void to_locale(strbuffer_t *strbuffer) { - const char *point; + char point; char *pos; - point = localeconv()->decimal_point; - if (*point == '.') { + point = get_decimal_point(); + if (point == '.') { /* No conversion needed */ return; } pos = strchr(strbuffer->value, '.'); if (pos) - *pos = *point; + *pos = point; } static void from_locale(char *buffer) { - const char *point; + char point; char *pos; - point = localeconv()->decimal_point; - if (*point == '.') { + point = get_decimal_point(); + if (point == '.') { /* No conversion needed */ return; } - pos = strchr(buffer, *point); + pos = strchr(buffer, point); if (pos) *pos = '.'; } -#endif int jsonp_strtod(strbuffer_t *strbuffer, double *out) { double value; char *end; -#if JSON_HAVE_LOCALECONV to_locale(strbuffer); -#endif errno = 0; value = strtod(strbuffer->value, &end); @@ -92,9 +92,7 @@ int jsonp_dtostr(char *buffer, size_t size, double value, int precision) { if (length >= size) return -1; -#if JSON_HAVE_LOCALECONV from_locale(buffer); -#endif /* Make sure there's a dot or 'e' in the output. Otherwise a real is converted to an integer when decoding */ |