Commit 4f0463a0 authored by Frank Stettner's avatar Frank Stettner Committed by Uwe Hermann

drivers: Fix locale dependent string to float conversion

Some drivers used locale dependent functions for converting strings
to float/double values. These functions fail when the decimal mark
is a "," in the locale settings but the string contains a ".".

This fixes bug #1064.
parent 688e44ae
...@@ -44,7 +44,7 @@ SR_PRIV gboolean sr_m2110_packet_valid(const uint8_t *buf) ...@@ -44,7 +44,7 @@ SR_PRIV gboolean sr_m2110_packet_valid(const uint8_t *buf)
if (!strncmp((const char *)buf, "OVERRNG", 7)) if (!strncmp((const char *)buf, "OVERRNG", 7))
return TRUE; return TRUE;
if (sscanf((const char *)buf, "%f", &val) == 1) if (sr_atof_ascii((const char *)buf, &val) == SR_OK)
return TRUE; return TRUE;
else else
return FALSE; return FALSE;
...@@ -65,7 +65,7 @@ SR_PRIV int sr_m2110_parse(const uint8_t *buf, float *floatval, ...@@ -65,7 +65,7 @@ SR_PRIV int sr_m2110_parse(const uint8_t *buf, float *floatval,
if (!strncmp((const char *)buf, "OVERRNG", 7)) if (!strncmp((const char *)buf, "OVERRNG", 7))
*floatval = INFINITY; *floatval = INFINITY;
else if (sscanf((const char *)buf, "%f", &val) == 1) { else if (sr_atof_ascii((const char *)buf, &val) == SR_OK) {
*floatval = val; *floatval = val;
dot_pos = strcspn((const char *)buf, "."); dot_pos = strcspn((const char *)buf, ".");
if (dot_pos < 7) if (dot_pos < 7)
......
...@@ -86,7 +86,7 @@ static int parse_value(const uint8_t *buf, struct metex14_info *info, ...@@ -86,7 +86,7 @@ static int parse_value(const uint8_t *buf, struct metex14_info *info,
return SR_OK; return SR_OK;
/* Bytes 2-8: Sign, value (up to 5 digits) and decimal point */ /* Bytes 2-8: Sign, value (up to 5 digits) and decimal point */
sscanf((const char *)&valstr, "%f", result); sr_atof_ascii((const char *)&valstr, result);
dot_pos = strcspn(valstr, "."); dot_pos = strcspn(valstr, ".");
if (dot_pos < cnt) if (dot_pos < cnt)
......
...@@ -87,7 +87,7 @@ static void process_line(struct sr_dev_inst *sdi) ...@@ -87,7 +87,7 @@ static void process_line(struct sr_dev_inst *sdi)
case AQ_U2: case AQ_U2:
case AQ_I1: case AQ_I1:
case AQ_I2: case AQ_I2:
if (sr_atod(devc->buf, &dbl) != SR_OK) { if (sr_atod_ascii(devc->buf, &dbl) != SR_OK) {
sr_err("Failed to convert '%s' to double, errno=%d %s", sr_err("Failed to convert '%s' to double, errno=%d %s",
devc->buf, errno, g_strerror(errno)); devc->buf, errno, g_strerror(errno));
dbl = 0.0; dbl = 0.0;
......
...@@ -1010,6 +1010,7 @@ SR_PRIV int sr_atol(const char *str, long *ret); ...@@ -1010,6 +1010,7 @@ SR_PRIV int sr_atol(const char *str, long *ret);
SR_PRIV int sr_atoi(const char *str, int *ret); SR_PRIV int sr_atoi(const char *str, int *ret);
SR_PRIV int sr_atod(const char *str, double *ret); SR_PRIV int sr_atod(const char *str, double *ret);
SR_PRIV int sr_atof(const char *str, float *ret); SR_PRIV int sr_atof(const char *str, float *ret);
SR_PRIV int sr_atod_ascii(const char *str, double *ret);
SR_PRIV int sr_atof_ascii(const char *str, float *ret); SR_PRIV int sr_atof_ascii(const char *str, float *ret);
/*--- soft-trigger.c --------------------------------------------------------*/ /*--- soft-trigger.c --------------------------------------------------------*/
......
...@@ -627,7 +627,7 @@ SR_PRIV int sr_scpi_get_double(struct sr_scpi_dev_inst *scpi, ...@@ -627,7 +627,7 @@ SR_PRIV int sr_scpi_get_double(struct sr_scpi_dev_inst *scpi,
if (ret != SR_OK && !response) if (ret != SR_OK && !response)
return ret; return ret;
if (sr_atod(response, scpi_response) == SR_OK) if (sr_atod_ascii(response, scpi_response) == SR_OK)
ret = SR_OK; ret = SR_OK;
else else
ret = SR_ERR_DATA; ret = SR_ERR_DATA;
......
...@@ -169,6 +169,38 @@ SR_PRIV int sr_atof(const char *str, float *ret) ...@@ -169,6 +169,38 @@ SR_PRIV int sr_atof(const char *str, float *ret)
return SR_OK; return SR_OK;
} }
/**
* @private
*
* Convert a string representation of a numeric value to a double. The
* conversion is strict and will fail if the complete string does not represent
* a valid double. The function sets errno according to the details of the
* failure. This version ignores the locale.
*
* @param str The string representation to convert.
* @param ret Pointer to double where the result of the conversion will be stored.
*
* @retval SR_OK Conversion successful.
* @retval SR_ERR Failure.
*/
SR_PRIV int sr_atod_ascii(const char *str, double *ret)
{
double tmp;
char *endptr = NULL;
errno = 0;
tmp = g_ascii_strtod(str, &endptr);
if (!endptr || *endptr || errno) {
if (!errno)
errno = EINVAL;
return SR_ERR;
}
*ret = tmp;
return SR_OK;
}
/** /**
* @private * @private
* *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment