[libgda] Don't use setlocale() anymore in library as it's not thread safe



commit d80398c0d2f4f96dbf0e1a09b4fb73b800638e78
Author: Vivien Malerba <malerba gnome-db org>
Date:   Mon Dec 23 12:40:40 2013 +0100

    Don't use setlocale() anymore in library as it's not thread safe

 libgda-ui/gdaui-cloud.c                          |    4 +-
 libgda/gda-data-handler.c                        |    4 +
 libgda/gda-data-handler.h                        |    2 +-
 libgda/gda-data-model.c                          |    1 -
 libgda/gda-value.c                               |  108 ++++++++++++----------
 libgda/handlers/gda-handler-numerical.c          |   75 +++++++++------
 libgda/handlers/gda-handler-time.c               |    2 +-
 providers/firebird/gda-firebird-recordset.c      |   10 +--
 providers/mysql/gda-mysql-recordset.c            |    9 +--
 providers/postgres/gda-postgres-recordset.c      |   12 +--
 tools/browser/schema-browser/relations-diagram.c |    4 +-
 11 files changed, 122 insertions(+), 109 deletions(-)
---
diff --git a/libgda-ui/gdaui-cloud.c b/libgda-ui/gdaui-cloud.c
index 4016c48..f9ff8f3 100644
--- a/libgda-ui/gdaui-cloud.c
+++ b/libgda-ui/gdaui-cloud.c
@@ -268,7 +268,7 @@ update_display (GdauiCloud *cloud)
                                cvalue = gda_data_model_get_value_at (cloud->priv->model,
                                                                      cloud->priv->weight_column, i, NULL);
                                if (cvalue) {
-                                       weight = atof (gda_value_stringify (cvalue));
+                                       weight = g_ascii_strtod (gda_value_stringify (cvalue), NULL);
                                        min_weight = MIN (min_weight, weight);
                                        max_weight = MAX (max_weight, weight);
                                }
@@ -316,7 +316,7 @@ update_display (GdauiCloud *cloud)
                                cvalue = gda_data_model_get_value_at (cloud->priv->model,
                                                                      cloud->priv->weight_column, i, NULL);
                                if (cvalue) {
-                                       weight = atof (gda_value_stringify (cvalue));
+                                       weight = g_ascii_strtod (gda_value_stringify (cvalue), NULL);
                                        weight = cloud->priv->min_scale + wrange * (weight - min_weight);
                                }
                        }
