1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
This commit is contained in:
stefanocasazza 2020-02-11 18:38:45 +01:00
parent 91ce2ab459
commit e0f5b65442
27 changed files with 1191 additions and 197 deletions

180
configure vendored
View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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();

View File

@ -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

View File

@ -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<bool isPartial, size_t workingIndex = 0, size_t workingSegmentCount = 0, typename StringClass, typename... Xs, typename T, typename... Ts>
static constexpr auto generateSegments(StringClass format, size_t& outputCount, std::tuple<Xs...>&& workingCommand, T&& t, Ts&&... ts)
@ -1258,7 +1260,10 @@ private:
}
}
}
#ifdef GCC_IS_GNU
#pragma GCC diagnostic pop
#endif
template<bool isPartial, bool overwrite, auto format, typename... Ts>
static size_t encode_impl(size_t writePosition, UString& workingString, Ts&&... ts)

View File

@ -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<UIPAllow*>& vipallow)
static uint32_t find(const char* ip_client, uint32_t len, UVector<UIPAllow*>& 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<UIPAllow*>& vipallow) { return (find( client, vipallow) != U_NOT_FOUND); }
static bool isAllowed(const char* ip_client, UVector<UIPAllow*>& vipallow) { return (find(ip_client, vipallow) != U_NOT_FOUND); }
static bool isAllowed(const UString& ip_client, UVector<UIPAllow*>& vipallow) { return (find(ip_client, vipallow) != U_NOT_FOUND); }
static bool isAllowed(in_addr_t client, UVector<UIPAllow*>& vipallow) { return (find( client, vipallow) != U_NOT_FOUND); }
static bool isAllowed(const char* ip_client, uint32_t len, UVector<UIPAllow*>& vipallow) { return (find(ip_client, len, vipallow) != U_NOT_FOUND); }
static bool isAllowed(const UString& ip_client, UVector<UIPAllow*>& 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

View File

@ -259,6 +259,8 @@ public:
* template <typename...Ts> void use(Ts&&... ts) { (bindParam(UOrmTypeHandler<Ts>(ts)), ...); } NB: don't work!
*/
/*
*/
template <class T1>
void use(T1& r1);
@ -476,6 +478,8 @@ private:
// Syntactic sugar for bindParam() used with use() binding registers
/*
*/
template <class T1>
inline void UOrmStatement::use(T1& r1)
{

View File

@ -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)
{

View File

@ -2895,8 +2895,10 @@ public:
else return substr<From>(std::make_index_sequence<To - From>{});
}
#ifdef GCC_IS_GNU
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#endif
template<size_t index = 0>
constexpr bool contains(char value) const
@ -2906,7 +2908,9 @@ public:
else return contains<index+1>(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<size_t workingIndex, size_t argumentCount, typename StringClass, typename T, typename... Ts>
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 <typename T, typename U>
struct decay_equiv : std::is_same<typename std::decay<T>::type, U>::type {};

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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)
{

View File

@ -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)

View File

@ -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;

View File

@ -1 +1 @@
06F6
073C

View File

@ -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

View File

@ -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@

View File

@ -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

409
tests/ulib/dtoa_milo.h Normal file
View File

@ -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 <assert.h>
#include <math.h>
#if defined(_MSC_VER)
#include "msinttypes/stdint.h"
#include <intrin.h>
#else
#include <stdint.h>
#endif
#define UINT64_C2(h, l) ((static_cast<uint64_t>(h) << 32) | static_cast<uint64_t>(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<unsigned __int128>(f) * static_cast<unsigned __int128>(rhs.f);
uint64_t h = p >> 64;
uint64_t l = static_cast<uint64_t>(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<int>(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<int>(dk);
if (k != dk)
k++;
unsigned index = static_cast<unsigned>((k >> 3) + 1);
*K = -(-348 + static_cast<int>(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<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1);
int kappa = static_cast<int>(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<char>(d);
kappa--;
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
if (tmp <= delta) {
*K += kappa;
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
return;
}
}
// kappa = 0
for (;;) {
p2 *= 10;
delta *= 10;
char d = static_cast<char>(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<char>(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<char>(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;
}

133
tests/ulib/eval_dtoa.cpp Normal file
View File

@ -0,0 +1,133 @@
/**
* eval_dtoa.cpp
*
* Testing dtoa...
*/
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <ulib/string.h>
#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;
}

139
tests/ulib/eval_itoa.cpp Normal file
View File

@ -0,0 +1,139 @@
/**
* eval_itoa.cpp
*
* Testing itoa...
*/
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <ulib/string.h>
#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;
}

View File

@ -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 )

113
tests/ulib/tsc.h Normal file
View File

@ -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 <stdint.h>
#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 */