From: Gerhard Sittig Date: Thu, 24 Sep 2020 19:18:21 +0000 (+0200) Subject: strutil: add text to float conversion which also gets precision from text X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=91ab2f6475aa559085bd87d36796a828ac041335 strutil: add text to float conversion which also gets precision from text Provide a common string helper routine which converts input text to a double precision floating point number, and also gets its precision in the process. --- diff --git a/src/libsigrok-internal.h b/src/libsigrok-internal.h index 1ff594bf..84e5faa5 100644 --- a/src/libsigrok-internal.h +++ b/src/libsigrok-internal.h @@ -1786,6 +1786,7 @@ 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_atod_ascii_digits(const char *str, double *ret, int *digits); SR_PRIV int sr_atof_ascii(const char *str, float *ret); SR_PRIV GString *sr_hexdump_new(const uint8_t *data, const size_t len); diff --git a/src/strutil.c b/src/strutil.c index 0dff3c4b..6ed2b85d 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -272,6 +272,77 @@ SR_PRIV int sr_atod_ascii(const char *str, double *ret) return SR_OK; } +/** + * Convert text to a floating point value, and get its precision. + * + * @param[in] str The input text to convert. + * @param[out] ret The conversion result, a double precision float number. + * @param[out] digits The number of significant decimals. + * + * @returns SR_OK in case of successful text to number conversion. + * @returns SR_ERR when conversion fails. + * + * @since 0.6.0 + */ +SR_PRIV int sr_atod_ascii_digits(const char *str, double *ret, int *digits) +{ + const char *p; + int *dig_ref, m_dig, exp; + char c; + double f; + + /* + * Convert floating point text to the number value, _and_ get + * the value's precision in the process. Steps taken to do it: + * - Skip leading whitespace. + * - Count the number of decimals after the mantissa's period. + * - Get the exponent's signed value. + * + * This implementation still uses common code for the actual + * conversion, but "violates API layers" by duplicating the + * text scan, to get the number of significant digits. + */ + p = str; + while (*p && isspace(*p)) + p++; + if (*p == '-' || *p == '+') + p++; + m_dig = 0; + exp = 0; + dig_ref = NULL; + while (*p) { + c = *p++; + if (toupper(c) == 'E') { + exp = strtol(p, NULL, 10); + break; + } + if (c == '.') { + m_dig = 0; + dig_ref = &m_dig; + continue; + } + if (isdigit(c)) { + if (dig_ref) + (*dig_ref)++; + continue; + } + /* Need not warn, conversion will fail. */ + break; + } + sr_spew("atod digits: txt \"%s\" -> m %d, e %d -> digits %d", + str, m_dig, exp, m_dig + -exp); + m_dig += -exp; + + if (sr_atod_ascii(str, &f) != SR_OK) + return SR_ERR; + if (ret) + *ret = f; + if (digits) + *digits = m_dig; + + return SR_OK; +} + /** * 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