diff --git a/libgda/gda-data-handler.c b/libgda/gda-data-handler.c
index d7c6231..9fd4495 100644
--- a/libgda/gda-data-handler.c
+++ b/libgda/gda-data-handler.c
@@ -126,6 +126,8 @@ gda_data_handler_get_sql_from_value (GdaDataHandler *dh, const GValue *value)
  * (in the user's locale, specially for the dates). If the value is 
  * NULL or is of type GDA_TYPE_NULL, the returned string is a copy of "" (empty string).
  *
+ * Note: the returned value will be in the current locale representation.
+ *
  * Returns: (transfer full): the new string, or %NULL if an error occurred
  */
 gchar *
@@ -191,6 +193,8 @@ gda_data_handler_get_value_from_sql (GdaDataHandler *dh, const gchar *sql, GType
  * if the @str string does not correspond to a valid string for the requested type, then
  * %NULL is returned.
  *
+ * Note: the @str string must be in the current locale representation
+ *
  * Returns: (transfer full): the new #GValue or %NULL on error
  */
 GValue *
diff --git a/libgda/gda-data-handler.h b/libgda/gda-data-handler.h
index 77974c4..95af351 100644
--- a/libgda/gda-data-handler.h
+++ b/libgda/gda-data-handler.h
@@ -63,7 +63,7 @@ struct _GdaDataHandlerIface
  * managing data in its various representations, and converting from one to another:
  * <itemizedlist>
  *   <listitem><para>as a #GValue which is a generic value container for the C language</para></listitem>
- *   <listitem><para>as a human readable string</para></listitem>
+ *   <listitem><para>as a human readable string (in the user defined locale)</para></listitem>
  *   <listitem><para>as an SQL string (a string which can be used in SQL statements)</para></listitem>
  * </itemizedlist>
  *
diff --git a/libgda/gda-data-model.c b/libgda/gda-data-model.c
index a213a3d..d68b6b7 100644
--- a/libgda/gda-data-model.c
+++ b/libgda/gda-data-model.c
@@ -2622,7 +2622,6 @@ real_gda_data_model_dump_as_string (GdaDataModel *model, gboolean dump_attribute
 #ifndef G_OS_WIN32
        if (dump_separators || dump_sep_line) {
                int utf8_mode;
-               setlocale (LC_ALL, NULL);
                utf8_mode = (strcmp (nl_langinfo (CODESET), "UTF-8") == 0);
                if (utf8_mode) {
                        if (dump_separators) {
diff --git a/libgda/gda-value.c b/libgda/gda-value.c
index f45026d..eb78696 100644
--- a/libgda/gda-value.c
+++ b/libgda/gda-value.c
@@ -54,8 +54,6 @@
 #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
 #endif
 
-extern gchar *gda_numeric_locale;
-
 #  ifdef GSEAL_ENABLE
 /**
  * GdaNumeric:
@@ -889,6 +887,14 @@ gda_numeric_free (GdaNumeric *numeric)
        g_free (numeric);
 }
 
+static gchar*
+gda_dtostr_dup (const double value)
+{
+       char buffer[G_ASCII_DTOSTR_BUF_SIZE];
+       g_ascii_dtostr (buffer, sizeof (buffer), value);
+       return g_strdup (buffer);
+}
+
 /**
  * gda_numeric_new:
  *
@@ -901,19 +907,16 @@ GdaNumeric*
 gda_numeric_new (void)
 {
        GdaNumeric *n = g_new0 (GdaNumeric, 1);
-       setlocale (LC_NUMERIC, "C");
-       n->number = g_strdup_printf ("%lf", 0.0);
-       setlocale (LC_NUMERIC, gda_numeric_locale);
+       n->number = gda_dtostr_dup (0.0);
        return n;
 }
 
 /**
  * gda_numeric_set_from_string:
  * @numeric: a #GdaNumeric
- * @str: a string representing a number
+ * @str: a string representing a number, in the C locale format
  *
  * Sets @numeric with a number represented by @str, in the C locale format (dot as a fraction separator).
- * By default converts @str to #gdouble.
  *
  * Since: 5.0.2
  */
@@ -923,13 +926,15 @@ gda_numeric_set_from_string (GdaNumeric *numeric, const gchar* str)
        g_return_if_fail (numeric);
        g_return_if_fail (str);
        g_free (numeric->number);
-       // FIXME: By default convert string to gdouble, for other number types we need to check string format
-       setlocale (LC_NUMERIC, "C");
-       gdouble n = g_strtod (str, NULL);
-       numeric->number = g_strdup_printf ("%lf", n);
-       setlocale (LC_NUMERIC, gda_numeric_locale);
-}
 
+       gdouble number;
+       gchar *endptr = NULL;
+       number = g_ascii_strtod (str, &endptr);
+       if (*endptr)
+               numeric->number = gda_dtostr_dup (number);
+       else
+               numeric->number = g_strdup (str);
+}
 
 /**
  * gda_numeric_set_double:
@@ -945,9 +950,7 @@ gda_numeric_set_double (GdaNumeric *numeric, gdouble number)
 {
        g_return_if_fail (numeric);
        g_free (numeric->number);
-       setlocale (LC_NUMERIC, "C");
-       numeric->number = g_strdup_printf ("%lf", number);
-       setlocale (LC_NUMERIC, gda_numeric_locale);
+       numeric->number = gda_dtostr_dup (number);
 }
 
 /**
@@ -961,11 +964,7 @@ gdouble
 gda_numeric_get_double (const GdaNumeric *numeric)
 {
        g_return_val_if_fail (numeric, 0.0);
-       gdouble res;
-       setlocale (LC_NUMERIC, "C");
-       res = atof (numeric->number);
-       setlocale (LC_NUMERIC, gda_numeric_locale);
-       return res;
+       return g_ascii_strtod (numeric->number, NULL);
 }
 
 /**
@@ -2323,7 +2322,7 @@ gda_value_set_from_value (GValue *value, const GValue *from)
  * #GdaDataHandler objects). Using this function should be limited to debugging and values serialization
  * purposes.
  *
- * Dates are converted in a YYYY-MM-DD format.
+ * Output is in the "C" locale for numbers, and dates are converted in a YYYY-MM-DD format.
  *
  * Returns: (transfer full): a new string, or %NULL if the conversion cannot be done. Free the value with a 
g_free() when you've finished using it.
  */
@@ -2332,44 +2331,53 @@ gda_value_stringify (const GValue *value)
 {
        if (!value)
                return g_strdup ("NULL");
-       if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_STRING)) {
+
+       GType type = G_VALUE_TYPE (value);
+       if (type == G_TYPE_FLOAT) {
+               char buffer[G_ASCII_DTOSTR_BUF_SIZE];
+               g_ascii_formatd (buffer, sizeof (buffer), "%f", g_value_get_float (value));
+               return g_strdup (buffer);
+       }
+       else if (type == G_TYPE_DOUBLE) {
+               char buffer[G_ASCII_DTOSTR_BUF_SIZE];
+               g_ascii_formatd (buffer, sizeof (buffer), "%f", g_value_get_double (value));
+               return g_strdup (buffer);
+       }
+       else if (type == GDA_TYPE_NUMERIC)
+               return gda_numeric_get_string (gda_value_get_numeric (value));
+       else if (type == G_TYPE_DATE) {
+               GDate *date;
+               date = (GDate *) g_value_get_boxed (value);
+               if (date) {
+                       if (g_date_valid (date))
+                               return g_strdup_printf ("%04u-%02u-%02u",
+                                                       g_date_get_year (date),
+                                                       g_date_get_month (date),
+                                                       g_date_get_day (date));
+                       else
+                               return g_strdup_printf ("%04u-%02u-%02u",
+                                                       date->year, date->month, date->day);
+               }
+               else
+                       return g_strdup ("0000-00-00");
+       }
+       else if (g_value_type_transformable (G_VALUE_TYPE (value), G_TYPE_STRING)) {
                GValue *string;
                gchar *str;
 
-               setlocale (LC_NUMERIC, "C");
                string = g_value_init (g_new0 (GValue, 1), G_TYPE_STRING);
                g_value_transform (value, string);
-               setlocale (LC_NUMERIC, gda_numeric_locale);
                str = g_value_dup_string (string);
                gda_value_free (string);
                return str;
        }
-       else {
-               GType type = G_VALUE_TYPE (value);
-               if (type == G_TYPE_DATE) {
-                       GDate *date;
-                       date = (GDate *) g_value_get_boxed (value);
-                       if (date) {
-                               if (g_date_valid (date))
-                                       return g_strdup_printf ("%04u-%02u-%02u",
-                                                               g_date_get_year (date),
-                                                               g_date_get_month (date),
-                                                               g_date_get_day (date));
-                               else
-                                       return g_strdup_printf ("%04u-%02u-%02u",
-                                                               date->year, date->month, date->day);
-                       }
-                       else
-                               return g_strdup ("0000-00-00");
-               }
-               else if (G_TYPE_IS_OBJECT (type)) {
-                       GObject *obj;
-                       obj = g_value_get_object (value);
-                       return g_strdup_printf ("%p (%s)", obj, G_OBJECT_TYPE_NAME (obj));
-               }
-               else
-                       return g_strdup ("");
+       else if (G_TYPE_IS_OBJECT (type)) {
+               GObject *obj;
+               obj = g_value_get_object (value);
+               return g_strdup_printf ("%p (%s)", obj, G_OBJECT_TYPE_NAME (obj));
        }
+       else
+               return g_strdup ("");
 }
 
 /**
diff --git a/libgda/handlers/gda-handler-numerical.c b/libgda/handlers/gda-handler-numerical.c
index 9f885a6..18d8564 100644
--- a/libgda/handlers/gda-handler-numerical.c
+++ b/libgda/handlers/gda-handler-numerical.c
@@ -26,8 +26,6 @@
 #include <locale.h>
 #include <glib/gi18n-lib.h>
 
-extern gchar *gda_numeric_locale;
-
 static void gda_handler_numerical_class_init (GdaHandlerNumericalClass * class);
 static void gda_handler_numerical_init (GdaHandlerNumerical * wid);
 static void gda_handler_numerical_dispose (GObject   * object);
@@ -201,28 +199,22 @@ gda_handler_numerical_get_str_from_value (G_GNUC_UNUSED GdaDataHandler *iface, c
        return gda_value_stringify ((GValue *) value);
 }
 
+/*
+ * if @c_locale is %TRUE, then @str is expected to be in the "C" locale, and if it is %FALSE,
+ * then @str is expected to be in the current (user defined) locale
+ */
 static GValue *
-gda_handler_numerical_get_value_from_sql (G_GNUC_UNUSED GdaDataHandler *iface, const gchar *sql, GType type)
-{
-       g_assert (sql);
-
-       GValue *value;
-       setlocale (LC_NUMERIC, "C");
-       value = gda_handler_numerical_get_value_from_str (iface, sql, type);
-       setlocale (LC_NUMERIC, gda_numeric_locale);
-
-       return value;
-}
-
-static GValue *
-gda_handler_numerical_get_value_from_str (G_GNUC_UNUSED GdaDataHandler *iface, const gchar *str, GType type)
+_gda_handler_numerical_get_value_from_str_locale (const gchar *str, GType type, gboolean c_locale)
 {
        g_assert (str);
        GValue *value = NULL;
        long long int llint;
        char *endptr = NULL;
 
-       llint = strtoll (str, &endptr, 10);
+       if (c_locale)
+               llint = g_ascii_strtoull (str, &endptr, 10);
+       else
+               llint = strtoll (str, &endptr, 10);
 
        if (type == G_TYPE_INT64) {
                if (!*endptr && (llint >= G_MININT64) && (llint <= G_MAXINT64)) {
@@ -232,12 +224,26 @@ gda_handler_numerical_get_value_from_str (G_GNUC_UNUSED GdaDataHandler *iface, c
        }
        else if (type == G_TYPE_DOUBLE) {
                gdouble dble;
-               dble = g_strtod (str, &endptr);
+               if (c_locale)
+                       dble = g_ascii_strtod (str, &endptr);
+               else
+                       dble = g_strtod (str, &endptr);
                if (!*endptr) {
                        value = g_value_init (g_new0 (GValue, 1), G_TYPE_DOUBLE);
                        g_value_set_double (value, dble);
                }
        }
+       else if (type == G_TYPE_FLOAT) {
+               gfloat flt;
+               if (c_locale)
+                       flt = g_ascii_strtod (str, &endptr);
+               else
+                       flt = strtof (str, &endptr);
+               if (!*endptr) {
+                       value = g_value_init (g_new0 (GValue, 1), G_TYPE_FLOAT);
+                       g_value_set_float (value, flt);
+               }
+       }
        else if (type == G_TYPE_INT) {
                if (!*endptr && (llint >= G_MININT) && (llint <= G_MAXINT)) {
                        value = g_value_init (g_new0 (GValue, 1), G_TYPE_INT);
@@ -274,20 +280,20 @@ gda_handler_numerical_get_value_from_str (G_GNUC_UNUSED GdaDataHandler *iface, c
                        p++;
                }
                if (ok) {
-                       gda_numeric_set_from_string (numeric, (gchar*) str);
-                       value = g_value_init (g_new0 (GValue, 1), GDA_TYPE_NUMERIC);
-                       gda_value_set_numeric (value, numeric);
+                       gdouble d;
+                       char *end = NULL;
+                       if (c_locale)
+                               d = g_ascii_strtod (str, &end);
+                       else
+                               d = strtod (str, &end);
+                       if (! *end) {
+                               value = g_value_init (g_new0 (GValue, 1), GDA_TYPE_NUMERIC);
+                               gda_numeric_set_double (numeric, d);
+                               gda_value_set_numeric (value, numeric);
+                       }
                }
                gda_numeric_free (numeric);
        }
-       else if (type == G_TYPE_FLOAT) {
-               gfloat flt;
-               flt = strtof (str, &endptr);
-               if (!*endptr) {
-                       value = g_value_init (g_new0 (GValue, 1), G_TYPE_FLOAT);
-                       g_value_set_float (value, flt);
-               }
-       }
        else if (type == GDA_TYPE_SHORT) {
                if (!*endptr && (llint >= G_MINSHORT) && (llint <= G_MAXSHORT)) {
                        value = g_value_init (g_new0 (GValue, 1), GDA_TYPE_SHORT);
@@ -358,6 +364,17 @@ gda_handler_numerical_get_value_from_str (G_GNUC_UNUSED GdaDataHandler *iface, c
        return value;
 }
 
+static GValue *
+gda_handler_numerical_get_value_from_sql (G_GNUC_UNUSED GdaDataHandler *iface, const gchar *sql, GType type)
+{
+       return _gda_handler_numerical_get_value_from_str_locale (sql, type, TRUE);
+}
+
+static GValue *
+gda_handler_numerical_get_value_from_str (G_GNUC_UNUSED GdaDataHandler *iface, const gchar *str, GType type)
+{
+       return _gda_handler_numerical_get_value_from_str_locale (str, type, FALSE);
+}
 
 static GValue *
 gda_handler_numerical_get_sane_init_value (G_GNUC_UNUSED GdaDataHandler *iface, GType type)
diff --git a/libgda/handlers/gda-handler-time.c b/libgda/handlers/gda-handler-time.c
index d18f97c..b4b7632 100644
--- a/libgda/handlers/gda-handler-time.c
+++ b/libgda/handlers/gda-handler-time.c
@@ -431,7 +431,7 @@ handler_compute_locale (GdaHandlerTime *hdl)
  * @value: a #GValue value
  *
  * Returns: a new string representing @value without taking the current
- * locale into account
+ * locale into account (i.e. in the "C" locale)
  */
 gchar *
 gda_handler_time_get_no_locale_str_from_value (GdaHandlerTime *dh, const GValue *value)
diff --git a/providers/firebird/gda-firebird-recordset.c b/providers/firebird/gda-firebird-recordset.c
index efb1e56..336c5c5 100644
--- a/providers/firebird/gda-firebird-recordset.c
+++ b/providers/firebird/gda-firebird-recordset.c
@@ -410,17 +410,11 @@ _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row, GType req_col_type){
                                break;
 
                        case SQL_FLOAT:
-                               sprintf(p, "%15g ", *(float *) (var->sqldata));
-                               //setlocale (LC_NUMERIC, "C");
-                               g_value_set_float (value, atof (p));
-                               //setlocale (LC_NUMERIC, gda_numeric_locale);
+                               g_value_set_float (value, *(float *) (var->sqldata));
                                break;
 
                        case SQL_DOUBLE:
-                               sprintf(p, "%24f ", *(double *) (var->sqldata));
-                               //setlocale (LC_NUMERIC, "C");
-                               g_value_set_double (value, atof (p));
-                               //setlocale (LC_NUMERIC, gda_numeric_locale);
+                               g_value_set_double (value, *(double *) (var->sqldata));
                                break;
 
                        case SQL_TIMESTAMP:
diff --git a/providers/mysql/gda-mysql-recordset.c b/providers/mysql/gda-mysql-recordset.c
index e534cad..8193877 100644
--- a/providers/mysql/gda-mysql-recordset.c
+++ b/providers/mysql/gda-mysql-recordset.c
@@ -963,7 +963,6 @@ new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, G_GNUC_UNUSED gint rownum, G
                                gda_value_set_blob (value, &blob);
                        }
                        else if (type == GDA_TYPE_NUMERIC) {
-                               setlocale (LC_NUMERIC, "C");
                                if (length > 0) {
                                        GdaNumeric *numeric;
                                        numeric = gda_numeric_new ();
@@ -973,14 +972,10 @@ new_row_from_mysql_stmt (GdaMysqlRecordset *imodel, G_GNUC_UNUSED gint rownum, G
                                        gda_value_set_numeric (value, numeric);
                                        gda_numeric_free (numeric);
                                }
-                               setlocale (LC_NUMERIC, gda_numeric_locale);
                        }
                        else if (type == G_TYPE_DOUBLE) {
-                               if (length > 0) {
-                                       setlocale (LC_NUMERIC, "C");
-                                       g_value_set_double (value, atof (bvalue));
-                                       setlocale (LC_NUMERIC, gda_numeric_locale);
-                               }
+                               if (length > 0)
+                                       g_value_set_double (value, g_ascii_strtod (bvalue, NULL));
                                else {
                                        /* error: wrong column type */
                                        gda_row_invalidate_value (row, value);
diff --git a/providers/postgres/gda-postgres-recordset.c b/providers/postgres/gda-postgres-recordset.c
index eb6525c..9ddc645 100644
--- a/providers/postgres/gda-postgres-recordset.c
+++ b/providers/postgres/gda-postgres-recordset.c
@@ -589,10 +589,10 @@ static void
 make_point (GdaGeometricPoint *point, const gchar *value)
 {
        value++;
-       point->x = atof (value);
+       point->x = g_ascii_strtod (value, NULL);
        value = strchr (value, ',');
        value++;
-       point->y = atof (value);
+       point->y = g_ascii_strtod (value, NULL);
 }
 
 static void
@@ -652,14 +652,10 @@ set_value (GdaConnection *cnc, GdaRow *row, GValue *value, GType type, const gch
        else if (type == GDA_TYPE_SHORT)
                gda_value_set_short (value, atoi (thevalue));
        else if (type == G_TYPE_FLOAT) {
-               setlocale (LC_NUMERIC, "C");
-               g_value_set_float (value, atof (thevalue));
-               setlocale (LC_NUMERIC, gda_numeric_locale);
+               g_value_set_float (value, g_ascii_strtod (thevalue, NULL));
        }
        else if (type == G_TYPE_DOUBLE) {
-               setlocale (LC_NUMERIC, "C");
-               g_value_set_double (value, atof (thevalue));
-               setlocale (LC_NUMERIC, gda_numeric_locale);
+               g_value_set_double (value, g_ascii_strtod (thevalue, NULL));
        }
        else if (type == GDA_TYPE_NUMERIC) {
                GdaNumeric* numeric = gda_numeric_new ();
diff --git a/tools/browser/schema-browser/relations-diagram.c 
b/tools/browser/schema-browser/relations-diagram.c
index f6cde38..42cefc5 100644
--- a/tools/browser/schema-browser/relations-diagram.c
+++ b/tools/browser/schema-browser/relations-diagram.c
@@ -414,8 +414,8 @@ relations_diagram_new_with_fav_id (BrowserConnection *bcnc, gint fav_id, GError
                                        y = xmlGetProp (node, BAD_CAST "y");
                                        browser_canvas_translate_item (BROWSER_CANVAS (diagram->priv->canvas),
                                                                       (BrowserCanvasItem*) table,
-                                                                      x ? atof ((gchar*) x) : 0.,
-                                                                      y ? atof ((gchar*) y) : 0.);
+                                                                      x ? g_ascii_strtod ((gchar*) x, NULL) 
: 0.,
+                                                                      y ? g_ascii_strtod ((gchar*) y, NULL) 
: 0.);
                                        if (x)
                                                xmlFree (x);
                                        if (y)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]