#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include "libsigrok.h"
#include "libsigrok-internal.h"
-/* Message logging helpers with subsystem-specific prefix string. */
-#define LOG_PREFIX "strutil: "
-#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
-#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
-#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
-#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
-#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
-#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
+#define LOG_PREFIX "strutil"
/**
* @file
*/
/**
- * Convert a numeric value value to its "natural" string representation.
- * in SI units
+ * @private
+ *
+ * Convert a string representation of a numeric value to a long integer. The
+ * conversion is strict and will fail if the complete string does not represent
+ * a valid long integer. The function sets errno according to the details of the
+ * failure.
+ *
+ * @param str The string representation to convert.
+ * @param ret Pointer to long where the result of the conversion will be stored.
+ *
+ * @return SR_OK if conversion is successful, otherwise SR_ERR.
+ *
+ * @since 0.3.0
+ */
+SR_PRIV int sr_atol(const char *str, long *ret)
+{
+ long tmp;
+ char *endptr = NULL;
+
+ errno = 0;
+ tmp = strtol(str, &endptr, 0);
+
+ if (!endptr || *endptr || errno) {
+ if (!errno)
+ errno = EINVAL;
+ return SR_ERR;
+ }
+
+ *ret = tmp;
+ return SR_OK;
+}
+
+/**
+ * @private
+ *
+ * Convert a string representation of a numeric value to an integer. The
+ * conversion is strict and will fail if the complete string does not represent
+ * a valid integer. The function sets errno according to the details of the
+ * failure.
+ *
+ * @param str The string representation to convert.
+ * @param ret Pointer to int where the result of the conversion will be stored.
+ *
+ * @return SR_OK if conversion is successful, otherwise SR_ERR.
+ *
+ * @since 0.3.0
+ */
+SR_PRIV int sr_atoi(const char *str, int *ret)
+{
+ long tmp;
+
+ if (sr_atol(str, &tmp) != SR_OK)
+ return SR_ERR;
+
+ if ((int) tmp != tmp) {
+ errno = ERANGE;
+ return SR_ERR;
+ }
+
+ *ret = (int) tmp;
+ 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.
+ *
+ * @param str The string representation to convert.
+ * @param ret Pointer to double where the result of the conversion will be stored.
+ *
+ * @return SR_OK if conversion is successful, otherwise SR_ERR.
+ *
+ * @since 0.3.0
+ */
+SR_PRIV int sr_atod(const char *str, double *ret)
+{
+ double tmp;
+ char *endptr = NULL;
+
+ errno = 0;
+ tmp = strtof(str, &endptr);
+
+ if (!endptr || *endptr || errno) {
+ if (!errno)
+ errno = EINVAL;
+ return SR_ERR;
+ }
+
+ *ret = tmp;
+ return SR_OK;
+}
+
+/**
+ * @private
+ *
+ * Convert a string representation of a numeric value to a float. The
+ * conversion is strict and will fail if the complete string does not represent
+ * a valid float. The function sets errno according to the details of the
+ * failure.
+ *
+ * @param str The string representation to convert.
+ * @param ret Pointer to float where the result of the conversion will be stored.
+ *
+ * @return SR_OK if conversion is successful, otherwise SR_ERR.
+ *
+ * @since 0.3.0
+ */
+SR_PRIV int sr_atof(const char *str, float *ret)
+{
+ double tmp;
+
+ if (sr_atod(str, &tmp) != SR_OK)
+ return SR_ERR;
+
+ if ((float) tmp != tmp) {
+ errno = ERANGE;
+ return SR_ERR;
+ }
+
+ *ret = (float) tmp;
+ return SR_OK;
+}
+
+/**
+ * @private
+ *
+ * Convert a string representation of a numeric value to a float. The
+ * conversion is strict and will fail if the complete string does not represent
+ * a valid float. 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 float where the result of the conversion will be stored.
+ *
+ * @return SR_OK if conversion is successful, otherwise SR_ERR.
+ *
+ * @since 0.3.0
+ */
+SR_PRIV int sr_atof_ascii(const char *str, float *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;
+ }
+
+ /* FIXME This fails unexpectedly. Some other method to safel downcast
+ * needs to be found. Checking against FLT_MAX doesn't work as well. */
+ /*
+ if ((float) tmp != tmp) {
+ errno = ERANGE;
+ sr_dbg("ERANGEEEE %e != %e", (float) tmp, tmp);
+ return SR_ERR;
+ }
+ */
+
+ *ret = (float) tmp;
+ return SR_OK;
+}
+
+/**
+ * Convert a numeric value value to its "natural" string representation
+ * in SI units.
*
* E.g. a value of 3000000, with units set to "W", would be converted
* to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW".
{
uint8_t i;
uint64_t quot, divisor[] = {
- 1, SR_KHZ(1), SR_MHZ(1), SR_GHZ(1),
- SR_GHZ(1000), SR_GHZ(1000*1000), SR_GHZ(1000*1000*1000)
+ SR_HZ(1), SR_KHZ(1), SR_MHZ(1), SR_GHZ(1),
+ SR_GHZ(1000), SR_GHZ(1000 * 1000), SR_GHZ(1000 * 1000 * 1000),
};
const char *p, prefix[] = "\0kMGTPE";
- char fmt[8], fract[20] = "", *f;
+ char fmt[16], fract[20] = "", *f;
if (unit == NULL)
unit = "";
for (i = 0; (quot = x / divisor[i]) >= 1000; i++);
if (i) {
- sprintf(fmt, ".%%0%dlu", i * 3);
+ sprintf(fmt, ".%%0%d"PRIu64, i * 3);
f = fract + sprintf(fract, fmt, x % divisor[i]) - 1;
while (f >= fract && strchr("0.", *f))
return NULL;
}
- if (sdi->driver->config_list(SR_CONF_TRIGGER_TYPE, &gvar, sdi) != SR_OK) {
+ if (sdi->driver->config_list(SR_CONF_TRIGGER_TYPE,
+ &gvar, sdi, NULL) != SR_OK) {
sr_err("%s: Device doesn't support any triggers.", __func__);
return NULL;
}
SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size)
{
int multiplier, done;
+ double frac_part;
char *s;
*size = strtoull(sizestring, &s, 10);
multiplier = 0;
+ frac_part = 0;
done = FALSE;
while (s && *s && multiplier == 0 && !done) {
switch (*s) {
case ' ':
break;
+ case '.':
+ frac_part = g_ascii_strtod(s, &s);
+ break;
case 'k':
case 'K':
multiplier = SR_KHZ(1);
}
s++;
}
- if (multiplier > 0)
+ if (multiplier > 0) {
*size *= multiplier;
+ *size += frac_part * multiplier;
+ } else
+ *size += frac_part;
if (*s && strcasecmp(s, "Hz"))
return SR_ERR;