]> sigrok.org Git - libsigrok.git/blobdiff - src/strutil.c
scpi-pps: properly set encoding digits
[libsigrok.git] / src / strutil.c
index d817e642d8f1cb9dfb44292c9ea0d8acf11f73af..3d7283b3e846e87338e7af9f97406dc266ccdee6 100644 (file)
@@ -211,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.