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