On 08/06/2012 11:13 AM, Michal Privoznik wrote:
On 06.08.2012 10:12, Martin Kletzander wrote:
> libvirt creates invalid commands if wrong locale is selected. For
> example with locale that uses comma as a decimal point, JSON commands
> created with decimal numbers are invalid because comma separates the
> entries in JSON.
>
> But even when decimal point is affected, grouping is not, because for
> grouping to be enabled with *printf, there has to be a apostrophe flag
> specified (and supported).
> ---
> Fortunately, there should be no other place where output-formatting is
> affected by this problem.
>
> I tried to change this in various ways with this posted one being the
> cleanest from my point of view, because:
> - setting locale is per-proccess, not per-thread (not thread-safe)
> - there is no number parsing that mangles the output number because
> of floating point precision
>
> src/util/json.c | 23 +++++++++++++++++++++--
> 1 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/src/util/json.c b/src/util/json.c
> index 5132989..753a548 100644
> --- a/src/util/json.c
> +++ b/src/util/json.c
> @@ -23,6 +23,8 @@
>
> #include <config.h>
>
> +#include <locale.h>
> +
> #include "json.h"
> #include "memory.h"
> #include "virterror_internal.h"
> @@ -44,7 +46,6 @@
> /* XXX fixme */
> #define VIR_FROM_THIS VIR_FROM_NONE
>
> -
> typedef struct _virJSONParserState virJSONParserState;
> typedef virJSONParserState *virJSONParserStatePtr;
> struct _virJSONParserState {
> @@ -200,9 +201,27 @@ virJSONValuePtr virJSONValueNewNumberUlong(unsigned long long
data)
> virJSONValuePtr virJSONValueNewNumberDouble(double data)
> {
> virJSONValuePtr val = NULL;
> - char *str;
> + char *str, *radix, *tmp;
> +
> if (virAsprintf(&str, "%lf", data) < 0)
> return NULL;
> +
> + /* because printing double is locale-dependent, we could end up
> + * with invalid JSON code, so we have to do something like this */
> + radix = localeconv()->decimal_point;
> + tmp = strstr(str, radix);
> + if (tmp) {
> + *tmp = '.';
> + if (strlen(radix) > 1) {
> + /* if the current locale specifies more characters as
> + * decimal point then cover the others with decimal
> + * numbers */
> + memcpy(tmp + 1,
> + tmp + strlen(radix),
> + strlen(str) - (tmp - str));
> + }
> + }
> +
> val = virJSONValueNewNumber(str);
> VIR_FREE(str);
> return val;
> --
When we are touching this - should we also care about thousand separator?
Michal
Thousands are separated only if the apostrophe flag is specified
(mentioned in the commit message).
Martin