[libvirt] [PATCH 1/2] util: implement virStrToDoubleSafe().

Following the GNU Documentation, functions to convert double/float to string and vice versa, use the locale to set the mantissa separator. Some languages use comma and other use dot as a separator. For example: 1,212.67 (en_US) = 1.112,67 (pt_BR). This can be used to parse values in float/double from XML and other definition files. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/libvirt_private.syms | 1 + src/util/virstring.c | 31 +++++++++++++++++++++++++++++++ src/util/virstring.h | 4 ++++ 3 files changed, 36 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 044510f..9d791e6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2659,6 +2659,7 @@ virStringTrimOptionalNewline; virStrncpy; virStrndup; virStrToDouble; +virStrToDoubleSafe; virStrToLong_i; virStrToLong_l; virStrToLong_ll; diff --git a/src/util/virstring.c b/src/util/virstring.c index 089b539..6dad00f 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -537,6 +537,37 @@ virStrToDouble(char const *s, } int +virStrToDoubleSafe(char const *s, + char **end_ptr, + double *result) +{ + char *cur_locale = NULL; + char *saved_locale = NULL; + int ret = -1; + + cur_locale = setlocale (LC_ALL, NULL); + if (!cur_locale) + return ret; + + if (VIR_STRDUP(saved_locale, cur_locale) < 0) + goto cleanup; + + if (!setlocale (LC_ALL, "C")) + goto cleanup; + + ret = virStrToDouble(s, end_ptr, result); + + // Cannot restore the locale. + if (!setlocale (LC_ALL, saved_locale)) + ret = -1; + + cleanup: + VIR_FREE(saved_locale); + VIR_FREE(cur_locale); + return ret; +} + +int virVasprintfInternal(bool report, int domcode, const char *filename, diff --git a/src/util/virstring.h b/src/util/virstring.h index 0038a40..fa551b7 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -108,6 +108,10 @@ int virStrToDouble(char const *s, char **end_ptr, double *result) ATTRIBUTE_RETURN_CHECK; +int virStrToDoubleSafe(char const *s, + char **end_ptr, + double *result) + ATTRIBUTE_RETURN_CHECK; void virSkipSpaces(const char **str) ATTRIBUTE_NONNULL(1); void virSkipSpacesAndBackslash(const char **str) ATTRIBUTE_NONNULL(1); -- 2.7.4

On Wed, Jun 14, 2017 at 01:24:42PM -0300, Julio Faracco wrote:
Following the GNU Documentation, functions to convert double/float to string and vice versa, use the locale to set the mantissa separator. Some languages use comma and other use dot as a separator.
For example: 1,212.67 (en_US) = 1.112,67 (pt_BR).
This can be used to parse values in float/double from XML and other definition files.
Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/libvirt_private.syms | 1 + src/util/virstring.c | 31 +++++++++++++++++++++++++++++++ src/util/virstring.h | 4 ++++ 3 files changed, 36 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 044510f..9d791e6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2659,6 +2659,7 @@ virStringTrimOptionalNewline; virStrncpy; virStrndup; virStrToDouble; +virStrToDoubleSafe; virStrToLong_i; virStrToLong_l; virStrToLong_ll; diff --git a/src/util/virstring.c b/src/util/virstring.c index 089b539..6dad00f 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -537,6 +537,37 @@ virStrToDouble(char const *s, }
int +virStrToDoubleSafe(char const *s, + char **end_ptr, + double *result) +{ + char *cur_locale = NULL; + char *saved_locale = NULL; + int ret = -1; + + cur_locale = setlocale (LC_ALL, NULL); + if (!cur_locale) + return ret; + + if (VIR_STRDUP(saved_locale, cur_locale) < 0) + goto cleanup; + + if (!setlocale (LC_ALL, "C")) + goto cleanup; +
This is MT-Unsafe. We cannot set this for the whole process, so NACK to this approach. You need to use uselocale() as in commit 43bfa23e6f96 (or just see virDoubleToStr()). Martin

Thanks to share the commit SHA, Martin. My only doubt is: I speak Brazilian portuguese (so pt_BR-Latin America and we use comma as separator). Should libvirt consider it as a separator? Or only dot? Because this approach fails to parse 12,34 (12.34 US) for example. 2017-06-15 5:27 GMT-03:00 Martin Kletzander <mkletzan@redhat.com>:
On Wed, Jun 14, 2017 at 01:24:42PM -0300, Julio Faracco wrote:
Following the GNU Documentation, functions to convert double/float to string and vice versa, use the locale to set the mantissa separator. Some languages use comma and other use dot as a separator.
For example: 1,212.67 (en_US) = 1.112,67 (pt_BR).
This can be used to parse values in float/double from XML and other definition files.
Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/libvirt_private.syms | 1 + src/util/virstring.c | 31 +++++++++++++++++++++++++++++++ src/util/virstring.h | 4 ++++ 3 files changed, 36 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 044510f..9d791e6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2659,6 +2659,7 @@ virStringTrimOptionalNewline; virStrncpy; virStrndup; virStrToDouble; +virStrToDoubleSafe; virStrToLong_i; virStrToLong_l; virStrToLong_ll; diff --git a/src/util/virstring.c b/src/util/virstring.c index 089b539..6dad00f 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -537,6 +537,37 @@ virStrToDouble(char const *s, }
int +virStrToDoubleSafe(char const *s, + char **end_ptr, + double *result) +{ + char *cur_locale = NULL; + char *saved_locale = NULL; + int ret = -1; + + cur_locale = setlocale (LC_ALL, NULL); + if (!cur_locale) + return ret; + + if (VIR_STRDUP(saved_locale, cur_locale) < 0) + goto cleanup; + + if (!setlocale (LC_ALL, "C")) + goto cleanup; +
This is MT-Unsafe. We cannot set this for the whole process, so NACK to this approach. You need to use uselocale() as in commit 43bfa23e6f96 (or just see virDoubleToStr()).
Martin

On Thu, Jun 15, 2017 at 05:51:42PM -0300, Julio Faracco wrote:
Thanks to share the commit SHA, Martin.
My only doubt is: I speak Brazilian portuguese (so pt_BR-Latin America and we use comma as separator). Should libvirt consider it as a separator? Or only dot? Because this approach fails to parse 12,34 (12.34 US) for example.
Well, it depends. In the XML it is defined hot it should look, that's not locale-dependent. Migration wouldn't work between machines with different locales. Where we should respect locale is anything that is not being parsed (and will not be parsed by any other program) and is meant only for reading by the user. I haven't actually checked the other patch you sent, so I don't know what you were using it in the end.

Great. I sent the V2. Do we have any possibility to create a Locale API (a virLocale API)? Or do you think that it is much work versus few advantages? 2017-06-16 4:03 GMT-03:00 Martin Kletzander <mkletzan@redhat.com>:
On Thu, Jun 15, 2017 at 05:51:42PM -0300, Julio Faracco wrote:
Thanks to share the commit SHA, Martin.
My only doubt is: I speak Brazilian portuguese (so pt_BR-Latin America and we use comma as separator). Should libvirt consider it as a separator? Or only dot? Because this approach fails to parse 12,34 (12.34 US) for example.
Well, it depends. In the XML it is defined hot it should look, that's not locale-dependent. Migration wouldn't work between machines with different locales. Where we should respect locale is anything that is not being parsed (and will not be parsed by any other program) and is meant only for reading by the user. I haven't actually checked the other patch you sent, so I don't know what you were using it in the end.
participants (2)
-
Julio Faracco
-
Martin Kletzander