Re: [PATCH v5 2/8] iio: core: add fixed point parsing with 64-bit parts
From: Andy Shevchenko <hidden>
Date: 2026-01-26 13:35:40
Also in:
linux-devicetree, linux-iio, lkml
On Mon, Jan 26, 2026 at 12:42:53PM +0000, Rodrigo Alencar wrote:
On 26/01/26 01:49PM, Andy Shevchenko wrote:quoted
On Fri, Jan 23, 2026 at 03:53:07PM +0000, Rodrigo Alencar via B4 Relay wrote:
...
quoted
quoted
+static int __iio_str_to_fixpoint64(const char *str, u64 fract_mult, + s64 *integer, s64 *fract, bool scale_db) +{ + u64 i = 0, f = 0; + char *end; + int digit_count, precision = ffs(fract_mult); + bool negative = false; + + if (str[0] == '-') { + negative = true; + str++; + } else if (str[0] == '+') { + str++; + } + + i = simple_strtoull(str, &end, 10); + digit_count = end - str; + if (digit_count > 20) + return -EINVAL;Not really. If we are talking about decimal (only) cases we need to also count leading 0:s. 0000000000000000000000000000000025 is still 25, no overflow. That's why I recommend to have a helper, maybe for now locally here, like int safe_strtoull(..., unsigned long long *res) { ... }Are you suggesting to not use simple_strtoull then?
Nope, I suggest to do an additional step before checking for the range.
Understood, leading zeros can be ignored only when parsing the integer part. Also, would be nice to have truncation of the fractional part while doing the parsing. How about: static int iio_safe_strtoull(const char *str, const char **end, size_t max_chars, u64 *res)
- max_chars = 0: ignores leading 0's and process all digits - max_chars > 0: process only initial max_chars digits and ignores the rest
I'm not sure why we would need that. It should parse the whole line until the first invalid character or overflow.
on overflow of u64, the function would return -EOVERFLOWquoted
that will do all necessary checks and returns -EINVAL, -ERANGE, et cetera. In the below we would need check for the error codes respectively.quoted
+ if (precision && *end == '.') { + str = end + 1; + f = simple_strtoull(str, &end, 10); + digit_count = end - str; + if (!digit_count || digit_count > 20) + return -EINVAL; + + if (digit_count > precision) { + digit_count -= precision; + f = div64_u64(f, int_pow(10, digit_count)); + } else { + digit_count = precision - digit_count; + f *= int_pow(10, digit_count); + } + } else if (!digit_count) { + return -EINVAL; + } + + if (scale_db) {quoted
+ /* Ignore the dB suffix */ + if (!strncmp(end, " dB", sizeof(" dB") - 1)) + end += sizeof(" dB") - 1; + else if (!strncmp(end, "dB", sizeof("dB") - 1)) + end += sizeof("dB") - 1;Now we have strends()strends() would not account for the acceptable '\n' before the end.
Good point.
I don't think we would need to test for " dB", " dB\n", "dB" and "dB\n"
Then you can try sysfs_eq() which does that check. But I think it requires the (end of the) string to be exact, and not something like 'dB \n'. -- With Best Regards, Andy Shevchenko