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

Martin Kletzander mkletzan at redhat.com
Mon Aug 6 09:15:35 UTC 2012


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




More information about the libvir-list mailing list