tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: strsuftoi(3), strsuftou(3) proposal in libc



In article <56318759.6010003%gmx.com@localhost>, Kamil Rytarowski  <n54%gmx.com@localhost> wrote:
>-=-=-=-=-=-
>
>I'm proposing adoption of a new functions in libc:
>- strsuftoi(3),
>- strsuftou(3),
>- their _l counterparts.
>
>Their are built over strtoi(3) and strtou(3), which are part of the
>Standard C Library in NetBSD-7.0. The only difference between *i and *u
>functions is operating over signed or unsigned values.
>
>These functions take exactly the same arguments as strtoi(3) and
>strtou(3), just they return different status values and they can handle
>multiplication of products in nptr.
>
>intmax_t
>strsuftoi(const char * restrict nptr, char ** restrict endptr, int base,
>         intmax_t lo, intmax_t hi, int *rstatus);
>
>The strsuftoi() function converts the string in nptr to an intmax_t
>value.  Two or more numbers may be separated by an ``x'' or ``*'' to
>indicate a product.
>
>Each number may have one of the following optional suffixes:
>
>      b    Block; multiply by 512
>      k    Kibi; multiply by 1024 (1 KiB)
>      m    Mebi; multiply by 1048576 (1 MiB)
>      g    Gibi; multiply by 1073741824 (1 GiB)
>      t    Tebi; multiply by 1099511627776 (1 TiB)
>      p    Pebi; multiply by 1125899906842624 (1 PiB)
>      e    Exbi; multiply by 1152921504606846976 (1 EiB)
>      w    Word; multiply by the number of bytes in an integer
>
> -- strsuftoi(3)
>
>There is one homegrown function with the same name (strsuftoi()) in
>ftp(1), used to parse commands.
>
>Commands which take a byte count as an argument (e.g., hash, rate, and
>xferbuf) support an optional suffix on the argument which changes the
>interpretation of the argument.  Supported suffixes are:
>      b    Causes no modification.  (Optional)
>      k    Kilo; multiply the argument by 1024
>      m    Mega; multiply the argument by 1048576
>      g    Giga; multiply the argument by 1073741824
>
> -- ftp(1)
>
>There is already strsuftoll(3) (it even calls exit internally) and
>strsuftollx(3). New functions are aimed to replace them and address the
>issues mentioned in the strsuftoi(3) manpage:
>
>The strsuftoi() function first appeared in NetBSD 8.  The strsuftoll(3)
>function was introduced in NetBSD 2 for the same purpose, but the
>interface makes it impossible to use safely and differentiate illegal
>returns.  The strsuftoi() functions is intentionally based on strtoi(3)
>to extend its features and fix the following problems of strsuftoll(3):
>
>o   Stop ignoring locale.
>o   Fail gracefully in case of invalid input data.
>o   Return intmax_t instead of long long.
>o   Stop being prone to buffer overflows when used incorrectly.
>o   Stop returning English strings.
>o   Stop calling exit(3) in case of invalid string.
>
> -- strsuftoi(3)
>
>strsuftoll(3) and strsuftollx(3) are used in:
>- dd(1),
>- makefs(8),
>- fssconfig(8),
>- vndcompress(1),
>- progress(1),
>- midirecord(1),
>- audioplay(1), audiorecord(1),
>- tunefs(8),
>- ftp(1).
>
>There are homegrown functions for the strsuftoi(3) functionality (called
>strsuftoi64()) to handle suffixes:
>
>Options with numeric arguments may contain an optional (case-insensitive)
>suffix:
>      b    Bytes; causes no modification.  (Default)
>      k    Kilo; multiply the argument by 1024.
>      m    Mega; multiply the argument by 1048576.
>      g    Giga; multiply the argument by 1073741824.
>      t    Tera; multiply the argument by 1099511627776.
>
>  -- newfs(8)
>
>Our tool login.conf(5) has homegrown functionality for the same purpose:
>
>size       A number which expresses a size in bytes.  It may have a
>           trailing b to multiply the value by 512, a k to multiply the
>           value by 1 K (1024), and a m to multiply the value by 1 M
>           (1048576).
>
>  -- login.conf(5)
>
>There is undocumented support for g (giga) and t (tera) in the source code.
>
>The code checking for overflows in multiplication is quite complicated,
>I'm attaching just the comments to follow the algorithm:
>
>
>        /*
>         * Get rid of the simple cases
>         */
>
>        /*
>         * sizeof() returns number of bytes needed for storage.
>         * This may be different from the actual number of useful bits.
>         */
>
>        /*
>         * First check the magnitude of each number.  If the sum of the
>         * magnatude is way to high, reject the number.  (If this test
>         * is not done then the first multiply below may overflow.)
>         */
>
>        /*
>         * Decompose the multiplication to be:
>         * h1 = n1 & ~1
>         * h2 = n2 &~1
>         * l1 = n1 & 1
>         * l2 = n2 & 1
>         * (h1 + l1) * (h2 + l2)
>         * (h1 * h2) + (h1 * l2) + (l1 * h2) + (l1 * l2)
>         *
>         * Since h1 && h2 do not have the low bit set, we can then say:
>         *
>         * (h1>>1 * h2>>1 * 4) + ...
>         *
>         * So if (h1>>1 * h2>>1) > (1<<(bpw - 2)) then the result will
>         * overflow.
>         *
>         * Finally, if MAX - ((h1 * l2) + (l1 * h2) + (l1 * l2))<(h1*h2)
>         * then adding in residual amout will cause an overflow.
>         */
>
>  -- src/lib/libutil/login_cap.c
>
>I'm attaching a patch for review adding strsuftoi(3) and strsuftou(3).
>This patch requires immediate switch in ftp(1) (or rename local
>homegrown strsuftoi() to something else..).
>
>Things not to be discussed:
>1. Whether string like '123x 123' is legal or not. Traditionally we
>strip whitespace from the beginning of strtol(3) like functions. '123
>x123' isn't fully converted string, while '123x 123' is. I was thinking
>about making only initial whitespace to the whole input (like '
>123x123') legal.
>2. Streamline 'b' meaning, change from nothing/dummy argument to block
>size (512 bytes).
>3. Accept uppercase and lowercase multiplication types (for
>compatibility with existing software and orders)?
>
>I don't see need for these functions in kernel or libstand, if you think
>it might be usable, please let me know and I will move it to src/common.
>
>estrsuftoi(3) and estrsuftou(3) will come with a next patch. Later I
>will propose a patch to switch our tools, one after another.
>
>At the end, I would like to obsolete strsuftoll(3) and strsuftollx(3)
>entirely.
>
>Originally, I had overflow library ideas, to be used by reallocarr(3)
>and strsuftoi(3) functions, however this isn't implementable without GCC
>or C11 compatible compiler. I'm adding a wild assumption in my
>implementation towards positive and negative values representation - I
>stripped the case of abs(type_min_value) = abs(type_max_value). It may
>be enforced by POSIX anyway.

This looks fine to me, what do others think?

christos



Home | Main Index | Thread Index | Old Index