Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libHX for openSUSE:Factory checked in at 2021-10-20 20:23:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libHX (Old) and /work/SRC/openSUSE:Factory/.libHX.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libHX" Wed Oct 20 20:23:43 2021 rev:64 rq:925881 version:4.2 Changes: -------- --- /work/SRC/openSUSE:Factory/libHX/libHX.changes 2021-10-16 22:47:17.984674703 +0200 +++ /work/SRC/openSUSE:Factory/.libHX.new.1890/libHX.changes 2021-10-20 20:24:30.293386245 +0200 @@ -1,0 +2,8 @@ +Sun Oct 17 16:55:45 UTC 2021 - Jan Engelhardt <jeng...@inai.de> + +- Update to release 4.2 + * string: New functions ``HX_strtod_unit``, ``HX_strtoull_unit``, + ``HX_unit_size``, ``HX_unit_size_cu`` for converting between + sizes and human-readable sizes like 1457664 <-> "1.45M"/"1.39M". + +------------------------------------------------------------------- Old: ---- libHX-4.1.tar.asc libHX-4.1.tar.xz New: ---- libHX-4.2.tar.asc libHX-4.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libHX.spec ++++++ --- /var/tmp/diff_new_pack.uFCO4t/_old 2021-10-20 20:24:30.785386549 +0200 +++ /var/tmp/diff_new_pack.uFCO4t/_new 2021-10-20 20:24:30.785386549 +0200 @@ -18,7 +18,7 @@ Name: libHX %define lname libHX32 -Version: 4.1 +Version: 4.2 Release: 0 Summary: Collection of routines for C and C++ programming License: LGPL-2.1-or-later ++++++ libHX-4.1.tar.xz -> libHX-4.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/Makefile.in new/libHX-4.2/Makefile.in --- old/libHX-4.1/Makefile.in 2021-10-13 14:57:21.762033922 +0200 +++ new/libHX-4.2/Makefile.in 2021-10-17 15:37:10.051321241 +0200 @@ -290,7 +290,6 @@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -LYX = @LYX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/configure new/libHX-4.2/configure --- old/libHX-4.1/configure 2021-10-13 14:57:20.466030028 +0200 +++ new/libHX-4.2/configure 2021-10-17 15:37:08.775317490 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libHX 4.1. +# Generated by GNU Autoconf 2.69 for libHX 4.2. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='libHX' PACKAGE_TARNAME='libhx' -PACKAGE_VERSION='4.1' -PACKAGE_STRING='libHX 4.1' +PACKAGE_VERSION='4.2' +PACKAGE_STRING='libHX 4.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -635,9 +635,6 @@ regular_CXXFLAGS regular_CFLAGS regular_CPPFLAGS -BUILD_DOCS_FALSE -BUILD_DOCS_TRUE -LYX libsocket_LIBS libpthread_LIBS librt_LIBS @@ -1340,7 +1337,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libHX 4.1 to adapt to many kinds of systems. +\`configure' configures libHX 4.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1410,7 +1407,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libHX 4.1:";; + short | recursive ) echo "Configuration of libHX 4.2:";; esac cat <<\_ACEOF @@ -1525,7 +1522,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libHX configure 4.1 +libHX configure 4.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2251,7 +2248,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libHX $as_me 4.1, which was +It was created by libHX $as_me 4.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3112,7 +3109,7 @@ # Define the identity of the package. PACKAGE='libhx' - VERSION='4.1' + VERSION='4.2' cat >>confdefs.h <<_ACEOF @@ -17096,56 +17093,6 @@ fi done -for ac_prog in lyx -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_LYX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$LYX"; then - ac_cv_prog_LYX="$LYX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_LYX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -LYX=$ac_cv_prog_LYX -if test -n "$LYX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LYX" >&5 -$as_echo "$LYX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$LYX" && break -done - - if test -n "$LYX"; then - BUILD_DOCS_TRUE= - BUILD_DOCS_FALSE='#' -else - BUILD_DOCS_TRUE='#' - BUILD_DOCS_FALSE= -fi - regular_CPPFLAGS="-D_FILE_OFFSET_BITS=64 -D_REENTRANT" regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ @@ -17311,10 +17258,6 @@ as_fn_error $? "conditional \"HAVE_DLFCN_H\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${BUILD_DOCS_TRUE}" && test -z "${BUILD_DOCS_FALSE}"; then - as_fn_error $? "conditional \"BUILD_DOCS\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 @@ -17712,7 +17655,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libHX $as_me 4.1, which was +This file was extended by libHX $as_me 4.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17778,7 +17721,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libHX config.status 4.1 +libHX config.status 4.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/configure.ac new/libHX-4.2/configure.ac --- old/libHX-4.1/configure.ac 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/configure.ac 2021-10-17 15:36:53.000000000 +0200 @@ -1,4 +1,4 @@ -AC_INIT([libHX], [4.1]) +AC_INIT([libHX], [4.2]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) @@ -106,8 +106,6 @@ AC_CHECK_FUNCS([fork execv execvp pipe]) AC_CHECK_FUNCS([getegid geteuid getpid getppid]) AC_CHECK_FUNCS([initgroups setgid]) -AC_CHECK_PROGS([LYX], [lyx]) -AM_CONDITIONAL([BUILD_DOCS], [test -n "$LYX"]) regular_CPPFLAGS="-D_FILE_OFFSET_BITS=64 -D_REENTRANT" regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/doc/api.rst new/libHX-4.2/doc/api.rst --- old/libHX-4.1/doc/api.rst 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/doc/api.rst 2021-10-17 15:36:53.000000000 +0200 @@ -9,6 +9,10 @@ ====== ====== ====== ======================================== RMV MinVer FirstA Name ====== ====== ====== ======================================== +4.2 4.2 4.2 HX_unit_size +4.2 4.2 4.2 HX_unit_size_cu +4.2 4.2 4.2 HX_strtod_unit +4.2 4.2 4.2 HX_strtoull_unit 3.27 3.27 3.27 HXOPT_KEEP_ARGV 3.27 3.27 3.27 HXproc_top_fd 3.27 3.27 3.27 HXproc_switch_user diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/doc/changelog.rst new/libHX-4.2/doc/changelog.rst --- old/libHX-4.1/doc/changelog.rst 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/doc/changelog.rst 2021-10-17 15:36:53.000000000 +0200 @@ -1,3 +1,13 @@ +v4.2 (2021-10-17) +================= + +Enhancements: + +* string: New functions ``HX_strtod_unit``, ``HX_strtoull_unit``, + ``HX_unit_size``, ``HX_unit_size_cu`` for converting between + sizes and human-readable sizes like 1457664 <-> "1.45M"/"1.39M". + + v4.1 (2021-10-13) ================= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/doc/string_ops.rst new/libHX-4.2/doc/string_ops.rst --- old/libHX-4.1/doc/string_ops.rst 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/doc/string_ops.rst 2021-10-17 15:36:53.000000000 +0200 @@ -316,7 +316,7 @@ .. code-block:: c - #include <libHX/string.h>libHX/string.h + #include <libHX/string.h> void *HX_memdup(const void *ptr, size_t length); char *HX_strdup(const char *str); @@ -352,6 +352,87 @@ deprecated, albeit no replacement is proposed. +Numbers to human-readable sizes with units +========================================== + +.. code-block:: c + + #include <libHX/string.h> + + char *HX_unit_size(char *out, size_t outsize, unsigned long long number, + unsigned int divisor, unsigned int cutoff); + char *HX_unit_size_p90(char *out, size_t outsize, + unsigned long long number, unsigned int divisor); + +``HX_unit_size`` takes an arbitrary number and and produces a more +readily-readable shortened (string) representation with a unit suffix. It does +this by dividing ``number`` by ``pow(divisor, i)`` for some integer _i_ such +that the resulting (integer) quotient is the highest possible value _v_ that is +less than ``cutoff``. This value _v_ is then emitted into ``out`` together with +the corresponding SI prefix. + +Note that the SI prefix for one iteration (i==1), i.e. kilo, is a lower-case +``'k'``. If you need consistent upper-case output in your program, (i.e. K/M/G +instead of k/M/G), use a subsequent call to ``HX_strupper``. + +When ``divisor`` is 0, it defaults to 1000. When ``cutoff`` is 0, an +implementation-defined cutoff point is used. When ``cutoff`` is less than +``divisor``, the result is implementation-defined. + +The output number of ``HX_unit_size`` is always integer; no fractions are +emitted. This is rooted in the following idea: + +* An output like ``1G`` is quite broad and some precision would be nice. The + author has historically preferred 3 digits instead of just 2, thanks to wget + and rsync. + +* ``1.34G`` has the same string length as ``1340M``, i.e. both occupy the same + visual space in console outputs, but the latter has another digit of + precision. + +* By ditching fractions this way, ``HX_unit_size`` also sidesteps the issue of + excess digits being emitted (usually up to 5) from the trivial use (by + wget/rsync) of ``printf("%.2f",??v)``. + +The ``HX_unit_size_cu`` function will instead mimic the behavior of coreutils +(/usr/bin/df, /usr/bin/ls). That is, it divides ``number`` by ``pow(divisor, +i)`` for some integer _i_ such that the resulting (real) quotient is +less-than-or-equal ``divisor-1``. It rounds the value up to the next integer if +the fractional part is >90%, and if the quotient is greater-or-equal 10, the +fractional part is stripped and not emitted to ``out``. + +In practice, the rounding up of ``HX_unit_size_cu`` lends itself to display +occupying sizes, whereas the implicit rounding down (of integer divisions) +in ``HX_unit_size`` lend itself to sizes in progress meters. + + +Unit-suffixed numbers to full numbers +===================================== + +.. code-block:: c + + #include <libHX/string.h> + + double HX_strtod_unit(const char *s, char **end, + unsigned int exponent); + unsigned long long HX_strtoull_unit(const char *s, char **end, + unsigned int exponent); + +The ``HX_strtod_unit`` and ``HX_strtoull_unit`` functions behave similar to +``strtod`` and ``strtoul``, respectively, in that they convert the initial part +of the string in ``s`` to a ``double`` and ``unsigned long long``, +respectively, and apply the selected multiplication factor from ``exponent`` in +resolving an optional unit suffix. + +Upon overflow, ``errno`` is set to ``ERANGE`` just like the stdlib functions. +Unlike some implementations of ``strtoul``, negative numbers are outright +rejected. + +.. code-block:: c + + unsigned long long bytes = HX_strtoull_unit("1.5G", NULL, 1024); + + Examples ======== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/include/Makefile.in new/libHX-4.2/include/Makefile.in --- old/libHX-4.1/include/Makefile.in 2021-10-13 14:57:21.798034030 +0200 +++ new/libHX-4.2/include/Makefile.in 2021-10-17 15:37:10.087321346 +0200 @@ -217,7 +217,6 @@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -LYX = @LYX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/include/libHX/string.h new/libHX-4.2/include/libHX/string.h --- old/libHX-4.1/include/libHX/string.h 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/include/libHX/string.h 2021-10-17 15:36:53.000000000 +0200 @@ -90,6 +90,10 @@ extern char *HX_strsep(char **, const char *); extern char *HX_strsep2(char **, const char *); extern char *HX_strupper(char *); +extern double HX_strtod_unit(const char *, char **, unsigned int exponent); +extern unsigned long long HX_strtoull_unit(const char *, char **, unsigned int exponent); +extern char *HX_unit_size(char *out, size_t bufsize, unsigned long long size, unsigned int divisor, unsigned int cutoff); +extern char *HX_unit_size_cu(char *out, size_t bufsize, unsigned long long size, unsigned int divisor); static __inline__ void *HX_memdup(const void *buf, size_t len) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/src/Makefile.am new/libHX-4.2/src/Makefile.am --- old/libHX-4.1/src/Makefile.am 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/src/Makefile.am 2021-10-17 15:36:53.000000000 +0200 @@ -12,8 +12,8 @@ libHX_la_SOURCES = deque.c dl.c format.c io.c map.c \ mc.c misc.c opt.c proc.c \ rand.c socket.c string.c time.c -libHX_la_LIBADD = ${libdl_LIBS} ${libpthread_LIBS} ${librt_LIBS} -libHX_la_LDFLAGS = -no-undefined -version-info 33:0:1 +libHX_la_LIBADD = ${libdl_LIBS} -lm ${libpthread_LIBS} ${librt_LIBS} +libHX_la_LDFLAGS = -no-undefined -version-info 34:0:2 if WITH_GNU_LD libHX_la_LDFLAGS += -Wl,--version-script=${srcdir}/libHX.map endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/src/Makefile.in new/libHX-4.2/src/Makefile.in --- old/libHX-4.1/src/Makefile.in 2021-10-13 14:57:21.930034427 +0200 +++ new/libHX-4.2/src/Makefile.in 2021-10-17 15:37:10.231321769 +0200 @@ -688,7 +688,6 @@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -LYX = @LYX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -779,8 +778,8 @@ lib_LTLIBRARIES = libHX.la $(am__append_1) libHX_la_SOURCES = deque.c dl.c format.c io.c map.c mc.c misc.c opt.c \ proc.c rand.c socket.c string.c time.c $(am__append_3) -libHX_la_LIBADD = ${libdl_LIBS} ${libpthread_LIBS} ${librt_LIBS} -libHX_la_LDFLAGS = -no-undefined -version-info 33:0:1 $(am__append_2) +libHX_la_LIBADD = ${libdl_LIBS} -lm ${libpthread_LIBS} ${librt_LIBS} +libHX_la_LDFLAGS = -no-undefined -version-info 34:0:2 $(am__append_2) EXTRA_libHX_la_DEPENDENCIES = libHX.map libHX_rtcheck_la_SOURCES = rtcheck.c libHX_rtcheck_la_LIBADD = ${libdl_LIBS} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/src/libHX.map new/libHX-4.2/src/libHX.map --- old/libHX-4.1/src/libHX.map 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/src/libHX.map 2021-10-17 15:36:53.000000000 +0200 @@ -135,3 +135,11 @@ HXproc_switch_user; HXproc_top_fd; } LIBHX_3.25; + +LIBHX_4.2 { +global: + HX_strtod_unit; + HX_strtoull_unit; + HX_unit_size; + HX_unit_size_cu; +} LIBHX_3.27; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/src/string.c new/libHX-4.2/src/string.c --- old/libHX-4.1/src/string.c 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/src/string.c 2021-10-17 15:36:53.000000000 +0200 @@ -8,6 +8,8 @@ * either version 2.1 or (at your option) any later version. */ #include <errno.h> +#include <limits.h> +#include <math.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> @@ -836,3 +838,169 @@ *expr = HX_toupper(*expr); return orig; } + +EXPORT_SYMBOL char *HX_unit_size(char *buf, size_t bufsize, + unsigned long long size, unsigned int divisor, unsigned int cutoff) +{ + static const char unit_names[] = "\0kMGTPEZYRQ"; + unsigned int unit_idx = 0; + if (divisor == 0) + divisor = 1000; + if (cutoff == 0) { + cutoff = 10000; + if (cutoff < divisor) + cutoff = divisor; + } + while (unit_idx < ARRAY_SIZE(unit_names) - 1 && size >= cutoff) { + ++unit_idx; + size /= divisor; + } + snprintf(buf, bufsize, "%llu%.1s", size, &unit_names[unit_idx]); + return buf; +} + +static inline unsigned long long p_90(unsigned long long x) +{ + /* Perform x*9/10, but without the risk of overflow. */ + return x - x / 10 - !!(x % 10); +} + +EXPORT_SYMBOL char *HX_unit_size_cu(char *buf, size_t bufsize, + unsigned long long orig_size, unsigned int divisor) +{ + /* No floating point. Take that, coreutils! */ + static const char unit_names[] = "\0kMGTPEZYRQ"; + unsigned int unit_idx = 0, last_rem = 0; + unsigned long long size = orig_size, gpow = 1, grand_rem; + if (divisor == 0) + divisor = 1000; + + while (unit_idx < ARRAY_SIZE(unit_names) - 1 && size >= divisor) { + ++unit_idx; + last_rem = size % divisor; + size /= divisor; + gpow *= divisor; + } + if (unit_idx == 0) { + snprintf(buf, bufsize, "%llu%.1s", size, &unit_names[unit_idx]); + return buf; + } + grand_rem = orig_size - size * gpow; + if (grand_rem != 0) { + if (grand_rem > p_90(gpow)) { + ++size; + last_rem = 0; + } else { + last_rem *= 10; + last_rem /= divisor; + ++last_rem; + if (last_rem == 10 || (size >= 10 && last_rem > 0)) { + ++size; + last_rem = 0; + } + } + if (unit_idx < ARRAY_SIZE(unit_names) - 1 && size == divisor) { + /* ++size from above may brought size to @divisor again */ + ++unit_idx; + size /= divisor; + } + } + if (size >= 10 && last_rem == 0) + snprintf(buf, bufsize, "%llu%.1s", size, &unit_names[unit_idx]); + else + snprintf(buf, bufsize, "%llu.%01u%.1s", size, last_rem, &unit_names[unit_idx]); + return buf; +} + +static unsigned int suffix_power(char u) +{ + switch (HX_toupper(u)) { + case 'K': return 1; + case 'M': return 2; + case 'G': return 3; + case 'T': return 4; + case 'P': return 5; + case 'E': return 6; + case 'Z': return 7; + case 'Y': return 8; + case 'R': return 9; + case 'Q': return 10; + default: return 0; + } +} + +EXPORT_SYMBOL double HX_strtod_unit(const char *s, char **out_end, unsigned int exponent) +{ + char *end; + double q; + + while (HX_isspace(*s)) + ++s; + if (*s == '-') { + if (out_end != nullptr) + *out_end = const_cast(char *, s); + errno = ERANGE; + return ULLONG_MAX; + } + q = strtod(s, &end); + if (exponent == 0) + exponent = 1000; + if (end == s) { + if (out_end != nullptr) + *out_end = end; + return q; + } + while (HX_isspace(*end)) + ++end; + unsigned int pwr = suffix_power(*end); + if (pwr == 0) { + if (out_end != nullptr) + *out_end = const_cast(char *, end); + return q; + } + if (out_end != nullptr) + *out_end = const_cast(char *, end + 1); + return q * pow(exponent, pwr); +} + +EXPORT_SYMBOL unsigned long long HX_strtoull_unit(const char *s, + char **out_end, unsigned int exponent) +{ + char *end; + unsigned long long ipart; + unsigned int pwr = 0; + + while (HX_isspace(*s)) + ++s; + if (*s == '-') { + if (out_end != nullptr) + *out_end = const_cast(char *, s); + errno = ERANGE; + return ULLONG_MAX; + } + ipart = strtoull(s, &end, 10); + if (*end == '.') { + double q = HX_strtod_unit(s, out_end, exponent); + return q < ULLONG_MAX ? q : ULLONG_MAX; + } + if (exponent == 0) + exponent = 1000; + while (HX_isspace(*end)) + ++end; + pwr = suffix_power(*end); + if (pwr == 0) { + if (out_end != nullptr) + *out_end = end; + return ipart; + } + if (out_end != nullptr) + *out_end = const_cast(char *, end + 1); + while (pwr-- > 0) { + if (ipart >= ULLONG_MAX / exponent) { + errno = ERANGE; + return ULLONG_MAX; + } + ipart *= exponent; + } + return ipart; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libHX-4.1/src/tc-string.c new/libHX-4.2/src/tc-string.c --- old/libHX-4.1/src/tc-string.c 2021-10-13 14:54:52.000000000 +0200 +++ new/libHX-4.2/src/tc-string.c 2021-10-17 15:36:53.000000000 +0200 @@ -288,6 +288,135 @@ assert(a[0] == 49 && a[0] == a[1] && a[1] == a[2]); } +static void t_units(void) +{ + static const struct { + unsigned long long num; + const char exp_1024[6], exp_1000[6]; + } vt[] = { + {1023, "1023", "1023"}, + {1024, "1024", "1024"}, + {1945, "1945", "1945"}, + {1946, "1946", "1946"}, + {1022975, "998k", "1022k"}, + {1022976, "999k", "1022k"}, + {1022977, "999k", "1022k"}, + {1047552, "1023k", "1047k"}, + {1047553, "1023k", "1047k"}, + {1992294, "1945k", "1992k"}, + {1992295, "1945k", "1992k"}, + {1072693248, "1023M", "1072M"}, + {1072693249, "1023M", "1072M"}, + {ULLONG_MAX, "15E", "18E"}, + }; + char buf[HXSIZEOF_Z64+3]; + printf("unit_size:\n"); + + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + HX_unit_size(buf, ARRAY_SIZE(buf), vt[i].num, 1024, 9120); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1024) != 0) { + printf("\texpected %s\n", vt[i].exp_1024); + abort(); + } + HX_unit_size(buf, ARRAY_SIZE(buf), vt[i].num, 1000, 9120); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1000) != 0) { + printf("\texpected %s\n", vt[i].exp_1000); + abort(); + } + } +} + +static void t_units_cu(void) +{ + static const struct { + unsigned long long num; + const char exp_1024[6], exp_1000[6]; + } vt[] = { + {1023, "1023", "1.1k"}, + {1024, "1.0k", "1.1k"}, + {1945, "1.9k", "2.0k"}, + {1946, "2.0k", "2.0k"}, + {1022975, "999k", "1.1M"}, + {1022976, "999k", "1.1M"}, + {1022977, "1000k", "1.1M"}, + {1047552, "1023k", "1.1M"}, + {1047553, "1.0M", "1.1M"}, + {1992294, "1.9M", "2.0M"}, + {1992295, "2.0M", "2.0M"}, + {1072693248, "1023M", "1.1G"}, + {1072693249, "1.0G", "1.1G"}, + {ULLONG_MAX, "16E", "19E"}, + }; + char buf[80]; + printf("unit_size_cu:\n"); + + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + HX_unit_size_cu(buf, ARRAY_SIZE(buf), vt[i].num, 1024); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1024) != 0) { + printf("\texpected %s\n", vt[i].exp_1024); + abort(); + } + HX_unit_size_cu(buf, ARRAY_SIZE(buf), vt[i].num, 1000); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1000) != 0) { + printf("\texpected %s\n", vt[i].exp_1000); + abort(); + } + } +} + +static void t_units_strto(void) +{ + static const struct { + const char input[24]; + unsigned int exponent; + unsigned long long expect_out; + const char expect_rem[8]; + } vt[] = { + {"-5k", 1000, ULLONG_MAX, "-5k"}, + {" -5.2k", 1000, ULLONG_MAX, "-5.2k"}, + {"1", 9999, 1, ""}, + {"1024", 9999, 1ULL << 10, ""}, + {"1048576", 9999, 1ULL << 20, ""}, + {"1073741824", 9999, 1ULL << 30, ""}, + {"1099511627776", 9999, 1ULL << 40, ""}, + {"1125899906842624", 9999, 1ULL << 50, ""}, + {"1152921504606846976", 9999, 1ULL << 60, ""}, + {"18446744073709551615", 9, ULLONG_MAX, ""}, + {"1k", 1000, 1000ULL, ""}, + {"1M", 1000, 1000000ULL, ""}, + {"1G", 1000, 1000000000ULL, ""}, + {"1T", 1000, 1000000000000ULL, ""}, + {"1P", 1000, 1000000000000000ULL, ""}, + {"1E", 1000, 1000000000000000000ULL, ""}, + {"1k", 1024, 1ULL << 10, ""}, + {"1M", 1024, 1ULL << 20, ""}, + {"1G", 1024, 1ULL << 30, ""}, + {"1T", 1024, 1ULL << 40, ""}, + {"1P", 1024, 1ULL << 50, ""}, + {"1E", 1024, 1ULL << 60, ""}, + {"0", 0, 0, ""}, + {"0k", 0, 0, ""}, + {"0 Z", 0, 0, ""}, + {"0.1k", 1000, 100, ""}, + {"0.1k", 1024, 102, ""}, + {" 0.1k", 1024, 102, ""}, + {"0.00000000000000001E", 1024, 11, ""}, + {"1.525444GiB", 1000, 1525444000, "iB"}, + {"1.525444GiB", 1024, 1637933022, "iB"}, + }; + char *end; + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + unsigned long long q = HX_strtoull_unit(vt[i].input, &end, vt[i].exponent); + printf("%s -> %llu __ %s\n", vt[i].input, q, end); + if (q != vt[i].expect_out || strcmp(end, vt[i].expect_rem) != 0) + printf("BUG\n"); + } +} + int main(int argc, const char **argv) { hxmc_t *tx = NULL; @@ -316,6 +445,9 @@ t_strtrim(); t_split(); t_split2(); + t_units(); + t_units_cu(); + t_units_strto(); t_strlcpy(); t_strlcpy2(); HXmc_free(tx);