[libgda] Don't use setlocale() anymore in library as it's not thread safe
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Don't use setlocale() anymore in library as it's not thread safe
- Date: Mon, 23 Dec 2013 13:08:05 +0000 (UTC)
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]