From e0f5b654428455ff44d072eabd8ebc9ad30599a6 Mon Sep 17 00:00:00 2001 From: stefanocasazza Date: Tue, 11 Feb 2020 18:38:45 +0100 Subject: [PATCH] sync --- configure | 180 ++++---- configure.ac | 95 ++-- examples/WiAuth/v2/wi_auth_declaration2.h | 26 +- include/ulib/examples/wi_auth_declaration.h | 2 +- include/ulib/internal/config.h.in | 3 + include/ulib/net/client/redis.h | 5 + include/ulib/net/ipaddress.h | 40 +- include/ulib/orm/orm.h | 4 + include/ulib/serialize/flatbuffers.h | 4 + include/ulib/string.h | 8 + src/ulib/net/ipaddress.cpp | 66 ++- src/ulib/net/server/plugin/mod_nocat.cpp | 4 +- src/ulib/net/server/plugin/mod_nodog.cpp | 2 +- src/ulib/net/server/server.cpp | 2 +- src/ulib/utility/interrupt.cpp | 4 + src/ulib/utility/uhttp.cpp | 2 +- src/ulib/utility/websocket.cpp | 2 +- tests/examples/TSA/tsaserial | 2 +- tests/ulib/Makefile.am | 4 +- tests/ulib/Makefile.in | 72 ++- tests/ulib/README | 8 +- {src/ulib/internal => tests/ulib}/branchlut.h | 0 tests/ulib/dtoa_milo.h | 409 ++++++++++++++++++ tests/ulib/eval_dtoa.cpp | 133 ++++++ tests/ulib/eval_itoa.cpp | 139 ++++++ tests/ulib/test_ipaddress.cpp | 59 ++- tests/ulib/tsc.h | 113 +++++ 27 files changed, 1191 insertions(+), 197 deletions(-) rename {src/ulib/internal => tests/ulib}/branchlut.h (100%) create mode 100644 tests/ulib/dtoa_milo.h create mode 100644 tests/ulib/eval_dtoa.cpp create mode 100644 tests/ulib/eval_itoa.cpp create mode 100644 tests/ulib/tsc.h diff --git a/configure b/configure index b20e02a4..8ed7c087 100755 --- a/configure +++ b/configure @@ -915,10 +915,10 @@ MINGW_FALSE MINGW_TRUE LINUX_FALSE LINUX_TRUE -CLANG_FALSE -CLANG_TRUE INTEL_FALSE INTEL_TRUE +CLANG_FALSE +CLANG_TRUE LN_S am__fastdepCXX_FALSE am__fastdepCXX_TRUE @@ -7586,85 +7586,37 @@ _ACEOF esac -# clang is mostly GCC-compatible, but its version is much lower, so we have to check for it -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiling with Intel C++" >&5 -$as_echo_n "checking if compiling with Intel C++... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiling with GNU C++" >&5 +$as_echo_n "checking if compiling with GNU C++... " >&6; } +GCC_COMPILER=$($CXX --version 2>/dev/null | grep -v -E '(llvm|clang)' | grep -i -c -E '(gcc|g\+\+)') -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - -#ifndef __INTEL_COMPILER -not intel -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - GCC_IS_INTEL=yes +GCC_IS_GNU=no +if [ "$GCC_COMPILER" -eq 0 ]; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } else - GCC_IS_INTEL=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + GCC_IS_GNU=yes + gcc_version=`gcc -dumpversion` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($gcc_version)" >&5 +$as_echo "yes ($gcc_version)" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCC_IS_INTEL" >&5 -$as_echo "$GCC_IS_INTEL" >&6; } -#AC_SUBST(GCC_IS_INTEL) +$as_echo "#define GCC_IS_GNU 1" >>confdefs.h - if false; then - INTEL_TRUE= - INTEL_FALSE='#' -else - INTEL_TRUE='#' - INTEL_FALSE= -fi - -if test "$GCC_IS_INTEL" = "yes"; then - if true; then - INTEL_TRUE= - INTEL_FALSE='#' -else - INTEL_TRUE='#' - INTEL_FALSE= -fi - -gcc_version=`icc -dumpversion` fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiling with clang" >&5 $as_echo_n "checking if compiling with clang... " >&6; } +CLANG_COMPILER=$($CXX --version 2>/dev/null | grep -i -c -E '(llvm|clang)') -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - -#ifndef __clang__ -not clang -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - GCC_IS_CLANG=yes -else - GCC_IS_CLANG=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCC_IS_CLANG" >&5 -$as_echo "$GCC_IS_CLANG" >&6; } -#AC_SUBST(GCC_IS_CLANG) +# AC_COMPILE_IFELSE( +# [AC_LANG_PROGRAM([], [[ +# #ifndef __clang__ +# not clang +# #endif +# ]])], +# [GCC_IS_CLANG=yes], [GCC_IS_CLANG=no]) +GCC_IS_CLANG=no if false; then CLANG_TRUE= CLANG_FALSE='#' @@ -7673,8 +7625,12 @@ else CLANG_FALSE= fi -if test "$GCC_IS_CLANG" = "yes"; then - if true; then +if [ "$CLANG_COMPILER" -eq 0 ]; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + GCC_IS_CLANG=yes + if true; then CLANG_TRUE= CLANG_FALSE='#' else @@ -7682,9 +7638,54 @@ else CLANG_FALSE= fi -gcc_version=`clang -dumpversion` + gcc_version=`clang -dumpversion` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($gcc_version)" >&5 +$as_echo "yes ($gcc_version)" >&6; } fi +#AC_SUBST(GCC_IS_CLANG) + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiling with Intel C++" >&5 +$as_echo_n "checking if compiling with Intel C++... " >&6; } +INTEL_COMPILER=$($CXX --version 2>/dev/null | grep -i -c '\(icc\)') + +# AC_COMPILE_IFELSE( +# [AC_LANG_PROGRAM([], [[ +# #ifndef __INTEL_COMPILER +# not intel +# #endif +# ]])], +# [GCC_IS_INTEL=yes], [GCC_IS_INTEL=no]) + +GCC_IS_INTEL=no + if false; then + INTEL_TRUE= + INTEL_FALSE='#' +else + INTEL_TRUE='#' + INTEL_FALSE= +fi + +if [ "$INTEL_COMPILER" -eq 0 ]; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + GCC_IS_INTEL=yes + if true; then + INTEL_TRUE= + INTEL_FALSE='#' +else + INTEL_TRUE='#' + INTEL_FALSE= +fi + + gcc_version=`icc -dumpversion` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($gcc_version)" >&5 +$as_echo "yes ($gcc_version)" >&6; } +fi + +#AC_SUBST(GCC_IS_INTEL) + ULIB_LIBS= MODULE_LIBTOOL_OPTIONS="-shared -export-dynamic -avoid-version" @@ -8610,11 +8611,10 @@ fi # Check for the compiler support gcc_major_4_1="no" -if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then +if test "x$GCC_IS_GNU" = xyes -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then # We don't want gcc 2.7 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a supported version of gcc" >&5 $as_echo_n "checking for a supported version of gcc... " >&6; } - gcc_version=`$CC -dumpversion` case "$gcc_version" in 1.*|2.7.*|2.8.*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no ($gcc_version)" >&5 @@ -21779,7 +21779,7 @@ else STDCPP_FALSE= fi - if test x"$GCC" = "xyes" ; then + if test "x$GCC_IS_GNU" = xyes ; then lcflags="-nodefaultlibs -nostdinc++" else lcflags="-library=no%Cstd -features=no%except -features=no%rtti" @@ -32714,7 +32714,7 @@ fi # If gcc compiler add values to *FLAGS... -if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$OPERATINGSYSTEM" = xlinux; then +if test "x$GCC_IS_GNU" = xyes -a "x$OPERATINGSYSTEM" = xlinux; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 @@ -33258,9 +33258,9 @@ fi case "$target_os" in *bsd*) if test "$enable_stdcpp" != "yes"; then - if test "$GCC" = "yes" -a "$ULIB_LIBC" = "-lc" ; then + if test "x$GCC_IS_GNU" = xyes -a "$ULIB_LIBC" = "-lc" ; then ULIB_LIBC="-Wl,-lc" - elif test "$GCC" = "yes" -a "$ULIB_LIBC" = "-lc_r" ; then + elif test "x$GCC_IS_GNU" = xyes -a "$ULIB_LIBC" = "-lc_r" ; then ULIB_LIBC="-Wl,-lc_r" fi fi @@ -33541,7 +33541,7 @@ if test "x$ac_cv_crc32_intrinsics" = xyes; then fi ########################## -if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then +if test "x$GCC_IS_GNU" = xyes -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then ## if test -f "$gcc_dir/libstdc++.a"; then @@ -33797,7 +33797,7 @@ $as_echo "${T_MD}Output Substitution:${T_ME}" >&6; } # Create compiler version string -if test x"$GCC" = x"yes" ; then +if test "x$GCC_IS_GNU" = xyes ; then cc_string=`${CC} --version | sed q` case $cc_string in [A-Za-z]*) ;; *) cc_string="GCC $cc_string";; esac elif test x"$SUN_STUDIO_CC" = x"yes" ; then @@ -34273,14 +34273,6 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${INTEL_TRUE}" && test -z "${INTEL_FALSE}"; then - as_fn_error $? "conditional \"INTEL\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${INTEL_TRUE}" && test -z "${INTEL_FALSE}"; then - as_fn_error $? "conditional \"INTEL\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${CLANG_TRUE}" && test -z "${CLANG_FALSE}"; then as_fn_error $? "conditional \"CLANG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -34289,6 +34281,14 @@ if test -z "${CLANG_TRUE}" && test -z "${CLANG_FALSE}"; then as_fn_error $? "conditional \"CLANG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${INTEL_TRUE}" && test -z "${INTEL_FALSE}"; then + as_fn_error $? "conditional \"INTEL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${INTEL_TRUE}" && test -z "${INTEL_FALSE}"; then + as_fn_error $? "conditional \"INTEL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then as_fn_error $? "conditional \"LINUX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/configure.ac b/configure.ac index 40c66655..8c2dda6b 100644 --- a/configure.ac +++ b/configure.ac @@ -279,45 +279,67 @@ AC_C_RESTRICT AC_C_VOLATILE AC_C_INLINE -# clang is mostly GCC-compatible, but its version is much lower, so we have to check for it -AC_MSG_CHECKING([if compiling with Intel C++]) +AC_MSG_CHECKING([if compiling with GNU C++]) +GCC_COMPILER=$($CXX --version 2>/dev/null | grep -v -E '(llvm|clang)' | grep -i -c -E '(gcc|g\+\+)') -AC_COMPILE_IFELSE( -[AC_LANG_PROGRAM([], [[ -#ifndef __INTEL_COMPILER -not intel -#endif -]])], -[GCC_IS_INTEL=yes], [GCC_IS_INTEL=no]) - -AC_MSG_RESULT([$GCC_IS_INTEL]) -#AC_SUBST(GCC_IS_INTEL) - -AM_CONDITIONAL(INTEL, false) -if test "$GCC_IS_INTEL" = "yes"; then -AM_CONDITIONAL(INTEL, true) -gcc_version=`icc -dumpversion` +GCC_IS_GNU=no +if [[ "$GCC_COMPILER" -eq 0 ]]; then + AC_MSG_RESULT([no]) +else + GCC_IS_GNU=yes + gcc_version=`gcc -dumpversion` + AC_MSG_RESULT([yes ($gcc_version)]) + AC_DEFINE([GCC_IS_GNU],[1],[Define if we are using gcc compiler]) fi AC_MSG_CHECKING([if compiling with clang]) +CLANG_COMPILER=$($CXX --version 2>/dev/null | grep -i -c -E '(llvm|clang)') -AC_COMPILE_IFELSE( -[AC_LANG_PROGRAM([], [[ -#ifndef __clang__ -not clang -#endif -]])], -[GCC_IS_CLANG=yes], [GCC_IS_CLANG=no]) +# AC_COMPILE_IFELSE( +# [AC_LANG_PROGRAM([], [[ +# #ifndef __clang__ +# not clang +# #endif +# ]])], +# [GCC_IS_CLANG=yes], [GCC_IS_CLANG=no]) + +GCC_IS_CLANG=no +AM_CONDITIONAL(CLANG, false) +if [[ "$CLANG_COMPILER" -eq 0 ]]; then + AC_MSG_RESULT([no]) +else + GCC_IS_CLANG=yes + AM_CONDITIONAL(CLANG, true) + gcc_version=`clang -dumpversion` + AC_MSG_RESULT([yes ($gcc_version)]) +fi -AC_MSG_RESULT([$GCC_IS_CLANG]) #AC_SUBST(GCC_IS_CLANG) -AM_CONDITIONAL(CLANG, false) -if test "$GCC_IS_CLANG" = "yes"; then -AM_CONDITIONAL(CLANG, true) -gcc_version=`clang -dumpversion` +AC_MSG_CHECKING([if compiling with Intel C++]) +INTEL_COMPILER=$($CXX --version 2>/dev/null | grep -i -c '\(icc\)') + +# AC_COMPILE_IFELSE( +# [AC_LANG_PROGRAM([], [[ +# #ifndef __INTEL_COMPILER +# not intel +# #endif +# ]])], +# [GCC_IS_INTEL=yes], [GCC_IS_INTEL=no]) + +GCC_IS_INTEL=no +AM_CONDITIONAL(INTEL, false) +if [[ "$INTEL_COMPILER" -eq 0 ]]; then + AC_MSG_RESULT([no]) +else + GCC_IS_INTEL=yes + AM_CONDITIONAL(INTEL, true) + gcc_version=`icc -dumpversion` + AC_MSG_RESULT([yes ($gcc_version)]) fi +#AC_SUBST(GCC_IS_INTEL) + ULIB_LIBS= MODULE_LIBTOOL_OPTIONS="-shared -export-dynamic -avoid-version" @@ -550,10 +572,9 @@ AM_CONDITIONAL(MS_LIB_AVAILABLE, test x$ms_librarian = xyes) # Check for the compiler support gcc_major_4_1="no" -if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then +if test "x$GCC_IS_GNU" = xyes -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then # We don't want gcc 2.7 AC_MSG_CHECKING([for a supported version of gcc]) - gcc_version=`$CC -dumpversion` case "$gcc_version" in 1.*|2.7.*|2.8.*) AC_MSG_RESULT([no ($gcc_version)]) @@ -716,7 +737,7 @@ if test "$enable_stdcpp" = "yes"; then else AC_MSG_RESULT(no) AM_CONDITIONAL(STDCPP, false) - if test x"$GCC" = "xyes" ; then + if test "x$GCC_IS_GNU" = xyes ; then lcflags="-nodefaultlibs -nostdinc++" else lcflags="-library=no%Cstd -features=no%except -features=no%rtti" @@ -2529,7 +2550,7 @@ fi # If gcc compiler add values to *FLAGS... -if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$OPERATINGSYSTEM" = xlinux; then +if test "x$GCC_IS_GNU" = xyes -a "x$OPERATINGSYSTEM" = xlinux; then TWOCAN_CONF_MSG(Checking for $CC compiler flags) @@ -2778,9 +2799,9 @@ AM_CONDITIONAL(DOXY, test "$DOXYGEN" != "no") case "$target_os" in *bsd*) if test "$enable_stdcpp" != "yes"; then - if test "$GCC" = "yes" -a "$ULIB_LIBC" = "-lc" ; then + if test "x$GCC_IS_GNU" = xyes -a "$ULIB_LIBC" = "-lc" ; then ULIB_LIBC="-Wl,-lc" - elif test "$GCC" = "yes" -a "$ULIB_LIBC" = "-lc_r" ; then + elif test "x$GCC_IS_GNU" = xyes -a "$ULIB_LIBC" = "-lc_r" ; then ULIB_LIBC="-Wl,-lc_r" fi fi @@ -2853,7 +2874,7 @@ if test "x$ac_cv_crc32_intrinsics" = xyes; then fi ########################## -if test "$ac_cv_c_compiler_gnu" = "yes" -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then +if test "x$GCC_IS_GNU" = xyes -a "x$GCC_IS_CLANG" = xno -a "x$GCC_IS_INTEL" = xno; then if test "$enable_static" = "yes" -a "$enable_shared" = "no" -a "$enable_stdcpp" = "yes"; then ## if test -f "$gcc_dir/libstdc++.a"; then @@ -2992,7 +3013,7 @@ fi TWOCAN_CONF_MSG(Output Substitution) # Create compiler version string -if test x"$GCC" = x"yes" ; then +if test "x$GCC_IS_GNU" = xyes ; then cc_string=`${CC} --version | sed q` case $cc_string in [[A-Za-z]]*) ;; *) cc_string="GCC $cc_string";; esac elif test x"$SUN_STUDIO_CC" = x"yes" ; then diff --git a/examples/WiAuth/v2/wi_auth_declaration2.h b/examples/WiAuth/v2/wi_auth_declaration2.h index 5364cfd3..75e7ce81 100644 --- a/examples/WiAuth/v2/wi_auth_declaration2.h +++ b/examples/WiAuth/v2/wi_auth_declaration2.h @@ -103,7 +103,7 @@ loop: *ip = lip; - (void) UIPAddress::getBinaryForm(ip->c_str(), addr, true); + (void) UIPAddress::getBinaryForm(*ip, addr, true); (void) rc->hmset(U_CONSTANT_TO_PARAM("CAPTIVE:id:%u ip %v"), addr, ip->rep); (void) rc->zadd(U_CONSTANT_TO_PARAM("CAPTIVE:byId 0 id:%u"), addr); @@ -380,9 +380,9 @@ static void usp_end_wi_auth2() static bool setLabelAndNetmaskFromAnagrafica(UString& label, UString& netmask) { - U_TRACE(5, "::setLabelAndNetmaskFromAnagrafica(%p,%p,%p)", &label, &netmask) + U_TRACE(5, "::setLabelAndNetmaskFromAnagrafica(%p,%p)", &label, &netmask) - U_INTERNAL_DUMP("ap_address = %V", ap_address) + U_INTERNAL_DUMP("ap_address = %V", ap_address->rep) U_INTERNAL_ASSERT(*ap_address) @@ -393,14 +393,18 @@ static bool setLabelAndNetmaskFromAnagrafica(UString& label, UString& netmask) */ loop: - pos = db_anagrafica->find(*ap_address, pos); + U_INTERNAL_DUMP("pos = %u db_anagrafica->size() = %u", pos, db_anagrafica->size()) - U_INTERNAL_DUMP("pos = %u", pos) + if (pos >= db_anagrafica->size()) U_RETURN(false); + + pos = db_anagrafica->find(*ap_address, pos); if (pos == U_NOT_FOUND) U_RETURN(false); pos += ap_address->size(); + U_INTERNAL_DUMP("db_anagrafica->c_char(%u) = %C", pos, db_anagrafica->c_char(pos)) + if (db_anagrafica->c_char(pos) != ',') goto loop; if (pos != U_NOT_FOUND) @@ -511,7 +515,7 @@ static bool setAccessPoint() *ap_address = ap->substr(pos1+1, pos2-pos1-1).copy(); if (*ap_address && - UIPAddress::getBinaryForm(ap_address->c_str(), addr, true) == false) + UIPAddress::getBinaryForm(*ap_address, addr, true) == false) { U_LOGGER("*** AP ADDRESS(%v) NOT VALID ***", ap_address->rep); @@ -948,7 +952,7 @@ static void lostSession(int bclean) *ap_address = rc->getString(0); *ap_hostname = rc->getString(1); - (void) UIPAddress::getBinaryForm(ip->c_str(), ip_peer); + (void) UIPAddress::getBinaryForm(*ip, ip_peer); addToLogout(*ap_label); } @@ -1100,7 +1104,7 @@ static void GET_checkCaptive() { *ap_address = vec[i]; - (void) UIPAddress::getBinaryForm(ap_address->c_str(), addr, true); + (void) UIPAddress::getBinaryForm(*ap_address, addr, true); url.snprintf(U_CONSTANT_TO_PARAM("http://%v:5280/ping"), ap_address->rep); @@ -1318,7 +1322,7 @@ static void GET_logout() if (getSession(*mac, *ap_label, U_CONSTANT_TO_PARAM("GET_logout"))) { - (void) UIPAddress::getBinaryForm(ip->c_str(), ip_peer); + (void) UIPAddress::getBinaryForm(*ip, ip_peer); idx = 0; @@ -1550,7 +1554,9 @@ static void POST_login() // U_LOGGER("*** SESSION(%V) created at POST_login() ***", key_session->rep); - (void) rc->zadd(U_CONSTANT_TO_PARAM("SESSION:byCaptiveIdAndApId %u%06u deviceId:%v;ip:%v"), addr, ap_label->strtoul(), mac->rep, ip->rep); + const char* ptr = getKeySessionPointer(); + + (void) rc->zadd(U_CONSTANT_TO_PARAM("SESSION:byCaptiveIdAndApId %u%06u %.*s"), addr, ap_label->strtoul(), key_session->remain(ptr), ptr); (void) rc->zadd(U_CONSTANT_TO_PARAM("SESSION:byLastUpdate %u %v"), u_now->tv_sec, key_session->rep); } diff --git a/include/ulib/examples/wi_auth_declaration.h b/include/ulib/examples/wi_auth_declaration.h index a0609460..0c3023fa 100644 --- a/include/ulib/examples/wi_auth_declaration.h +++ b/include/ulib/examples/wi_auth_declaration.h @@ -3455,7 +3455,7 @@ next: if (pvallow) { - if (UIPAllow::isAllowed(user_rec->_ip.data(), *pvallow)) + if (UIPAllow::isAllowed(user_rec->_ip, *pvallow)) { *uid = db_user->getKeyID(); diff --git a/include/ulib/internal/config.h.in b/include/ulib/internal/config.h.in index ec72e573..a776dbf8 100644 --- a/include/ulib/internal/config.h.in +++ b/include/ulib/internal/config.h.in @@ -62,6 +62,9 @@ /* Define to 1 if the fallocate() function is supported */ #undef FALLOCATE_IS_SUPPORTED +/* Define if we are using gcc compiler */ +#undef GCC_IS_GNU + /* GNU C/C++ Compiler version */ #undef GCC_VERSION diff --git a/include/ulib/net/client/redis.h b/include/ulib/net/client/redis.h index 7bbe4c69..c0a245f1 100644 --- a/include/ulib/net/client/redis.h +++ b/include/ulib/net/client/redis.h @@ -1204,8 +1204,10 @@ private: class UCompileTimeRESPEncoder : public UCompileTimeStringFormatter { private: +#ifdef GCC_IS_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +#endif template static constexpr auto generateSegments(StringClass format, size_t& outputCount, std::tuple&& workingCommand, T&& t, Ts&&... ts) @@ -1258,7 +1260,10 @@ private: } } } + +#ifdef GCC_IS_GNU #pragma GCC diagnostic pop +#endif template static size_t encode_impl(size_t writePosition, UString& workingString, Ts&&... ts) diff --git a/include/ulib/net/ipaddress.h b/include/ulib/net/ipaddress.h index 52b23249..79b809e0 100644 --- a/include/ulib/net/ipaddress.h +++ b/include/ulib/net/ipaddress.h @@ -118,9 +118,8 @@ public: // Check whether a ip address client ought to be allowed (belong to the same network)... - inline bool isAllowed(const char* ip_client); - - bool isAllowed(UString& ip_client) { return isAllowed(ip_client.c_str()); } + inline bool isAllowed(const UString& ip_client) { return isAllowed(U_STRING_TO_PARAM(ip_client)); } + inline bool isAllowed(const char* ip_client, uint32_t len); bool isAllowed(in_addr_t client) __pure; bool isAllowed(in_addr_t ifa_addr, in_addr_t ifa_netmask) @@ -163,13 +162,13 @@ public: U_RETURN(U_NOT_FOUND); } - static uint32_t find(const char* ip_client, UVector& vipallow) + static uint32_t find(const char* ip_client, uint32_t len, UVector& vipallow) { - U_TRACE(0, "UIPAllow::find(%S,%p)", ip_client, &vipallow) + U_TRACE(0, "UIPAllow::find(%.*S,%u,%p)", len, ip_client, len, &vipallow) for (uint32_t i = 0, vlen = vipallow.size(); i < vlen; ++i) { - if (vipallow[i]->isAllowed(ip_client)) U_RETURN(i); + if (vipallow[i]->isAllowed(ip_client, len)) U_RETURN(i); } U_RETURN(U_NOT_FOUND); @@ -187,9 +186,9 @@ public: U_RETURN(U_NOT_FOUND); } - static bool isAllowed(in_addr_t client, UVector& vipallow) { return (find( client, vipallow) != U_NOT_FOUND); } - static bool isAllowed(const char* ip_client, UVector& vipallow) { return (find(ip_client, vipallow) != U_NOT_FOUND); } - static bool isAllowed(const UString& ip_client, UVector& vipallow) { return (find(ip_client, vipallow) != U_NOT_FOUND); } + static bool isAllowed(in_addr_t client, UVector& vipallow) { return (find( client, vipallow) != U_NOT_FOUND); } + static bool isAllowed(const char* ip_client, uint32_t len, UVector& vipallow) { return (find(ip_client, len, vipallow) != U_NOT_FOUND); } + static bool isAllowed(const UString& ip_client, UVector& vipallow) { return (find(ip_client, vipallow) != U_NOT_FOUND); } // DEBUG @@ -298,20 +297,8 @@ public: // converts the internet address from the IPv4 numbers-and-dots notation into binary form // (in network byte order) and stores it in the structure that points to - static bool getBinaryForm(const char* addr_str, uint32_t& addr, bool bconvert = false) - { - U_TRACE(0, "UIPAddress::getBinaryForm(%S,%p,%b)", addr_str, &addr, bconvert) - - U_INTERNAL_ASSERT(u_isIPv4Addr(addr_str, u__strlen(addr_str, __PRETTY_FUNCTION__))) - - struct in_addr ia; - - if (U_SYSCALL(inet_aton, "%p,%p", addr_str, &ia) == 0) U_RETURN(false); - - addr = (bconvert ? ntohl(ia.s_addr) : ia.s_addr); - - U_RETURN(true); - } + static bool getBinaryForm(const UString& addr_str, uint32_t& addr, bool bconvert = false) { return getBinaryForm(U_STRING_TO_PARAM(addr_str), addr, bconvert); } + static bool getBinaryForm(const char* addr_str, uint32_t len, uint32_t& addr, bool bconvert = false); #ifdef ENABLE_IPV6 /********************************************************************************/ @@ -466,13 +453,13 @@ private: friend class UClientImage_Base; }; -inline bool UIPAllow::isAllowed(const char* ip_client) +inline bool UIPAllow::isAllowed(const char* ip_client, uint32_t len) { - U_TRACE(0, "UIPAllow::isAllowed(%S)", ip_client) + U_TRACE(0, "UIPAllow::isAllowed(%.*S,%u)", len, ip_client, len) in_addr_t client; - if (UIPAddress::getBinaryForm(ip_client, client) && + if (UIPAddress::getBinaryForm(ip_client, len, client) && isAllowed(client)) { U_RETURN(true); @@ -480,5 +467,4 @@ inline bool UIPAllow::isAllowed(const char* ip_client) U_RETURN(false); } - #endif diff --git a/include/ulib/orm/orm.h b/include/ulib/orm/orm.h index d3ec7ae9..55de2dbe 100644 --- a/include/ulib/orm/orm.h +++ b/include/ulib/orm/orm.h @@ -259,6 +259,8 @@ public: * template void use(Ts&&... ts) { (bindParam(UOrmTypeHandler(ts)), ...); } NB: don't work! */ +/* +*/ template void use(T1& r1); @@ -476,6 +478,8 @@ private: // Syntactic sugar for bindParam() used with use() binding registers +/* +*/ template inline void UOrmStatement::use(T1& r1) { diff --git a/include/ulib/serialize/flatbuffers.h b/include/ulib/serialize/flatbuffers.h index 5282086a..02845bc1 100644 --- a/include/ulib/serialize/flatbuffers.h +++ b/include/ulib/serialize/flatbuffers.h @@ -677,8 +677,10 @@ public: // INIT +#ifdef GCC_IS_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif static void setStack(uint8_t* ptr, uint32_t len) { @@ -688,7 +690,9 @@ public: stack_max = len / UFlatBufferValue::size(); } +#ifdef GCC_IS_GNU #pragma GCC diagnostic pop +#endif static void setBuffer(uint8_t* ptr, uint32_t len) { diff --git a/include/ulib/string.h b/include/ulib/string.h index c7251fab..1acc7c08 100644 --- a/include/ulib/string.h +++ b/include/ulib/string.h @@ -2895,8 +2895,10 @@ public: else return substr(std::make_index_sequence{}); } +#ifdef GCC_IS_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +#endif template constexpr bool contains(char value) const @@ -2906,7 +2908,9 @@ public: else return contains(value); } +#ifdef GCC_IS_GNU #pragma GCC diagnostic pop +#endif // so that CTV is transparently a UString to U_STRING_TO_PARAM char const *data() const noexcept { return string; } @@ -2963,8 +2967,10 @@ static void snprintf_specialization(Lambda&& lambda, T t) class UCompileTimeStringFormatter { protected: +#ifdef GCC_IS_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +#endif template static constexpr auto generateSegments(StringClass format, T&& t, Ts&&... ts) @@ -2982,7 +2988,9 @@ protected: } } +#ifdef GCC_IS_GNU #pragma GCC diagnostic pop +#endif template struct decay_equiv : std::is_same::type, U>::type {}; diff --git a/src/ulib/net/ipaddress.cpp b/src/ulib/net/ipaddress.cpp index 08827f34..9b395db9 100644 --- a/src/ulib/net/ipaddress.cpp +++ b/src/ulib/net/ipaddress.cpp @@ -656,6 +656,70 @@ UString UIPAddress::toString(uint8_t* addr) U_RETURN_STRING(x); } +bool UIPAddress::getBinaryForm(const char* addr_str, uint32_t len, uint32_t& addr, bool bconvert) +{ + U_TRACE(0, "UIPAddress::getBinaryForm(%.*S,%u,%p,%b)", len, addr_str, len, &addr, bconvert) + + uint32_t i; + const char* ptr; + unsigned long a[4] = { 0 }; + const char* p = addr_str; + const char* end = addr_str + len; + + for (i = 0; i < 4; ++i) + { + if (u__isdigit(*(ptr = p)) == false) U_RETURN(false); + + while (u__isdigit(*p)) ++p; + + a[i] = u_strtoul(ptr, p); + + if (p >= end) break; + + if (*p++ != '.') U_RETURN(false); + } + + U_INTERNAL_ASSERT(u_isIPv4Addr(addr_str, len)) + + switch (i) + { + case 0: a[1] = a[0] & 0xffffff; a[0] >>= 24; /* FALL THRU */ + case 1: a[2] = a[1] & 0x00ffff; a[1] >>= 16; /* FALL THRU */ + case 2: a[3] = a[2] & 0x0000ff; a[2] >>= 8; /* FALL THRU */ + case 3: break; + case 4: U_RETURN(false); + } + + if (a[0] > 255 || + a[1] > 255 || + a[2] > 255 || + a[3] > 255) + { + U_RETURN(false); + } + + unsigned char* d = (unsigned char*)&addr; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (bconvert) + { + d[0] = a[3]; + d[1] = a[2]; + d[2] = a[1]; + d[3] = a[0]; + } + else +#endif + { + d[0] = a[0]; + d[1] = a[1]; + d[2] = a[2]; + d[3] = a[3]; + } + + U_RETURN(true); +} + // Simple IP-based access-control system // Interpret a "HOST/BITS" IP mask specification. (Ex. 192.168.1.64/28) @@ -665,7 +729,7 @@ bool UIPAllow::parseMask(const UString& spec) // get bit before slash - char addr_str[U_INET_ADDRSTRLEN]; + char addr_str[U_INET_ADDRSTRLEN+1]; uint32_t len, addr_len = spec.find('/'); // extract and parse addr part diff --git a/src/ulib/net/server/plugin/mod_nocat.cpp b/src/ulib/net/server/plugin/mod_nocat.cpp index 3d475cd4..7e253bd9 100644 --- a/src/ulib/net/server/plugin/mod_nocat.cpp +++ b/src/ulib/net/server/plugin/mod_nocat.cpp @@ -1282,7 +1282,7 @@ bool UNoCatPlugIn::creatNewPeer(uint32_t index_AUTH) U_INTERNAL_ASSERT_EQUALS(peer, U_NULLPTR) - uint32_t index_network = UIPAllow::find(UServer_Base::client_address, *vLocalNetworkMask); + uint32_t index_network = UIPAllow::find(U_CLIENT_ADDRESS_TO_PARAM, *vLocalNetworkMask); U_INTERNAL_DUMP("index_network = %u", index_network) @@ -1930,7 +1930,7 @@ __pure uint32_t UNoCatPlugIn::getIndexAUTH(const char* ip_address) { // NB: we are multi portal, we must find which portal we indicate to redirect the client... - index_AUTH = UIPAllow::find(ip_address, *vLocalNetworkMask); + index_AUTH = UIPAllow::find(ip_address, strlen(ip_address), *vLocalNetworkMask); if (index_AUTH >= sz_AUTH) index_AUTH = 0; } diff --git a/src/ulib/net/server/plugin/mod_nodog.cpp b/src/ulib/net/server/plugin/mod_nodog.cpp index e05dd147..79ac7d14 100644 --- a/src/ulib/net/server/plugin/mod_nodog.cpp +++ b/src/ulib/net/server/plugin/mod_nodog.cpp @@ -1449,7 +1449,7 @@ next: eraseTimer(); if (checkUrl(buffer, sizeof(buffer), sz, U_CONSTANT_TO_PARAM("NEW")) == 0) goto end; - index_network = UIPAllow::find(UServer_Base::client_address, *vLocalNetworkMask); + index_network = UIPAllow::find(U_CLIENT_ADDRESS_TO_PARAM, *vLocalNetworkMask); U_INTERNAL_DUMP("index_network = %u", index_network) diff --git a/src/ulib/net/server/server.cpp b/src/ulib/net/server/server.cpp index 5b838e0a..8e45b05f 100644 --- a/src/ulib/net/server/server.cpp +++ b/src/ulib/net/server/server.cpp @@ -3200,7 +3200,7 @@ next: { in_addr_t addr; - if (UIPAddress::getBinaryForm(IP_address->c_str(), addr) == false) U_ERROR("IP_ADDRESS conversion fail: %V", IP_address->rep); + if (UIPAddress::getBinaryForm(*IP_address, addr) == false) U_ERROR("IP_ADDRESS conversion fail: %V", IP_address->rep); socket->setAddress(&addr); diff --git a/src/ulib/utility/interrupt.cpp b/src/ulib/utility/interrupt.cpp index 4f46afdb..fcb9938d 100644 --- a/src/ulib/utility/interrupt.cpp +++ b/src/ulib/utility/interrupt.cpp @@ -257,8 +257,10 @@ retry: (void) U_SYSCALL(sigaction, "%d,%p,%p", SIGSEGV, old + SIGSEGV, U_NULLPTR); } +#ifdef GCC_IS_GNU #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn" +#endif RETSIGTYPE UInterrupt::handlerSegvWithInfo(int signo, siginfo_t* info, void* context) { @@ -295,7 +297,9 @@ RETSIGTYPE UInterrupt::handlerSegvWithInfo(int signo, siginfo_t* info, void* con ::abort(); } +#ifdef GCC_IS_GNU #pragma GCC diagnostic pop +#endif void UInterrupt::getSignalInfo(int signo, siginfo_t* info) { diff --git a/src/ulib/utility/uhttp.cpp b/src/ulib/utility/uhttp.cpp index 1ea51f80..0e6c8bc7 100644 --- a/src/ulib/utility/uhttp.cpp +++ b/src/ulib/utility/uhttp.cpp @@ -8559,7 +8559,7 @@ bool UHTTP::checkUriProtected() if (ok && U_http_ip_client_len) { - ok = UIPAllow::isAllowed(UServer_Base::client_address, *vallow_IP); + ok = UIPAllow::isAllowed(U_CLIENT_ADDRESS_TO_PARAM, *vallow_IP); } if (ok == false) diff --git a/src/ulib/utility/websocket.cpp b/src/ulib/utility/websocket.cpp index ef92724d..725c52de 100644 --- a/src/ulib/utility/websocket.cpp +++ b/src/ulib/utility/websocket.cpp @@ -654,7 +654,7 @@ bool UWebSocket::sendData(const bool isServer, USocket* socket, int type, const # ifdef USE_LIBBROTLI UString compressed; - if (compressed = UStringExt::brotli(data, len, (U_PARALLELIZATION_CHILD ? BROTLI_MAX_QUALITY : UHTTP::brotli_level_for_dynamic_content))) + if ((compressed = UStringExt::brotli(data, len, (U_PARALLELIZATION_CHILD ? BROTLI_MAX_QUALITY : UHTTP::brotli_level_for_dynamic_content)))) { opcode = U_WS_OPCODE_BROTLI; diff --git a/tests/examples/TSA/tsaserial b/tests/examples/TSA/tsaserial index 7ba33155..9dd79763 100644 --- a/tests/examples/TSA/tsaserial +++ b/tests/examples/TSA/tsaserial @@ -1 +1 @@ -06F6 +073C diff --git a/tests/ulib/Makefile.am b/tests/ulib/Makefile.am index 81e676d2..b250788e 100644 --- a/tests/ulib/Makefile.am +++ b/tests/ulib/Makefile.am @@ -18,7 +18,7 @@ PRG = test_timeval test_timer test_notifier test_string \ test_services test_base64 test_header test_entity \ test_ipaddress test_socket test_ftp test_http test_rdb_client \ test_tokenizer test_query_parser test_multipart test_command test_dialog test_json test_redis test_elasticsearch \ - test_smtp test_pop3 test_imap test_hash_map test_serialize + test_smtp test_pop3 test_imap test_hash_map test_serialize eval_itoa eval_dtoa ## test_twilio TST = timeval.test timer.test notifier.test string.test \ @@ -103,6 +103,8 @@ test_mongodb_SOURCES = test_mongodb.cpp test_elasticsearch_SOURCES = test_elasticsearch.cpp test_hash_map_SOURCES = test_hash_map.cpp test_serialize_SOURCES = test_serialize.cpp +eval_itoa_SOURCES = eval_itoa.cpp tsc.h branchlut.h +eval_dtoa_SOURCES = eval_dtoa.cpp tsc.h dtoa_milo.h if PTHREAD PRG += test_thread diff --git a/tests/ulib/Makefile.in b/tests/ulib/Makefile.in index 0c4ede87..193c8bc8 100644 --- a/tests/ulib/Makefile.in +++ b/tests/ulib/Makefile.in @@ -218,13 +218,22 @@ am__EXEEXT_19 = test_timeval$(EXEEXT) test_timer$(EXEEXT) \ test_dialog$(EXEEXT) test_json$(EXEEXT) test_redis$(EXEEXT) \ test_elasticsearch$(EXEEXT) test_smtp$(EXEEXT) \ test_pop3$(EXEEXT) test_imap$(EXEEXT) test_hash_map$(EXEEXT) \ - test_serialize$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \ - $(am__EXEEXT_3) $(am__EXEEXT_4) $(am__EXEEXT_5) \ - $(am__EXEEXT_6) $(am__EXEEXT_7) $(am__EXEEXT_8) \ - $(am__EXEEXT_9) $(am__EXEEXT_10) $(am__EXEEXT_2) \ - $(am__EXEEXT_3) $(am__EXEEXT_11) $(am__EXEEXT_12) \ - $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) \ - $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__EXEEXT_18) + test_serialize$(EXEEXT) eval_itoa$(EXEEXT) eval_dtoa$(EXEEXT) \ + $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ + $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \ + $(am__EXEEXT_10) $(am__EXEEXT_2) $(am__EXEEXT_3) \ + $(am__EXEEXT_11) $(am__EXEEXT_12) $(am__EXEEXT_13) \ + $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__EXEEXT_16) \ + $(am__EXEEXT_17) $(am__EXEEXT_18) +am_eval_dtoa_OBJECTS = eval_dtoa.$(OBJEXT) +eval_dtoa_OBJECTS = $(am_eval_dtoa_OBJECTS) +eval_dtoa_LDADD = $(LDADD) +eval_dtoa_DEPENDENCIES = $(top_builddir)/src/ulib/lib@ULIB@.la +am_eval_itoa_OBJECTS = eval_itoa.$(OBJEXT) +eval_itoa_OBJECTS = $(am_eval_itoa_OBJECTS) +eval_itoa_LDADD = $(LDADD) +eval_itoa_DEPENDENCIES = $(top_builddir)/src/ulib/lib@ULIB@.la am_test_application_OBJECTS = test_application.$(OBJEXT) test_application_OBJECTS = $(am_test_application_OBJECTS) test_application_LDADD = $(LDADD) @@ -595,7 +604,26 @@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = SOURCES = $(product1_la_SOURCES) $(product2_la_SOURCES) \ + $(eval_dtoa_SOURCES) $(eval_itoa_SOURCES) \ $(test_application_SOURCES) $(test_arping_SOURCES) \ $(test_base64_SOURCES) $(test_bit_array_SOURCES) \ $(test_cache_SOURCES) $(test_cdb_SOURCES) \ @@ -633,7 +661,8 @@ SOURCES = $(product1_la_SOURCES) $(product2_la_SOURCES) \ $(test_unixsocket_server_SOURCES) $(test_url_SOURCES) \ $(test_vector_SOURCES) $(test_zip_SOURCES) DIST_SOURCES = $(am__product1_la_SOURCES_DIST) \ - $(am__product2_la_SOURCES_DIST) $(test_application_SOURCES) \ + $(am__product2_la_SOURCES_DIST) $(eval_dtoa_SOURCES) \ + $(eval_itoa_SOURCES) $(test_application_SOURCES) \ $(am__test_arping_SOURCES_DIST) $(test_base64_SOURCES) \ $(test_bit_array_SOURCES) $(test_cache_SOURCES) \ $(test_cdb_SOURCES) $(am__test_certificate_SOURCES_DIST) \ @@ -1118,13 +1147,14 @@ PRG = test_timeval test_timer test_notifier test_string test_file \ test_http test_rdb_client test_tokenizer test_query_parser \ test_multipart test_command test_dialog test_json test_redis \ test_elasticsearch test_smtp test_pop3 test_imap test_hash_map \ - test_serialize $(am__append_1) $(am__append_3) $(am__append_4) \ - $(am__append_5) $(am__append_6) $(am__append_8) \ - $(am__append_10) $(am__append_12) $(am__append_14) \ - $(am__append_16) $(am__append_18) $(am__append_20) \ - $(am__append_22) $(am__append_24) $(am__append_26) \ - $(am__append_28) $(am__append_30) $(am__append_32) \ - $(am__append_34) $(am__append_36) + test_serialize eval_itoa eval_dtoa $(am__append_1) \ + $(am__append_3) $(am__append_4) $(am__append_5) \ + $(am__append_6) $(am__append_8) $(am__append_10) \ + $(am__append_12) $(am__append_14) $(am__append_16) \ + $(am__append_18) $(am__append_20) $(am__append_22) \ + $(am__append_24) $(am__append_26) $(am__append_28) \ + $(am__append_30) $(am__append_32) $(am__append_34) \ + $(am__append_36) TST = timeval.test timer.test notifier.test string.test file.test \ cdb.test rdb.test file_config.test log.test vector.test \ options.test application.test tree.test compress.test \ @@ -1188,6 +1218,8 @@ test_mongodb_SOURCES = test_mongodb.cpp test_elasticsearch_SOURCES = test_elasticsearch.cpp test_hash_map_SOURCES = test_hash_map.cpp test_serialize_SOURCES = test_serialize.cpp +eval_itoa_SOURCES = eval_itoa.cpp tsc.h branchlut.h +eval_dtoa_SOURCES = eval_dtoa.cpp tsc.h dtoa_milo.h @PTHREAD_TRUE@test_thread_SOURCES = test_thread.cpp @ZIP_TRUE@test_zip_SOURCES = test_zip.cpp @LIBTDB_TRUE@test_tdb_SOURCES = test_tdb.cpp @@ -1293,6 +1325,14 @@ clean-checkPROGRAMS: echo " rm -f" $$list; \ rm -f $$list +eval_dtoa$(EXEEXT): $(eval_dtoa_OBJECTS) $(eval_dtoa_DEPENDENCIES) $(EXTRA_eval_dtoa_DEPENDENCIES) + @rm -f eval_dtoa$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(eval_dtoa_OBJECTS) $(eval_dtoa_LDADD) $(LIBS) + +eval_itoa$(EXEEXT): $(eval_itoa_OBJECTS) $(eval_itoa_DEPENDENCIES) $(EXTRA_eval_itoa_DEPENDENCIES) + @rm -f eval_itoa$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(eval_itoa_OBJECTS) $(eval_itoa_LDADD) $(LIBS) + test_application$(EXEEXT): $(test_application_OBJECTS) $(test_application_DEPENDENCIES) $(EXTRA_test_application_DEPENDENCIES) @rm -f test_application$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_application_OBJECTS) $(test_application_LDADD) $(LIBS) @@ -1597,6 +1637,8 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval_dtoa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval_itoa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_application.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_base64.Po@am__quote@ diff --git a/tests/ulib/README b/tests/ulib/README index d88458d8..4a252812 100644 --- a/tests/ulib/README +++ b/tests/ulib/README @@ -4,11 +4,11 @@ Four Debian releases are available on the main site: Debian 8.11, or jessie. Access this release through dists/oldoldstable Debian 8.11 was released Saturday, 23rd June 2018. -Debian 9.11, or stretch. Access this release through dists/oldstable -Debian 9.11 was released Sunday, 8th September 2019. +Debian 9.12, or stretch. Access this release through dists/oldstable +Debian 9.12 was released Saturday, 8th February 2020. -Debian 10.1, or buster. Access this release through dists/stable -Debian 10.1 was released Saturday, 7th September 2019. +Debian 10.3, or buster. Access this release through dists/stable +Debian 10.3 was released Saturday, 8th February 2020. Testing, or bullseye. Access this release through dists/testing. The current tested development snapshot is named bullseye. Packages which diff --git a/src/ulib/internal/branchlut.h b/tests/ulib/branchlut.h similarity index 100% rename from src/ulib/internal/branchlut.h rename to tests/ulib/branchlut.h diff --git a/tests/ulib/dtoa_milo.h b/tests/ulib/dtoa_milo.h new file mode 100644 index 00000000..837ef443 --- /dev/null +++ b/tests/ulib/dtoa_milo.h @@ -0,0 +1,409 @@ +// https://github.com/miloyip/dtoa-benchmark +// Function  Time (ns)  Speedup +// sprintf 1,256.376 1.00x +// ... +// milo 138.021 9.10x + +#pragma once +#include +#include + +#if defined(_MSC_VER) +#include "msinttypes/stdint.h" +#include +#else +#include +#endif + +#define UINT64_C2(h, l) ((static_cast(h) << 32) | static_cast(l)) + +struct DiyFp { + DiyFp() {} + + DiyFp(uint64_t _f, int _e) : f(_f), e(_e) {} + + DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize; + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + assert(e == rhs.e); + assert(f >= rhs.f); + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + unsigned __int128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = p >> 64; + uint64_t l = static_cast(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, f); + return DiyFp(f << (63 - index), e - (63 - index)); +#elif defined(__GNUC__) + int s = __builtin_clzll(f); + return DiyFp(f << s, e - s); +#else + DiyFp res = *this; + while (!(res.f & kDpHiddenBit)) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 1); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1); + return res; +#endif + } + + DiyFp NormalizeBoundary() const { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, f); + return DiyFp (f << (63 - index), e - (63 - index)); +#else + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; +#endif + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMinExponent = -kDpExponentBias; + static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPower(int e, int* K) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76), + UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea), + UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df), + UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f), + UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c), + UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5), + UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d), + UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637), + UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7), + UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5), + UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b), + UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996), + UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8), + UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053), + UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd), + UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94), + UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b), + UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac), + UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3), + UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb), + UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c), + UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000), + UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984), + UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70), + UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245), + UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8), + UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a), + UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea), + UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85), + UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2), + UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3), + UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25), + UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece), + UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5), + UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a), + UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a), + UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129), + UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429), + UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d), + UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841), + UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9), + UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast(dk); + if (k != dk) + k++; + + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + + assert(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0])); + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline unsigned CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + if (n < 1000000000) return 9; + return 10; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int kappa = static_cast(CountDecimalDigit32(p1)); + *len = 0; + + while (kappa > 0) { + uint32_t d; + switch (kappa) { + case 10: d = p1 / 1000000000; p1 %= 1000000000; break; + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default: +#if defined(_MSC_VER) + __assume(0); +#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + __builtin_unreachable(); +#else + d = 0; +#endif + } + if (d || *len) + buffer[(*len)++] = '0' + static_cast(d); + kappa--; + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = '0' + d; + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', + '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', + '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', + '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', + '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', + '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', + '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', + '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', + '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', + '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' + }; + return cDigitsLut; +} + +inline void WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = '0' + static_cast(K / 100); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = '0' + static_cast(K); + + *buffer = '\0'; +} + +inline void Prettify(char* buffer, int length, int k) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (length <= kk && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + buffer[kk + 2] = '\0'; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + memmove(&buffer[kk + 1], &buffer[kk], length - kk); + buffer[kk] = '.'; + buffer[length + 1] = '\0'; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + memmove(&buffer[offset], &buffer[0], length); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + buffer[length + offset] = '\0'; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + memmove(&buffer[2], &buffer[1], length - 1); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa_milo(double value, char* buffer) { + // Not handling NaN and inf + assert(!isnan(value)); + assert(!isinf(value)); + + if (value == 0) { + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + buffer[3] = '\0'; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + Prettify(buffer, length, K); + } + + return buffer; +} diff --git a/tests/ulib/eval_dtoa.cpp b/tests/ulib/eval_dtoa.cpp new file mode 100644 index 00000000..dc38f4b1 --- /dev/null +++ b/tests/ulib/eval_dtoa.cpp @@ -0,0 +1,133 @@ +/** + * eval_dtoa.cpp + * + * Testing dtoa... + */ + +#define __STDC_FORMAT_MACROS +#include + +#include +#include "dtoa_milo.h" + +#include "tsc.h" + +#define N 100000 + +typedef void (*vPFdpc) (double,char*); + +static void func_overhead(void* func, const char* name, int type) +{ + int i; + uint64_t t0, t1, tsc_overhead; + uint64_t min, max, avg; + uint64_t times[N]; + char a[32]; + + tsc_overhead = measure_tsc_overhead(); + + // we run N times and take the min + for (i = 0; i < N; i++) { + t0 = bench_start(); + + switch (type) + { + case 0: + { + ((vPFdpc)func)(i,a); + ((vPFdpc)func)(i*10.01,a); + ((vPFdpc)func)(i*100.01,a); + ((vPFdpc)func)(i*1000.01,a); + ((vPFdpc)func)(i*10000.01,a); + } + break; + case 1: + { + ((vPFdpc)func)(-i,a); + ((vPFdpc)func)(-i*10.01,a); + ((vPFdpc)func)(-i*100.01,a); + ((vPFdpc)func)(-i*1000.01,a); + ((vPFdpc)func)(-i*10000.01,a); + } + break; + case 2: + { + ((vPFdpc)func)(i,a); + ((vPFdpc)func)(i*10.01,a); + ((vPFdpc)func)(i*100.01,a); + ((vPFdpc)func)(i*1000.01,a); + ((vPFdpc)func)(i*10000.01,a); + } + break; + case 3: + { + ((vPFdpc)func)(-i,a); + ((vPFdpc)func)(-i*10.01,a); + ((vPFdpc)func)(-i*100.01,a); + ((vPFdpc)func)(-i*1000.01,a); + ((vPFdpc)func)(-i*10000.01,a); + } + break; + } + + t1 = bench_end(); + times[i] = t1 - t0 - tsc_overhead; + } + + min = ~0, max = 0, avg = 0; + for (i = 0; i < N; i++) { + avg += times[i]; + if (times[i] < min) { min = times[i]; } + if (times[i] > max) { max = times[i]; } + } + avg /= N; + + printf("\n- %s -\n", name); + printf("Cost (min): %" PRIu64 " cycles\n", min); + printf("Cost (avg): %" PRIu64 " cycles\n", avg); + printf("Cost (max): %" PRIu64 " cycles\n", max); +} + +int +U_EXPORT main(int argc, char* argv[]) +{ + U_ULIB_INIT(argv); + + U_TRACE(5,"main(%d)",argc) + + printf("=> Testing dtoa...\n"); + + /* + char a[32], b[32]; + double sz1, sz2; + + for (double i = DOUBLE_MIN; i < 0; ++i) + { + sz1 = sprintf(a, "%g", i); + sz2 = u_dtoa(i, b); + + if (sz1 != sz2 || + memcmp(a, b, sz1)) + { + U_ERROR("sz1=%u sz2=%u a=%.*S b=%.*S", sz1, sz2, sz1, a, sz2, b) + } + } + + for (double j = 0; j <= DOUBLE_MAX; ++j) + { + sz1 = sprintf(a, "%g", j); + sz2 = u_dtoa(j, b); + + if (sz1 != sz2 || + memcmp(a, b, sz1)) + { + U_ERROR("sz1=%u sz2=%u a=%.*S b=%.*S", sz1, sz2, sz1, a, sz2, b) + } + } + */ + + func_overhead((void*)u_dtoa, "u_dtoa", 2); + func_overhead((void*)dtoa_milo, "dtoa_milo", 2); + + return 0; +} diff --git a/tests/ulib/eval_itoa.cpp b/tests/ulib/eval_itoa.cpp new file mode 100644 index 00000000..9e1562d3 --- /dev/null +++ b/tests/ulib/eval_itoa.cpp @@ -0,0 +1,139 @@ +/** + * eval_itoa.cpp + * + * Testing itoa... + */ + +#define __STDC_FORMAT_MACROS +#include + +#include +#include "branchlut.h" + +#include "tsc.h" + +#define N 100000 + +typedef void (*uPFi32pc) ( int32_t,char*); +typedef void (*uPFi64pc) ( int64_t,char*); +typedef void (*uPFu32pc) (uint32_t,char*); +typedef void (*uPFu64pc) (uint64_t,char*); + +static void func_overhead(void* func, const char* name, int type) +{ + int i; + uint64_t t0, t1, tsc_overhead; + uint64_t min, max, avg; + uint64_t times[N]; + char a[32]; + + tsc_overhead = measure_tsc_overhead(); + + // we run N times and take the min + for (i = 0; i < N; i++) { + t0 = bench_start(); + + switch (type) + { + case 0: + { + ((uPFu32pc)func)(i,a); + ((uPFu32pc)func)(i*10,a); + ((uPFu32pc)func)(i*100,a); + ((uPFu32pc)func)(i*1000,a); + ((uPFu32pc)func)(i*10000,a); + } + break; + case 1: + { + ((uPFi32pc)func)(-i,a); + ((uPFi32pc)func)(-i*10,a); + ((uPFi32pc)func)(-i*100,a); + ((uPFi32pc)func)(-i*1000,a); + ((uPFi32pc)func)(-i*10000,a); + } + break; + case 2: + { + ((uPFu64pc)func)((uint64_t)i,a); + ((uPFu64pc)func)((uint64_t)i*10,a); + ((uPFu64pc)func)((uint64_t)i*100,a); + ((uPFu64pc)func)((uint64_t)i*1000,a); + ((uPFu64pc)func)((uint64_t)i*10000,a); + } + break; + case 3: + { + ((uPFi64pc)func)((int64_t)-i,a); + ((uPFi64pc)func)((int64_t)-i*10,a); + ((uPFi64pc)func)((int64_t)-i*100,a); + ((uPFi64pc)func)((int64_t)-i*1000,a); + ((uPFi64pc)func)((int64_t)-i*10000,a); + } + break; + } + + t1 = bench_end(); + times[i] = t1 - t0 - tsc_overhead; + } + + min = ~0, max = 0, avg = 0; + for (i = 0; i < N; i++) { + avg += times[i]; + if (times[i] < min) { min = times[i]; } + if (times[i] > max) { max = times[i]; } + } + avg /= N; + + printf("\n- %s -\n", name); + printf("Cost (min): %" PRIu64 " cycles\n", min); + printf("Cost (avg): %" PRIu64 " cycles\n", avg); + printf("Cost (max): %" PRIu64 " cycles\n", max); +} + +int +U_EXPORT main(int argc, char* argv[]) +{ + U_ULIB_INIT(argv); + + U_TRACE(5,"main(%d)",argc) + + printf("=> Testing itoa...\n"); + + /* + char a[32], b[32]; + uint32_t sz1, sz2; + + for (int64_t i = LLONG_MIN; i < 0; ++i) + { + sz1 = sprintf(a, "%lld", i); + sz2 = u_num2str64s(i, b); + + if (sz1 != sz2 || + memcmp(a, b, sz1)) + { + U_ERROR("sz1=%u sz2=%u a=%.*S b=%.*S", sz1, sz2, sz1, a, sz2, b) + } + } + + for (uint64_t j = 0; j <= LLONG_MAX; ++j) + { + sz1 = sprintf(a, "%llu", j); + sz2 = u_num2str64(j, b); + + if (sz1 != sz2 || + memcmp(a, b, sz1)) + { + U_ERROR("sz1=%u sz2=%u a=%.*S b=%.*S", sz1, sz2, sz1, a, sz2, b) + } + } + */ + + func_overhead((void*)u_num2str32, "u_num2str32", 0); + func_overhead((void*)u_num2str64, "u_num2str64", 2); + + func_overhead((void*)u32toa_branchlut, "u32toa_branchlut", 0); + func_overhead((void*)u64toa_branchlut, "u64toa_branchlut", 2); + + return 0; +} diff --git a/tests/ulib/test_ipaddress.cpp b/tests/ulib/test_ipaddress.cpp index ebdaf552..174a055e 100644 --- a/tests/ulib/test_ipaddress.cpp +++ b/tests/ulib/test_ipaddress.cpp @@ -14,8 +14,9 @@ U_EXPORT main (int argc, char* argv[]) bool result; UIPAddress x; + uint32_t addr; char address[16]; - UString name = UString(argv[1]), domain, name_domain, name_ret; + UString tmp, name = UString(argv[1]), domain, name_domain, name_ret; if (argv[2] && argv[2][0]) @@ -30,14 +31,64 @@ U_EXPORT main (int argc, char* argv[]) U_ASSERT( result == false ) + tmp = U_STRING_FROM_CONSTANT("127.0.0.1"); + + x.getBinaryForm(tmp, addr, true); + + U_INTERNAL_DUMP("addr = %#08x %B", addr, addr) + +#if __BYTE_ORDER == __LITTLE_ENDIAN + U_INTERNAL_ASSERT( addr == 0x7f000001 ) +#else + U_INTERNAL_ASSERT( addr == 0x0100007f ) +#endif + + x.getBinaryForm(tmp, addr, false); + + U_INTERNAL_DUMP("addr = %#08x %B", addr, addr) + +#if __BYTE_ORDER == __LITTLE_ENDIAN + U_INTERNAL_ASSERT( addr == 0x0100007f ) +#else + U_INTERNAL_ASSERT( addr == 0x7f000001 ) +#endif + + tmp = U_STRING_FROM_CONSTANT("255.255.255.255"); + + x.getBinaryForm(tmp, addr, true); + + U_INTERNAL_DUMP("addr = %#08x %B", addr, addr) + + U_INTERNAL_ASSERT( addr == 0xffffffff ) + + x.getBinaryForm(tmp, addr, false); + + U_INTERNAL_DUMP("addr = %#08x %B", addr, addr) + + U_INTERNAL_ASSERT( addr == 0xffffffff ) + + tmp = U_STRING_FROM_CONSTANT("255.0.0.255"); + + x.getBinaryForm(tmp, addr, true); + + U_INTERNAL_DUMP("addr = %#08x %B", addr, addr) + + U_INTERNAL_ASSERT( addr == 0xff0000ff ) + + x.getBinaryForm(tmp, addr, false); + + U_INTERNAL_DUMP("addr = %#08x %B", addr, addr) + + U_INTERNAL_ASSERT( addr == 0xff0000ff ) + // Test code for matching IP masks UIPAllow a; - U_ASSERT( a.parseMask(U_STRING_FROM_CONSTANT("127.0.0.5")) == true ) - // 127.0.0.5 + U_ASSERT( a.parseMask(U_STRING_FROM_CONSTANT("127.0.0.5")) == true ) + x.setHostName(U_STRING_FROM_CONSTANT("127.0.0.5")); U_ASSERT( a.isAllowed(x.getInAddr()) == true ) @@ -142,7 +193,7 @@ U_EXPORT main (int argc, char* argv[]) U_INTERNAL_ASSERT_EQUALS(n, 2) - n = UIPAllow::find("192.168.253.253", vipallow); + n = UIPAllow::find(U_STRING_FROM_CONSTANT("192.168.253.253"), vipallow); U_INTERNAL_ASSERT( n != U_NOT_FOUND ) diff --git a/tests/ulib/tsc.h b/tests/ulib/tsc.h new file mode 100644 index 00000000..89b0e67e --- /dev/null +++ b/tests/ulib/tsc.h @@ -0,0 +1,113 @@ +// Support for using the TSC register on intel machines as a timing method. +// +// Should compile with -O to ensure inline attribute is honoured. +// + +#ifndef __TSC_HDR +#define __TSC_HDR + +#include + +#define TSC_OVERHEAD_N 100000 + +static inline void _sync_tsc(void) +{ + asm volatile("cpuid" : : : "%rax", "%rbx", "%rcx", "%rdx"); +} + +static inline uint64_t _rdtsc(void) +{ + unsigned a, d; + asm volatile("rdtsc" : "=a" (a), "=d" (d) : : "%rbx", "%rcx"); + return ((uint64_t) a) | (((uint64_t) d) << 32); +} + +static inline uint64_t _rdtscp(void) +{ + unsigned a, d; + asm volatile("rdtscp" : "=a" (a), "=d" (d) : : "%rbx", "%rcx"); + return ((uint64_t) a) | (((uint64_t) d) << 32); +} + +static inline uint64_t bench_start(void) +{ + // unsigned cycles_low, cycles_high; + // uint64_t t; + // + // asm volatile( "CPUID\n\t" // serialize + // "RDTSC\n\t" // read clock + // "mov %%edx, %0\n\t" + // "mov %%eax, %1\n\t" + // : "=r" (cycles_high), "=r" (cycles_low) + // :: "%rax", "%rbx", "%rcx", "%rdx" ); + // return ((uint64_t) cycles_high << 32) | cycles_low; + + _sync_tsc(); + return _rdtsc(); +} + +static inline uint64_t bench_end(void) +{ + // unsigned cycles_low, cycles_high; + // uint64_t t; + // + // asm volatile( "RDTSCP\n\t" // read clock + serialize + // "mov %%edx, %0\n\t" + // "mov %%eax, %1\n\t" + // "CPUID\n\t" // serialze -- but outside clock region! + // : "=r" (cycles_high), "=r" (cycles_low) + // :: "%rax", "%rbx", "%rcx", "%rdx" ); + // return ((uint64_t) cycles_high << 32) | cycles_low; + + uint64_t t = _rdtscp(); + _sync_tsc(); + return t; +} + +static uint64_t measure_tsc_overhead(void) +{ + uint64_t t0, t1, overhead = ~0; + int i; + + for (i = 0; i < TSC_OVERHEAD_N; i++) { + t0 = bench_start(); + asm volatile(""); + t1 = bench_end(); + if (t1 - t0 < overhead) + overhead = t1 - t0; + } + + return overhead; +} + +/* +# TSC Frequency +To convert from cycles to wall-clock time we need to know TSC frequency +Frequency scaling on modern Intel chips doesn't affect the TSC. + +Sadly, there doesn't seem to be a good way to do this. + +# Intel V3B: 17.14 +That rate may be set by the maximum core-clock to bus-clock ratio of the +processor or may be set by the maximum resolved frequency at which the +processor is booted. The maximum resolved frequency may differ from the +processor base frequency, see Section 18.15.5 for more detail. On certain +processors, the TSC frequency may not be the same as the frequency in the brand +string. + +# Linux Source +http://lxr.free-electrons.com/source/arch/x86/kernel/tsc.c?v=2.6.31#L399 + +Linux runs a calibration phase where it uses some hardware timers and checks +how many TSC cycles occur in 50ms. +*/ +#define TSC_FREQ_MHZ 3500 + +static inline uint64_t cycles_to_ns(uint64_t cycles) +{ + // XXX: This is not safe! We don't have a good cross-platform way to + // determine the TSC frequency for some strange reason. + return cycles * 1000 / TSC_FREQ_MHZ; +} + +#endif /* __TSC_HDR */