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