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:
parent
688e44ae06
commit
4f0463a079
|
@ -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,
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
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);
|
||||||
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,
|
||||||
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)
|
||||||
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
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue