[libvirt] [PATCH] json: fix interface locale dependency

Michal Privoznik mprivozn at redhat.com
Mon Aug 6 09:13:19 UTC 2012


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




More information about the libvir-list mailing list