On Mon, Aug 06, 2012 at 10:12:17AM +0200, 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) Actually in glibc there is a per-thread locale: /* Switch the current thread's locale to DATASET. If DATASET is null, instead just return the current setting. The special value LC_GLOBAL_LOCALE is the initial setting for all threads and can also be installed any time, meaning the thread uses the global settings controlled by `setlocale'. */ extern __locale_t uselocale (__locale_t __dataset) __THROW; > 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; GLib has a g_ascii_dtostr() which forces uses of '.' as separator. Since GLib is LGPLv2+ licensed, we can just copy their impl, which actually uses GLibc's uselocale() if possible, otherwise has a fallback impl. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list