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.
This commit is contained in:
Frank Stettner 2017-11-02 18:04:59 +01:00 committed by Uwe Hermann
parent 688e44ae06
commit 4f0463a079
6 changed files with 38 additions and 5 deletions

View File

@ -44,7 +44,7 @@ SR_PRIV gboolean sr_m2110_packet_valid(const uint8_t *buf)
if (!strncmp((const char *)buf, "OVERRNG", 7))
return TRUE;
if (sscanf((const char *)buf, "%f", &val) == 1)
if (sr_atof_ascii((const char *)buf, &val) == SR_OK)
return TRUE;
else
return FALSE;
@ -65,7 +65,7 @@ SR_PRIV int sr_m2110_parse(const uint8_t *buf, float *floatval,
if (!strncmp((const char *)buf, "OVERRNG", 7))
*floatval = INFINITY;
else if (sscanf((const char *)buf, "%f", &val) == 1) {
else if (sr_atof_ascii((const char *)buf, &val) == SR_OK) {
*floatval = val;
dot_pos = strcspn((const char *)buf, ".");
if (dot_pos < 7)

View File

@ -86,7 +86,7 @@ static int parse_value(const uint8_t *buf, struct metex14_info *info,
return SR_OK;
/* 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, ".");
if (dot_pos < cnt)

View File

@ -87,7 +87,7 @@ static void process_line(struct sr_dev_inst *sdi)
case AQ_U2:
case AQ_I1:
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",
devc->buf, errno, g_strerror(errno));
dbl = 0.0;

View File

@ -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_atod(const char *str, double *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);
/*--- soft-trigger.c --------------------------------------------------------*/

View File

@ -627,7 +627,7 @@ SR_PRIV int sr_scpi_get_double(struct sr_scpi_dev_inst *scpi,
if (ret != SR_OK && !response)
return ret;
if (sr_atod(response, scpi_response) == SR_OK)
if (sr_atod_ascii(response, scpi_response) == SR_OK)
ret = SR_OK;
else
ret = SR_ERR_DATA;

View File

@ -169,6 +169,38 @@ SR_PRIV int sr_atof(const char *str, float *ret)
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
*