]> sigrok.org Git - libsigrok.git/blobdiff - src/strutil.c
scpi-pps: properly set encoding digits
[libsigrok.git] / src / strutil.c
index 050f37bf7090532cc67282e07c10ce2867a985b6..3d7283b3e846e87338e7af9f97406dc266ccdee6 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#include <config.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 #include <errno.h>
-#include "libsigrok.h"
+#include <libsigrok/libsigrok.h>
 #include "libsigrok-internal.h"
 
 /** @cond PRIVATE */
@@ -56,8 +58,6 @@
  *
  * @retval SR_OK Conversion successful.
  * @retval SR_ERR Failure.
- *
- * @since 0.3.0
  */
 SR_PRIV int sr_atol(const char *str, long *ret)
 {
@@ -90,8 +90,6 @@ SR_PRIV int sr_atol(const char *str, long *ret)
  *
  * @retval SR_OK Conversion successful.
  * @retval SR_ERR Failure.
- *
- * @since 0.3.0
  */
 SR_PRIV int sr_atoi(const char *str, int *ret)
 {
@@ -122,8 +120,6 @@ SR_PRIV int sr_atoi(const char *str, int *ret)
  *
  * @retval SR_OK Conversion successful.
  * @retval SR_ERR Failure.
- *
- * @since 0.3.0
  */
 SR_PRIV int sr_atod(const char *str, double *ret)
 {
@@ -156,8 +152,6 @@ SR_PRIV int sr_atod(const char *str, double *ret)
  *
  * @retval SR_OK Conversion successful.
  * @retval SR_ERR Failure.
- *
- * @since 0.3.0
  */
 SR_PRIV int sr_atof(const char *str, float *ret)
 {
@@ -188,8 +182,6 @@ SR_PRIV int sr_atof(const char *str, float *ret)
  *
  * @retval SR_OK Conversion successful.
  * @retval SR_ERR Failure.
- *
- * @since 0.3.0
  */
 SR_PRIV int sr_atof_ascii(const char *str, float *ret)
 {
@@ -219,6 +211,77 @@ SR_PRIV int sr_atof_ascii(const char *str, float *ret)
        return SR_OK;
 }
 
+/**
+ * Convert a string representation of a numeric value to a @sr_rational. The
+ * conversion is strict and will fail if the complete string does not represent
+ * a valid number. 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 sr_rational where the result of the conversion will be stored.
+ *
+ * @retval SR_OK Conversion successful.
+ * @retval SR_ERR Failure.
+ *
+ * @since 0.5.0
+ */
+SR_API int sr_parse_rational(const char *str, struct sr_rational *ret)
+{
+       char *endptr = NULL;
+       int64_t integral;
+       int64_t fractional = 0;
+       int64_t denominator = 1;
+       int32_t fractional_len = 0;
+       int32_t exponent = 0;
+
+       errno = 0;
+       integral = g_ascii_strtoll(str, &endptr, 10);
+
+       if (errno)
+               return SR_ERR;
+
+       if (*endptr == '.') {
+               const char* start = endptr + 1;
+               fractional = g_ascii_strtoll(start, &endptr, 10);
+               if (errno)
+                       return SR_ERR;
+               fractional_len = endptr - start;
+       }
+
+       if ((*endptr == 'E') || (*endptr == 'e')) {
+               exponent = g_ascii_strtoll(endptr + 1, &endptr, 10);
+               if (errno)
+                       return SR_ERR;
+       }
+
+       if (*endptr != '\0')
+               return SR_ERR;
+
+       for (int i = 0; i < fractional_len; i++)
+               integral *= 10;
+       exponent -= fractional_len;
+
+       if (integral >= 0)
+               integral += fractional;
+       else
+               integral -= fractional;
+
+       while (exponent > 0) {
+               integral *= 10;
+               exponent--;
+       }
+
+       while (exponent < 0) {
+               denominator *= 10;
+               exponent++;
+       }
+
+       ret->p = integral;
+       ret->q = denominator;
+
+       return SR_OK;
+}
+
 /**
  * Convert a numeric value value to its "natural" string representation
  * in SI units.
@@ -246,7 +309,7 @@ SR_API char *sr_si_string_u64(uint64_t x, const char *unit)
        const char *p, prefix[] = "\0kMGTPE";
        char fmt[16], fract[20] = "", *f;
 
-       if (unit == NULL)
+       if (!unit)
                unit = "";
 
        for (i = 0; (quot = x / divisor[i]) >= 1000; i++);
@@ -420,7 +483,7 @@ SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size)
        } else
                *size += frac_part;
 
-       if (s && *s && strcasecmp(s, "Hz"))
+       if (s && *s && g_ascii_strcasecmp(s, "Hz"))
                return SR_ERR;
 
        return SR_OK;
@@ -532,9 +595,9 @@ SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q)
        if (s && *s) {
                while (*s == ' ')
                        s++;
-               if (!strcasecmp(s, "mv"))
+               if (!g_ascii_strcasecmp(s, "mv"))
                        *q = 1000L;
-               else if (!strcasecmp(s, "v"))
+               else if (!g_ascii_strcasecmp(s, "v"))
                        *q = 1;
                else
                        /* Must have a base suffix. */