diff --git a/beast/config/CompilerConfig.h b/beast/config/CompilerConfig.h index 7cdaf733a3..1a279e6fee 100644 --- a/beast/config/CompilerConfig.h +++ b/beast/config/CompilerConfig.h @@ -24,13 +24,8 @@ #ifndef BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED #define BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED -// This file has to work when included in a C source file. - -#ifndef BEAST_CONFIG_PLATFORMCONFIG_H_INCLUDED -#error "PlatformConfig.h must come first!" -#endif - #include +#include "PlatformConfig.h" // This file defines miscellaneous macros for debugging, assertions, etc. @@ -47,6 +42,15 @@ # define BEAST_CDECL #endif +/** This macro fixes C++'s constexpr for VS2012, which doesn't understand it. +*/ +#if BEAST_MSVC +# define BEAST_CONSTEXPR const +#else +# define BEAST_CONSTEXPR constexpr +#endif + + // Debugging and assertion macros #if BEAST_LOG_ASSERTIONS || BEAST_DEBUG diff --git a/beast/container/tests/hardened_hash.test.cpp b/beast/container/tests/hardened_hash.test.cpp index a225b49941..a3f2d1a2fb 100644 --- a/beast/container/tests/hardened_hash.test.cpp +++ b/beast/container/tests/hardened_hash.test.cpp @@ -17,7 +17,7 @@ */ //============================================================================== -// MODULES: ../../crypto/impl/Sha256.cpp +// MODULES: ../../crypto/impl/Sha256.cpp ../../container/impl/spookyv2.cpp #if BEAST_INCLUDE_BEASTCONFIG #include "../../../BeastConfig.h" @@ -131,7 +131,7 @@ public: static std::size_t const bytes = bits / 8; template - static + static unsigned_integer from_number (Int v) { @@ -167,7 +167,7 @@ public: { for (std::size_t i (0); i < size; ++i) s << - std::hex << + std::hex << std::setfill ('0') << std::setw (2*sizeof(UInt)) << v.m_vec[i] @@ -293,7 +293,7 @@ public: "i=" << std::setw(2) << i << " " << "sha256=0x" << d_ << " " << "hash=0x" << - std::setfill ('0') << + std::setfill ('0') << std::setw (2*sizeof(std::size_t)) << result ; pass(); diff --git a/beast/utility/Utility.cpp b/beast/utility/Utility.cpp index 45fcdeefcf..380e2224d5 100644 --- a/beast/utility/Utility.cpp +++ b/beast/utility/Utility.cpp @@ -31,3 +31,4 @@ #include "tests/bassert.test.cpp" #include "tests/empty_base_optimization.test.cpp" +#include "tests/Zero.test.cpp" diff --git a/beast/utility/Zero.h b/beast/utility/Zero.h new file mode 100644 index 0000000000..6a11f2ee78 --- /dev/null +++ b/beast/utility/Zero.h @@ -0,0 +1,140 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2014, Tom Ritchford + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_ZERO_H_INCLUDED +#define BEAST_UTILITY_ZERO_H_INCLUDED + +#include "../config/CompilerConfig.h" + +namespace beast { + +/** Zero allows classes to offer efficient comparisons to zero. + + Zero is a struct to allow classes to efficiently compare with zero without + requiring an rvalue construction. + + It's often the case that we have classes which combine a number and a unit. + In such cases, comparisons like t > 0 or t != 0 make sense, but comparisons + like t > 1 or t != 1 do not. + + The class Zero allows such comparisons to be easily made. + + The comparing class T either needs to have a method called signum() which + returns a positive number, 0, or a negative; or there needs to be a signum + function which resolves in the namespace which takes an instance of T and + returns a positive, zero or negative number. + */ + +struct Zero {}; + +namespace { + +static BEAST_CONSTEXPR Zero zero{}; + +} // namespace + +/** The default implementation of signum calls the method on the class. + + Calls to signum must be made from a namespace that does not include + overloads of the function. + */ +template +auto signum(T const& t) -> decltype(t.signum()) { + return t.signum(); +} + +namespace detail { +namespace zero_helper { + +template +auto call_signum (T const& t) -> decltype(signum(t)) { + return signum(t); +} + +} // zero_helper +} // detail + +/** Handle operators where T is on the left side using signum. */ +template +bool operator==(T const& t, Zero) { + return detail::zero_helper::call_signum(t) == 0; +} + +template +bool operator!=(T const& t, Zero) { + return detail::zero_helper::call_signum(t) != 0; +} + +template +bool operator>(T const& t, Zero) { + return detail::zero_helper::call_signum(t) > 0; +} + +template +bool operator>=(T const& t, Zero) { + return detail::zero_helper::call_signum(t) >= 0; +} + +template +bool operator<(T const& t, Zero) { + return detail::zero_helper::call_signum(t) < 0; +} + +template +bool operator<=(T const& t, Zero) { + return detail::zero_helper::call_signum(t) <= 0; +} + + +/** Handle operators where T is on the right side by reversing the operation, + so that T is on the left side. + */ +template +bool operator==(Zero, T const& t) { + return t == zero; +} + +template +bool operator!=(Zero, T const& t) { + return t != zero; +} + +template +bool operator>(Zero, T const& t) { + return t < zero; +} + +template +bool operator>=(Zero, T const& t) { + return t <= zero; +} + +template +bool operator<(Zero, T const& t) { + return t > zero; +} + +template +bool operator<=(Zero, T const& t) { + return t >= zero; +} + +} // beast + +#endif diff --git a/beast/utility/tests/Zero.test.cpp b/beast/utility/tests/Zero.test.cpp new file mode 100644 index 0000000000..07843f8a86 --- /dev/null +++ b/beast/utility/tests/Zero.test.cpp @@ -0,0 +1,136 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2014, Nikolaos D. Bougalis + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../Zero.h" + +#include "../../unit_test/suite.h" + +namespace beast { + +struct adl_tester {}; + +int signum (adl_tester) { return 0; } + + +namespace detail { + +struct adl_tester2 {}; + +int signum (adl_tester2) { return 0; } + +} // detail + +class Zero_test : public beast::unit_test::suite +{ +private: + struct IntegerWrapper + { + int value; + + IntegerWrapper (int v) + : value (v) + { + } + + int signum() const + { + return value; + } + }; + +public: + void expect_same(bool result, bool correct, char const* message) + { + expect(result == correct, message); + } + + void + test_lhs_zero (IntegerWrapper x) + { + expect_same (x >= zero, x.signum () >= 0, + "lhs greater-than-or-equal-to"); + expect_same (x > zero, x.signum () > 0, + "lhs greater than"); + expect_same (x == zero, x.signum () == 0, + "lhs equal to"); + expect_same (x != zero, x.signum () != 0, + "lhs not equal to"); + expect_same (x < zero, x.signum () < 0, + "lhs less than"); + expect_same (x <= zero, x.signum () <= 0, + "lhs less-than-or-equal-to"); + } + + void + test_lhs_zero () + { + testcase ("lhs zero"); + + test_lhs_zero(-7); + test_lhs_zero(0); + test_lhs_zero(32); + } + + void + test_rhs_zero (IntegerWrapper x) + { + expect_same (zero >= x, 0 >= x.signum (), + "rhs greater-than-or-equal-to"); + expect_same (zero > x, 0 > x.signum (), + "rhs greater than"); + expect_same (zero == x, 0 == x.signum (), + "rhs equal to"); + expect_same (zero != x, 0 != x.signum (), + "rhs not equal to"); + expect_same (zero < x, 0 < x.signum (), + "rhs less than"); + expect_same (zero <= x, 0 <= x.signum (), + "rhs less-than-or-equal-to"); + } + + void + test_rhs_zero () + { + testcase ("rhs zero"); + + test_rhs_zero(-4); + test_rhs_zero(0); + test_rhs_zero(64); + } + + void + test_adl () + { + expect (adl_tester{} == zero, "ADL failure!"); + expect (detail::adl_tester2{} == zero, "ADL failure!"); + } + + void + run() + { + test_lhs_zero (); + test_rhs_zero (); + test_adl (); + } + +}; + +BEAST_DEFINE_TESTSUITE(Zero, types, beast); + +} diff --git a/tests.sh b/tests.sh old mode 100644 new mode 100755