Re: [PATCH v12 02/11] lib: kstrtox: add kstrtoudec64() and kstrtodec64()
From: Rodrigo Alencar
Date: Sun May 17 2026 - 05:10:44 EST
On 26/05/15 08:21PM, David Laight wrote:
> On Fri, 15 May 2026 17:05:06 +0100
> Rodrigo Alencar <455.rodrigo.alencar@xxxxxxxxx> wrote:
>
> > On 26/05/13 10:41AM, Rodrigo Alencar wrote:
> > > On 26/05/10 01:42PM, Rodrigo Alencar via B4 Relay wrote:
> > > > From: Rodrigo Alencar <rodrigo.alencar@xxxxxxxxxx>
> > > >
> > > > Add helpers that parses decimal numbers into 64-bit number, i.e., decimal
> > > > point numbers with pre-defined scale are parsed into a 64-bit value (fixed
> > > > precision). After the decimal point, digits beyond the specified scale
> > > > are ignored.
> > >
> > > Hi Andy,
> > >
> > > I am starting over here, the other conversation is getting hard to follow.
> > > This is my new proposal...
> >
> > +cc David
>
> I just wouldn't do it this way :-)
>
> You end up with more code than you would get if you just converted the digits.
I am not sure about having more code, most of it is reused. The rest is input
validation and scaling.
...
> > > This function now becomes:
> > >
> > > static int _kstrtoudec64(const char *s, unsigned int scale, u64 *res)
> > > {
> > > u64 _res = 0;
> > > unsigned int rv_int, rv_frac;
> > >
integer part is parsed here:
> > > rv_int = _parse_integer(s, 10, &_res);
> > > if (rv_int & KSTRTOX_OVERFLOW)
> > > return -ERANGE;
> > > s += rv_int;
> > >
> > > if (*s == '.')
> > > s++; /* skip decimal point */
> > >
fractional part is parsed here:
(combined into the result so we can just skip the decimal point)
> > > rv_frac = _parse_integer_limit_init(s, 10, _res, &_res, scale);
> > > if (rv_frac & KSTRTOX_OVERFLOW)
> > > return -ERANGE;
> > > s += rv_frac;
> > >
input validation on the presence of digits:
(similar to checking rv in _kstrtoull())
> > > if (!rv_int && !rv_frac && !isdigit(*s))
> > > return -EINVAL; /* no digits at all */
> > >
> > > while (isdigit(*s)) /* truncate digits */
> > > s++;
> > >
termination requirement:
> > > if (*s == '\n')
> > > s++;
> > > if (*s)
> > > return -EINVAL;
> > >
result is scaled according to (scale - rv_frac):
> > > if (_res && (scale > (19 + rv_frac) || /* log10(2^64) = 19.26 */
> > > check_mul_overflow(_res, int_pow(10, scale - rv_frac), &_res)))
> > > return -ERANGE;
> > >
> > > *res = _res;
> > > return 0;
> > > }
> > >
That above looks straightforward to me and the tests in the next patch are thorough.
...
> > I have a v13 ready with this. I'll give it a go soon...
> >
>
--
Kind regards,
Rodrigo Alencar