diff options
140 files changed, 3184 insertions, 1622 deletions
diff --git a/3rdparty/bx/.appveyor.yml b/3rdparty/bx/.appveyor.yml index 001d04317b3..b0b107726f8 100644 --- a/3rdparty/bx/.appveyor.yml +++ b/3rdparty/bx/.appveyor.yml @@ -1,11 +1,12 @@ shallow_clone: true os: - - Visual Studio 2017 + - Visual Studio 2019 environment: matrix: - TOOLSET: vs2017 +# - TOOLSET: vs2019 configuration: - Debug diff --git a/3rdparty/bx/.travis.yml b/3rdparty/bx/.travis.yml index 54bf844abf2..82e0ac2e024 100644 --- a/3rdparty/bx/.travis.yml +++ b/3rdparty/bx/.travis.yml @@ -26,4 +26,4 @@ branches: notifications: email: false -osx_image: xcode9.3 +osx_image: xcode11 diff --git a/3rdparty/bx/3rdparty/catch/catch.hpp b/3rdparty/bx/3rdparty/catch/catch.hpp index 9b14505916c..0384171ae4a 100644 --- a/3rdparty/bx/3rdparty/catch/catch.hpp +++ b/3rdparty/bx/3rdparty/catch/catch.hpp @@ -1,9 +1,9 @@ /* - * Catch v2.9.0 - * Generated: 2019-06-16 10:41:32.122746 + * Catch v2.13.4 + * Generated: 2020-12-29 14:48:00.116107 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -14,8 +14,8 @@ #define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 9 -#define CATCH_VERSION_PATCH 0 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 4 #ifdef __clang__ # pragma clang system_header @@ -132,36 +132,51 @@ namespace Catch { #endif -#if defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + #endif -#ifdef __clang__ +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) && !defined(__CUDACC__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ +# endif + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) #endif // __clang__ @@ -186,6 +201,7 @@ namespace Catch { // Android somehow still does not support std::to_string #if defined(__ANDROID__) # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE #endif //////////////////////////////////////////////////////////////////////////////// @@ -219,11 +235,10 @@ namespace Catch { //////////////////////////////////////////////////////////////////////////////// // Visual C++ -#ifdef _MSC_VER +#if defined(_MSC_VER) -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) // Universal Windows platform does not support SEH // Or console colours (or console at all...) @@ -236,9 +251,12 @@ namespace Catch { // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + #endif // _MSC_VER #if defined(_REENTRANT) || defined(_MSC_VER) @@ -276,40 +294,56 @@ namespace Catch { #endif //////////////////////////////////////////////////////////////////////////////// -// Check if string_view is available and usable -// The check is split apart to work around v140 (VS2015) preprocessor issue... -#if defined(__has_include) -#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW -#endif + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE #endif -//////////////////////////////////////////////////////////////////////////////// -// Check if optional is available and usable -#if defined(__has_include) -# if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL -# endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) -#endif // __has_include +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif -//////////////////////////////////////////////////////////////////////////////// -// Check if variant is available and usable +// Various stdlib support checks that require __has_include #if defined(__has_include) -# if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) -# if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 -# include <ciso646> -# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# define CATCH_CONFIG_NO_CPP17_VARIANT -# else -# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) -# else -# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT -# endif // defined(__clang__) && (__clang_major__ < 8) -# endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) -#endif // __has_include + // Check if string_view is available and usable + #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) + # include <cstddef> + # if __cpp_lib_byte > 0 + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif + # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include <ciso646> + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) # define CATCH_CONFIG_COUNTER @@ -334,10 +368,6 @@ namespace Catch { # define CATCH_CONFIG_CPP17_OPTIONAL #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) # define CATCH_CONFIG_CPP17_STRING_VIEW #endif @@ -346,6 +376,10 @@ namespace Catch { # define CATCH_CONFIG_CPP17_VARIANT #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #endif @@ -362,25 +396,53 @@ namespace Catch { # define CATCH_CONFIG_POLYFILL_ISNAN #endif -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) # define CATCH_CONFIG_USE_ASYNC #endif +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) @@ -445,7 +507,7 @@ namespace Catch { SourceLineInfo( SourceLineInfo&& ) noexcept = default; SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - bool empty() const noexcept; + bool empty() const noexcept { return file[0] == '\0'; } bool operator == ( SourceLineInfo const& other ) const noexcept; bool operator < ( SourceLineInfo const& other ) const noexcept; @@ -486,9 +548,10 @@ namespace Catch { } // end namespace Catch #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // end catch_tag_alias_autoregistrar.h // start catch_test_registry.h @@ -515,6 +578,7 @@ namespace Catch { virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; }; + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); @@ -527,53 +591,30 @@ namespace Catch { #include <cstddef> #include <string> #include <iosfwd> +#include <cassert> namespace Catch { /// A non-owning string class (similar to the forthcoming std::string_view) /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. c_str() must return a null terminated - /// string, however, and so the StringRef will internally take ownership - /// (taking a copy), if necessary. In theory this ownership is not externally - /// visible - but it does mean (substring) StringRefs should not be shared between - /// threads. + /// it may not be null terminated. class StringRef { public: using size_type = std::size_t; + using const_iterator = const char*; private: - friend struct StringRefTestAccess; - - char const* m_start; - size_type m_size; - - char* m_data = nullptr; - - void takeOwnership(); - static constexpr char const* const s_empty = ""; - public: // construction/ assignment - StringRef() noexcept - : StringRef( s_empty, 0 ) - {} - - StringRef( StringRef const& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ) - {} + char const* m_start = s_empty; + size_type m_size = 0; - StringRef( StringRef&& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - other.m_data = nullptr; - } + public: // construction + constexpr StringRef() noexcept = default; StringRef( char const* rawChars ) noexcept; - StringRef( char const* rawChars, size_type size ) noexcept + constexpr StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) {} @@ -583,101 +624,64 @@ namespace Catch { m_size( stdString.size() ) {} - ~StringRef() noexcept { - delete[] m_data; - } - - auto operator = ( StringRef const &other ) noexcept -> StringRef& { - delete[] m_data; - m_data = nullptr; - m_start = other.m_start; - m_size = other.m_size; - return *this; + explicit operator std::string() const { + return std::string(m_start, m_size); } - operator std::string() const; - - void swap( StringRef& other ) noexcept; - public: // operators auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } - auto operator[] ( size_type index ) const noexcept -> char; + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } public: // named queries - auto empty() const noexcept -> bool { + constexpr auto empty() const noexcept -> bool { return m_size == 0; } - auto size() const noexcept -> size_type { + constexpr auto size() const noexcept -> size_type { return m_size; } - auto numberOfCharacters() const noexcept -> size_type; + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception auto c_str() const -> char const*; public: // substrings and searches - auto substr( size_type start, size_type size ) const noexcept -> StringRef; + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; - // Returns the current start pointer. - // Note that the pointer can change when if the StringRef is a substring - auto currentData() const noexcept -> char const*; + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; - private: // ownership queries - may not be consistent between calls - auto isOwned() const noexcept -> bool; - auto isSubstring() const noexcept -> bool; - }; + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; - auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { return StringRef( rawChars, size ); } - } // namespace Catch -inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { return Catch::StringRef( rawChars, size ); } // end catch_stringref.h -// start catch_type_traits.hpp - - -#include <type_traits> - -namespace Catch{ - -#ifdef CATCH_CPP17_OR_GREATER - template <typename...> - inline constexpr auto is_unique = std::true_type{}; - - template <typename T, typename... Rest> - inline constexpr auto is_unique<T, Rest...> = std::bool_constant< - (!std::is_same_v<T, Rest> && ...) && is_unique<Rest...> - >{}; -#else - -template <typename...> -struct is_unique : std::true_type{}; - -template <typename T0, typename T1, typename... Rest> -struct is_unique<T0, T1, Rest...> : std::integral_constant -<bool, - !std::is_same<T0, T1>::value - && is_unique<T0, Rest...>::value - && is_unique<T1, Rest...>::value ->{}; - -#endif -} - -// end catch_type_traits.hpp // start catch_preprocessor.hpp @@ -762,7 +766,7 @@ struct is_unique<T0, T1, Rest...> : std::integral_constant #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) @@ -774,35 +778,49 @@ struct is_unique<T0, T1, Rest...> : std::integral_constant template<typename...> struct TypeList {};\ template<typename...Ts>\ constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\ + template<template<typename...> class...> struct TemplateTypeList{};\ + template<template<typename...> class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\ + template<typename...>\ + struct append;\ + template<typename...>\ + struct rewrap;\ + template<template<typename...> class, typename...>\ + struct create;\ + template<template<typename...> class, typename>\ + struct convert;\ \ - template<template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2> \ - constexpr auto append(L1<E1...>, L2<E2...>) noexcept -> L1<E1...,E2...> { return {}; }\ + template<typename T> \ + struct append<T> { using type = T; };\ template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\ - constexpr auto append(L1<E1...>, L2<E2...>, Rest...) noexcept -> decltype(append(L1<E1...,E2...>{}, Rest{}...)) { return {}; }\ + struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\ template< template<typename...> class L1, typename...E1, typename...Rest>\ - constexpr auto append(L1<E1...>, TypeList<mpl_::na>, Rest...) noexcept -> L1<E1...> { return {}; }\ + struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\ \ template< template<typename...> class Container, template<typename...> class List, typename...elems>\ - constexpr auto rewrap(List<elems...>) noexcept -> TypeList<Container<elems...>> { return {}; }\ + struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\ template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\ - constexpr auto rewrap(List<Elems...>,Elements...) noexcept -> decltype(append(TypeList<Container<Elems...>>{}, rewrap<Container>(Elements{}...))) { return {}; }\ + struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\ \ template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\ - constexpr auto create(TypeList<Types...>) noexcept -> decltype(append(Final<>{}, rewrap<Containers>(Types{}...)...)) { return {}; }\ + struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\ template<template <typename...> class Final, template <typename...> class List, typename...Ts>\ - constexpr auto convert(List<Ts...>) noexcept -> decltype(append(Final<>{},TypeList<Ts>{}...)) { return {}; } + struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; }; #define INTERNAL_CATCH_NTTP_1(signature, ...)\ template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\ template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\ constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \ + template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\ + template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\ + constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \ \ template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ - constexpr auto rewrap(List<__VA_ARGS__>) noexcept -> TypeList<Container<__VA_ARGS__>> { return {}; }\ + struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\ template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\ - constexpr auto rewrap(List<__VA_ARGS__>,Elements...elems) noexcept -> decltype(append(TypeList<Container<__VA_ARGS__>>{}, rewrap<Container>(elems...))) { return {}; }\ + struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\ template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\ - constexpr auto create(TypeList<Types...>) noexcept -> decltype(append(Final<>{}, rewrap<Containers>(Types{}...)...)) { return {}; } + struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; }; #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName) #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\ @@ -898,22 +916,33 @@ struct is_unique<T0, T1, Rest...> : std::integral_constant #include <type_traits> namespace Catch { -template<typename T> -struct always_false : std::false_type {}; + template<typename T> + struct always_false : std::false_type {}; + + template <typename> struct true_given : std::true_type {}; + struct is_callable_tester { + template <typename Fun, typename... Args> + true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); + template <typename...> + std::false_type static test(...); + }; -template <typename> struct true_given : std::true_type {}; -struct is_callable_tester { - template <typename Fun, typename... Args> - true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); - template <typename...> - std::false_type static test(...); -}; + template <typename T> + struct is_callable; -template <typename T> -struct is_callable; + template <typename Fun, typename... Args> + struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {}; -template <typename Fun, typename... Args> -struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {}; +#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 + // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is + // replaced with std::invoke_result here. + template <typename Func, typename... U> + using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>; +#else + // Keep ::type here because we still support C++11 + template <typename Func, typename... U> + using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type; +#endif } // namespace Catch @@ -1012,21 +1041,24 @@ struct AutoReg : NonCopyable { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ \ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ @@ -1034,21 +1066,24 @@ struct AutoReg : NonCopyable { }; \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ namespace {\ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ @@ -1061,7 +1096,7 @@ struct AutoReg : NonCopyable { int index = 0; \ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ using expander = int[];\ - (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ @@ -1070,8 +1105,7 @@ struct AutoReg : NonCopyable { }();\ }\ }\ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature)) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR @@ -1091,8 +1125,10 @@ struct AutoReg : NonCopyable { #endif #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ template<typename TestType> static void TestFuncName(); \ namespace {\ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \ @@ -1106,19 +1142,18 @@ struct AutoReg : NonCopyable { constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\ } \ }; \ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ - using TestInit = decltype(create<TestName, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>{})); \ + using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \ TestInit t; \ t.reg_tests(); \ return 0; \ }(); \ } \ } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ template<typename TestType> \ static void TestFuncName() @@ -1139,7 +1174,9 @@ struct AutoReg : NonCopyable { #endif #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ template<typename TestType> static void TestFunc(); \ namespace {\ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ @@ -1149,17 +1186,17 @@ struct AutoReg : NonCopyable { void reg_tests() { \ int index = 0; \ using expander = int[]; \ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */\ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\ } \ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ - using TestInit = decltype(convert<TestName>(TmplList {})); \ + using TestInit = typename convert<TestName, TmplList>::type; \ TestInit t; \ t.reg_tests(); \ return 0; \ - }(); \ + }(); \ }}\ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ template<typename TestType> \ static void TestFunc() @@ -1167,8 +1204,10 @@ struct AutoReg : NonCopyable { INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList ) #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ namespace {\ namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ INTERNAL_CATCH_TYPE_GEN\ @@ -1181,7 +1220,7 @@ struct AutoReg : NonCopyable { int index = 0; \ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ using expander = int[];\ - (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ @@ -1190,8 +1229,7 @@ struct AutoReg : NonCopyable { }();\ }\ }\ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\ - CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS\ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR @@ -1211,8 +1249,10 @@ struct AutoReg : NonCopyable { #endif #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ template<typename TestType> \ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ void test();\ @@ -1229,19 +1269,18 @@ struct AutoReg : NonCopyable { constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ - using TestInit = decltype(create<TestNameClass, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>{}));\ + using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\ TestInit t;\ t.reg_tests();\ return 0;\ }(); \ }\ }\ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ template<typename TestType> \ void TestName<TestType>::test() @@ -1262,7 +1301,9 @@ struct AutoReg : NonCopyable { #endif #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ template<typename TestType> \ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ void test();\ @@ -1275,17 +1316,17 @@ struct AutoReg : NonCopyable { void reg_tests(){\ int index = 0;\ using expander = int[];\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */ \ + (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \ }\ };\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ - using TestInit = decltype(convert<TestNameClass>(TmplList {}));\ + using TestInit = typename convert<TestNameClass, TmplList>::type;\ TestInit t;\ t.reg_tests();\ return 0;\ }(); \ }}\ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ template<typename TestType> \ void TestName<TestType>::test() @@ -1391,7 +1432,7 @@ namespace Catch { auto makeStream( StringRef const &filename ) -> IStream const*; - class ReusableStringStream { + class ReusableStringStream : NonCopyable { std::size_t m_index; std::ostream* m_oss; public: @@ -1419,7 +1460,7 @@ namespace Catch { namespace Detail { struct EnumInfo { StringRef m_name; - std::vector<std::pair<int, std::string>> m_values; + std::vector<std::pair<int, StringRef>> m_values; ~EnumInfo(); @@ -1434,6 +1475,7 @@ namespace Catch { template<typename E> Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) { + static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); std::vector<int> intValues; intValues.reserve( values.size() ); for( auto enumValue : values ) @@ -1515,9 +1557,9 @@ namespace Catch { template<typename T> class IsStreamInsertable { - template<typename SS, typename TT> + template<typename Stream, typename U> static auto test(int) - -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type()); + -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type()); template<typename, typename> static auto test(...)->std::false_type; @@ -1679,6 +1721,12 @@ namespace Catch { } }; +#if defined(CATCH_CONFIG_CPP17_BYTE) + template<> + struct StringMaker<std::byte> { + static std::string convert(std::byte value); + }; +#endif // defined(CATCH_CONFIG_CPP17_BYTE) template<> struct StringMaker<int> { static std::string convert(int value); @@ -1772,8 +1820,8 @@ namespace Catch { #endif namespace Detail { - template<typename InputIterator> - std::string rangeToString(InputIterator first, InputIterator last) { + template<typename InputIterator, typename Sentinel = InputIterator> + std::string rangeToString(InputIterator first, Sentinel last) { ReusableStringStream rss; rss << "{ "; if (first != last) { @@ -1931,20 +1979,27 @@ namespace Catch { #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER namespace Catch { - struct not_this_one {}; // Tag type for detecting which begin/ end are being selected - - // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace + // Import begin/ end from std here using std::begin; using std::end; - not_this_one begin( ... ); - not_this_one end( ... ); + namespace detail { + template <typename...> + struct void_type { + using type = void; + }; + + template <typename T, typename = void> + struct is_range_impl : std::false_type { + }; + + template <typename T> + struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type { + }; + } // namespace detail template <typename T> - struct is_range { - static const bool value = - !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value && - !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value; + struct is_range : detail::is_range_impl<T> { }; #if defined(_MANAGED) // Managed types are never ranges @@ -2114,7 +2169,7 @@ namespace Catch { \ template<> struct StringMaker<enumName> { \ static std::string convert( enumName value ) { \ static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ - return enumInfo.lookup( static_cast<int>( value ) ); \ + return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \ } \ }; \ } @@ -2312,6 +2367,18 @@ namespace Catch { auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; } + template <typename RhsT> + auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { + return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs }; + } + template <typename RhsT> + auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { + return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs }; + } + template <typename RhsT> + auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { + return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs }; + } template<typename RhsT> auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { @@ -2392,7 +2459,7 @@ namespace Catch { virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; + virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) virtual void benchmarkPreparing( std::string const& name ) = 0; @@ -2630,15 +2697,16 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ + CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ INTERNAL_CATCH_TRY { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look - // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. + } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ @@ -2855,14 +2923,16 @@ namespace Catch { } // end namespace Catch #define INTERNAL_CATCH_SECTION( ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ - CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ - CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // end catch_section.h // start catch_interfaces_exception.h @@ -2953,6 +3023,9 @@ namespace Catch { {} std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) + return ""; +#else try { if( it == itEnd ) std::rethrow_exception(std::current_exception()); @@ -2962,6 +3035,7 @@ namespace Catch { catch( T& ex ) { return m_translateFunction( ex ); } +#endif } protected: @@ -2980,9 +3054,10 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ static std::string translatorName( signature ); \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ static std::string translatorName( signature ) #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) @@ -3124,7 +3199,10 @@ namespace Catch { bool contains( std::string const& s, std::string const& infix ); void toLowerInPlace( std::string& s ); std::string toLower( std::string const& s ); + //! Returns a new string without whitespace at the start/end std::string trim( std::string const& str ); + //! Returns a substring of the original ref without whitespace. Beware lifetimes! + StringRef trim(StringRef ref); // !!! Be aware, returns refs into original string - make sure original string outlives them std::vector<StringRef> splitStringRef( StringRef str, char delimiter ); @@ -3180,6 +3258,15 @@ namespace Matchers { virtual bool match( ObjectT const& arg ) const = 0; }; +#if defined(__OBJC__) + // Hack to fix Catch GH issue #1661. Could use id for generic Object support. + // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation + template<> + struct MatcherMethod<NSString*> { + virtual bool match( NSString* arg ) const = 0; + }; +#endif + #ifdef __clang__ # pragma clang diagnostic pop #endif @@ -3217,9 +3304,10 @@ namespace Matchers { return description; } - MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) { - m_matchers.push_back( &other ); - return *this; + MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) { + auto copy(*this); + copy.m_matchers.push_back( &other ); + return copy; } std::vector<MatcherBase<ArgT> const*> m_matchers; @@ -3250,9 +3338,10 @@ namespace Matchers { return description; } - MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) { - m_matchers.push_back( &other ); - return *this; + MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) { + auto copy(*this); + copy.m_matchers.push_back( &other ); + return copy; } std::vector<MatcherBase<ArgT> const*> m_matchers; @@ -3296,10 +3385,34 @@ using Matchers::Impl::MatcherBase; } // namespace Catch // end catch_matchers.h -// start catch_matchers_floating.h +// start catch_matchers_exception.hpp -#include <type_traits> -#include <cmath> +namespace Catch { +namespace Matchers { +namespace Exception { + +class ExceptionMessageMatcher : public MatcherBase<std::exception> { + std::string m_message; +public: + + ExceptionMessageMatcher(std::string const& message): + m_message(message) + {} + + bool match(std::exception const& ex) const override; + + std::string describe() const override; +}; + +} // namespace Exception + +Exception::ExceptionMessageMatcher Message(std::string const& message); + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_exception.hpp +// start catch_matchers_floating.h namespace Catch { namespace Matchers { @@ -3318,22 +3431,43 @@ namespace Matchers { }; struct WithinUlpsMatcher : MatcherBase<double> { - WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType); + WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); bool match(double const& matchee) const override; std::string describe() const override; private: double m_target; - int m_ulps; + uint64_t m_ulps; FloatingPointKind m_type; }; + // Given IEEE-754 format for floats and doubles, we can assume + // that float -> double promotion is lossless. Given this, we can + // assume that if we do the standard relative comparison of + // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get + // the same result if we do this for floats, as if we do this for + // doubles that were promoted from floats. + struct WithinRelMatcher : MatcherBase<double> { + WithinRelMatcher(double target, double epsilon); + bool match(double const& matchee) const override; + std::string describe() const override; + private: + double m_target; + double m_epsilon; + }; + } // namespace Floating // The following functions create the actual matcher objects. // This allows the types to be inferred - Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff); - Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff); + Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); + Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); Floating::WithinAbsMatcher WithinAbs(double target, double margin); + Floating::WithinRelMatcher WithinRel(double target, double eps); + // defaults epsilon to 100*numeric_limits<double>::epsilon() + Floating::WithinRelMatcher WithinRel(double target); + Floating::WithinRelMatcher WithinRel(float target, float eps); + // defaults epsilon to 100*numeric_limits<float>::epsilon() + Floating::WithinRelMatcher WithinRel(float target); } // namespace Matchers } // namespace Catch @@ -3464,12 +3598,12 @@ namespace Catch { namespace Matchers { namespace Vector { - template<typename T> - struct ContainsElementMatcher : MatcherBase<std::vector<T>> { + template<typename T, typename Alloc> + struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} - bool match(std::vector<T> const &v) const override { + bool match(std::vector<T, Alloc> const &v) const override { for (auto const& el : v) { if (el == m_comparator) { return true; @@ -3485,12 +3619,12 @@ namespace Matchers { T const& m_comparator; }; - template<typename T> - struct ContainsMatcher : MatcherBase<std::vector<T>> { + template<typename T, typename AllocComp, typename AllocMatch> + struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> { - ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} + ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} - bool match(std::vector<T> const &v) const override { + bool match(std::vector<T, AllocMatch> const &v) const override { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; @@ -3512,18 +3646,18 @@ namespace Matchers { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } - std::vector<T> const& m_comparator; + std::vector<T, AllocComp> const& m_comparator; }; - template<typename T> - struct EqualsMatcher : MatcherBase<std::vector<T>> { + template<typename T, typename AllocComp, typename AllocMatch> + struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { - EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} + EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {} - bool match(std::vector<T> const &v) const override { + bool match(std::vector<T, AllocMatch> const &v) const override { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults - // to using !=. but could be specialised for, e.g. std::vector<T> etc + // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc // - then just call that directly if (m_comparator.size() != v.size()) return false; @@ -3535,15 +3669,15 @@ namespace Matchers { std::string describe() const override { return "Equals: " + ::Catch::Detail::stringify( m_comparator ); } - std::vector<T> const& m_comparator; + std::vector<T, AllocComp> const& m_comparator; }; - template<typename T> - struct ApproxMatcher : MatcherBase<std::vector<T>> { + template<typename T, typename AllocComp, typename AllocMatch> + struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> { - ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {} + ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {} - bool match(std::vector<T> const &v) const override { + bool match(std::vector<T, AllocMatch> const &v) const override { if (m_comparator.size() != v.size()) return false; for (std::size_t i = 0; i < v.size(); ++i) @@ -3570,16 +3704,14 @@ namespace Matchers { return *this; } - std::vector<T> const& m_comparator; + std::vector<T, AllocComp> const& m_comparator; mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); }; - template<typename T> - struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> { - UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {} - bool match(std::vector<T> const& vec) const override { - // Note: This is a reimplementation of std::is_permutation, - // because I don't want to include <algorithm> inside the common path + template<typename T, typename AllocComp, typename AllocMatch> + struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> { + UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {} + bool match(std::vector<T, AllocMatch> const& vec) const override { if (m_target.size() != vec.size()) { return false; } @@ -3590,7 +3722,7 @@ namespace Matchers { return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); } private: - std::vector<T> const& m_target; + std::vector<T, AllocComp> const& m_target; }; } // namespace Vector @@ -3598,29 +3730,29 @@ namespace Matchers { // The following functions create the actual matcher objects. // This allows the types to be inferred - template<typename T> - Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) { - return Vector::ContainsMatcher<T>( comparator ); + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { + return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator ); } - template<typename T> - Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) { - return Vector::ContainsElementMatcher<T>( comparator ); + template<typename T, typename Alloc = std::allocator<T>> + Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) { + return Vector::ContainsElementMatcher<T, Alloc>( comparator ); } - template<typename T> - Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) { - return Vector::EqualsMatcher<T>( comparator ); + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) { + return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator ); } - template<typename T> - Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) { - return Vector::ApproxMatcher<T>( comparator ); + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) { + return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator ); } - template<typename T> - Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) { - return Vector::UnorderedEqualsMatcher<T>(target); + template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> + Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) { + return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target ); } } // namespace Matchers @@ -3758,13 +3890,13 @@ namespace Catch { (Catch::ReusableStringStream() << __VA_ARGS__).str() #define CATCH_INTERNAL_ERROR(...) \ - Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)); + Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__)) #define CATCH_ERROR(...) \ - Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )); + Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ )) #define CATCH_RUNTIME_ERROR(...) \ - Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )); + Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ )) #define CATCH_ENFORCE( condition, ... ) \ do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false) @@ -3816,7 +3948,6 @@ namespace Generators { class SingleValueGenerator final : public IGenerator<T> { T m_value; public: - SingleValueGenerator(T const& value) : m_value( value ) {} SingleValueGenerator(T&& value) : m_value(std::move(value)) {} T const& get() const override { @@ -3829,6 +3960,9 @@ namespace Generators { template<typename T> class FixedValuesGenerator final : public IGenerator<T> { + static_assert(!std::is_same<T, bool>::value, + "FixedValuesGenerator does not support bools because of std::vector<bool>" + "specialization, use SingleValue Generator instead."); std::vector<T> m_values; size_t m_idx = 0; public: @@ -3876,21 +4010,21 @@ namespace Generators { m_generators.emplace_back(std::move(generator)); } void populate(T&& val) { - m_generators.emplace_back(value(std::move(val))); + m_generators.emplace_back(value(std::forward<T>(val))); } template<typename U> void populate(U&& val) { - populate(T(std::move(val))); + populate(T(std::forward<U>(val))); } template<typename U, typename... Gs> - void populate(U&& valueOrGenerator, Gs... moreGenerators) { + void populate(U&& valueOrGenerator, Gs &&... moreGenerators) { populate(std::forward<U>(valueOrGenerator)); populate(std::forward<Gs>(moreGenerators)...); } public: template <typename... Gs> - Generators(Gs... moreGenerators) { + Generators(Gs &&... moreGenerators) { m_generators.reserve(sizeof...(Gs)); populate(std::forward<Gs>(moreGenerators)...); } @@ -3921,7 +4055,7 @@ namespace Generators { struct as {}; template<typename T, typename... Gs> - auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> { + auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> { return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...); } template<typename T> @@ -3929,24 +4063,24 @@ namespace Generators { return Generators<T>(std::move(generator)); } template<typename T, typename... Gs> - auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> { + auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> { return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); } template<typename T, typename U, typename... Gs> - auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> { + auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> { return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); } - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; + auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; template<typename L> // Note: The type after -> is weird, because VS2015 cannot parse // the expression used in the typedef inside, when it is in // return type. Yeah. - auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { + auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { using UnderlyingType = typename decltype(generatorExpression())::type; - IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); + IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo ); if (!tracker.hasGenerator()) { tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); } @@ -3959,11 +4093,17 @@ namespace Generators { } // namespace Catch #define GENERATE( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) #define GENERATE_COPY( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) #define GENERATE_REF( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) // end catch_generators.hpp // start catch_generators_generic.hpp @@ -4048,6 +4188,9 @@ namespace Generators { template <typename T> class RepeatGenerator : public IGenerator<T> { + static_assert(!std::is_same<T, bool>::value, + "RepeatGenerator currently does not support bools" + "because of std::vector<bool> specialization"); GeneratorWrapper<T> m_generator; mutable std::vector<T> m_returned; size_t m_target_repeats; @@ -4126,18 +4269,7 @@ namespace Generators { } }; -#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 - // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is - // replaced with std::invoke_result here. Also *_t format is preferred over - // typename *::type format. - template <typename Func, typename U> - using MapFunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>; -#else - template <typename Func, typename U> - using MapFunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type; -#endif - - template <typename Func, typename U, typename T = MapFunctionReturnType<Func, U>> + template <typename Func, typename U, typename T = FunctionReturnType<Func, U>> GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) { return GeneratorWrapper<T>( pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)) @@ -4162,12 +4294,14 @@ namespace Generators { m_chunk_size(size), m_generator(std::move(generator)) { m_chunk.reserve(m_chunk_size); - m_chunk.push_back(m_generator.get()); - for (size_t i = 1; i < m_chunk_size; ++i) { - if (!m_generator.next()) { - Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); - } + if (m_chunk_size != 0) { m_chunk.push_back(m_generator.get()); + for (size_t i = 1; i < m_chunk_size; ++i) { + if (!m_generator.next()) { + Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); + } + m_chunk.push_back(m_generator.get()); + } } } std::vector<T> const& get() const override { @@ -4238,6 +4372,7 @@ namespace Catch { { if( !IMutableContext::currentContext ) IMutableContext::createContext(); + // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) return *IMutableContext::currentContext; } @@ -4247,6 +4382,9 @@ namespace Catch { } void cleanUpContext(); + + class SimplePcg32; + SimplePcg32& rng(); } // end catch_context.h @@ -4317,6 +4455,7 @@ namespace Catch { } // end namespace Catch // end catch_option.hpp +#include <chrono> #include <iosfwd> #include <string> #include <vector> @@ -4374,6 +4513,7 @@ namespace Catch { virtual int abortAfter() const = 0; virtual bool showInvisibles() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; + virtual double minDuration() const = 0; virtual TestSpec const& testSpec() const = 0; virtual bool hasTestFilters() const = 0; virtual std::vector<std::string> const& getTestsOrTags() const = 0; @@ -4387,12 +4527,63 @@ namespace Catch { virtual int benchmarkSamples() const = 0; virtual double benchmarkConfidenceInterval() const = 0; virtual unsigned int benchmarkResamples() const = 0; + virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; }; using IConfigPtr = std::shared_ptr<IConfig const>; } // end catch_interfaces_config.h +// start catch_random_number_generator.h + +#include <cstdint> + +namespace Catch { + + // This is a simple implementation of C++11 Uniform Random Number + // Generator. It does not provide all operators, because Catch2 + // does not use it, but it should behave as expected inside stdlib's + // distributions. + // The implementation is based on the PCG family (http://pcg-random.org) + class SimplePcg32 { + using state_type = std::uint64_t; + public: + using result_type = std::uint32_t; + static constexpr result_type (min)() { + return 0; + } + static constexpr result_type (max)() { + return static_cast<result_type>(-1); + } + + // Provide some default initial state for the default constructor + SimplePcg32():SimplePcg32(0xed743cc4U) {} + + explicit SimplePcg32(result_type seed_); + + void seed(result_type seed_); + void discard(uint64_t skip); + + result_type operator()(); + + private: + friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs); + friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs); + + // In theory we also need operator<< and operator>> + // In practice we do not use them, so we will skip them for now + + std::uint64_t m_state; + // This part of the state determines which "stream" of the numbers + // is chosen -- we take it as a constant for Catch2, so we only + // need to deal with seeding the main state. + // Picked by reading 8 bytes from `/dev/random` :-) + static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL; + }; + +} // end namespace Catch + +// end catch_random_number_generator.h #include <random> namespace Catch { @@ -4400,14 +4591,13 @@ namespace Generators { template <typename Float> class RandomFloatingGenerator final : public IGenerator<Float> { - // FIXME: What is the right seed? - std::minstd_rand m_rand; + Catch::SimplePcg32& m_rng; std::uniform_real_distribution<Float> m_dist; Float m_current_number; public: RandomFloatingGenerator(Float a, Float b): - m_rand(getCurrentContext().getConfig()->rngSeed()), + m_rng(rng()), m_dist(a, b) { static_cast<void>(next()); } @@ -4416,20 +4606,20 @@ public: return m_current_number; } bool next() override { - m_current_number = m_dist(m_rand); + m_current_number = m_dist(m_rng); return true; } }; template <typename Integer> class RandomIntegerGenerator final : public IGenerator<Integer> { - std::minstd_rand m_rand; + Catch::SimplePcg32& m_rng; std::uniform_int_distribution<Integer> m_dist; Integer m_current_number; public: RandomIntegerGenerator(Integer a, Integer b): - m_rand(getCurrentContext().getConfig()->rngSeed()), + m_rng(rng()), m_dist(a, b) { static_cast<void>(next()); } @@ -4438,7 +4628,7 @@ public: return m_current_number; } bool next() override { - m_current_number = m_dist(m_rand); + m_current_number = m_dist(m_rng); return true; } }; @@ -4498,7 +4688,7 @@ public: template <typename T> GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { - static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); + static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric"); return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step)); } @@ -4508,6 +4698,45 @@ GeneratorWrapper<T> range(T const& start, T const& end) { return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end)); } +template <typename T> +class IteratorGenerator final : public IGenerator<T> { + static_assert(!std::is_same<T, bool>::value, + "IteratorGenerator currently does not support bools" + "because of std::vector<bool> specialization"); + + std::vector<T> m_elems; + size_t m_current = 0; +public: + template <typename InputIterator, typename InputSentinel> + IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) { + if (m_elems.empty()) { + Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values")); + } + } + + T const& get() const override { + return m_elems[m_current]; + } + + bool next() override { + ++m_current; + return m_current != m_elems.size(); + } +}; + +template <typename InputIterator, + typename InputSentinel, + typename ResultType = typename std::iterator_traits<InputIterator>::value_type> +GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) { + return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to)); +} + +template <typename Container, + typename ResultType = typename Container::value_type> +GeneratorWrapper<ResultType> from_range(Container const& cnt) { + return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end())); +} + } // namespace Generators } // namespace Catch @@ -4711,7 +4940,7 @@ namespace Catch { arcSafeRelease( m_substr ); } - bool match( NSString* const& str ) const override { + bool match( NSString* str ) const override { return false; } @@ -4721,7 +4950,7 @@ namespace Catch { struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* const& str ) const override { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } @@ -4734,7 +4963,7 @@ namespace Catch { struct Contains : StringHolder { Contains( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* const& str ) const override { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location != NSNotFound; } @@ -4747,7 +4976,7 @@ namespace Catch { struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* const& str ) const override { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } @@ -4759,7 +4988,7 @@ namespace Catch { struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* const& str ) const override { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } @@ -4810,7 +5039,8 @@ return @ desc; \ // end catch_objc.hpp #endif -#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES +// Benchmarking needs the externally-facing parts of reporters to work +#if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING) // start catch_external_interfaces.h // start catch_reporter_bases.hpp @@ -4852,7 +5082,7 @@ namespace Catch virtual bool matches( std::string const& str ) const; private: - std::string adjustCase( std::string const& str ) const; + std::string normaliseString( std::string const& str ) const; CaseSensitive::Choice m_caseSensitivity; WildcardPosition m_wildcard = NoWildcard; std::string m_pattern; @@ -4866,17 +5096,23 @@ namespace Catch namespace Catch { + struct IConfig; + class TestSpec { - struct Pattern { + class Pattern { + public: + explicit Pattern( std::string const& name ); virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; + std::string const& name() const; + private: + std::string const m_name; }; using PatternPtr = std::shared_ptr<Pattern>; class NamePattern : public Pattern { public: - NamePattern( std::string const& name ); - virtual ~NamePattern(); + explicit NamePattern( std::string const& name, std::string const& filterString ); bool matches( TestCaseInfo const& testCase ) const override; private: WildcardPattern m_wildcardPattern; @@ -4884,8 +5120,7 @@ namespace Catch { class TagPattern : public Pattern { public: - TagPattern( std::string const& tag ); - virtual ~TagPattern(); + explicit TagPattern( std::string const& tag, std::string const& filterString ); bool matches( TestCaseInfo const& testCase ) const override; private: std::string m_tag; @@ -4893,8 +5128,7 @@ namespace Catch { class ExcludedPattern : public Pattern { public: - ExcludedPattern( PatternPtr const& underlyingPattern ); - virtual ~ExcludedPattern(); + explicit ExcludedPattern( PatternPtr const& underlyingPattern ); bool matches( TestCaseInfo const& testCase ) const override; private: PatternPtr m_underlyingPattern; @@ -4904,15 +5138,25 @@ namespace Catch { std::vector<PatternPtr> m_patterns; bool matches( TestCaseInfo const& testCase ) const; + std::string name() const; }; public: + struct FilterMatch { + std::string name; + std::vector<TestCase const*> tests; + }; + using Matches = std::vector<FilterMatch>; + using vectorStrings = std::vector<std::string>; + bool hasFilters() const; bool matches( TestCaseInfo const& testCase ) const; + Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const; + const vectorStrings & getInvalidArgs() const; private: std::vector<Filter> m_filters; - + std::vector<std::string> m_invalidArgs; friend class TestSpecParser; }; } @@ -4947,9 +5191,13 @@ namespace Catch { class TestSpecParser { enum Mode{ None, Name, QuotedName, Tag, EscapedName }; Mode m_mode = None; + Mode lastMode = None; bool m_exclusion = false; - std::size_t m_start = std::string::npos, m_pos = 0; + std::size_t m_pos = 0; + std::size_t m_realPatternPos = 0; std::string m_arg; + std::string m_substring; + std::string m_patternName; std::vector<std::size_t> m_escapeChars; TestSpec::Filter m_currentFilter; TestSpec m_testSpec; @@ -4962,32 +5210,32 @@ namespace Catch { TestSpec testSpec(); private: - void visitChar( char c ); - void startNewMode( Mode mode, std::size_t start ); + bool visitChar( char c ); + void startNewMode( Mode mode ); + bool processNoneChar( char c ); + void processNameChar( char c ); + bool processOtherChar( char c ); + void endMode(); void escape(); - std::string subString() const; + bool isControlChar( char c ) const; + void saveLastMode(); + void revertBackToLastMode(); + void addFilter(); + bool separate(); - template<typename T> - void addPattern() { - std::string token = subString(); - for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) - token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); - m_escapeChars.clear(); - if( startsWith( token, "exclude:" ) ) { - m_exclusion = true; - token = token.substr( 8 ); - } - if( !token.empty() ) { - TestSpec::PatternPtr pattern = std::make_shared<T>( token ); - if( m_exclusion ) - pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern ); - m_currentFilter.m_patterns.push_back( pattern ); - } - m_exclusion = false; - m_mode = None; + // Handles common preprocessing of the pattern for name/tag patterns + std::string preprocessPattern(); + // Adds the current pattern as a test name + void addNamePattern(); + // Adds the current pattern as a tag + void addTagPattern(); + + inline void addCharToPattern(char c) { + m_substring += c; + m_patternName += c; + m_realPatternPos++; } - void addFilter(); }; TestSpec parseTestSpec( std::string const& arg ); @@ -5033,10 +5281,12 @@ namespace Catch { unsigned int benchmarkSamples = 100; double benchmarkConfidenceInterval = 0.95; unsigned int benchmarkResamples = 100000; + std::chrono::milliseconds::rep benchmarkWarmupTime = 100; Verbosity verbosity = Verbosity::Normal; WarnAbout::What warnings = WarnAbout::Nothing; ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; + double minDuration = -1; RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; UseColour::YesOrNo useColour = UseColour::Auto; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; @@ -5087,6 +5337,7 @@ namespace Catch { bool warnAboutMissingAssertions() const override; bool warnAboutNoTests() const override; ShowDurations::OrNot showDurations() const override; + double minDuration() const override; RunTests::InWhatOrder runOrder() const override; unsigned int rngSeed() const override; UseColour::YesOrNo useColour() const override; @@ -5098,6 +5349,7 @@ namespace Catch { int benchmarkSamples() const override; double benchmarkConfidenceInterval() const override; unsigned int benchmarkResamples() const override; + std::chrono::milliseconds benchmarkWarmupTime() const override; private: @@ -5395,6 +5647,8 @@ namespace Catch { virtual void noMatchingTestCases( std::string const& spec ) = 0; + virtual void reportInvalidArguments(std::string const&) {} + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; @@ -5461,6 +5715,9 @@ namespace Catch { // Returns double formatted as %.3f (format expected on output) std::string getFormattedDuration( double duration ); + //! Should the reporter show + bool shouldShowDuration( IConfig const& config, double duration ); + std::string serializeFilters( std::vector<std::string> const& container ); template<typename DerivedT> @@ -5487,6 +5744,8 @@ namespace Catch { void noMatchingTestCases(std::string const&) override {} + void reportInvalidArguments(std::string const&) override {} + void testRunStarting(TestRunInfo const& _testRunInfo) override { currentTestRunInfo = _testRunInfo; } @@ -5821,14 +6080,16 @@ namespace Catch { #if !defined(CATCH_CONFIG_DISABLE) #define CATCH_REGISTER_REPORTER( name, reporterType ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #define CATCH_REGISTER_LISTENER( listenerType ) \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #else // CATCH_CONFIG_DISABLE #define CATCH_REGISTER_REPORTER(name, reporterType) @@ -5850,8 +6111,6 @@ namespace Catch { static std::string getDescription(); - ReporterPreferences getPreferences() const override; - void noMatchingTestCases(std::string const& spec) override; void assertionStarting(AssertionInfo const&) override; @@ -5890,6 +6149,8 @@ namespace Catch { void noMatchingTestCases(std::string const& spec) override; + void reportInvalidArguments(std::string const&arg) override; + void assertionStarting(AssertionInfo const&) override; bool assertionEnded(AssertionStats const& _assertionStats) override; @@ -5949,6 +6210,14 @@ namespace Catch { #include <vector> namespace Catch { + enum class XmlFormatting { + None = 0x00, + Indent = 0x01, + Newline = 0x02, + }; + + XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs); + XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs); class XmlEncode { public: @@ -5970,14 +6239,14 @@ namespace Catch { class ScopedElement { public: - ScopedElement( XmlWriter* writer ); + ScopedElement( XmlWriter* writer, XmlFormatting fmt ); ScopedElement( ScopedElement&& other ) noexcept; ScopedElement& operator=( ScopedElement&& other ) noexcept; ~ScopedElement(); - ScopedElement& writeText( std::string const& text, bool indent = true ); + ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); template<typename T> ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { @@ -5987,6 +6256,7 @@ namespace Catch { private: mutable XmlWriter* m_writer = nullptr; + XmlFormatting m_fmt; }; XmlWriter( std::ostream& os = Catch::cout() ); @@ -5995,11 +6265,11 @@ namespace Catch { XmlWriter( XmlWriter const& ) = delete; XmlWriter& operator=( XmlWriter const& ) = delete; - XmlWriter& startElement( std::string const& name ); + XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - ScopedElement scopedElement( std::string const& name ); + ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - XmlWriter& endElement(); + XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); @@ -6012,9 +6282,9 @@ namespace Catch { return writeAttribute( name, rss.str() ); } - XmlWriter& writeText( std::string const& text, bool indent = true ); + XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); - XmlWriter& writeComment( std::string const& text ); + XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); void writeStylesheetRef( std::string const& url ); @@ -6024,6 +6294,8 @@ namespace Catch { private: + void applyFormatting(XmlFormatting fmt); + void writeDeclaration(); void newlineIfNecessary(); @@ -6125,6 +6397,7 @@ namespace Catch { void testRunEnded(TestRunStats const& testRunStats) override; #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) + void benchmarkPreparing(std::string const& name) override; void benchmarkStarting(BenchmarkInfo const&) override; void benchmarkEnded(BenchmarkStats<> const&) override; void benchmarkFailed(std::string const&) override; @@ -6144,6 +6417,12 @@ namespace Catch { #endif #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) +// start catch_benchmarking_all.hpp + +// A proxy header that includes all of the benchmarking headers to allow +// concise include of the benchmarking features. You should prefer the +// individual includes in standard use. + // start catch_benchmark.hpp // Benchmark @@ -6279,20 +6558,18 @@ namespace Catch { return {}; } }; - template <typename Sig> - using ResultOf_t = typename std::result_of<Sig>::type; // invoke and not return void :( template <typename Fun, typename... Args> - CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke(Fun&& fun, Args&&... args) { - return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); + CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) { + return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); } const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; } // namespace Detail template <typename Fun> - Detail::CompleteType_t<Detail::ResultOf_t<Fun()>> user_code(Fun&& fun) { + Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) { CATCH_TRY{ return Detail::complete_invoke(std::forward<Fun>(fun)); } CATCH_CATCH_ALL{ @@ -6537,8 +6814,8 @@ namespace Catch { Result result; int iterations; }; - template <typename Clock, typename Sig> - using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<Detail::ResultOf_t<Sig>>>; + template <typename Clock, typename Func, typename... Args> + using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>; } // namespace Benchmark } // namespace Catch @@ -6549,7 +6826,7 @@ namespace Catch { namespace Benchmark { namespace Detail { template <typename Clock, typename Fun, typename... Args> - TimingOf<Clock, Fun(Args...)> measure(Fun&& fun, Args&&... args) { + TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) { auto start = Clock::now(); auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...); auto end = Clock::now(); @@ -6568,11 +6845,11 @@ namespace Catch { namespace Benchmark { namespace Detail { template <typename Clock, typename Fun> - TimingOf<Clock, Fun(int)> measure_one(Fun&& fun, int iters, std::false_type) { + TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) { return Detail::measure<Clock>(fun, iters); } template <typename Clock, typename Fun> - TimingOf<Clock, Fun(Chronometer)> measure_one(Fun&& fun, int iters, std::true_type) { + TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) { Detail::ChronometerModel<Clock> meter; auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); @@ -6589,7 +6866,7 @@ namespace Catch { }; template <typename Clock, typename Fun> - TimingOf<Clock, Fun(run_for_at_least_argument_t<Clock, Fun>)> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) { + TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) { auto iters = seed; while (iters < (1 << 30)) { auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>()); @@ -6657,11 +6934,13 @@ namespace Catch { #include <algorithm> #include <functional> #include <vector> +#include <iterator> #include <numeric> #include <tuple> #include <cmath> #include <utility> #include <cstddef> +#include <random> namespace Catch { namespace Benchmark { @@ -7011,10 +7290,10 @@ namespace Catch { template <typename Clock> ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const { auto min_time = env.clock_resolution.mean * Detail::minimum_ticks; - auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(Detail::warmup_time)); + auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime())); auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun); int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed)); - return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(Detail::warmup_time), Detail::warmup_iterations }; + return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations }; } template <typename Clock = default_clock> @@ -7046,7 +7325,7 @@ namespace Catch { }); auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); - BenchmarkStats<std::chrono::duration<double, std::nano>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; + BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; getResultCapture().benchmarkEnded(stats); } CATCH_CATCH_ALL{ @@ -7087,6 +7366,77 @@ namespace Catch { BenchmarkName = [&] // end catch_benchmark.hpp +// start catch_constructor.hpp + +// Constructor and destructor helpers + + +#include <type_traits> + +namespace Catch { + namespace Benchmark { + namespace Detail { + template <typename T, bool Destruct> + struct ObjectStorage + { + using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; + + ObjectStorage() : data() {} + + ObjectStorage(const ObjectStorage& other) + { + new(&data) T(other.stored_object()); + } + + ObjectStorage(ObjectStorage&& other) + { + new(&data) T(std::move(other.stored_object())); + } + + ~ObjectStorage() { destruct_on_exit<T>(); } + + template <typename... Args> + void construct(Args&&... args) + { + new (&data) T(std::forward<Args>(args)...); + } + + template <bool AllowManualDestruction = !Destruct> + typename std::enable_if<AllowManualDestruction>::type destruct() + { + stored_object().~T(); + } + + private: + // If this is a constructor benchmark, destruct the underlying object + template <typename U> + void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); } + // Otherwise, don't + template <typename U> + void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { } + + T& stored_object() { + return *static_cast<T*>(static_cast<void*>(&data)); + } + + T const& stored_object() const { + return *static_cast<T*>(static_cast<void*>(&data)); + } + + TStorage data; + }; + } + + template <typename T> + using storage_for = Detail::ObjectStorage<T, true>; + + template <typename T> + using destructable_object = Detail::ObjectStorage<T, false>; + } +} + +// end catch_constructor.hpp +// end catch_benchmarking_all.hpp #endif #endif // ! CATCH_CONFIG_IMPL_ONLY @@ -7114,23 +7464,37 @@ namespace TestCaseTracking { SourceLineInfo location; NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); + friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { + return lhs.name == rhs.name + && lhs.location == rhs.location; + } }; - struct ITracker; + class ITracker; using ITrackerPtr = std::shared_ptr<ITracker>; - struct ITracker { - virtual ~ITracker(); + class ITracker { + NameAndLocation m_nameAndLocation; + + public: + ITracker(NameAndLocation const& nameAndLoc) : + m_nameAndLocation(nameAndLoc) + {} // static queries - virtual NameAndLocation const& nameAndLocation() const = 0; + NameAndLocation const& nameAndLocation() const { + return m_nameAndLocation; + } + + virtual ~ITracker(); // dynamic queries virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; // Started but not complete virtual bool hasChildren() const = 0; + virtual bool hasStarted() const = 0; virtual ITracker& parent() = 0; @@ -7185,7 +7549,6 @@ namespace TestCaseTracking { }; using Children = std::vector<ITrackerPtr>; - NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; Children m_children; @@ -7194,11 +7557,13 @@ namespace TestCaseTracking { public: TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - NameAndLocation const& nameAndLocation() const override; bool isComplete() const override; bool isSuccessfullyCompleted() const override; bool isOpen() const override; bool hasChildren() const override; + bool hasStarted() const override { + return m_runState != NotStarted; + } void addChild( ITrackerPtr const& child ) override; @@ -7223,6 +7588,7 @@ namespace TestCaseTracking { class SectionTracker : public TrackerBase { std::vector<std::string> m_filters; + std::string m_trimmed_name; public: SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); @@ -7236,6 +7602,10 @@ namespace TestCaseTracking { void addInitialFilters( std::vector<std::string> const& filters ); void addNextFilters( std::vector<std::string> const& filters ); + //! Returns filters active in this tracker + std::vector<std::string> const& getFilters() const; + //! Returns whitespace-trimmed name of the tracked section + std::string const& trimmedName() const; }; } // namespace TestCaseTracking @@ -7424,9 +7794,10 @@ namespace Catch { } bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) { + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS static std::random_device entropy; - CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++ @@ -7514,7 +7885,8 @@ namespace Detail { bool Approx::equalityComparisonImpl(const double other) const { // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value // Thanks to Richard Harris for his help refining the scaled margin value - return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); + return marginComparison(m_value, other, m_margin) + || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value))); } void Approx::setMargin(double newMargin) { @@ -7558,7 +7930,24 @@ namespace Catch { #ifdef CATCH_PLATFORM_MAC - #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + #if defined(__i386__) || defined(__x86_64__) + #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + #elif defined(__aarch64__) + #define CATCH_TRAP() __asm__(".inst 0xd4200000") + #endif + +#elif defined(CATCH_PLATFORM_IPHONE) + + // use inline assembler + #if defined(__i386__) || defined(__x86_64__) + #define CATCH_TRAP() __asm__("int $3") + #elif defined(__aarch64__) + #define CATCH_TRAP() __asm__(".inst 0xd4200000") + #elif defined(__arm__) && !defined(__thumb__) + #define CATCH_TRAP() __asm__(".inst 0xe7f001f0") + #elif defined(__arm__) && defined(__thumb__) + #define CATCH_TRAP() __asm__(".inst 0xde01") + #endif #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break @@ -7578,10 +7967,12 @@ namespace Catch { #define CATCH_TRAP() DebugBreak() #endif -#ifdef CATCH_TRAP - #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() -#else - #define CATCH_BREAK_INTO_DEBUGGER() []{}() +#ifndef CATCH_BREAK_INTO_DEBUGGER + #ifdef CATCH_TRAP + #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() + #else + #define CATCH_BREAK_INTO_DEBUGGER() []{}() + #endif #endif // end catch_debugger.h @@ -7728,7 +8119,7 @@ namespace Catch { void sectionEnded( SectionEndInfo const& endInfo ) override; void sectionEndedEarly( SectionEndInfo const& endInfo ) override; - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; + auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) void benchmarkPreparing( std::string const& name ) override; @@ -7799,6 +8190,8 @@ namespace Catch { bool m_includeSuccessfulResults; }; + void seedRng(IConfig const& config); + unsigned int rngSeed(); } // end namespace Catch // end catch_run_context.h @@ -7945,7 +8338,7 @@ namespace Catch { } bool AssertionResult::hasExpression() const { - return m_info.capturedExpression[0] != 0; + return !m_info.capturedExpression.empty(); } bool AssertionResult::hasMessage() const { @@ -7953,16 +8346,22 @@ namespace Catch { } std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return "!(" + m_info.capturedExpression + ")"; - else - return m_info.capturedExpression; + // Possibly overallocating by 3 characters should be basically free + std::string expr; expr.reserve(m_info.capturedExpression.size() + 3); + if (isFalseTest(m_info.resultDisposition)) { + expr += "!("; + } + expr += m_info.capturedExpression; + if (isFalseTest(m_info.resultDisposition)) { + expr += ')'; + } + return expr; } std::string AssertionResult::getExpressionInMacro() const { std::string expr; - if( m_info.macroName[0] == 0 ) - expr = m_info.capturedExpression; + if( m_info.macroName.empty() ) + expr = static_cast<std::string>(m_info.capturedExpression); else { expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); expr += m_info.macroName; @@ -8696,7 +9095,7 @@ namespace detail { } inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { std::string srcLC = source; - std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } ); + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( unsigned char c ) { return static_cast<char>( std::tolower(c) ); } ); if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") target = true; else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") @@ -9344,9 +9743,14 @@ namespace Catch { if( !line.empty() && !startsWith( line, '#' ) ) { if( !startsWith( line, '"' ) ) line = '"' + line + '"'; - config.testsOrTags.push_back( line + ',' ); + config.testsOrTags.push_back( line ); + config.testsOrTags.emplace_back( "," ); } } + //Remove comma in the end + if(!config.testsOrTags.empty()) + config.testsOrTags.erase( config.testsOrTags.end()-1 ); + return ParserResult::ok( ParseResultType::Matched ); }; auto const setTestOrder = [&]( std::string const& order ) { @@ -9381,14 +9785,16 @@ namespace Catch { }; auto const setWaitForKeypress = [&]( std::string const& keypress ) { auto keypressLc = toLower( keypress ); - if( keypressLc == "start" ) + if (keypressLc == "never") + config.waitForKeypress = WaitForKeypress::Never; + else if( keypressLc == "start" ) config.waitForKeypress = WaitForKeypress::BeforeStart; else if( keypressLc == "exit" ) config.waitForKeypress = WaitForKeypress::BeforeExit; else if( keypressLc == "both" ) config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; else - return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); + return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" ); return ParserResult::ok( ParseResultType::Matched ); }; auto const setVerbosity = [&]( std::string const& verbosity ) { @@ -9458,6 +9864,9 @@ namespace Catch { | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) ["-d"]["--durations"] ( "show test durations" ) + | Opt( config.minDuration, "seconds" ) + ["-D"]["--min-duration"] + ( "show test durations for tests taking at least the given number of seconds" ) | Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] ( "load test names to run from a file" ) @@ -9488,7 +9897,7 @@ namespace Catch { | Opt( config.libIdentify ) ["--libidentify"] ( "report name and version according to libidentify standard" ) - | Opt( setWaitForKeypress, "start|exit|both" ) + | Opt( setWaitForKeypress, "never|start|exit|both" ) ["--wait-for-keypress"] ( "waits for a keypress before exiting" ) | Opt( config.benchmarkSamples, "samples" ) @@ -9503,7 +9912,10 @@ namespace Catch { | Opt( config.benchmarkNoAnalysis ) ["--benchmark-no-analysis"] ( "perform only measurements; do not perform any analysis" ) - | Arg( config.testsOrTags, "test name|pattern|tags" ) + | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" ) + ["--benchmark-warmup-time"] + ( "amount of time in milliseconds spent on warming up each test (default: 100)" ) + | Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); return cli; @@ -9518,9 +9930,6 @@ namespace Catch { namespace Catch { - bool SourceLineInfo::empty() const noexcept { - return file[0] == '\0'; - } bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); } @@ -9556,11 +9965,23 @@ namespace Catch { : m_data( data ), m_stream( openStream() ) { + // We need to trim filter specs to avoid trouble with superfluous + // whitespace (esp. important for bdd macros, as those are manually + // aligned with whitespace). + + for (auto& elem : m_data.testsOrTags) { + elem = trim(elem); + } + for (auto& elem : m_data.sectionsToRun) { + elem = trim(elem); + } + TestSpecParser parser(ITagAliasRegistry::get()); - if (!data.testsOrTags.empty()) { + if (!m_data.testsOrTags.empty()) { m_hasTestFilters = true; - for( auto const& testOrTags : data.testsOrTags ) - parser.parse( testOrTags ); + for (auto const& testOrTags : m_data.testsOrTags) { + parser.parse(testOrTags); + } } m_testSpec = parser.testSpec(); } @@ -9593,6 +10014,7 @@ namespace Catch { bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } + double Config::minDuration() const { return m_data.minDuration; } RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } unsigned int Config::rngSeed() const { return m_data.rngSeed; } UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } @@ -9601,10 +10023,11 @@ namespace Catch { bool Config::showInvisibles() const { return m_data.showInvisibles; } Verbosity Config::verbosity() const { return m_data.verbosity; } - bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } - int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } - double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } - unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; } + bool Config::benchmarkNoAnalysis() const { return m_data.benchmarkNoAnalysis; } + int Config::benchmarkSamples() const { return m_data.benchmarkSamples; } + double Config::benchmarkConfidenceInterval() const { return m_data.benchmarkConfidenceInterval; } + unsigned int Config::benchmarkResamples() const { return m_data.benchmarkResamples; } + std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); } IStream const* Config::openStream() { return Catch::makeStream(m_data.outputFilename); @@ -9645,7 +10068,7 @@ namespace Catch { }; struct NoColourImpl : IColourImpl { - void use( Colour::Code ) {} + void use( Colour::Code ) override {} static IColourImpl* instance() { static NoColourImpl s_instance; @@ -9777,7 +10200,7 @@ namespace { bool useColourOnPlatform() { return -#ifdef CATCH_PLATFORM_MAC +#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) !isDebuggerActive() && #endif #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) @@ -9818,13 +10241,13 @@ namespace Catch { namespace Catch { Colour::Colour( Code _colourCode ) { use( _colourCode ); } - Colour::Colour( Colour&& rhs ) noexcept { - m_moved = rhs.m_moved; - rhs.m_moved = true; + Colour::Colour( Colour&& other ) noexcept { + m_moved = other.m_moved; + other.m_moved = true; } - Colour& Colour::operator=( Colour&& rhs ) noexcept { - m_moved = rhs.m_moved; - rhs.m_moved = true; + Colour& Colour::operator=( Colour&& other ) noexcept { + m_moved = other.m_moved; + other.m_moved = true; return *this; } @@ -9836,7 +10259,7 @@ namespace Catch { // However, under some conditions it does happen (see #1626), // and this change is small enough that we can let practicality // triumph over purity in this case. - if (impl != NULL) { + if (impl != nullptr) { impl->use( _colourCode ); } } @@ -9905,6 +10328,12 @@ namespace Catch { IContext::~IContext() = default; IMutableContext::~IMutableContext() = default; Context::~Context() = default; + + SimplePcg32& rng() { + static SimplePcg32 s_rng; + return s_rng; + } + } // end catch_context.cpp // start catch_debug_console.cpp @@ -9918,7 +10347,16 @@ namespace Catch { } // end catch_debug_console.h -#ifdef CATCH_PLATFORM_WINDOWS +#if defined(CATCH_CONFIG_ANDROID_LOGWRITE) +#include <android/log.h> + + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() ); + } + } + +#elif defined(CATCH_PLATFORM_WINDOWS) namespace Catch { void writeToDebugConsole( std::string const& text ) { @@ -9939,10 +10377,9 @@ namespace Catch { // end catch_debug_console.cpp // start catch_debugger.cpp -#ifdef CATCH_PLATFORM_MAC +#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) -# include <assert.h> -# include <stdbool.h> +# include <cassert> # include <sys/types.h> # include <unistd.h> # include <cstddef> @@ -10115,7 +10552,7 @@ namespace Catch { EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override; }; - std::vector<std::string> parseEnums( StringRef enums ); + std::vector<StringRef> parseEnums( StringRef enums ); } // Detail @@ -10132,13 +10569,25 @@ namespace Catch { namespace Detail { - std::vector<std::string> parseEnums( StringRef enums ) { + namespace { + // Extracts the actual name part of an enum instance + // In other words, it returns the Blue part of Bikeshed::Colour::Blue + StringRef extractInstanceName(StringRef enumInstance) { + // Find last occurence of ":" + size_t name_start = enumInstance.size(); + while (name_start > 0 && enumInstance[name_start - 1] != ':') { + --name_start; + } + return enumInstance.substr(name_start, enumInstance.size() - name_start); + } + } + + std::vector<StringRef> parseEnums( StringRef enums ) { auto enumValues = splitStringRef( enums, ',' ); - std::vector<std::string> parsed; + std::vector<StringRef> parsed; parsed.reserve( enumValues.size() ); for( auto const& enumValue : enumValues ) { - auto identifiers = splitStringRef( enumValue, ':' ); - parsed.push_back( Catch::trim( identifiers.back() ) ); + parsed.push_back(trim(extractInstanceName(enumValue))); } return parsed; } @@ -10150,7 +10599,7 @@ namespace Catch { if( valueToName.first == value ) return valueToName.second; } - return "{** unexpected enum value **}"; + return "{** unexpected enum value **}"_sr; } std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { @@ -10162,16 +10611,14 @@ namespace Catch { assert( valueNames.size() == values.size() ); std::size_t i = 0; for( auto value : values ) - enumInfo->m_values.push_back({ value, valueNames[i++] }); + enumInfo->m_values.emplace_back(value, valueNames[i++]); return enumInfo; } EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) { - auto enumInfo = makeEnumInfo( enumName, allValueNames, values ); - EnumInfo* raw = enumInfo.get(); - m_enumInfos.push_back( std::move( enumInfo ) ); - return *raw; + m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values)); + return *m_enumInfos.back(); } } // Detail @@ -10372,7 +10819,7 @@ namespace Catch { // 32kb for the alternate stack seems to be sufficient. However, this value // is experimentally determined, so that's not guaranteed. - constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; + static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; static SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, @@ -10449,22 +10896,6 @@ namespace Catch { // end catch_fatal_condition.cpp // start catch_generators.cpp -// start catch_random_number_generator.h - -#include <algorithm> -#include <random> - -namespace Catch { - - struct IConfig; - - std::mt19937& rng(); - void seedRng( IConfig const& config ); - unsigned int rngSeed(); - -} - -// end catch_random_number_generator.h #include <limits> #include <set> @@ -10480,8 +10911,8 @@ namespace Generators { GeneratorUntypedBase::~GeneratorUntypedBase() {} - auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { - return getResultCapture().acquireGeneratorTracker( lineInfo ); + auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { + return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo ); } } // namespace Generators @@ -10537,6 +10968,8 @@ namespace Catch { void noMatchingTestCases( std::string const& spec ) override; + void reportInvalidArguments(std::string const&arg) override; + static std::set<Verbosity> getSupportedVerbosities(); #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) @@ -10754,7 +11187,7 @@ namespace Catch { namespace Catch { std::size_t listTests( Config const& config ) { - TestSpec testSpec = config.testSpec(); + TestSpec const& testSpec = config.testSpec(); if( config.hasTestFilters() ) Catch::cout() << "Matching test cases:\n"; else { @@ -10788,7 +11221,7 @@ namespace Catch { } std::size_t listTestsNamesOnly( Config const& config ) { - TestSpec testSpec = config.testSpec(); + TestSpec const& testSpec = config.testSpec(); std::size_t matchedTests = 0; std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( auto const& testCaseInfo : matchedTestCases ) { @@ -10810,14 +11243,23 @@ namespace Catch { } std::string TagInfo::all() const { - std::string out; - for( auto const& spelling : spellings ) - out += "[" + spelling + "]"; + size_t size = 0; + for (auto const& spelling : spellings) { + // Add 2 for the brackes + size += spelling.size() + 2; + } + + std::string out; out.reserve(size); + for (auto const& spelling : spellings) { + out += '['; + out += spelling; + out += ']'; + } return out; } std::size_t listTags( Config const& config ) { - TestSpec testSpec = config.testSpec(); + TestSpec const& testSpec = config.testSpec(); if( config.hasTestFilters() ) Catch::cout() << "Tags for matching test cases:\n"; else { @@ -10911,6 +11353,29 @@ using Matchers::Impl::MatcherBase; } // namespace Catch // end catch_matchers.cpp +// start catch_matchers_exception.cpp + +namespace Catch { +namespace Matchers { +namespace Exception { + +bool ExceptionMessageMatcher::match(std::exception const& ex) const { + return ex.what() == m_message; +} + +std::string ExceptionMessageMatcher::describe() const { + return "exception message matches \"" + m_message + "\""; +} + +} +Exception::ExceptionMessageMatcher Message(std::string const& message) { + return Exception::ExceptionMessageMatcher(message); +} + +// namespace Exception +} // namespace Matchers +} // namespace Catch +// end catch_matchers_exception.cpp // start catch_matchers_floating.cpp // start catch_polyfills.hpp @@ -10939,85 +11404,100 @@ namespace Catch { } // end namespace Catch // end catch_to_string.hpp +#include <algorithm> +#include <cmath> #include <cstdlib> #include <cstdint> #include <cstring> #include <sstream> +#include <type_traits> #include <iomanip> #include <limits> namespace Catch { -namespace Matchers { -namespace Floating { -enum class FloatingPointKind : uint8_t { - Float, - Double -}; -} -} -} - namespace { -template <typename T> -struct Converter; - -template <> -struct Converter<float> { - static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); - Converter(float f) { + int32_t convert(float f) { + static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); + int32_t i; std::memcpy(&i, &f, sizeof(f)); + return i; } - int32_t i; -}; -template <> -struct Converter<double> { - static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); - Converter(double d) { + int64_t convert(double d) { + static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); + int64_t i; std::memcpy(&i, &d, sizeof(d)); + return i; } - int64_t i; -}; -template <typename T> -auto convert(T t) -> Converter<T> { - return Converter<T>(t); -} + template <typename FP> + bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) { + // Comparison with NaN should always be false. + // This way we can rule it out before getting into the ugly details + if (Catch::isnan(lhs) || Catch::isnan(rhs)) { + return false; + } -template <typename FP> -bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) { - // Comparison with NaN should always be false. - // This way we can rule it out before getting into the ugly details - if (Catch::isnan(lhs) || Catch::isnan(rhs)) { - return false; + auto lc = convert(lhs); + auto rc = convert(rhs); + + if ((lc < 0) != (rc < 0)) { + // Potentially we can have +0 and -0 + return lhs == rhs; + } + + auto ulpDiff = std::abs(lc - rc); + return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff; } - auto lc = convert(lhs); - auto rc = convert(rhs); +#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) - if ((lc.i < 0) != (rc.i < 0)) { - // Potentially we can have +0 and -0 - return lhs == rhs; + float nextafter(float x, float y) { + return ::nextafterf(x, y); } - auto ulpDiff = std::abs(lc.i - rc.i); - return ulpDiff <= maxUlpDiff; -} + double nextafter(double x, double y) { + return ::nextafter(x, y); + } + +#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^ template <typename FP> -FP step(FP start, FP direction, int steps) { - for (int i = 0; i < steps; ++i) { +FP step(FP start, FP direction, uint64_t steps) { + for (uint64_t i = 0; i < steps; ++i) { +#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) + start = Catch::nextafter(start, direction); +#else start = std::nextafter(start, direction); +#endif } return start; } +// Performs equivalent check of std::fabs(lhs - rhs) <= margin +// But without the subtraction to allow for INFINITY in comparison +bool marginComparison(double lhs, double rhs, double margin) { + return (lhs + margin >= rhs) && (rhs + margin >= lhs); +} + +template <typename FloatingPoint> +void write(std::ostream& out, FloatingPoint num) { + out << std::scientific + << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1) + << num; +} + } // end anonymous namespace -namespace Catch { namespace Matchers { namespace Floating { + + enum class FloatingPointKind : uint8_t { + Float, + Double + }; + WithinAbsMatcher::WithinAbsMatcher(double target, double margin) :m_target{ target }, m_margin{ margin } { CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.' @@ -11034,10 +11514,11 @@ namespace Floating { return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target); } - WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType) + WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType) :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { - CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.' - << " ULPs have to be non-negative."); + CATCH_ENFORCE(m_type == FloatingPointKind::Double + || m_ulps < (std::numeric_limits<uint32_t>::max)(), + "Provided ULP is impossibly large for a float comparison."); } #if defined(__clang__) @@ -11064,36 +11545,57 @@ namespace Floating { std::string WithinUlpsMatcher::describe() const { std::stringstream ret; - ret << "is within " << m_ulps << " ULPs of " << ::Catch::Detail::stringify(m_target); + ret << "is within " << m_ulps << " ULPs of "; if (m_type == FloatingPointKind::Float) { + write(ret, static_cast<float>(m_target)); ret << 'f'; + } else { + write(ret, m_target); } ret << " (["; - ret << std::fixed << std::setprecision(std::numeric_limits<double>::max_digits10); if (m_type == FloatingPointKind::Double) { - ret << step(m_target, static_cast<double>(-INFINITY), m_ulps) - << ", " - << step(m_target, static_cast<double>(INFINITY), m_ulps); + write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps)); + ret << ", "; + write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps)); } else { - ret << step<float>(static_cast<float>(m_target), -INFINITY, m_ulps) - << ", " - << step<float>(static_cast<float>(m_target), INFINITY, m_ulps); + // We have to cast INFINITY to float because of MinGW, see #1782 + write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps)); + ret << ", "; + write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps)); } ret << "])"; return ret.str(); - //return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : ""); + } + + WithinRelMatcher::WithinRelMatcher(double target, double epsilon): + m_target(target), + m_epsilon(epsilon){ + CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense."); + CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense."); + } + + bool WithinRelMatcher::match(double const& matchee) const { + const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target)); + return marginComparison(matchee, m_target, + std::isinf(relMargin)? 0 : relMargin); + } + + std::string WithinRelMatcher::describe() const { + Catch::ReusableStringStream sstr; + sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other"; + return sstr.str(); } }// namespace Floating -Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) { +Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) { return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); } -Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) { +Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) { return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); } @@ -11101,6 +11603,22 @@ Floating::WithinAbsMatcher WithinAbs(double target, double margin) { return Floating::WithinAbsMatcher(target, margin); } +Floating::WithinRelMatcher WithinRel(double target, double eps) { + return Floating::WithinRelMatcher(target, eps); +} + +Floating::WithinRelMatcher WithinRel(double target) { + return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100); +} + +Floating::WithinRelMatcher WithinRel(float target, float eps) { + return Floating::WithinRelMatcher(target, eps); +} + +Floating::WithinRelMatcher WithinRel(float target) { + return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100); +} + } // namespace Matchers } // namespace Catch @@ -11281,10 +11799,10 @@ namespace Catch { Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { auto trimmed = [&] (size_t start, size_t end) { - while (names[start] == ',' || isspace(names[start])) { + while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) { ++start; } - while (names[end] == ',' || isspace(names[end])) { + while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) { --end; } return names.substr(start, end - start + 1); @@ -11323,17 +11841,17 @@ namespace Catch { pos = skipq(pos, c); break; case ',': - if (start != pos && openings.size() == 0) { + if (start != pos && openings.empty()) { m_messages.emplace_back(macroName, lineInfo, resultType); - m_messages.back().message = trimmed(start, pos); + m_messages.back().message = static_cast<std::string>(trimmed(start, pos)); m_messages.back().message += " := "; start = pos; } } } - assert(openings.size() == 0 && "Mismatched openings"); + assert(openings.empty() && "Mismatched openings"); m_messages.emplace_back(macroName, lineInfo, resultType); - m_messages.back().message = trimmed(start, names.size() - 1); + m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1)); m_messages.back().message += " := "; } Capturer::~Capturer() { @@ -11519,7 +12037,7 @@ namespace Catch { if (tmpnam_s(m_buffer)) { CATCH_RUNTIME_ERROR("Could not get a temp filename"); } - if (fopen_s(&m_file, m_buffer, "w")) { + if (fopen_s(&m_file, m_buffer, "w+")) { char buffer[100]; if (strerror_s(buffer, errno)) { CATCH_RUNTIME_ERROR("Could not translate errno to a string"); @@ -11627,20 +12145,61 @@ namespace Catch { namespace Catch { - std::mt19937& rng() { - static std::mt19937 s_rng; - return s_rng; +namespace { + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4146) // we negate uint32 during the rotate +#endif + // Safe rotr implementation thanks to John Regehr + uint32_t rotate_right(uint32_t val, uint32_t count) { + const uint32_t mask = 31; + count &= mask; + return (val >> count) | (val << (-count & mask)); + } + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +} + + SimplePcg32::SimplePcg32(result_type seed_) { + seed(seed_); } - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) { - std::srand( config.rngSeed() ); - rng().seed( config.rngSeed() ); + void SimplePcg32::seed(result_type seed_) { + m_state = 0; + (*this)(); + m_state += seed_; + (*this)(); + } + + void SimplePcg32::discard(uint64_t skip) { + // We could implement this to run in O(log n) steps, but this + // should suffice for our use case. + for (uint64_t s = 0; s < skip; ++s) { + static_cast<void>((*this)()); } } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); + SimplePcg32::result_type SimplePcg32::operator()() { + // prepare the output value + const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u); + const auto output = rotate_right(xorshifted, m_state >> 59u); + + // advance state + m_state = m_state * 6364136223846793005ULL + s_inc; + + return output; + } + + bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { + return lhs.m_state == rhs.m_state; + } + + bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) { + return lhs.m_state != rhs.m_state; } } // end catch_random_number_generator.cpp @@ -11659,6 +12218,8 @@ namespace Catch { struct IConfig; std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ); + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ); @@ -11771,11 +12332,13 @@ namespace Catch { namespace Catch { class StartupExceptionRegistry { +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) public: void add(std::exception_ptr const& exception) noexcept; std::vector<std::exception_ptr> const& getExceptions() const noexcept; private: std::vector<std::exception_ptr> m_exceptions; +#endif }; } // end namespace Catch @@ -11858,7 +12421,11 @@ namespace Catch { m_tagAliasRegistry.add( alias, tag, lineInfo ); } void registerStartupException() noexcept override { +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) m_exceptionRegistry.add(std::current_exception()); +#else + CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); +#endif } IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { return m_enumValuesRegistry; @@ -11962,17 +12529,32 @@ namespace Catch { std::shared_ptr<GeneratorTracker> tracker; ITracker& currentTracker = ctx.currentTracker(); - if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + // Under specific circumstances, the generator we want + // to acquire is also the current tracker. If this is + // the case, we have to avoid looking through current + // tracker's children, and instead return the current + // tracker. + // A case where this check is important is e.g. + // for (int i = 0; i < 5; ++i) { + // int n = GENERATE(1, 2); + // } + // + // without it, the code above creates 5 nested generators. + if (currentTracker.nameAndLocation() == nameAndLocation) { + auto thisTracker = currentTracker.parent().findChild(nameAndLocation); + assert(thisTracker); + assert(thisTracker->isGeneratorTracker()); + tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker); + } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isGeneratorTracker() ); tracker = std::static_pointer_cast<GeneratorTracker>( childTracker ); - } - else { + } else { tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker ); currentTracker.addChild( tracker ); } - if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( !tracker->isComplete() ) { tracker->open(); } @@ -11986,8 +12568,68 @@ namespace Catch { } void close() override { TrackerBase::close(); - // Generator interface only finds out if it has another item on atual move - if (m_runState == CompletedSuccessfully && m_generator->next()) { + // If a generator has a child (it is followed by a section) + // and none of its children have started, then we must wait + // until later to start consuming its values. + // This catches cases where `GENERATE` is placed between two + // `SECTION`s. + // **The check for m_children.empty cannot be removed**. + // doing so would break `GENERATE` _not_ followed by `SECTION`s. + const bool should_wait_for_child = [&]() { + // No children -> nobody to wait for + if ( m_children.empty() ) { + return false; + } + // If at least one child started executing, don't wait + if ( std::find_if( + m_children.begin(), + m_children.end(), + []( TestCaseTracking::ITrackerPtr tracker ) { + return tracker->hasStarted(); + } ) != m_children.end() ) { + return false; + } + + // No children have started. We need to check if they _can_ + // start, and thus we should wait for them, or they cannot + // start (due to filters), and we shouldn't wait for them + auto* parent = m_parent; + // This is safe: there is always at least one section + // tracker in a test case tracking tree + while ( !parent->isSectionTracker() ) { + parent = &( parent->parent() ); + } + assert( parent && + "Missing root (test case) level section" ); + + auto const& parentSection = + static_cast<SectionTracker&>( *parent ); + auto const& filters = parentSection.getFilters(); + // No filters -> no restrictions on running sections + if ( filters.empty() ) { + return true; + } + + for ( auto const& child : m_children ) { + if ( child->isSectionTracker() && + std::find( filters.begin(), + filters.end(), + static_cast<SectionTracker&>( *child ) + .trimmedName() ) != + filters.end() ) { + return true; + } + } + return false; + }(); + + // This check is a bit tricky, because m_generator->next() + // has a side-effect, where it consumes generator's current + // value, but we do not want to invoke the side-effect if + // this generator is still waiting for any child to start. + if ( should_wait_for_child || + ( m_runState == CompletedSuccessfully && + m_generator->next() ) ) { m_children.clear(); m_runState = Executing; } @@ -12123,10 +12765,10 @@ namespace Catch { return true; } - auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { + auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { using namespace Generators; - GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) ); - assert( tracker.isOpen() ); + GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext, + TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) ); m_lastAssertionInfo.lineInfo = lineInfo; return tracker; } @@ -12169,17 +12811,17 @@ namespace Catch { #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) void RunContext::benchmarkPreparing(std::string const& name) { - m_reporter->benchmarkPreparing(name); - } + m_reporter->benchmarkPreparing(name); + } void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { m_reporter->benchmarkStarting( info ); } void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { m_reporter->benchmarkEnded( stats ); } - void RunContext::benchmarkFailed(std::string const & error) { - m_reporter->benchmarkFailed(error); - } + void RunContext::benchmarkFailed(std::string const & error) { + m_reporter->benchmarkFailed(error); + } #endif // CATCH_CONFIG_ENABLE_BENCHMARKING void RunContext::pushScopedMessage(MessageInfo const & message) { @@ -12215,7 +12857,7 @@ namespace Catch { // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); - tempResult.message = message; + tempResult.message = static_cast<std::string>(message); AssertionResult result(m_lastAssertionInfo, tempResult); assertionEnded(result); @@ -12378,7 +13020,7 @@ namespace Catch { m_lastAssertionInfo = info; AssertionResultData data( resultType, LazyExpression( false ) ); - data.message = message; + data.message = static_cast<std::string>(message); AssertionResult assertionResult{ m_lastAssertionInfo, data }; assertionEnded( assertionResult ); if( !assertionResult.isOk() ) @@ -12441,6 +13083,18 @@ namespace Catch { else CATCH_INTERNAL_ERROR("No result capture instance"); } + + void seedRng(IConfig const& config) { + if (config.rngSeed() != 0) { + std::srand(config.rngSeed()); + rng().seed(config.rngSeed()); + } + } + + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + } // end catch_run_context.cpp // start catch_section.cpp @@ -12502,7 +13156,7 @@ namespace Catch { void libIdentify(); int applyCommandLine( int argc, char const * const * argv ); - #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) + #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) int applyCommandLine( int argc, wchar_t const * const * argv ); #endif @@ -12569,6 +13223,8 @@ namespace Catch { // end catch_version.h #include <cstdlib> #include <iomanip> +#include <set> +#include <iterator> namespace Catch { @@ -12602,45 +13258,61 @@ namespace Catch { return ret; } - Catch::Totals runTests(std::shared_ptr<Config> const& config) { - auto reporter = makeReporter(config); - - RunContext context(config, std::move(reporter)); - - Totals totals; - - context.testGroupStarting(config->name(), 1, 1); - - TestSpec testSpec = config->testSpec(); - - auto const& allTestCases = getAllTestCasesSorted(*config); - for (auto const& testCase : allTestCases) { - bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) || - (testSpec.hasFilters() && matchTest(testCase, testSpec, *config)); - - if (!context.aborting() && matching) - totals += context.runTest(testCase); - else - context.reporter().skipTest(testCase); + class TestGroup { + public: + explicit TestGroup(std::shared_ptr<Config> const& config) + : m_config{config} + , m_context{config, makeReporter(config)} + { + auto const& allTestCases = getAllTestCasesSorted(*m_config); + m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config); + auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); + + if (m_matches.empty() && invalidArgs.empty()) { + for (auto const& test : allTestCases) + if (!test.isHidden()) + m_tests.emplace(&test); + } else { + for (auto const& match : m_matches) + m_tests.insert(match.tests.begin(), match.tests.end()); + } } - if (config->warnAboutNoTests() && totals.testCases.total() == 0) { - ReusableStringStream testConfig; + Totals execute() { + auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); + Totals totals; + m_context.testGroupStarting(m_config->name(), 1, 1); + for (auto const& testCase : m_tests) { + if (!m_context.aborting()) + totals += m_context.runTest(*testCase); + else + m_context.reporter().skipTest(*testCase); + } - bool first = true; - for (const auto& input : config->getTestsOrTags()) { - if (!first) { testConfig << ' '; } - first = false; - testConfig << input; + for (auto const& match : m_matches) { + if (match.tests.empty()) { + m_context.reporter().noMatchingTestCases(match.name); + totals.error = -1; + } + } + + if (!invalidArgs.empty()) { + for (auto const& invalidArg: invalidArgs) + m_context.reporter().reportInvalidArguments(invalidArg); } - context.reporter().noMatchingTestCases(testConfig.str()); - totals.error = -1; + m_context.testGroupEnded(m_config->name(), totals, 1, 1); + return totals; } - context.testGroupEnded(config->name(), totals, 1, 1); - return totals; - } + private: + using Tests = std::set<TestCase const*>; + + std::shared_ptr<Config> m_config; + RunContext m_context; + Tests m_tests; + TestSpec::Matches m_matches; + }; void applyFilenamesAsTags(Catch::IConfig const& config) { auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config)); @@ -12709,7 +13381,7 @@ namespace Catch { } void Session::libIdentify() { Catch::cout() - << std::left << std::setw(16) << "description: " << "A Catch test executable\n" + << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n" << std::left << std::setw(16) << "category: " << "testframework\n" << std::left << std::setw(16) << "framework: " << "Catch Test\n" << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; @@ -12740,17 +13412,17 @@ namespace Catch { return 0; } -#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) +#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { char **utf8Argv = new char *[ argc ]; for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr ); utf8Argv[ i ] = new char[ bufSize ]; - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); + WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr ); } int returnCode = applyCommandLine( argc, utf8Argv ); @@ -12817,7 +13489,12 @@ namespace Catch { if( Option<std::size_t> listed = list( m_config ) ) return static_cast<int>( *listed ); - auto totals = runTests( m_config ); + TestGroup tests { m_config }; + auto const totals = tests.execute(); + + if( m_config->warnAboutNoTests() && totals.error == -1 ) + return 2; + // Note that on unices only the lower 8 bits are usually used, clamping // the return value to 255 prevents false negative when some multiple // of 256 tests has failed @@ -12865,6 +13542,7 @@ namespace Catch { // end catch_singletons.cpp // start catch_startup_exception_registry.cpp +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) namespace Catch { void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { CATCH_TRY { @@ -12880,6 +13558,7 @@ void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexce } } // end namespace Catch +#endif // end catch_startup_exception_registry.cpp // start catch_stream.cpp @@ -13064,7 +13743,7 @@ namespace Catch { namespace { char toLowerCh(char c) { - return static_cast<char>( std::tolower( c ) ); + return static_cast<char>( std::tolower( static_cast<unsigned char>(c) ) ); } } @@ -13099,6 +13778,18 @@ namespace Catch { return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); } + StringRef trim(StringRef ref) { + const auto is_ws = [](char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; + }; + size_t real_begin = 0; + while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; } + size_t real_end = ref.size(); + while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; } + + return ref.substr(real_begin, real_end - real_begin); + } + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { bool replaced = false; std::size_t i = str.find( replaceThis ); @@ -13144,124 +13835,46 @@ namespace Catch { // end catch_string_manip.cpp // start catch_stringref.cpp -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wexit-time-destructors" -#endif - +#include <algorithm> #include <ostream> #include <cstring> #include <cstdint> -namespace { - const uint32_t byte_2_lead = 0xC0; - const uint32_t byte_3_lead = 0xE0; - const uint32_t byte_4_lead = 0xF0; -} - namespace Catch { StringRef::StringRef( char const* rawChars ) noexcept : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) {} - StringRef::operator std::string() const { - return std::string( m_start, m_size ); - } - - void StringRef::swap( StringRef& other ) noexcept { - std::swap( m_start, other.m_start ); - std::swap( m_size, other.m_size ); - std::swap( m_data, other.m_data ); - } - auto StringRef::c_str() const -> char const* { - if( !isSubstring() ) - return m_start; - - const_cast<StringRef *>( this )->takeOwnership(); - return m_data; - } - auto StringRef::currentData() const noexcept -> char const* { + CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance"); return m_start; } - - auto StringRef::isOwned() const noexcept -> bool { - return m_data != nullptr; - } - auto StringRef::isSubstring() const noexcept -> bool { - return m_start[m_size] != '\0'; + auto StringRef::data() const noexcept -> char const* { + return m_start; } - void StringRef::takeOwnership() { - if( !isOwned() ) { - m_data = new char[m_size+1]; - memcpy( m_data, m_start, m_size ); - m_data[m_size] = '\0'; - } - } auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { - if( start < m_size ) - return StringRef( m_start+start, size ); - else + if (start < m_size) { + return StringRef(m_start + start, (std::min)(m_size - start, size)); + } else { return StringRef(); - } - auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { - return - size() == other.size() && - (std::strncmp( m_start, other.m_start, size() ) == 0); - } - auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { - return !operator==( other ); - } - - auto StringRef::operator[](size_type index) const noexcept -> char { - return m_start[index]; - } - - auto StringRef::numberOfCharacters() const noexcept -> size_type { - size_type noChars = m_size; - // Make adjustments for uft encodings - for( size_type i=0; i < m_size; ++i ) { - char c = m_start[i]; - if( ( c & byte_2_lead ) == byte_2_lead ) { - noChars--; - if (( c & byte_3_lead ) == byte_3_lead ) - noChars--; - if( ( c & byte_4_lead ) == byte_4_lead ) - noChars--; - } } - return noChars; - } - - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { - std::string str; - str.reserve( lhs.size() + rhs.size() ); - str += lhs; - str += rhs; - return str; - } - auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { - return std::string( lhs ) + std::string( rhs ); } - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { - return std::string( lhs ) + std::string( rhs ); + auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { + return m_size == other.m_size + && (std::memcmp( m_start, other.m_start, m_size ) == 0); } auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { - return os.write(str.currentData(), str.size()); + return os.write(str.data(), str.size()); } auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { - lhs.append(rhs.currentData(), rhs.size()); + lhs.append(rhs.data(), rhs.size()); return lhs; } } // namespace Catch - -#if defined(__clang__) -# pragma clang diagnostic pop -#endif // end catch_stringref.cpp // start catch_tag_alias.cpp @@ -13380,8 +13993,7 @@ namespace Catch { std::vector<std::string> tags; std::string desc, tag; bool inTag = false; - std::string _descOrTags = nameAndTags.tags; - for (char c : _descOrTags) { + for (char c : nameAndTags.tags) { if( !inTag ) { if( c == '[' ) inTag = true; @@ -13411,10 +14023,11 @@ namespace Catch { } } if( isHidden ) { - tags.push_back( "." ); + // Add all "hidden" tags to make them behave identically + tags.insert( tags.end(), { ".", "!hide" } ); } - TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo ); + TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo ); return TestCase( _testCase, std::move(info) ); } @@ -13506,30 +14119,89 @@ namespace Catch { // end catch_test_case_info.cpp // start catch_test_case_registry_impl.cpp +#include <algorithm> #include <sstream> namespace Catch { - std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { + namespace { + struct TestHasher { + using hash_t = uint64_t; + + explicit TestHasher( hash_t hashSuffix ): + m_hashSuffix{ hashSuffix } {} + + uint32_t operator()( TestCase const& t ) const { + // FNV-1a hash with multiplication fold. + const hash_t prime = 1099511628211u; + hash_t hash = 14695981039346656037u; + for ( const char c : t.name ) { + hash ^= c; + hash *= prime; + } + hash ^= m_hashSuffix; + hash *= prime; + const uint32_t low{ static_cast<uint32_t>( hash ) }; + const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) }; + return low * high; + } - std::vector<TestCase> sorted = unsortedTestCases; + private: + hash_t m_hashSuffix; + }; + } // end unnamed namespace + std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end() ); - break; - case RunTests::InRandomOrder: - seedRng( config ); - std::shuffle( sorted.begin(), sorted.end(), rng() ); - break; case RunTests::InDeclarationOrder: // already in declaration order break; + + case RunTests::InLexicographicalOrder: { + std::vector<TestCase> sorted = unsortedTestCases; + std::sort( sorted.begin(), sorted.end() ); + return sorted; + } + + case RunTests::InRandomOrder: { + seedRng( config ); + TestHasher h{ config.rngSeed() }; + + using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>; + std::vector<hashedTest> indexed_tests; + indexed_tests.reserve( unsortedTestCases.size() ); + + for (auto const& testCase : unsortedTestCases) { + indexed_tests.emplace_back(h(testCase), &testCase); + } + + std::sort(indexed_tests.begin(), indexed_tests.end(), + [](hashedTest const& lhs, hashedTest const& rhs) { + if (lhs.first == rhs.first) { + return lhs.second->name < rhs.second->name; + } + return lhs.first < rhs.first; + }); + + std::vector<TestCase> sorted; + sorted.reserve( indexed_tests.size() ); + + for (auto const& hashed : indexed_tests) { + sorted.emplace_back(*hashed.second); + } + + return sorted; + } } - return sorted; + return unsortedTestCases; + } + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ) { + return !testCase.throws() || config.allowThrows(); } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + return testSpec.matches( testCase ) && isThrowSafe( testCase, config ); } void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { @@ -13590,7 +14262,7 @@ namespace Catch { } std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; + std::string className(classOrQualifiedMethodName); if( startsWith( className, '&' ) ) { std::size_t lastColons = className.rfind( "::" ); @@ -13658,15 +14330,12 @@ namespace TestCaseTracking { m_currentTracker = tracker; } - TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), + TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ): + ITracker(nameAndLocation), m_ctx( ctx ), m_parent( parent ) {} - NameAndLocation const& TrackerBase::nameAndLocation() const { - return m_nameAndLocation; - } bool TrackerBase::isComplete() const { return m_runState == CompletedSuccessfully || m_runState == Failed; } @@ -13732,7 +14401,7 @@ namespace TestCaseTracking { m_runState = CompletedSuccessfully; break; case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) + if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) ) m_runState = CompletedSuccessfully; break; @@ -13767,7 +14436,8 @@ namespace TestCaseTracking { } SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_trimmed_name(trim(nameAndLocation.name)) { if( parent ) { while( !parent->isSectionTracker() ) @@ -13781,12 +14451,12 @@ namespace TestCaseTracking { bool SectionTracker::isComplete() const { bool complete = true; - if ((m_filters.empty() || m_filters[0] == "") || - std::find(m_filters.begin(), m_filters.end(), - m_nameAndLocation.name) != m_filters.end()) + if (m_filters.empty() + || m_filters[0] == "" + || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { complete = TrackerBase::isComplete(); + } return complete; - } bool SectionTracker::isSectionTracker() const { return true; } @@ -13810,20 +14480,29 @@ namespace TestCaseTracking { } void SectionTracker::tryOpen() { - if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) + if( !isComplete() ) open(); } void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) { if( !filters.empty() ) { - m_filters.push_back(""); // Root - should never be consulted - m_filters.push_back(""); // Test Case - not a section filter + m_filters.reserve( m_filters.size() + filters.size() + 2 ); + m_filters.emplace_back(""); // Root - should never be consulted + m_filters.emplace_back(""); // Test Case - not a section filter m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); } } void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) { if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); + m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); + } + + std::vector<std::string> const& SectionTracker::getFilters() const { + return m_filters; + } + + std::string const& SectionTracker::trimmedName() const { + return m_trimmed_name; } } // namespace TestCaseTracking @@ -13875,47 +14554,81 @@ namespace Catch { namespace Catch { + TestSpec::Pattern::Pattern( std::string const& name ) + : m_name( name ) + {} + TestSpec::Pattern::~Pattern() = default; - TestSpec::NamePattern::~NamePattern() = default; - TestSpec::TagPattern::~TagPattern() = default; - TestSpec::ExcludedPattern::~ExcludedPattern() = default; - TestSpec::NamePattern::NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + std::string const& TestSpec::Pattern::name() const { + return m_name; + } + + TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString ) + : Pattern( filterString ) + , m_wildcardPattern( toLower( name ), CaseSensitive::No ) {} + bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); + return m_wildcardPattern.matches( testCase.name ); } - TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString ) + : Pattern( filterString ) + , m_tag( toLower( tag ) ) + {} + bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { return std::find(begin(testCase.lcaseTags), end(testCase.lcaseTags), m_tag) != end(testCase.lcaseTags); } - TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) + : Pattern( underlyingPattern->name() ) + , m_underlyingPattern( underlyingPattern ) + {} + + bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { + return !m_underlyingPattern->matches( testCase ); + } bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( auto const& pattern : m_patterns ) { - if( !pattern->matches( testCase ) ) - return false; - } - return true; + return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } ); + } + + std::string TestSpec::Filter::name() const { + std::string name; + for( auto const& p : m_patterns ) + name += p->name(); + return name; } bool TestSpec::hasFilters() const { return !m_filters.empty(); } + bool TestSpec::matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( auto const& filter : m_filters ) - if( filter.matches( testCase ) ) - return true; - return false; + return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } ); } + + TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const + { + Matches matches( m_filters.size() ); + std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){ + std::vector<TestCase const*> currentMatches; + for( auto const& test : testCases ) + if( isThrowSafe( test, config ) && filter.matches( test ) ) + currentMatches.emplace_back( &test ); + return FilterMatch{ filter.name(), currentMatches }; + } ); + return matches; + } + + const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{ + return (m_invalidArgs); + } + } // end catch_test_spec.cpp // start catch_test_spec_parser.cpp @@ -13927,64 +14640,136 @@ namespace Catch { TestSpecParser& TestSpecParser::parse( std::string const& arg ) { m_mode = None; m_exclusion = false; - m_start = std::string::npos; m_arg = m_tagAliases->expandAliases( arg ); m_escapeChars.clear(); + m_substring.reserve(m_arg.size()); + m_patternName.reserve(m_arg.size()); + m_realPatternPos = 0; + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); - if( m_mode == Name ) - addPattern<TestSpec::NamePattern>(); + //if visitChar fails + if( !visitChar( m_arg[m_pos] ) ){ + m_testSpec.m_invalidArgs.push_back(arg); + break; + } + endMode(); return *this; } TestSpec TestSpecParser::testSpec() { addFilter(); return m_testSpec; } + bool TestSpecParser::visitChar( char c ) { + if( (m_mode != EscapedName) && (c == '\\') ) { + escape(); + addCharToPattern(c); + return true; + }else if((m_mode != EscapedName) && (c == ',') ) { + return separate(); + } - void TestSpecParser::visitChar( char c ) { - if( m_mode == None ) { - switch( c ) { - case ' ': return; - case '~': m_exclusion = true; return; - case '[': return startNewMode( Tag, ++m_pos ); - case '"': return startNewMode( QuotedName, ++m_pos ); - case '\\': return escape(); - default: startNewMode( Name, m_pos ); break; - } + switch( m_mode ) { + case None: + if( processNoneChar( c ) ) + return true; + break; + case Name: + processNameChar( c ); + break; + case EscapedName: + endMode(); + addCharToPattern(c); + return true; + default: + case Tag: + case QuotedName: + if( processOtherChar( c ) ) + return true; + break; } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern<TestSpec::NamePattern>(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern<TestSpec::NamePattern>(); - startNewMode( Tag, ++m_pos ); - } - else if( c == '\\' ) - escape(); + + m_substring += c; + if( !isControlChar( c ) ) { + m_patternName += c; + m_realPatternPos++; + } + return true; + } + // Two of the processing methods return true to signal the caller to return + // without adding the given character to the current pattern strings + bool TestSpecParser::processNoneChar( char c ) { + switch( c ) { + case ' ': + return true; + case '~': + m_exclusion = true; + return false; + case '[': + startNewMode( Tag ); + return false; + case '"': + startNewMode( QuotedName ); + return false; + default: + startNewMode( Name ); + return false; } - else if( m_mode == EscapedName ) - m_mode = Name; - else if( m_mode == QuotedName && c == '"' ) - addPattern<TestSpec::NamePattern>(); - else if( m_mode == Tag && c == ']' ) - addPattern<TestSpec::TagPattern>(); } - void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { + void TestSpecParser::processNameChar( char c ) { + if( c == '[' ) { + if( m_substring == "exclude:" ) + m_exclusion = true; + else + endMode(); + startNewMode( Tag ); + } + } + bool TestSpecParser::processOtherChar( char c ) { + if( !isControlChar( c ) ) + return false; + m_substring += c; + endMode(); + return true; + } + void TestSpecParser::startNewMode( Mode mode ) { m_mode = mode; - m_start = start; + } + void TestSpecParser::endMode() { + switch( m_mode ) { + case Name: + case QuotedName: + return addNamePattern(); + case Tag: + return addTagPattern(); + case EscapedName: + revertBackToLastMode(); + return; + case None: + default: + return startNewMode( None ); + } } void TestSpecParser::escape() { - if( m_mode == None ) - m_start = m_pos; + saveLastMode(); m_mode = EscapedName; - m_escapeChars.push_back( m_pos ); + m_escapeChars.push_back(m_realPatternPos); + } + bool TestSpecParser::isControlChar( char c ) const { + switch( m_mode ) { + default: + return false; + case None: + return c == '~'; + case Name: + return c == '['; + case EscapedName: + return true; + case QuotedName: + return c == '"'; + case Tag: + return c == '[' || c == ']'; + } } - std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } void TestSpecParser::addFilter() { if( !m_currentFilter.m_patterns.empty() ) { @@ -13993,6 +14778,86 @@ namespace Catch { } } + void TestSpecParser::saveLastMode() { + lastMode = m_mode; + } + + void TestSpecParser::revertBackToLastMode() { + m_mode = lastMode; + } + + bool TestSpecParser::separate() { + if( (m_mode==QuotedName) || (m_mode==Tag) ){ + //invalid argument, signal failure to previous scope. + m_mode = None; + m_pos = m_arg.size(); + m_substring.clear(); + m_patternName.clear(); + m_realPatternPos = 0; + return false; + } + endMode(); + addFilter(); + return true; //success + } + + std::string TestSpecParser::preprocessPattern() { + std::string token = m_patternName; + for (std::size_t i = 0; i < m_escapeChars.size(); ++i) + token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1); + m_escapeChars.clear(); + if (startsWith(token, "exclude:")) { + m_exclusion = true; + token = token.substr(8); + } + + m_patternName.clear(); + m_realPatternPos = 0; + + return token; + } + + void TestSpecParser::addNamePattern() { + auto token = preprocessPattern(); + + if (!token.empty()) { + TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring); + if (m_exclusion) + pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); + m_currentFilter.m_patterns.push_back(pattern); + } + m_substring.clear(); + m_exclusion = false; + m_mode = None; + } + + void TestSpecParser::addTagPattern() { + auto token = preprocessPattern(); + + if (!token.empty()) { + // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo]) + // we have to create a separate hide tag and shorten the real one + if (token.size() > 1 && token[0] == '.') { + token.erase(token.begin()); + TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring); + if (m_exclusion) { + pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); + } + m_currentFilter.m_patterns.push_back(pattern); + } + + TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring); + + if (m_exclusion) { + pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern); + } + m_currentFilter.m_patterns.push_back(pattern); + } + m_substring.clear(); + m_exclusion = false; + m_mode = None; + } + TestSpec parseTestSpec( std::string const& arg ) { return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); } @@ -14094,13 +14959,11 @@ namespace Detail { enum Arch { Big, Little }; static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + int one = 1; + // If the lowest byte we read is non-zero, we can assume + // that little endian format is used. + auto value = *reinterpret_cast<char*>(&one); + return value ? Little : Big; } }; } @@ -14224,6 +15087,13 @@ std::string StringMaker<wchar_t *>::convert(wchar_t * str) { } #endif +#if defined(CATCH_CONFIG_CPP17_BYTE) +#include <cstddef> +std::string StringMaker<std::byte>::convert(std::byte value) { + return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value)); +} +#endif // defined(CATCH_CONFIG_CPP17_BYTE) + std::string StringMaker<int>::convert(int value) { return ::Catch::Detail::stringify(static_cast<long long>(value)); } @@ -14369,11 +15239,48 @@ namespace Catch { // end catch_totals.cpp // start catch_uncaught_exceptions.cpp +// start catch_config_uncaught_exceptions.hpp + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP +#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP + +#if defined(_MSC_VER) +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif +#endif + +#include <exception> + +#if defined(__cpp_lib_uncaught_exceptions) \ + && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) + +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif // __cpp_lib_uncaught_exceptions + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \ + && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \ + && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) + +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP +// end catch_config_uncaught_exceptions.hpp #include <exception> namespace Catch { bool uncaught_exceptions() { -#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) + return false; +#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) return std::uncaught_exceptions() > 0; #else return std::uncaught_exception(); @@ -14413,7 +15320,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 9, 0, "", 0 ); + static Version version( 2, 13, 4, "", 0 ); return version; } @@ -14421,14 +15328,12 @@ namespace Catch { // end catch_version.cpp // start catch_wildcard_pattern.cpp -#include <sstream> - namespace Catch { WildcardPattern::WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), - m_pattern( adjustCase( pattern ) ) + m_pattern( normaliseString( pattern ) ) { if( startsWith( m_pattern, '*' ) ) { m_pattern = m_pattern.substr( 1 ); @@ -14443,28 +15348,27 @@ namespace Catch { bool WildcardPattern::matches( std::string const& str ) const { switch( m_wildcard ) { case NoWildcard: - return m_pattern == adjustCase( str ); + return m_pattern == normaliseString( str ); case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); + return endsWith( normaliseString( str ), m_pattern ); case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); + return startsWith( normaliseString( str ), m_pattern ); case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); + return contains( normaliseString( str ), m_pattern ); default: CATCH_INTERNAL_ERROR( "Unknown enum" ); } } - std::string WildcardPattern::adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + std::string WildcardPattern::normaliseString( std::string const& str ) const { + return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str ); } } // end catch_wildcard_pattern.cpp // start catch_xmlwriter.cpp #include <iomanip> - -using uchar = unsigned char; +#include <type_traits> namespace Catch { @@ -14504,8 +15408,30 @@ namespace { os.flags(f); } + bool shouldNewline(XmlFormatting fmt) { + return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline)); + } + + bool shouldIndent(XmlFormatting fmt) { + return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent)); + } + } // anonymous namespace + XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) { + return static_cast<XmlFormatting>( + static_cast<std::underlying_type<XmlFormatting>::type>(lhs) | + static_cast<std::underlying_type<XmlFormatting>::type>(rhs) + ); + } + + XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) { + return static_cast<XmlFormatting>( + static_cast<std::underlying_type<XmlFormatting>::type>(lhs) & + static_cast<std::underlying_type<XmlFormatting>::type>(rhs) + ); + } + XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) : m_str( str ), m_forWhat( forWhat ) @@ -14516,7 +15442,7 @@ namespace { // (see: http://www.w3.org/TR/xml/#syntax) for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { - uchar c = m_str[idx]; + unsigned char c = m_str[idx]; switch (c) { case '<': os << "<"; break; case '&': os << "&"; break; @@ -14576,7 +15502,7 @@ namespace { bool valid = true; uint32_t value = headerValue(c); for (std::size_t n = 1; n < encBytes; ++n) { - uchar nc = m_str[idx + n]; + unsigned char nc = m_str[idx + n]; valid &= ((nc & 0xC0) == 0x80); value = (value << 6) | (nc & 0x3F); } @@ -14610,13 +15536,17 @@ namespace { return os; } - XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) - : m_writer( writer ) + XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt ) + : m_writer( writer ), + m_fmt(fmt) {} XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept - : m_writer( other.m_writer ){ + : m_writer( other.m_writer ), + m_fmt(other.m_fmt) + { other.m_writer = nullptr; + other.m_fmt = XmlFormatting::None; } XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { if ( m_writer ) { @@ -14624,16 +15554,19 @@ namespace { } m_writer = other.m_writer; other.m_writer = nullptr; + m_fmt = other.m_fmt; + other.m_fmt = XmlFormatting::None; return *this; } XmlWriter::ScopedElement::~ScopedElement() { - if( m_writer ) - m_writer->endElement(); + if (m_writer) { + m_writer->endElement(m_fmt); + } } - XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { - m_writer->writeText( text, indent ); + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) { + m_writer->writeText( text, fmt ); return *this; } @@ -14643,37 +15576,47 @@ namespace { } XmlWriter::~XmlWriter() { - while( !m_tags.empty() ) + while (!m_tags.empty()) { endElement(); + } + newlineIfNecessary(); } - XmlWriter& XmlWriter::startElement( std::string const& name ) { + XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) { ensureTagClosed(); newlineIfNecessary(); - m_os << m_indent << '<' << name; + if (shouldIndent(fmt)) { + m_os << m_indent; + m_indent += " "; + } + m_os << '<' << name; m_tags.push_back( name ); - m_indent += " "; m_tagIsOpen = true; + applyFormatting(fmt); return *this; } - XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); + XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) { + ScopedElement scoped( this, fmt ); + startElement( name, fmt ); return scoped; } - XmlWriter& XmlWriter::endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); + XmlWriter& XmlWriter::endElement(XmlFormatting fmt) { + m_indent = m_indent.substr(0, m_indent.size() - 2); + if( m_tagIsOpen ) { m_os << "/>"; m_tagIsOpen = false; + } else { + newlineIfNecessary(); + if (shouldIndent(fmt)) { + m_os << m_indent; + } + m_os << "</" << m_tags.back() << ">"; } - else { - m_os << m_indent << "</" << m_tags.back() << ">"; - } - m_os << std::endl; + m_os << std::flush; + applyFormatting(fmt); m_tags.pop_back(); return *this; } @@ -14689,22 +15632,26 @@ namespace { return *this; } - XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { + XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) { if( !text.empty() ){ bool tagWasOpen = m_tagIsOpen; ensureTagClosed(); - if( tagWasOpen && indent ) + if (tagWasOpen && shouldIndent(fmt)) { m_os << m_indent; + } m_os << XmlEncode( text ); - m_needsNewline = true; + applyFormatting(fmt); } return *this; } - XmlWriter& XmlWriter::writeComment( std::string const& text ) { + XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) { ensureTagClosed(); - m_os << m_indent << "<!--" << text << "-->"; - m_needsNewline = true; + if (shouldIndent(fmt)) { + m_os << m_indent; + } + m_os << "<!--" << text << "-->"; + applyFormatting(fmt); return *this; } @@ -14720,11 +15667,16 @@ namespace { void XmlWriter::ensureTagClosed() { if( m_tagIsOpen ) { - m_os << ">" << std::endl; + m_os << '>' << std::flush; + newlineIfNecessary(); m_tagIsOpen = false; } } + void XmlWriter::applyFormatting(XmlFormatting fmt) { + m_needsNewline = shouldNewline(fmt); + } + void XmlWriter::writeDeclaration() { m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; } @@ -14770,6 +15722,17 @@ namespace Catch { return std::string(buffer); } + bool shouldShowDuration( IConfig const& config, double duration ) { + if ( config.showDurations() == ShowDurations::Always ) { + return true; + } + if ( config.showDurations() == ShowDurations::Never ) { + return false; + } + const double min = config.minDuration(); + return min >= 0 && duration >= min; + } + std::string serializeFilters( std::vector<std::string> const& container ) { ReusableStringStream oss; bool first = true; @@ -15000,24 +15963,25 @@ private: if (itMessage == messages.end()) return; - // using messages.end() directly yields (or auto) compilation error: - std::vector<MessageInfo>::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd)); + const auto itEnd = messages.cend(); + const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd)); { Colour colourGuard(colour); stream << " with " << pluralise(N, "message") << ':'; } - for (; itMessage != itEnd; ) { + while (itMessage != itEnd) { // If this assertion is a warning ignore any INFO messages if (printInfoMessages || itMessage->type != ResultWas::Info) { - stream << " '" << itMessage->message << '\''; - if (++itMessage != itEnd) { + printMessage(); + if (itMessage != itEnd) { Colour colourGuard(dimColour()); stream << " and"; } + continue; } + ++itMessage; } } @@ -15035,10 +15999,6 @@ private: return "Reports test results on a single line, suitable for IDEs"; } - ReporterPreferences CompactReporter::getPreferences() const { - return m_reporterPrefs; - } - void CompactReporter::noMatchingTestCases( std::string const& spec ) { stream << "No test cases matched '" << spec << '\'' << std::endl; } @@ -15065,8 +16025,9 @@ private: } void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + double dur = _sectionStats.durationInSeconds; + if ( shouldShowDuration( *m_config, dur ) ) { + stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl; } } @@ -15278,15 +16239,11 @@ class Duration { static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; - uint64_t m_inNanoseconds; + double m_inNanoseconds; Unit m_units; public: - explicit Duration(double inNanoseconds, Unit units = Unit::Auto) - : Duration(static_cast<uint64_t>(inNanoseconds), units) { - } - - explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto) + explicit Duration(double inNanoseconds, Unit units = Unit::Auto) : m_inNanoseconds(inNanoseconds), m_units(units) { if (m_units == Unit::Auto) { @@ -15315,7 +16272,7 @@ public: case Unit::Minutes: return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute); default: - return static_cast<double>(m_inNanoseconds); + return m_inNanoseconds; } } auto unitsAsString() const -> std::string { @@ -15336,7 +16293,7 @@ public: } friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { - return os << duration.value() << " " << duration.unitsAsString(); + return os << duration.value() << ' ' << duration.unitsAsString(); } }; } // end anon namespace @@ -15368,9 +16325,9 @@ public: headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2)); headerCols += spacer; } - m_os << headerCols << "\n"; + m_os << headerCols << '\n'; - m_os << Catch::getLineOfChars<'-'>() << "\n"; + m_os << Catch::getLineOfChars<'-'>() << '\n'; } } void close() { @@ -15389,30 +16346,29 @@ public: friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { auto colStr = tp.m_oss.str(); - // This takes account of utf8 encodings - auto strSize = Catch::StringRef(colStr).numberOfCharacters(); + const auto strSize = colStr.size(); tp.m_oss.str(""); tp.open(); if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) { tp.m_currentColumn = -1; - tp.m_os << "\n"; + tp.m_os << '\n'; } tp.m_currentColumn++; auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width)) - ? std::string(colInfo.width - (strSize + 2), ' ') + auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width)) + ? std::string(colInfo.width - (strSize + 1), ' ') : std::string(); if (colInfo.justification == ColumnInfo::Left) - tp.m_os << colStr << padding << " "; + tp.m_os << colStr << padding << ' '; else - tp.m_os << padding << colStr << " "; + tp.m_os << padding << colStr << ' '; return tp; } friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { if (tp.m_currentColumn > 0) { - tp.m_os << "\n"; + tp.m_os << '\n'; tp.m_currentColumn = -1; } return tp; @@ -15422,12 +16378,26 @@ public: ConsoleReporter::ConsoleReporter(ReporterConfig const& config) : StreamingReporterBase(config), m_tablePrinter(new TablePrinter(config.stream(), - { - { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left }, - { "samples mean std dev", 14, ColumnInfo::Right }, - { "iterations low mean low std dev", 14, ColumnInfo::Right }, - { "estimated high mean high std dev", 14, ColumnInfo::Right } - })) {} + [&config]() -> std::vector<ColumnInfo> { + if (config.fullConfig()->benchmarkNoAnalysis()) + { + return{ + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, + { " samples", 14, ColumnInfo::Right }, + { " iterations", 14, ColumnInfo::Right }, + { " mean", 14, ColumnInfo::Right } + }; + } + else + { + return{ + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left }, + { "samples mean std dev", 14, ColumnInfo::Right }, + { "iterations low mean low std dev", 14, ColumnInfo::Right }, + { "estimated high mean high std dev", 14, ColumnInfo::Right } + }; + } + }())) {} ConsoleReporter::~ConsoleReporter() = default; std::string ConsoleReporter::getDescription() { @@ -15438,6 +16408,10 @@ void ConsoleReporter::noMatchingTestCases(std::string const& spec) { stream << "No test cases matched '" << spec << '\'' << std::endl; } +void ConsoleReporter::reportInvalidArguments(std::string const&arg){ + stream << "Invalid Filter: " << arg << std::endl; +} + void ConsoleReporter::assertionStarting(AssertionInfo const&) {} bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { @@ -15473,8 +16447,9 @@ void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { stream << "\nNo assertions in test case"; stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; } - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + double dur = _sectionStats.durationInSeconds; + if (shouldShowDuration(*m_config, dur)) { + stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl; } if (m_headerPrinted) { m_headerPrinted = false; @@ -15500,24 +16475,32 @@ void ConsoleReporter::benchmarkPreparing(std::string const& name) { } void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { - (*m_tablePrinter) << info.samples << ColumnBreak() - << info.iterations << ColumnBreak() - << Duration(info.estimatedDuration) << ColumnBreak(); + (*m_tablePrinter) << info.samples << ColumnBreak() + << info.iterations << ColumnBreak(); + if (!m_config->benchmarkNoAnalysis()) + (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak(); } void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) { - (*m_tablePrinter) << ColumnBreak() - << Duration(stats.mean.point.count()) << ColumnBreak() - << Duration(stats.mean.lower_bound.count()) << ColumnBreak() - << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak() - << Duration(stats.standardDeviation.point.count()) << ColumnBreak() - << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak() - << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak(); + if (m_config->benchmarkNoAnalysis()) + { + (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak(); + } + else + { + (*m_tablePrinter) << ColumnBreak() + << Duration(stats.mean.point.count()) << ColumnBreak() + << Duration(stats.mean.lower_bound.count()) << ColumnBreak() + << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak() + << Duration(stats.standardDeviation.point.count()) << ColumnBreak() + << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak() + << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak(); + } } void ConsoleReporter::benchmarkFailed(std::string const& error) { Colour colour(Colour::Red); (*m_tablePrinter) - << "Benchmark failed (" << error << ")" + << "Benchmark failed (" << error << ')' << ColumnBreak() << RowBreak(); } #endif // CATCH_CONFIG_ENABLE_BENCHMARKING @@ -15599,11 +16582,9 @@ void ConsoleReporter::printTestCaseAndSectionHeader() { SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; - if (!lineInfo.empty()) { - stream << getLineOfChars<'-'>() << '\n'; - Colour colourGuard(Colour::FileName); - stream << lineInfo << '\n'; - } + stream << getLineOfChars<'-'>() << '\n'; + Colour colourGuard(Colour::FileName); + stream << lineInfo << '\n'; stream << getLineOfChars<'.'>() << '\n' << std::endl; } @@ -15728,8 +16709,10 @@ void ConsoleReporter::printSummaryDivider() { } void ConsoleReporter::printTestFilters() { - if (m_config->testSpec().hasFilters()) - stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n'; + if (m_config->testSpec().hasFilters()) { + Colour guard(Colour::BrightYellow); + stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n'; + } } CATCH_REGISTER_REPORTER("console", ConsoleReporter) @@ -15879,8 +16862,8 @@ namespace Catch { for( auto const& child : groupNode.children ) writeTestCase( *child ); - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false ); + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline ); } void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { @@ -15925,13 +16908,18 @@ namespace Catch { xml.writeAttribute( "name", name ); } xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); + // This is not ideal, but it should be enough to mimic gtest's + // junit output. + // Ideally the JUnit reporter would also handle `skipTest` + // events and write those out appropriately. + xml.writeAttribute( "status", "run" ); writeAssertions( sectionNode ); if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline ); if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline ); } for( auto const& childNode : sectionNode.childSections ) if( className.empty() ) @@ -15955,11 +16943,7 @@ namespace Catch { elementName = "error"; break; case ResultWas::ExplicitFailure: - elementName = "failure"; - break; case ResultWas::ExpressionFailed: - elementName = "failure"; - break; case ResultWas::DidntThrowException: elementName = "failure"; break; @@ -15977,10 +16961,25 @@ namespace Catch { XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "message", result.getExpression() ); xml.writeAttribute( "type", result.getTestMacroName() ); ReusableStringStream rss; + if (stats.totals.assertions.total() > 0) { + rss << "FAILED" << ":\n"; + if (result.hasExpression()) { + rss << " "; + rss << result.getExpressionInMacro(); + rss << '\n'; + } + if (result.hasExpandedExpression()) { + rss << "with expansion:\n"; + rss << Column(result.getExpandedExpression()).indent(2) << '\n'; + } + } else { + rss << '\n'; + } + if( !result.getMessage().empty() ) rss << result.getMessage() << '\n'; for( auto const& msg : stats.infoMessages ) @@ -15988,7 +16987,7 @@ namespace Catch { rss << msg.message << '\n'; rss << "at " << result.getSourceInfo(); - xml.writeText( rss.str(), false ); + xml.writeText( rss.str(), XmlFormatting::Newline ); } } @@ -16032,6 +17031,13 @@ namespace Catch { m_reporter->noMatchingTestCases( spec ); } + void ListeningReporter::reportInvalidArguments(std::string const&arg){ + for ( auto const& listener : m_listeners ) { + listener->reportInvalidArguments( arg ); + } + m_reporter->reportInvalidArguments( arg ); + } + #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) void ListeningReporter::benchmarkPreparing( std::string const& name ) { for (auto const& listener : m_listeners) { @@ -16327,9 +17333,9 @@ namespace Catch { e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); if( !testCaseStats.stdOut.empty() ) - m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); + m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline ); if( !testCaseStats.stdErr.empty() ) - m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); + m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline ); m_xml.endElement(); } @@ -16341,6 +17347,10 @@ namespace Catch { .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.scopedElement( "OverallResultsCases") + .writeAttribute( "successes", testGroupStats.totals.testCases.passed ) + .writeAttribute( "failures", testGroupStats.totals.testCases.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk ); m_xml.endElement(); } @@ -16350,26 +17360,33 @@ namespace Catch { .writeAttribute( "successes", testRunStats.totals.assertions.passed ) .writeAttribute( "failures", testRunStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.scopedElement( "OverallResultsCases") + .writeAttribute( "successes", testRunStats.totals.testCases.passed ) + .writeAttribute( "failures", testRunStats.totals.testCases.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk ); m_xml.endElement(); } #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) - void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) { + void XmlReporter::benchmarkPreparing(std::string const& name) { m_xml.startElement("BenchmarkResults") - .writeAttribute("name", info.name) - .writeAttribute("samples", info.samples) + .writeAttribute("name", name); + } + + void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) { + m_xml.writeAttribute("samples", info.samples) .writeAttribute("resamples", info.resamples) .writeAttribute("iterations", info.iterations) - .writeAttribute("clockResolution", static_cast<uint64_t>(info.clockResolution)) - .writeAttribute("estimatedDuration", static_cast<uint64_t>(info.estimatedDuration)) + .writeAttribute("clockResolution", info.clockResolution) + .writeAttribute("estimatedDuration", info.estimatedDuration) .writeComment("All values in nano seconds"); } void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) { m_xml.startElement("mean") - .writeAttribute("value", static_cast<uint64_t>(benchmarkStats.mean.point.count())) - .writeAttribute("lowerBound", static_cast<uint64_t>(benchmarkStats.mean.lower_bound.count())) - .writeAttribute("upperBound", static_cast<uint64_t>(benchmarkStats.mean.upper_bound.count())) + .writeAttribute("value", benchmarkStats.mean.point.count()) + .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count()) + .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count()) .writeAttribute("ci", benchmarkStats.mean.confidence_interval); m_xml.endElement(); m_xml.startElement("standardDeviation") @@ -16420,7 +17437,7 @@ namespace Catch { #ifndef __OBJC__ -#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) +#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { #else diff --git a/3rdparty/bx/LICENSE b/3rdparty/bx/LICENSE index 1c8e1e05472..9fbd22dcba1 100644 --- a/3rdparty/bx/LICENSE +++ b/3rdparty/bx/LICENSE @@ -1,4 +1,4 @@ -Copyright 2010-2019 Branimir Karadzic +Copyright 2010-2021 Branimir Karadzic Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/3rdparty/bx/README.md b/3rdparty/bx/README.md index 00d6d8a0205..3a6547daf5c 100644 --- a/3rdparty/bx/README.md +++ b/3rdparty/bx/README.md @@ -3,10 +3,10 @@ bx Base library. -[](https://travis-ci.org/bkaradzic/bx) +[](https://travis-ci.com/bkaradzic/bx) [](https://ci.appveyor.com/project/bkaradzic/bx) [](https://bkaradzic.github.io/bgfx/license.html) -[](https://gitter.im/bkaradzic/bgfx) +[](https://discord.gg/9eMbv7J) Contact ------- @@ -23,7 +23,7 @@ https://github.com/bkaradzic/bx <img align="right" src="http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png"> </a> - Copyright 2010-2019 Branimir Karadzic + Copyright 2010-2021 Branimir Karadzic Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/3rdparty/bx/include/bx/allocator.h b/3rdparty/bx/include/bx/allocator.h index 7a140b0b562..94d7835da8a 100644 --- a/3rdparty/bx/include/bx/allocator.h +++ b/3rdparty/bx/include/bx/allocator.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -7,6 +7,7 @@ #define BX_ALLOCATOR_H_HEADER_GUARD #include "bx.h" +#include "uint32_t.h" #if BX_CONFIG_ALLOCATOR_DEBUG # define BX_ALLOC(_allocator, _size) bx::alloc(_allocator, _size, 0, __FILE__, __LINE__) diff --git a/3rdparty/bx/include/bx/bx.h b/3rdparty/bx/include/bx/bx.h index 2cfc676d795..36f40aab493 100644 --- a/3rdparty/bx/include/bx/bx.h +++ b/3rdparty/bx/include/bx/bx.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -20,24 +20,28 @@ #define BX_COUNTOF(_x) sizeof(bx::CountOfRequireArrayArgumentT(_x) ) /// -#define BX_IGNORE_C4127(_x) bx::ignoreC4127(!!(_x) ) +#if BX_COMPILER_MSVC +# define BX_IGNORE_C4127(_x) bx::ignoreC4127(!!(_x) ) +#else +# define BX_IGNORE_C4127(_x) (!!(_x) ) +#endif // BX_COMPILER_MSVC /// -#define BX_ENABLED(_x) bx::isEnabled<!!(_x)>() +#define BX_ENABLED(_x) BX_IGNORE_C4127(bx::isEnabled<!!(_x)>::value) namespace bx { constexpr int32_t kExitSuccess = 0; constexpr int32_t kExitFailure = 1; - /// Template for avoiding MSVC: C4127: conditional expression is constant - template<bool> - constexpr bool isEnabled(); - /// template<class Ty> constexpr bool isTriviallyCopyable(); + /// Find the address of an object of a class that has an overloaded unary ampersand (&) operator. + template <class Ty> + Ty* addressOf(Ty& _a); + /// Swap two values. template<typename Ty> void swap(Ty& _a, Ty& _b); diff --git a/3rdparty/bx/include/bx/commandline.h b/3rdparty/bx/include/bx/commandline.h index 058b51c5a5a..48815ddccce 100644 --- a/3rdparty/bx/include/bx/commandline.h +++ b/3rdparty/bx/include/bx/commandline.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/config.h b/3rdparty/bx/include/bx/config.h index 247968a04d7..9a9670731a8 100644 --- a/3rdparty/bx/include/bx/config.h +++ b/3rdparty/bx/include/bx/config.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/cpu.h b/3rdparty/bx/include/bx/cpu.h index 9cadf408bd0..20f6a5fd970 100644 --- a/3rdparty/bx/include/bx/cpu.h +++ b/3rdparty/bx/include/bx/cpu.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/debug.h b/3rdparty/bx/include/bx/debug.h index b5a9bc0534e..d8cf15e0690 100644 --- a/3rdparty/bx/include/bx/debug.h +++ b/3rdparty/bx/include/bx/debug.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/easing.h b/3rdparty/bx/include/bx/easing.h index 034999081cf..3aa44ca0a20 100644 --- a/3rdparty/bx/include/bx/easing.h +++ b/3rdparty/bx/include/bx/easing.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/endian.h b/3rdparty/bx/include/bx/endian.h index f9eeba0ec54..9eeb0ef19e5 100644 --- a/3rdparty/bx/include/bx/endian.h +++ b/3rdparty/bx/include/bx/endian.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/error.h b/3rdparty/bx/include/bx/error.h index f1416b64a7b..d00d8af4b48 100644 --- a/3rdparty/bx/include/bx/error.h +++ b/3rdparty/bx/include/bx/error.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -8,22 +8,22 @@ #include "string.h" -#define BX_ERROR_SET(_ptr, _result, _msg) \ - BX_MACRO_BLOCK_BEGIN \ - (_ptr)->setError(_result, "" _msg); \ - BX_MACRO_BLOCK_END +#define BX_ERROR_SET(_ptr, _result, _msg) \ + BX_MACRO_BLOCK_BEGIN \ + (_ptr)->setError(_result, "" _msg); \ + BX_MACRO_BLOCK_END -#define BX_ERROR_USE_TEMP_WHEN_NULL(_ptr) \ - const bx::Error tmpError; /* It should not be used directly! */ \ - _ptr = NULL == _ptr ? const_cast<bx::Error*>(&tmpError) : _ptr +#define BX_ERROR_USE_TEMP_WHEN_NULL(_ptr) \ + const bx::Error tmpError; /* It should not be used directly! */ \ + _ptr = NULL == _ptr ? const_cast<bx::Error*>(&tmpError) : _ptr -#define BX_ERROR_SCOPE(_ptr) \ - BX_ERROR_USE_TEMP_WHEN_NULL(_ptr); \ - bx::ErrorScope bxErrorScope(const_cast<bx::Error*>(&tmpError) ) +#define BX_ERROR_SCOPE(_ptr, ...) \ + BX_ERROR_USE_TEMP_WHEN_NULL(_ptr); \ + bx::ErrorScope bxErrorScope(const_cast<bx::Error*>(&tmpError), "" __VA_ARGS__) -#define BX_ERROR_RESULT(_err, _code) \ - BX_STATIC_ASSERT(_code != 0, "ErrorCode 0 is reserved!"); \ - static const bx::ErrorResult _err = { _code } +#define BX_ERROR_RESULT(_err, _code) \ + BX_STATIC_ASSERT(_code != 0, "ErrorCode 0 is reserved!"); \ + static constexpr bx::ErrorResult _err = { _code } namespace bx { @@ -81,13 +81,17 @@ namespace bx public: /// - ErrorScope(Error* _err); + ErrorScope(Error* _err, const StringView& _name); /// ~ErrorScope(); + /// + const StringView& getName() const; + private: Error* m_err; + const StringView m_name; }; } // namespace bx diff --git a/3rdparty/bx/include/bx/file.h b/3rdparty/bx/include/bx/file.h index 42c15ba9622..e692224131c 100644 --- a/3rdparty/bx/include/bx/file.h +++ b/3rdparty/bx/include/bx/file.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/filepath.h b/3rdparty/bx/include/bx/filepath.h index 920c0b4bbe2..3de0ce0d4fc 100644 --- a/3rdparty/bx/include/bx/filepath.h +++ b/3rdparty/bx/include/bx/filepath.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -9,11 +9,11 @@ #include "error.h" #include "string.h" -BX_ERROR_RESULT(BX_ERROR_ACCESS, BX_MAKEFOURCC('b', 'x', 0, 0) ); -BX_ERROR_RESULT(BX_ERROR_NOT_DIRECTORY, BX_MAKEFOURCC('b', 'x', 0, 1) ); - namespace bx { + BX_ERROR_RESULT(kErrorAccess, BX_MAKEFOURCC('b', 'x', 1, 1) ); + BX_ERROR_RESULT(kErrorNotDirectory, BX_MAKEFOURCC('b', 'x', 1, 2) ); + constexpr int32_t kMaxFilePath = 1024; /// Special predefined OS directories. diff --git a/3rdparty/bx/include/bx/float4x4_t.h b/3rdparty/bx/include/bx/float4x4_t.h index 9ec367f0739..893029cc290 100644 --- a/3rdparty/bx/include/bx/float4x4_t.h +++ b/3rdparty/bx/include/bx/float4x4_t.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -10,25 +10,35 @@ namespace bx { - /// + /// 4x4 matrix. BX_ALIGN_DECL_16(struct) float4x4_t { simd128_t col[4]; }; - /// + /// Multiplies vector `_a` with matrix `_b` ignoring W component of vector `_a`. simd128_t simd_mul_xyz1(simd128_t _a, const float4x4_t* _b); - /// + /// Multiplies vector `_a` with matrix `_b`. simd128_t simd_mul(simd128_t _a, const float4x4_t* _b); - /// + /// Multiplies two matrices. void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b); - /// + /// Multiplies two 3x4 affine matrices (i.e. "model" or "world" matrices). + /// This function is a micro-optimized version of float4x4_mul() in the case + /// when the last row of the both input matrices are (0, 0, 0, 1). + void model4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b); + + /// Multiplies a 3x4 affine matrix with a general 4x4 matrix. + /// This function is a micro-optimized version of float4x4_mul() in the case + /// when the last row of the _model input matrix is (0, 0, 0, 1). + void model4x4_mul_viewproj4x4(float4x4_t* _result, const float4x4_t* _model, const float4x4_t* _viewProj); + + /// Transpose of matrix. void float4x4_transpose(float4x4_t* _result, const float4x4_t* _mtx); - /// + /// Inverse of matrix. void float4x4_inverse(float4x4_t* _result, const float4x4_t* _a); } // namespace bx diff --git a/3rdparty/bx/include/bx/handlealloc.h b/3rdparty/bx/include/bx/handlealloc.h index a4432b9d176..92a9d8671ed 100644 --- a/3rdparty/bx/include/bx/handlealloc.h +++ b/3rdparty/bx/include/bx/handlealloc.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -12,7 +12,7 @@ namespace bx { - static const uint16_t kInvalidHandle = UINT16_MAX; + constexpr uint16_t kInvalidHandle = UINT16_MAX; /// class HandleAlloc diff --git a/3rdparty/bx/include/bx/hash.h b/3rdparty/bx/include/bx/hash.h index 976fa21acb7..42d76e1a681 100644 --- a/3rdparty/bx/include/bx/hash.h +++ b/3rdparty/bx/include/bx/hash.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/allocator.inl b/3rdparty/bx/include/bx/inline/allocator.inl index ce4ccc92a72..8e5085fa4a7 100644 --- a/3rdparty/bx/include/bx/inline/allocator.inl +++ b/3rdparty/bx/include/bx/inline/allocator.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -22,20 +22,12 @@ namespace bx { } - inline bool isAligned(const void* _ptr, size_t _align) - { - union { const void* ptr; uintptr_t addr; } un; - un.ptr = _ptr; - return 0 == (un.addr & (_align-1) ); - } - inline void* alignPtr(void* _ptr, size_t _extra, size_t _align) { union { void* ptr; uintptr_t addr; } un; un.ptr = _ptr; uintptr_t unaligned = un.addr + _extra; // space for header - uintptr_t mask = _align-1; - uintptr_t aligned = BX_ALIGN_MASK(unaligned, mask); + uintptr_t aligned = bx::alignUp(unaligned, int32_t(_align) ); un.addr = aligned; return un.ptr; } diff --git a/3rdparty/bx/include/bx/inline/bx.inl b/3rdparty/bx/include/bx/inline/bx.inl index b0083571ac4..fc527ec79ce 100644 --- a/3rdparty/bx/include/bx/inline/bx.inl +++ b/3rdparty/bx/include/bx/inline/bx.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -15,10 +15,16 @@ namespace bx template<typename Ty, size_t Num> char(&CountOfRequireArrayArgumentT(const Ty(&)[Num]))[Num]; - template<bool> - inline constexpr bool isEnabled() + template<bool B> + struct isEnabled { - return true; + // Template for avoiding MSVC: C4127: conditional expression is constant + static constexpr bool value = B; + }; + + inline constexpr bool ignoreC4127(bool _x) + { + return _x; } template<class Ty> @@ -27,15 +33,14 @@ namespace bx return __is_trivially_copyable(Ty); } - template<> - inline constexpr bool isEnabled<false>() - { - return false; - } - - inline constexpr bool ignoreC4127(bool _x) + template<class Ty> + inline Ty* addressOf(Ty& _a) { - return _x; + return reinterpret_cast<Ty*>( + &const_cast<char&>( + reinterpret_cast<const volatile char&>(_a) + ) + ); } template<typename Ty> diff --git a/3rdparty/bx/include/bx/inline/cpu.inl b/3rdparty/bx/include/bx/inline/cpu.inl index b5a83a4f68d..f02fc177175 100644 --- a/3rdparty/bx/include/bx/inline/cpu.inl +++ b/3rdparty/bx/include/bx/inline/cpu.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -8,13 +8,16 @@ #endif // BX_CPU_H_HEADER_GUARD #if BX_COMPILER_MSVC -# if BX_PLATFORM_WINRT +# if BX_PLATFORM_WINRT || (BX_PLATFORM_WINDOWS && !BX_CPU_X86) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif // WIN32_LEAN_AND_MEAN # include <windows.h> -# endif // BX_PLATFORM_WINRT +# endif // BX_PLATFORM_WINRT || (BX_PLATFORM_WINDOWS && !BX_CPU_X86) # if BX_CPU_X86 # include <emmintrin.h> // _mm_fence -# endif +# endif // BX_CPU_X86 extern "C" void _ReadBarrier(); # pragma intrinsic(_ReadBarrier) @@ -68,7 +71,7 @@ namespace bx _ReadBarrier(); #else asm volatile("":::"memory"); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } inline void writeBarrier() @@ -77,7 +80,7 @@ namespace bx _WriteBarrier(); #else asm volatile("":::"memory"); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } inline void readWriteBarrier() @@ -86,18 +89,20 @@ namespace bx _ReadWriteBarrier(); #else asm volatile("":::"memory"); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } inline void memoryBarrier() { -#if BX_PLATFORM_WINRT - MemoryBarrier(); -#elif BX_COMPILER_MSVC +#if BX_COMPILER_MSVC +# if BX_CPU_X86 _mm_mfence(); +# else + MemoryBarrier(); +# endif // BX_CPU_X86 #else __sync_synchronize(); -#endif // BX_COMPILER +#endif // BX_COMPILER_MSVC } template<> @@ -107,7 +112,7 @@ namespace bx return int32_t(_InterlockedCompareExchange( (volatile long*)(_ptr), long(_new), long(_old) ) ); #else return __sync_val_compare_and_swap( (volatile int32_t*)_ptr, _old, _new); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } template<> @@ -117,7 +122,7 @@ namespace bx return uint32_t(_InterlockedCompareExchange( (volatile long*)(_ptr), long(_new), long(_old) ) ); #else return __sync_val_compare_and_swap( (volatile int32_t*)_ptr, _old, _new); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } template<> @@ -127,7 +132,7 @@ namespace bx return _InterlockedCompareExchange64(_ptr, _new, _old); #else return __sync_val_compare_and_swap( (volatile int64_t*)_ptr, _old, _new); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } template<> @@ -137,7 +142,7 @@ namespace bx return uint64_t(_InterlockedCompareExchange64( (volatile int64_t*)(_ptr), int64_t(_new), int64_t(_old) ) ); #else return __sync_val_compare_and_swap( (volatile int64_t*)_ptr, _old, _new); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } template<> @@ -147,7 +152,7 @@ namespace bx return _InterlockedExchangeAdd( (volatile long*)_ptr, _add); #else return __sync_fetch_and_add(_ptr, _add); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -176,7 +181,7 @@ namespace bx # endif #else return __sync_fetch_and_add(_ptr, _add); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -192,7 +197,7 @@ namespace bx return atomicFetchAndAdd(_ptr, _add) + _add; #else return __sync_add_and_fetch(_ptr, _add); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -202,7 +207,7 @@ namespace bx return atomicFetchAndAdd(_ptr, _add) + _add; #else return __sync_add_and_fetch(_ptr, _add); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -224,7 +229,7 @@ namespace bx return atomicFetchAndAdd(_ptr, -_sub); #else return __sync_fetch_and_sub(_ptr, _sub); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -234,7 +239,7 @@ namespace bx return atomicFetchAndAdd(_ptr, -_sub); #else return __sync_fetch_and_sub(_ptr, _sub); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -256,7 +261,7 @@ namespace bx return atomicFetchAndAdd(_ptr, -_sub) - _sub; #else return __sync_sub_and_fetch(_ptr, _sub); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -266,7 +271,7 @@ namespace bx return atomicFetchAndAdd(_ptr, -_sub) - _sub; #else return __sync_sub_and_fetch(_ptr, _sub); -#endif // BX_COMPILER_ +#endif // BX_COMPILER_* } template<> @@ -347,7 +352,7 @@ namespace bx return _InterlockedExchangePointer(_ptr, _new); #else return __sync_lock_test_and_set(_ptr, _new); -#endif // BX_COMPILER +#endif // BX_COMPILER_* } } // namespace bx diff --git a/3rdparty/bx/include/bx/inline/easing.inl b/3rdparty/bx/include/bx/inline/easing.inl index 02bd7d4e225..18bbe943091 100644 --- a/3rdparty/bx/include/bx/inline/easing.inl +++ b/3rdparty/bx/include/bx/inline/easing.inl @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/endian.inl b/3rdparty/bx/include/bx/inline/endian.inl index c0fd7480c7a..de0f7abf945 100644 --- a/3rdparty/bx/include/bx/inline/endian.inl +++ b/3rdparty/bx/include/bx/inline/endian.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/error.inl b/3rdparty/bx/include/bx/inline/error.inl index badb75633b0..382c624990a 100644 --- a/3rdparty/bx/include/bx/inline/error.inl +++ b/3rdparty/bx/include/bx/inline/error.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -22,7 +22,7 @@ namespace bx inline void Error::setError(ErrorResult _errorResult, const StringView& _msg) { - BX_CHECK(0 != _errorResult.code, "Invalid ErrorResult passed to setError!"); + BX_ASSERT(0 != _errorResult.code, "Invalid ErrorResult passed to setError!"); if (!isOk() ) { @@ -59,15 +59,38 @@ namespace bx return _rhs.code != m_code; } - inline ErrorScope::ErrorScope(Error* _err) + inline ErrorScope::ErrorScope(Error* _err, const StringView& _name) : m_err(_err) + , m_name(_name) { - BX_CHECK(NULL != _err, "_err can't be NULL"); + BX_ASSERT(NULL != _err, "_err can't be NULL"); } inline ErrorScope::~ErrorScope() { - BX_CHECK(m_err->isOk(), "Error: %d", m_err->get().code); + if (m_name.isEmpty() ) + { + BX_ASSERT(m_err->isOk(), "Error: 0x%08x `%.*s`" + , m_err->get().code + , m_err->getMessage().getLength() + , m_err->getMessage().getPtr() + ); + } + else + { + BX_ASSERT(m_err->isOk(), "Error: %.*s - 0x%08x `%.*s`" + , m_name.getLength() + , m_name.getPtr() + , m_err->get().code + , m_err->getMessage().getLength() + , m_err->getMessage().getPtr() + ); + } + } + + inline const StringView& ErrorScope::getName() const + { + return m_name; } } // namespace bx diff --git a/3rdparty/bx/include/bx/inline/float4x4_t.inl b/3rdparty/bx/include/bx/inline/float4x4_t.inl index 27bf00d5618..6a3bfb6d90a 100644 --- a/3rdparty/bx/include/bx/inline/float4x4_t.inl +++ b/3rdparty/bx/include/bx/inline/float4x4_t.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -40,10 +40,99 @@ namespace bx BX_SIMD_INLINE void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b) { +#if BX_CONFIG_SUPPORTS_SIMD _result->col[0] = simd_mul(_a->col[0], _b); _result->col[1] = simd_mul(_a->col[1], _b); _result->col[2] = simd_mul(_a->col[2], _b); _result->col[3] = simd_mul(_a->col[3], _b); +#else + const float* aa = (const float*)_a; + const float* bb = (const float*)_b; + float *rr = (float*)_result; + + rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8] + aa[ 3]*bb[12]; + rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9] + aa[ 3]*bb[13]; + rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10] + aa[ 3]*bb[14]; + rr[ 3] = aa[ 0]*bb[ 3] + aa[ 1]*bb[ 7] + aa[ 2]*bb[11] + aa[ 3]*bb[15]; + + rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8] + aa[ 7]*bb[12]; + rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9] + aa[ 7]*bb[13]; + rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10] + aa[ 7]*bb[14]; + rr[ 7] = aa[ 4]*bb[ 3] + aa[ 5]*bb[ 7] + aa[ 6]*bb[11] + aa[ 7]*bb[15]; + + rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8] + aa[11]*bb[12]; + rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9] + aa[11]*bb[13]; + rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10] + aa[11]*bb[14]; + rr[11] = aa[ 8]*bb[ 3] + aa[ 9]*bb[ 7] + aa[10]*bb[11] + aa[11]*bb[15]; + + rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + aa[15]*bb[12]; + rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + aa[15]*bb[13]; + rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + aa[15]*bb[14]; + rr[15] = aa[12]*bb[ 3] + aa[13]*bb[ 7] + aa[14]*bb[11] + aa[15]*bb[15]; +#endif // BX_CONFIG_SUPPORTS_SIMD + } + + BX_SIMD_INLINE void model4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b) + { +#if BX_CONFIG_SUPPORTS_SIMD + // With SIMD faster to do the general 4x4 form: + float4x4_mul(_result, _a, _b); +#else + const float* aa = (const float*)_a; // aa[ 3] == aa[ 7] == aa[11] == 0.0f, aa[15] = 1.0f + const float* bb = (const float*)_b; // bb[ 3] == bb[ 7] == bb[11] == 0.0f, bb[15] = 1.0f + float *rr = (float*)_result; + + rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8]; + rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9]; + rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10]; + rr[ 3] = 0.0f; + + rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8]; + rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9]; + rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10]; + rr[ 7] = 0.0f; + + rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8]; + rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9]; + rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10]; + rr[11] = 0.0f; + + rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + bb[12]; + rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + bb[13]; + rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + bb[14]; + rr[15] = 1.0f; +#endif // BX_CONFIG_SUPPORTS_SIMD + } + + BX_SIMD_INLINE void model4x4_mul_viewproj4x4(float4x4_t* _result, const float4x4_t* _model, const float4x4_t* _viewProj) + { +#if BX_CONFIG_SUPPORTS_SIMD + // With SIMD faster to do the general 4x4 form: + float4x4_mul(_result, _model, _viewProj); +#else + const float* aa = (const float*)_model; // aa[ 3] == aa[ 7] == aa[11] == 0.0f, aa[15] == 1.0f + const float* bb = (const float*)_viewProj; + float *rr = (float*)_result; + rr[ 0] = aa[ 0]*bb[ 0] + aa[ 1]*bb[ 4] + aa[ 2]*bb[ 8]; + rr[ 1] = aa[ 0]*bb[ 1] + aa[ 1]*bb[ 5] + aa[ 2]*bb[ 9]; + rr[ 2] = aa[ 0]*bb[ 2] + aa[ 1]*bb[ 6] + aa[ 2]*bb[10]; + rr[ 3] = aa[ 0]*bb[ 3] + aa[ 1]*bb[ 7] + aa[ 2]*bb[11]; + + rr[ 4] = aa[ 4]*bb[ 0] + aa[ 5]*bb[ 4] + aa[ 6]*bb[ 8]; + rr[ 5] = aa[ 4]*bb[ 1] + aa[ 5]*bb[ 5] + aa[ 6]*bb[ 9]; + rr[ 6] = aa[ 4]*bb[ 2] + aa[ 5]*bb[ 6] + aa[ 6]*bb[10]; + rr[ 7] = aa[ 4]*bb[ 3] + aa[ 5]*bb[ 7] + aa[ 6]*bb[11]; + + rr[ 8] = aa[ 8]*bb[ 0] + aa[ 9]*bb[ 4] + aa[10]*bb[ 8]; + rr[ 9] = aa[ 8]*bb[ 1] + aa[ 9]*bb[ 5] + aa[10]*bb[ 9]; + rr[10] = aa[ 8]*bb[ 2] + aa[ 9]*bb[ 6] + aa[10]*bb[10]; + rr[11] = aa[ 8]*bb[ 3] + aa[ 9]*bb[ 7] + aa[10]*bb[11]; + + rr[12] = aa[12]*bb[ 0] + aa[13]*bb[ 4] + aa[14]*bb[ 8] + bb[12]; + rr[13] = aa[12]*bb[ 1] + aa[13]*bb[ 5] + aa[14]*bb[ 9] + bb[13]; + rr[14] = aa[12]*bb[ 2] + aa[13]*bb[ 6] + aa[14]*bb[10] + bb[14]; + rr[15] = aa[12]*bb[ 3] + aa[13]*bb[ 7] + aa[14]*bb[11] + bb[15]; +#endif // BX_CONFIG_SUPPORTS_SIMD } BX_SIMD_FORCE_INLINE void float4x4_transpose(float4x4_t* _result, const float4x4_t* _mtx) diff --git a/3rdparty/bx/include/bx/inline/handlealloc.inl b/3rdparty/bx/include/bx/inline/handlealloc.inl index 94b7ebbda4a..4579e05ba43 100644 --- a/3rdparty/bx/include/bx/inline/handlealloc.inl +++ b/3rdparty/bx/include/bx/inline/handlealloc.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -186,7 +186,7 @@ namespace bx template <uint16_t MaxHandlesT> inline uint16_t HandleListT<MaxHandlesT>::getNext(uint16_t _handle) const { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + BX_ASSERT(isValid(_handle), "Invalid handle %d!", _handle); const Link& curr = m_links[_handle]; return curr.m_next; } @@ -194,7 +194,7 @@ namespace bx template <uint16_t MaxHandlesT> inline uint16_t HandleListT<MaxHandlesT>::getPrev(uint16_t _handle) const { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + BX_ASSERT(isValid(_handle), "Invalid handle %d!", _handle); const Link& curr = m_links[_handle]; return curr.m_prev; } @@ -202,7 +202,7 @@ namespace bx template <uint16_t MaxHandlesT> inline void HandleListT<MaxHandlesT>::remove(uint16_t _handle) { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + BX_ASSERT(isValid(_handle), "Invalid handle %d!", _handle); Link& curr = m_links[_handle]; if (kInvalidHandle != curr.m_prev) @@ -358,7 +358,7 @@ namespace bx template <uint16_t MaxHandlesT> inline void HandleAllocLruT<MaxHandlesT>::free(uint16_t _handle) { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + BX_ASSERT(isValid(_handle), "Invalid handle %d!", _handle); m_list.remove(_handle); m_alloc.free(_handle); } @@ -366,7 +366,7 @@ namespace bx template <uint16_t MaxHandlesT> inline void HandleAllocLruT<MaxHandlesT>::touch(uint16_t _handle) { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + BX_ASSERT(isValid(_handle), "Invalid handle %d!", _handle); m_list.remove(_handle); m_list.pushFront(_handle); } diff --git a/3rdparty/bx/include/bx/inline/hash.inl b/3rdparty/bx/include/bx/inline/hash.inl index 56430e1470b..6b2ebcc8de0 100644 --- a/3rdparty/bx/include/bx/inline/hash.inl +++ b/3rdparty/bx/include/bx/inline/hash.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/math.inl b/3rdparty/bx/include/bx/inline/math.inl index 6f946e1f82a..1da6b2d2c32 100644 --- a/3rdparty/bx/include/bx/inline/math.inl +++ b/3rdparty/bx/include/bx/inline/math.inl @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -124,7 +124,11 @@ namespace bx inline BX_CONSTEXPR_FUNC float lerp(float _a, float _b, float _t) { - return _a + (_b - _a) * _t; + // Reference(s): + // - Linear interpolation past, present and future + // https://web.archive.org/web/20200404165201/https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + // + return mad(_t, _b, nms(_t, _a, _a) ); } inline BX_CONSTEXPR_FUNC float invLerp(float _a, float _b, float _value) @@ -277,11 +281,21 @@ namespace bx return _a - trunc(_a); } + inline BX_CONSTEXPR_FUNC float nms(float _a, float _b, float _c) + { + return _c - _a * _b; + } + inline BX_CONSTEXPR_FUNC float mad(float _a, float _b, float _c) { return _a * _b + _c; } + inline BX_CONSTEXPR_FUNC float rcp(float _a) + { + return 1.0f / _a; + } + inline BX_CONST_FUNC float mod(float _a, float _b) { return _a - _b * floor(_a / _b); @@ -330,6 +344,11 @@ namespace bx return square(_a)*(3.0f - 2.0f*_a); } + inline BX_CONST_FUNC float invSmoothStep(float _a) + { + return 0.5f - sin(asin(1.0f - 2.0f * _a) / 3.0f); + } + inline BX_CONSTEXPR_FUNC float bias(float _time, float _bias) { return _time / ( ( (1.0f/_bias - 2.0f)*(1.0f - _time) ) + 1.0f); @@ -483,6 +502,16 @@ namespace bx }; } + inline BX_CONSTEXPR_FUNC Vec3 div(const Vec3 _a, const Vec3 _b) + { + return mul(_a, rcp(_b) ); + } + + inline BX_CONSTEXPR_FUNC Vec3 div(const Vec3 _a, float _b) + { + return mul(_a, rcp(_b) ); + } + inline BX_CONSTEXPR_FUNC Vec3 mad(const Vec3 _a, const float _b, const Vec3 _c) { return add(mul(_a, _b), _c); diff --git a/3rdparty/bx/include/bx/inline/mpscqueue.inl b/3rdparty/bx/include/bx/inline/mpscqueue.inl index fcff39bff86..c05d8eb8c52 100644 --- a/3rdparty/bx/include/bx/inline/mpscqueue.inl +++ b/3rdparty/bx/include/bx/inline/mpscqueue.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/mutex.inl b/3rdparty/bx/include/bx/inline/mutex.inl index 7b1ee37c909..6d06f522707 100644 --- a/3rdparty/bx/include/bx/inline/mutex.inl +++ b/3rdparty/bx/include/bx/inline/mutex.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/os.inl b/3rdparty/bx/include/bx/inline/os.inl new file mode 100644 index 00000000000..3c7eee96a44 --- /dev/null +++ b/3rdparty/bx/include/bx/inline/os.inl @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_H_HEADER_GUARD +# error "Must be included from bx/os.h!" +#endif // BX_H_HEADER_GUARD + +namespace bx +{ + template<typename ProtoT> + inline ProtoT dlsym(void* _handle, const StringView& _symbol) + { + return reinterpret_cast<ProtoT>(dlsym(_handle, _symbol) ); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/inline/pixelformat.inl b/3rdparty/bx/include/bx/inline/pixelformat.inl index 72e2c943c86..7985b32a088 100644 --- a/3rdparty/bx/include/bx/inline/pixelformat.inl +++ b/3rdparty/bx/include/bx/inline/pixelformat.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/readerwriter.inl b/3rdparty/bx/include/bx/inline/readerwriter.inl index 66c8d6d45a7..27f848423bb 100644 --- a/3rdparty/bx/include/bx/inline/readerwriter.inl +++ b/3rdparty/bx/include/bx/inline/readerwriter.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -118,7 +118,7 @@ namespace bx inline int32_t SizerWriter::write(const void* /*_data*/, int32_t _size, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t morecore = int32_t(m_pos - m_top) + _size; @@ -132,7 +132,7 @@ namespace bx m_pos += size; if (size != _size) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "SizerWriter: write truncated."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "SizerWriter: write truncated."); } return size; } @@ -170,7 +170,7 @@ namespace bx inline int32_t MemoryReader::read(void* _data, int32_t _size, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int64_t remainder = m_top-m_pos; int32_t size = uint32_min(_size, uint32_t(min<int64_t>(remainder, INT32_MAX) ) ); @@ -178,7 +178,7 @@ namespace bx m_pos += size; if (size != _size) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "MemoryReader: read truncated."); + BX_ERROR_SET(_err, kErrorReaderWriterRead, "MemoryReader: read truncated."); } return size; } @@ -233,13 +233,13 @@ namespace bx inline int32_t MemoryWriter::write(const void* _data, int32_t _size, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t morecore = int32_t(m_pos - m_size) + _size; if (0 < morecore) { - morecore = BX_ALIGN_MASK(morecore, 0xfff); + morecore = alignUp(morecore, 0x1000); m_data = (uint8_t*)m_memBlock->more(morecore); m_size = m_memBlock->getSize(); } @@ -251,7 +251,7 @@ namespace bx m_top = max(m_top, m_pos); if (size != _size) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "MemoryWriter: write truncated."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "MemoryWriter: write truncated."); } return size; } @@ -422,7 +422,7 @@ namespace bx const int64_t offset = bx::seek(_reader, size); if (offset != aligned) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "Align: read truncated."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "Align: read truncated."); } return int32_t(offset - current); } diff --git a/3rdparty/bx/include/bx/inline/ringbuffer.inl b/3rdparty/bx/include/bx/inline/ringbuffer.inl index d0f0a8b2eda..d4ec68239b8 100644 --- a/3rdparty/bx/include/bx/inline/ringbuffer.inl +++ b/3rdparty/bx/include/bx/inline/ringbuffer.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -161,7 +161,7 @@ namespace bx , m_size(_size) , m_buffer(_buffer) { - BX_CHECK(_control.available() >= _size, "%d >= %d", _control.available(), _size); + BX_ASSERT(_control.available() >= _size, "%d >= %d", _control.available(), _size); } template <typename ControlT> @@ -210,7 +210,7 @@ namespace bx { uint32_t size = m_control.reserve(_size); BX_UNUSED(size); - BX_CHECK(size == _size, "%d == %d", size, _size); + BX_ASSERT(size == _size, "%d == %d", size, _size); m_write = m_control.m_current; m_end = m_write+_size; } diff --git a/3rdparty/bx/include/bx/inline/rng.inl b/3rdparty/bx/include/bx/inline/rng.inl index 4ac29703f0c..0aebbf101c3 100644 --- a/3rdparty/bx/include/bx/inline/rng.inl +++ b/3rdparty/bx/include/bx/inline/rng.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -137,7 +137,7 @@ namespace bx template<typename Rng, typename Ty> inline void shuffle(Rng* _rng, Ty* _array, uint32_t _num) { - BX_CHECK(_num != 0, "Number of elements can't be 0!"); + BX_ASSERT(_num != 0, "Number of elements can't be 0!"); for (uint32_t ii = 0, num = _num-1; ii < num; ++ii) { diff --git a/3rdparty/bx/include/bx/inline/simd128_langext.inl b/3rdparty/bx/include/bx/inline/simd128_langext.inl index 2c58becd247..f007de35cd6 100644 --- a/3rdparty/bx/include/bx/inline/simd128_langext.inl +++ b/3rdparty/bx/include/bx/inline/simd128_langext.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -347,6 +347,14 @@ BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf); } template<> + BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmpneq(simd128_langext_t _a, simd128_langext_t _b) + { + simd128_langext_t result; + result.vi = _a.vf != _b.vf; + return result; + } + + template<> BX_SIMD_FORCE_INLINE simd128_langext_t simd_cmplt(simd128_langext_t _a, simd128_langext_t _b) { simd128_langext_t result; diff --git a/3rdparty/bx/include/bx/inline/simd128_neon.inl b/3rdparty/bx/include/bx/inline/simd128_neon.inl index 1aa40952e31..d71ffb6969e 100644 --- a/3rdparty/bx/include/bx/inline/simd128_neon.inl +++ b/3rdparty/bx/include/bx/inline/simd128_neon.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -9,6 +9,15 @@ namespace bx { + +#if BX_COMPILER_CLANG +# define SHUFFLE_A(_a, _i0, _i1, _i2, _i3) __builtin_shufflevector(_a, _a, _i0, _i1, _i2, _i3 ) +# define SHUFFLE_AB(_a, _b, _i0, _i1, _i2, _i3) __builtin_shufflevector(_a, _b, _i0, _i1, _i2, _i3 ) +#else +# define SHUFFLE_A(_a, _i0, _i1, _i2, _i3) __builtin_shuffle(_a, (uint32x4_t){ _i0, _i1, _i2, _i3 }) +# define SHUFFLE_AB(_a, _b, _i0, _i1, _i2, _i3) __builtin_shuffle(_a, _b, (uint32x4_t){ _i0, _i1, _i2, _i3 }) +#endif + #define ELEMx 0 #define ELEMy 1 #define ELEMz 2 @@ -17,7 +26,7 @@ namespace bx template<> \ BX_SIMD_FORCE_INLINE simd128_neon_t simd_swiz_##_x##_y##_z##_w(simd128_neon_t _a) \ { \ - return __builtin_shuffle(_a, (uint32x4_t){ ELEM##_x, ELEM##_y, ELEM##_z, ELEM##_w }); \ + return SHUFFLE_A(_a, ELEM##_x, ELEM##_y, ELEM##_z, ELEM##_w ); \ } #include "simd128_swizzle.inl" @@ -74,50 +83,52 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_xyAB(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 0, 1, 4, 5 }); + return SHUFFLE_AB(_a, _b, 0, 1, 4, 5 ); } template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_ABxy(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 4, 5, 0, 1 }); + return SHUFFLE_AB(_a, _b, 4, 5, 0, 1 ); } template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_CDzw(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 6, 7, 2, 3 }); + return SHUFFLE_AB(_a, _b, 6, 7, 2, 3 ); } template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_zwCD(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 2, 3, 6, 7 }); + return SHUFFLE_AB(_a, _b, 2, 3, 6, 7 ); } template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_xAyB(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 0, 4, 1, 5 }); + return SHUFFLE_AB(_a, _b, 0, 4, 1, 5 ); } template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_AxBy(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 1, 5, 0, 4 }); + return SHUFFLE_AB(_a, _b, 4, 0, 5, 1 ); } template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_zCwD(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 2, 6, 3, 7 }); + return SHUFFLE_AB(_a, _b, 2, 6, 3, 7 ); } template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_shuf_CzDw(simd128_neon_t _a, simd128_neon_t _b) { - return __builtin_shuffle(_a, _b, (uint32x4_t){ 6, 2, 7, 3 }); + return SHUFFLE_AB(_a, _b, 6, 2, 7, 3 ); } +#undef SHUFFLE_A +#undef SHUFFLE_AB template<> BX_SIMD_FORCE_INLINE float simd_x(simd128_neon_t _a) @@ -273,10 +284,16 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); } template<> + BX_SIMD_FORCE_INLINE simd128_neon_t simd_cmpneq(simd128_neon_t _a, simd128_neon_t _b) + { + return simd_cmpneq_ni(_a, _b); + } + + template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_cmplt(simd128_neon_t _a, simd128_neon_t _b) { - const uint32x4_t tmp = vcltq_f32(_a, _b); - const simd128_neon_t result = vreinterpretq_f32_u32(tmp); + const uint32x4_t tmp = vcltq_f32(_a, _b); + const simd128_neon_t result = vreinterpretq_f32_u32(tmp); return result; } @@ -284,8 +301,8 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_cmple(simd128_neon_t _a, simd128_neon_t _b) { - const uint32x4_t tmp = vcleq_f32(_a, _b); - const simd128_neon_t result = vreinterpretq_f32_u32(tmp); + const uint32x4_t tmp = vcleq_f32(_a, _b); + const simd128_neon_t result = vreinterpretq_f32_u32(tmp); return result; } @@ -293,8 +310,8 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_cmpgt(simd128_neon_t _a, simd128_neon_t _b) { - const uint32x4_t tmp = vcgtq_f32(_a, _b); - const simd128_neon_t result = vreinterpretq_f32_u32(tmp); + const uint32x4_t tmp = vcgtq_f32(_a, _b); + const simd128_neon_t result = vreinterpretq_f32_u32(tmp); return result; } @@ -302,8 +319,8 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_cmpge(simd128_neon_t _a, simd128_neon_t _b) { - const uint32x4_t tmp = vcgeq_f32(_a, _b); - const simd128_neon_t result = vreinterpretq_f32_u32(tmp); + const uint32x4_t tmp = vcgeq_f32(_a, _b); + const simd128_neon_t result = vreinterpretq_f32_u32(tmp); return result; } @@ -367,6 +384,7 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_sll(simd128_neon_t _a, int _count) { +#if !BX_COMPILER_CLANG if (__builtin_constant_p(_count) ) { const uint32x4_t tmp0 = vreinterpretq_u32_f32(_a); @@ -375,7 +393,7 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); return result; } - +#endif const uint32x4_t tmp0 = vreinterpretq_u32_f32(_a); const int32x4_t shift = vdupq_n_s32(_count); const uint32x4_t tmp1 = vshlq_u32(tmp0, shift); @@ -387,6 +405,7 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_srl(simd128_neon_t _a, int _count) { +#if !BX_COMPILER_CLANG if (__builtin_constant_p(_count) ) { const uint32x4_t tmp0 = vreinterpretq_u32_f32(_a); @@ -395,7 +414,7 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); return result; } - +#endif const uint32x4_t tmp0 = vreinterpretq_u32_f32(_a); const int32x4_t shift = vdupq_n_s32(-_count); const uint32x4_t tmp1 = vshlq_u32(tmp0, shift); @@ -407,6 +426,7 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); template<> BX_SIMD_FORCE_INLINE simd128_neon_t simd_sra(simd128_neon_t _a, int _count) { +#if !BX_COMPILER_CLANG if (__builtin_constant_p(_count) ) { const int32x4_t tmp0 = vreinterpretq_s32_f32(_a); @@ -415,7 +435,7 @@ BX_SIMD128_IMPLEMENT_TEST(yzw, yzww); return result; } - +#endif const int32x4_t tmp0 = vreinterpretq_s32_f32(_a); const int32x4_t shift = vdupq_n_s32(-_count); const int32x4_t tmp1 = vshlq_s32(tmp0, shift); diff --git a/3rdparty/bx/include/bx/inline/simd128_ref.inl b/3rdparty/bx/include/bx/inline/simd128_ref.inl index 5cd98c74478..28c525a3168 100644 --- a/3rdparty/bx/include/bx/inline/simd128_ref.inl +++ b/3rdparty/bx/include/bx/inline/simd128_ref.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -59,21 +59,21 @@ namespace bx return (_mask) == (tmp&(_mask) ); \ } -BX_SIMD128_IMPLEMENT_TEST(x , 0x1); -BX_SIMD128_IMPLEMENT_TEST(y , 0x2); -BX_SIMD128_IMPLEMENT_TEST(xy , 0x3); -BX_SIMD128_IMPLEMENT_TEST(z , 0x4); -BX_SIMD128_IMPLEMENT_TEST(xz , 0x5); -BX_SIMD128_IMPLEMENT_TEST(yz , 0x6); -BX_SIMD128_IMPLEMENT_TEST(xyz , 0x7); -BX_SIMD128_IMPLEMENT_TEST(w , 0x8); -BX_SIMD128_IMPLEMENT_TEST(xw , 0x9); -BX_SIMD128_IMPLEMENT_TEST(yw , 0xa); -BX_SIMD128_IMPLEMENT_TEST(xyw , 0xb); -BX_SIMD128_IMPLEMENT_TEST(zw , 0xc); -BX_SIMD128_IMPLEMENT_TEST(xzw , 0xd); -BX_SIMD128_IMPLEMENT_TEST(yzw , 0xe); -BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf); +BX_SIMD128_IMPLEMENT_TEST(x , 0x1) +BX_SIMD128_IMPLEMENT_TEST(y , 0x2) +BX_SIMD128_IMPLEMENT_TEST(xy , 0x3) +BX_SIMD128_IMPLEMENT_TEST(z , 0x4) +BX_SIMD128_IMPLEMENT_TEST(xz , 0x5) +BX_SIMD128_IMPLEMENT_TEST(yz , 0x6) +BX_SIMD128_IMPLEMENT_TEST(xyz , 0x7) +BX_SIMD128_IMPLEMENT_TEST(w , 0x8) +BX_SIMD128_IMPLEMENT_TEST(xw , 0x9) +BX_SIMD128_IMPLEMENT_TEST(yw , 0xa) +BX_SIMD128_IMPLEMENT_TEST(xyw , 0xb) +BX_SIMD128_IMPLEMENT_TEST(zw , 0xc) +BX_SIMD128_IMPLEMENT_TEST(xzw , 0xd) +BX_SIMD128_IMPLEMENT_TEST(yzw , 0xe) +BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf) #undef BX_SIMD128_IMPLEMENT_TEST @@ -397,6 +397,17 @@ BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf); } template<> + BX_SIMD_FORCE_INLINE simd128_ref_t simd_cmpneq(simd128_ref_t _a, simd128_ref_t _b) + { + simd128_ref_t result; + result.ixyzw[0] = _a.fxyzw[0] != _b.fxyzw[0] ? 0xffffffff : 0x0; + result.ixyzw[1] = _a.fxyzw[1] != _b.fxyzw[1] ? 0xffffffff : 0x0; + result.ixyzw[2] = _a.fxyzw[2] != _b.fxyzw[2] ? 0xffffffff : 0x0; + result.ixyzw[3] = _a.fxyzw[3] != _b.fxyzw[3] ? 0xffffffff : 0x0; + return result; + } + + template<> BX_SIMD_FORCE_INLINE simd128_ref_t simd_cmplt(simd128_ref_t _a, simd128_ref_t _b) { simd128_ref_t result; diff --git a/3rdparty/bx/include/bx/inline/simd128_sse.inl b/3rdparty/bx/include/bx/inline/simd128_sse.inl index 213fe174b98..8f6586b71f0 100644 --- a/3rdparty/bx/include/bx/inline/simd128_sse.inl +++ b/3rdparty/bx/include/bx/inline/simd128_sse.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -41,21 +41,21 @@ namespace bx return (_mask) == (_mm_movemask_ps(_test)&(_mask) ); \ } -BX_SIMD128_IMPLEMENT_TEST(x , 0x1); -BX_SIMD128_IMPLEMENT_TEST(y , 0x2); -BX_SIMD128_IMPLEMENT_TEST(xy , 0x3); -BX_SIMD128_IMPLEMENT_TEST(z , 0x4); -BX_SIMD128_IMPLEMENT_TEST(xz , 0x5); -BX_SIMD128_IMPLEMENT_TEST(yz , 0x6); -BX_SIMD128_IMPLEMENT_TEST(xyz , 0x7); -BX_SIMD128_IMPLEMENT_TEST(w , 0x8); -BX_SIMD128_IMPLEMENT_TEST(xw , 0x9); -BX_SIMD128_IMPLEMENT_TEST(yw , 0xa); -BX_SIMD128_IMPLEMENT_TEST(xyw , 0xb); -BX_SIMD128_IMPLEMENT_TEST(zw , 0xc); -BX_SIMD128_IMPLEMENT_TEST(xzw , 0xd); -BX_SIMD128_IMPLEMENT_TEST(yzw , 0xe); -BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf); +BX_SIMD128_IMPLEMENT_TEST(x , 0x1) +BX_SIMD128_IMPLEMENT_TEST(y , 0x2) +BX_SIMD128_IMPLEMENT_TEST(xy , 0x3) +BX_SIMD128_IMPLEMENT_TEST(z , 0x4) +BX_SIMD128_IMPLEMENT_TEST(xz , 0x5) +BX_SIMD128_IMPLEMENT_TEST(yz , 0x6) +BX_SIMD128_IMPLEMENT_TEST(xyz , 0x7) +BX_SIMD128_IMPLEMENT_TEST(w , 0x8) +BX_SIMD128_IMPLEMENT_TEST(xw , 0x9) +BX_SIMD128_IMPLEMENT_TEST(yw , 0xa) +BX_SIMD128_IMPLEMENT_TEST(xyw , 0xb) +BX_SIMD128_IMPLEMENT_TEST(zw , 0xc) +BX_SIMD128_IMPLEMENT_TEST(xzw , 0xd) +BX_SIMD128_IMPLEMENT_TEST(yzw , 0xe) +BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf) #undef BX_SIMD128_IMPLEMENT_TEST @@ -309,6 +309,12 @@ BX_SIMD128_IMPLEMENT_TEST(xyzw , 0xf); } template<> + BX_SIMD_FORCE_INLINE simd128_sse_t simd_cmpneq(simd128_sse_t _a, simd128_sse_t _b) + { + return _mm_cmpneq_ps(_a, _b); + } + + template<> BX_SIMD_FORCE_INLINE simd128_sse_t simd_cmplt(simd128_sse_t _a, simd128_sse_t _b) { return _mm_cmplt_ps(_a, _b); diff --git a/3rdparty/bx/include/bx/inline/simd256_avx.inl b/3rdparty/bx/include/bx/inline/simd256_avx.inl index 221c1d283fc..c29a899d996 100644 --- a/3rdparty/bx/include/bx/inline/simd256_avx.inl +++ b/3rdparty/bx/include/bx/inline/simd256_avx.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/simd256_ref.inl b/3rdparty/bx/include/bx/inline/simd256_ref.inl index cbcdd726e6a..f5202bca42f 100644 --- a/3rdparty/bx/include/bx/inline/simd256_ref.inl +++ b/3rdparty/bx/include/bx/inline/simd256_ref.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/simd_ni.inl b/3rdparty/bx/include/bx/inline/simd_ni.inl index 6b78be8a308..ad648826ddb 100644 --- a/3rdparty/bx/include/bx/inline/simd_ni.inl +++ b/3rdparty/bx/include/bx/inline/simd_ni.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -125,6 +125,15 @@ namespace bx } template<typename Ty> + BX_SIMD_INLINE Ty simd_cmpneq_ni(Ty _a, Ty _b) + { + const Ty tmp0 = simd_cmpeq(_a, _b); + const Ty result = simd_not(tmp0); + + return result; + } + + template<typename Ty> BX_SIMD_INLINE Ty simd_min_ni(Ty _a, Ty _b) { const Ty mask = simd_cmplt(_a, _b); diff --git a/3rdparty/bx/include/bx/inline/sort.inl b/3rdparty/bx/include/bx/inline/sort.inl index 85e7b0a9fd0..928f1cbdcd0 100644 --- a/3rdparty/bx/include/bx/inline/sort.inl +++ b/3rdparty/bx/include/bx/inline/sort.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -9,21 +9,25 @@ namespace bx { -#define BX_RADIXSORT_BITS 11 -#define BX_RADIXSORT_HISTOGRAM_SIZE (1<<BX_RADIXSORT_BITS) -#define BX_RADIXSORT_BIT_MASK (BX_RADIXSORT_HISTOGRAM_SIZE-1) + namespace radix_sort_detail + { + constexpr uint32_t kBits = 11; + constexpr uint32_t kHistogramSize = 1<<kBits; + constexpr uint32_t kBitMask = kHistogramSize-1; + + } // namespace radix_sort_detail inline void radixSort(uint32_t* _keys, uint32_t* _tempKeys, uint32_t _size) { uint32_t* keys = _keys; uint32_t* tempKeys = _tempKeys; - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint32_t histogram[radix_sort_detail::kHistogramSize]; uint16_t shift = 0; uint32_t pass = 0; for (; pass < 3; ++pass) { - memSet(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + memSet(histogram, 0, sizeof(uint32_t)*radix_sort_detail::kHistogramSize); bool sorted = true; { @@ -32,7 +36,7 @@ namespace bx for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) { key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; ++histogram[index]; sorted &= prevKey <= key; } @@ -44,7 +48,7 @@ namespace bx } uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + for (uint32_t ii = 0; ii < radix_sort_detail::kHistogramSize; ++ii) { uint32_t count = histogram[ii]; histogram[ii] = offset; @@ -54,7 +58,7 @@ namespace bx for (uint32_t ii = 0; ii < _size; ++ii) { uint32_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; uint32_t dest = histogram[index]++; tempKeys[dest] = key; } @@ -63,7 +67,7 @@ namespace bx tempKeys = keys; keys = swapKeys; - shift += BX_RADIXSORT_BITS; + shift += radix_sort_detail::kBits; } done: @@ -82,12 +86,12 @@ done: Ty* values = _values; Ty* tempValues = _tempValues; - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint32_t histogram[radix_sort_detail::kHistogramSize]; uint16_t shift = 0; uint32_t pass = 0; for (; pass < 3; ++pass) { - memSet(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + memSet(histogram, 0, sizeof(uint32_t)*radix_sort_detail::kHistogramSize); bool sorted = true; { @@ -96,7 +100,7 @@ done: for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) { key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; ++histogram[index]; sorted &= prevKey <= key; } @@ -108,7 +112,7 @@ done: } uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + for (uint32_t ii = 0; ii < radix_sort_detail::kHistogramSize; ++ii) { uint32_t count = histogram[ii]; histogram[ii] = offset; @@ -118,7 +122,7 @@ done: for (uint32_t ii = 0; ii < _size; ++ii) { uint32_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; uint32_t dest = histogram[index]++; tempKeys[dest] = key; tempValues[dest] = values[ii]; @@ -132,7 +136,7 @@ done: tempValues = values; values = swapValues; - shift += BX_RADIXSORT_BITS; + shift += radix_sort_detail::kBits; } done: @@ -152,12 +156,12 @@ done: uint64_t* keys = _keys; uint64_t* tempKeys = _tempKeys; - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint32_t histogram[radix_sort_detail::kHistogramSize]; uint16_t shift = 0; uint32_t pass = 0; for (; pass < 6; ++pass) { - memSet(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + memSet(histogram, 0, sizeof(uint32_t)*radix_sort_detail::kHistogramSize); bool sorted = true; { @@ -166,7 +170,7 @@ done: for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) { key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; ++histogram[index]; sorted &= prevKey <= key; } @@ -178,7 +182,7 @@ done: } uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + for (uint32_t ii = 0; ii < radix_sort_detail::kHistogramSize; ++ii) { uint32_t count = histogram[ii]; histogram[ii] = offset; @@ -188,7 +192,7 @@ done: for (uint32_t ii = 0; ii < _size; ++ii) { uint64_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; uint32_t dest = histogram[index]++; tempKeys[dest] = key; } @@ -197,7 +201,7 @@ done: tempKeys = keys; keys = swapKeys; - shift += BX_RADIXSORT_BITS; + shift += radix_sort_detail::kBits; } done: @@ -216,12 +220,12 @@ done: Ty* values = _values; Ty* tempValues = _tempValues; - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint32_t histogram[radix_sort_detail::kHistogramSize]; uint16_t shift = 0; uint32_t pass = 0; for (; pass < 6; ++pass) { - memSet(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + memSet(histogram, 0, sizeof(uint32_t)*radix_sort_detail::kHistogramSize); bool sorted = true; { @@ -230,7 +234,7 @@ done: for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) { key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; ++histogram[index]; sorted &= prevKey <= key; } @@ -242,7 +246,7 @@ done: } uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + for (uint32_t ii = 0; ii < radix_sort_detail::kHistogramSize; ++ii) { uint32_t count = histogram[ii]; histogram[ii] = offset; @@ -252,7 +256,7 @@ done: for (uint32_t ii = 0; ii < _size; ++ii) { uint64_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint16_t index = (key>>shift)&radix_sort_detail::kBitMask; uint32_t dest = histogram[index]++; tempKeys[dest] = key; tempValues[dest] = values[ii]; @@ -266,7 +270,7 @@ done: tempValues = values; values = swapValues; - shift += BX_RADIXSORT_BITS; + shift += radix_sort_detail::kBits; } done: @@ -281,8 +285,4 @@ done: } } -#undef BX_RADIXSORT_BITS -#undef BX_RADIXSORT_HISTOGRAM_SIZE -#undef BX_RADIXSORT_BIT_MASK - } // namespace bx diff --git a/3rdparty/bx/include/bx/inline/spscqueue.inl b/3rdparty/bx/include/bx/inline/spscqueue.inl index 94c05d81712..80d316e62a3 100644 --- a/3rdparty/bx/include/bx/inline/spscqueue.inl +++ b/3rdparty/bx/include/bx/inline/spscqueue.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/inline/string.inl b/3rdparty/bx/include/bx/inline/string.inl index 61c49339cd8..1aa830f2f74 100644 --- a/3rdparty/bx/include/bx/inline/string.inl +++ b/3rdparty/bx/include/bx/inline/string.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -226,6 +226,12 @@ namespace bx } template<bx::AllocatorI** AllocatorT> + inline void StringT<AllocatorT>::append(const char* _ptr, const char* _term) + { + append(StringView(_ptr, _term) ); + } + + template<bx::AllocatorI** AllocatorT> inline void StringT<AllocatorT>::clear() { if (0 != m_len) @@ -236,6 +242,12 @@ namespace bx } } + template<bx::AllocatorI** AllocatorT> + inline const char* StringT<AllocatorT>::getCPtr() const + { + return getPtr(); + } + inline StringView strSubstr(const StringView& _str, int32_t _start, int32_t _len) { return StringView(_str, _start, _len); @@ -264,7 +276,7 @@ namespace bx StringView line(curr.getPtr(), m_curr.getPtr() ); - return strRTrim(line, "\n\r"); + return strRTrim(strRTrim(line, "\n"), "\r"); } return m_curr; diff --git a/3rdparty/bx/include/bx/inline/uint32_t.inl b/3rdparty/bx/include/bx/inline/uint32_t.inl index 8fc1af6199b..c2965c53bc2 100644 --- a/3rdparty/bx/include/bx/inline/uint32_t.inl +++ b/3rdparty/bx/include/bx/inline/uint32_t.inl @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -687,6 +687,72 @@ namespace bx return result; } + template <typename Ty> + inline bool isAligned(Ty _a, int32_t _align) + { + const Ty mask = Ty(_align - 1); + return 0 == (_a & mask); + } + + template <typename Ty> + inline bool isAligned(const Ty* _ptr, int32_t _align) + { + union { const void* ptr; uintptr_t addr; } un = { _ptr }; + return isAligned(un.addr, _align); + } + + template <typename Ty> + inline bool isAligned(Ty* _ptr, int32_t _align) + { + return isAligned( (const void*)_ptr, _align); + } + + template <typename Ty> + inline Ty alignDown(Ty _a, int32_t _align) + { + const Ty mask = Ty(_align - 1); + return Ty(_a & ~mask); + } + + template <typename Ty> + inline Ty* alignDown(Ty* _ptr, int32_t _align) + { + union { Ty* ptr; uintptr_t addr; } un = { _ptr }; + un.addr = alignDown(un.addr, _align); + return un.ptr; + } + + template <typename Ty> + inline const Ty* alignDown(const Ty* _ptr, int32_t _align) + { + union { const Ty* ptr; uintptr_t addr; } un = { _ptr }; + un.addr = alignDown(un.addr, _align); + return un.ptr; + } + + template <typename Ty> + inline Ty alignUp(Ty _a, int32_t _align) + { + const Ty mask = Ty(_align - 1); + return Ty( (_a + mask) & ~mask); + } + + template <typename Ty> + inline Ty* alignUp(Ty* _ptr, int32_t _align) + { + union { Ty* ptr; uintptr_t addr; } un = { _ptr }; + un.addr = alignUp(un.addr, _align); + return un.ptr; + } + + template <typename Ty> + inline const Ty* alignUp(const Ty* _ptr, int32_t _align) + { + union { const Ty* ptr; uintptr_t addr; } un = { _ptr }; + un.addr = alignUp(un.addr, _align); + return un.ptr; + } + inline BX_CONST_FUNC uint16_t halfFromFloat(float _a) { union { uint32_t ui; float flt; } ftou; diff --git a/3rdparty/bx/include/bx/macros.h b/3rdparty/bx/include/bx/macros.h index 2f92c1ff424..0d13cc96948 100644 --- a/3rdparty/bx/include/bx/macros.h +++ b/3rdparty/bx/include/bx/macros.h @@ -1,13 +1,15 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ +#ifndef BX_H_HEADER_GUARD +# error "Do not include macros.h directly #include <bx/bx.h> instead." +#endif // BX_H_HEADER_GUARD + #ifndef BX_MACROS_H_HEADER_GUARD #define BX_MACROS_H_HEADER_GUARD -#include "bx.h" - /// #if BX_COMPILER_MSVC // Workaround MSVS bug... @@ -41,12 +43,6 @@ #define BX_FILE_LINE_LITERAL "" __FILE__ "(" BX_STRINGIZE(__LINE__) "): " /// -#define BX_ALIGN_MASK(_value, _mask) ( ( (_value)+(_mask) ) & ( (~0)&(~(_mask) ) ) ) -#define BX_ALIGN_16(_value) BX_ALIGN_MASK(_value, 0xf) -#define BX_ALIGN_256(_value) BX_ALIGN_MASK(_value, 0xff) -#define BX_ALIGN_4096(_value) BX_ALIGN_MASK(_value, 0xfff) - -/// #define BX_ALIGNOF(_type) __alignof(_type) #if defined(__has_feature) @@ -81,11 +77,9 @@ # define BX_NO_VTABLE # define BX_PRINTF_ARGS(_format, _args) __attribute__( (format(__printf__, _format, _args) ) ) -# if BX_CLANG_HAS_FEATURE(cxx_thread_local) -# define BX_THREAD_LOCAL __thread -# endif // BX_COMPILER_CLANG - -# if (!BX_PLATFORM_OSX && (BX_COMPILER_GCC >= 40200)) || (BX_COMPILER_GCC >= 40500) +# if BX_CLANG_HAS_FEATURE(cxx_thread_local) \ + || (!BX_PLATFORM_OSX && (BX_COMPILER_GCC >= 40200) ) \ + || (BX_COMPILER_GCC >= 40500) # define BX_THREAD_LOCAL __thread # endif // BX_COMPILER_GCC @@ -234,9 +228,9 @@ # define BX_CLASS(_class, ...) BX_MACRO_DISPATCHER(BX_CLASS_, __VA_ARGS__)(_class, __VA_ARGS__) #endif // BX_COMPILER_MSVC -#ifndef BX_CHECK -# define BX_CHECK(_condition, ...) BX_NOOP() -#endif // BX_CHECK +#ifndef BX_ASSERT +# define BX_ASSERT(_condition, ...) BX_NOOP() +#endif // BX_ASSERT #ifndef BX_TRACE # define BX_TRACE(...) BX_NOOP() @@ -244,7 +238,7 @@ #ifndef BX_WARN # define BX_WARN(_condition, ...) BX_NOOP() -#endif // BX_CHECK +#endif // BX_ASSERT // static_assert sometimes causes unused-local-typedef... BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunused-local-typedef") diff --git a/3rdparty/bx/include/bx/maputil.h b/3rdparty/bx/include/bx/maputil.h index fcdc4b58d97..9b61d49cd8f 100644 --- a/3rdparty/bx/include/bx/maputil.h +++ b/3rdparty/bx/include/bx/maputil.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/math.h b/3rdparty/bx/include/bx/math.h index ebd06625102..bd05e84d7ac 100644 --- a/3rdparty/bx/include/bx/math.h +++ b/3rdparty/bx/include/bx/math.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -249,10 +249,17 @@ namespace bx /// BX_CONSTEXPR_FUNC float fract(float _a); + /// Returns result of negated multiply-sub operation -(_a * _b - _c). + /// + BX_CONSTEXPR_FUNC float nms(float _a, float _b, float _c); + /// Returns result of multipla and add (_a * _b + _c). /// BX_CONSTEXPR_FUNC float mad(float _a, float _b, float _c); + /// Returns reciprocal of _a. + BX_CONSTEXPR_FUNC float rcp(float _a); + /// Returns the floating-point remainder of the division operation _a/_b. /// BX_CONST_FUNC float mod(float _a, float _b); @@ -276,6 +283,9 @@ namespace bx BX_CONSTEXPR_FUNC float smoothStep(float _a); /// + BX_CONST_FUNC float invSmoothStep(float _a); + + /// BX_CONSTEXPR_FUNC float bias(float _time, float _bias); /// @@ -324,6 +334,12 @@ namespace bx BX_CONSTEXPR_FUNC Vec3 mul(const Vec3 _a, float _b); /// + BX_CONSTEXPR_FUNC Vec3 div(const Vec3 _a, const Vec3 _b); + + /// + BX_CONSTEXPR_FUNC Vec3 div(const Vec3 _a, float _b); + + /// BX_CONSTEXPR_FUNC Vec3 mad(const Vec3 _a, const float _b, const Vec3 _c); /// @@ -359,7 +375,7 @@ namespace bx /// BX_CONSTEXPR_FUNC Vec3 max(const Vec3 _a, const Vec3 _b); - /// + /// Returns component wise reciprocal of _a. BX_CONSTEXPR_FUNC Vec3 rcp(const Vec3 _a); /// diff --git a/3rdparty/bx/include/bx/mpscqueue.h b/3rdparty/bx/include/bx/mpscqueue.h index bbc80049872..f738c22dbef 100644 --- a/3rdparty/bx/include/bx/mpscqueue.h +++ b/3rdparty/bx/include/bx/mpscqueue.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/mutex.h b/3rdparty/bx/include/bx/mutex.h index 8f8ec18de08..ef9337bdc99 100644 --- a/3rdparty/bx/include/bx/mutex.h +++ b/3rdparty/bx/include/bx/mutex.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/os.h b/3rdparty/bx/include/bx/os.h index 2a8cb0d6883..f2102810b14 100644 --- a/3rdparty/bx/include/bx/os.h +++ b/3rdparty/bx/include/bx/os.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -41,6 +41,10 @@ namespace bx void* dlsym(void* _handle, const StringView& _symbol); /// + template<typename ProtoT> + ProtoT dlsym(void* _handle, const StringView& _symbol); + + /// bool getEnv(char* _out, uint32_t* _inOutSize, const StringView& _name); /// @@ -54,4 +58,6 @@ namespace bx } // namespace bx +#include "inline/os.inl" + #endif // BX_OS_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/pixelformat.h b/3rdparty/bx/include/bx/pixelformat.h index 03c5f62415b..3895e85b31e 100644 --- a/3rdparty/bx/include/bx/pixelformat.h +++ b/3rdparty/bx/include/bx/pixelformat.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/platform.h b/3rdparty/bx/include/bx/platform.h index d4445d3a3b9..eea5fcb04e2 100644 --- a/3rdparty/bx/include/bx/platform.h +++ b/3rdparty/bx/include/bx/platform.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -57,7 +57,6 @@ #define BX_PLATFORM_OSX 0 #define BX_PLATFORM_PS4 0 #define BX_PLATFORM_RPI 0 -#define BX_PLATFORM_STEAMLINK 0 #define BX_PLATFORM_WINDOWS 0 #define BX_PLATFORM_WINRT 0 #define BX_PLATFORM_XBOXONE 0 @@ -135,18 +134,18 @@ #endif // #if BX_CPU_PPC -// _LITTLE_ENDIAN exists on ppc64le. -# if _LITTLE_ENDIAN -# undef BX_CPU_ENDIAN_LITTLE -# define BX_CPU_ENDIAN_LITTLE 1 -# else +// __BIG_ENDIAN__ is gcc predefined macro +# if defined(__BIG_ENDIAN__) # undef BX_CPU_ENDIAN_BIG # define BX_CPU_ENDIAN_BIG 1 +# else +# undef BX_CPU_ENDIAN_LITTLE +# define BX_CPU_ENDIAN_LITTLE 1 # endif #else # undef BX_CPU_ENDIAN_LITTLE # define BX_CPU_ENDIAN_LITTLE 1 -#endif // BX_PLATFORM_ +#endif // BX_CPU_PPC // http://sourceforge.net/apps/mediawiki/predef/index.php?title=Operating_Systems #if defined(_DURANGO) || defined(_XBOX_ONE) @@ -184,10 +183,6 @@ # include <sys/cdefs.h> // Defines __BIONIC__ and includes android/api-level.h # undef BX_PLATFORM_ANDROID # define BX_PLATFORM_ANDROID __ANDROID_API__ -#elif defined(__STEAMLINK__) -// SteamLink compiler defines __linux__ -# undef BX_PLATFORM_STEAMLINK -# define BX_PLATFORM_STEAMLINK 1 #elif defined(__VCCOREVER__) // RaspberryPi compiler defines __linux__ # undef BX_PLATFORM_RPI @@ -274,7 +269,6 @@ || BX_PLATFORM_OSX \ || BX_PLATFORM_PS4 \ || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK \ ) /// @@ -290,7 +284,6 @@ || BX_PLATFORM_OSX \ || BX_PLATFORM_PS4 \ || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK \ || BX_PLATFORM_WINDOWS \ || BX_PLATFORM_WINRT \ || BX_PLATFORM_XBOXONE \ @@ -317,7 +310,6 @@ /// #define BX_PLATFORM_OS_EMBEDDED (0 \ || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK \ ) /// @@ -390,8 +382,6 @@ # define BX_PLATFORM_NAME "PlayStation 4" #elif BX_PLATFORM_RPI # define BX_PLATFORM_NAME "RaspberryPi" -#elif BX_PLATFORM_STEAMLINK -# define BX_PLATFORM_NAME "SteamLink" #elif BX_PLATFORM_WINDOWS # define BX_PLATFORM_NAME "Windows" #elif BX_PLATFORM_WINRT diff --git a/3rdparty/bx/include/bx/process.h b/3rdparty/bx/include/bx/process.h index 222b8ed79a8..9c5ee0403a2 100644 --- a/3rdparty/bx/include/bx/process.h +++ b/3rdparty/bx/include/bx/process.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/readerwriter.h b/3rdparty/bx/include/bx/readerwriter.h index ed61f46aa82..45265b2c112 100644 --- a/3rdparty/bx/include/bx/readerwriter.h +++ b/3rdparty/bx/include/bx/readerwriter.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -14,21 +14,21 @@ #include "string.h" #include "uint32_t.h" -BX_ERROR_RESULT(BX_ERROR_READERWRITER_OPEN, BX_MAKEFOURCC('R', 'W', 0, 1) ); -BX_ERROR_RESULT(BX_ERROR_READERWRITER_READ, BX_MAKEFOURCC('R', 'W', 0, 2) ); -BX_ERROR_RESULT(BX_ERROR_READERWRITER_WRITE, BX_MAKEFOURCC('R', 'W', 0, 3) ); -BX_ERROR_RESULT(BX_ERROR_READERWRITER_EOF, BX_MAKEFOURCC('R', 'W', 0, 4) ); -BX_ERROR_RESULT(BX_ERROR_READERWRITER_ALREADY_OPEN, BX_MAKEFOURCC('R', 'W', 0, 5) ); - namespace bx { + BX_ERROR_RESULT(kErrorReaderWriterOpen, BX_MAKEFOURCC('b', 'x', 2, 1) ); + BX_ERROR_RESULT(kErrorReaderWriterRead, BX_MAKEFOURCC('b', 'x', 2, 2) ); + BX_ERROR_RESULT(kErrorReaderWriterWrite, BX_MAKEFOURCC('b', 'x', 2, 3) ); + BX_ERROR_RESULT(kErrorReaderWriterEof, BX_MAKEFOURCC('b', 'x', 2, 4) ); + BX_ERROR_RESULT(kErrorReaderWriterAlreadyOpen, BX_MAKEFOURCC('b', 'x', 2, 5) ); + /// The position from where offset is added. struct Whence { /// Whence values: enum Enum { - Begin, //!< From begining of file. + Begin, //!< From beginning of file. Current, //!< From current position of file. End, //!< From end of file. }; @@ -285,13 +285,13 @@ namespace bx /// Write string view. int32_t write(WriterI* _writer, const StringView& _str, Error* _err = NULL); - /// Write formated string. + /// Write formatted string. int32_t write(WriterI* _writer, const StringView& _format, va_list _argList, Error* _err); - /// Write formated string. + /// Write formatted string. int32_t write(WriterI* _writer, Error* _err, const StringView* _format, ...); - /// Write formated string. + /// Write formatted string. int32_t write(WriterI* _writer, Error* _err, const char* _format, ...); /// Write repeat the same value. @@ -337,7 +337,7 @@ namespace bx /// Open for read. bool open(ReaderOpenI* _reader, const FilePath& _filePath, Error* _err = NULL); - /// Open fro write. + /// Open for write. bool open(WriterOpenI* _writer, const FilePath& _filePath, bool _append = false, Error* _err = NULL); /// Open process. diff --git a/3rdparty/bx/include/bx/ringbuffer.h b/3rdparty/bx/include/bx/ringbuffer.h index 2a93b985b4a..112c7c13ba7 100644 --- a/3rdparty/bx/include/bx/ringbuffer.h +++ b/3rdparty/bx/include/bx/ringbuffer.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/rng.h b/3rdparty/bx/include/bx/rng.h index 5469b5efd9c..b8b4a457edc 100644 --- a/3rdparty/bx/include/bx/rng.h +++ b/3rdparty/bx/include/bx/rng.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/semaphore.h b/3rdparty/bx/include/bx/semaphore.h index e3bd3899305..3e0fa49f918 100644 --- a/3rdparty/bx/include/bx/semaphore.h +++ b/3rdparty/bx/include/bx/semaphore.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/settings.h b/3rdparty/bx/include/bx/settings.h index 7dd45e626fb..e5dbc8ac68d 100644 --- a/3rdparty/bx/include/bx/settings.h +++ b/3rdparty/bx/include/bx/settings.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/simd_t.h b/3rdparty/bx/include/bx/simd_t.h index 0c41844655b..c804c990118 100644 --- a/3rdparty/bx/include/bx/simd_t.h +++ b/3rdparty/bx/include/bx/simd_t.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -32,7 +32,7 @@ # include <xmmintrin.h> // __m128 # undef BX_SIMD_SSE # define BX_SIMD_SSE 1 -#elif defined(__ARM_NEON__) && !BX_COMPILER_CLANG +#elif defined(__ARM_NEON__) && (!BX_COMPILER_CLANG || BX_CLANG_HAS_EXTENSION(attribute_ext_vector_type) ) # include <arm_neon.h> # undef BX_SIMD_NEON # define BX_SIMD_NEON 1 @@ -197,6 +197,9 @@ BX_SIMD128_IMPLEMENT_TEST(xyzw); Ty simd_cmpeq(Ty _a, Ty _b); template<typename Ty> + Ty simd_cmpneq(Ty _a, Ty _b); + + template<typename Ty> Ty simd_cmplt(Ty _a, Ty _b); template<typename Ty> @@ -371,6 +374,9 @@ BX_SIMD128_IMPLEMENT_TEST(xyzw); Ty simd_not_ni(Ty _a); template<typename Ty> + Ty simd_cmpneq_ni(Ty _a, Ty _b); + + template<typename Ty> Ty simd_min_ni(Ty _a, Ty _b); template<typename Ty> diff --git a/3rdparty/bx/include/bx/sort.h b/3rdparty/bx/include/bx/sort.h index b32febd90ff..bd4c2b17d80 100644 --- a/3rdparty/bx/include/bx/sort.h +++ b/3rdparty/bx/include/bx/sort.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/spscqueue.h b/3rdparty/bx/include/bx/spscqueue.h index 7ea7c448750..e4381b0443c 100644 --- a/3rdparty/bx/include/bx/spscqueue.h +++ b/3rdparty/bx/include/bx/spscqueue.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/string.h b/3rdparty/bx/include/bx/string.h index 43798a4f549..7b27cc3a103 100644 --- a/3rdparty/bx/include/bx/string.h +++ b/3rdparty/bx/include/bx/string.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -129,7 +129,14 @@ namespace bx void append(const StringView& _str); /// + void append(const char* _ptr, const char* _term); + + /// void clear(); + + /// Returns zero-terminated C string pointer. + /// + const char* getCPtr() const; }; /// Retruns true if character is part of space set. @@ -244,9 +251,15 @@ namespace bx /// Returns string view with characters _chars trimmed from right. StringView strRTrim(const StringView& _str, const StringView& _chars); + /// Returns string view with whitespace characters trimmed from right. + StringView strRTrimSpace(const StringView& _str); + /// Returns string view with characters _chars trimmed from left and right. StringView strTrim(const StringView& _str, const StringView& _chars); + /// Returns string view with whitespace characters trimmed from left and right. + StringView strTrimSpace(const StringView& _str); + /// Find new line. Returns pointer after new line terminator. StringView strFindNl(const StringView& _str); diff --git a/3rdparty/bx/include/bx/thread.h b/3rdparty/bx/include/bx/thread.h index 2526741ce08..10d11cbfd1f 100644 --- a/3rdparty/bx/include/bx/thread.h +++ b/3rdparty/bx/include/bx/thread.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -9,6 +9,8 @@ #include "allocator.h" #include "mpscqueue.h" +#if BX_CONFIG_SUPPORTS_THREADING + namespace bx { /// @@ -29,8 +31,16 @@ namespace bx /// virtual ~Thread(); + /// Create and initialize thread. + /// + /// @param[in] _fn Thread function. + /// @param[in] _userData User data passed to thread function. + /// @param[in] _stackSize Stack size, if zero is passed it will use OS default thread stack + /// size. + /// @param[in] _name Thread name used by debugger. + /// @returns True if thread is created, otherwise returns false. /// - void init(ThreadFn _fn, void* _userData = NULL, uint32_t _stackSize = 0, const char* _name = NULL); + bool init(ThreadFn _fn, void* _userData = NULL, uint32_t _stackSize = 0, const char* _name = NULL); /// void shutdown(); @@ -87,4 +97,6 @@ namespace bx } // namespace bx +#endif + #endif // BX_THREAD_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/timer.h b/3rdparty/bx/include/bx/timer.h index bbe5e084d4f..3ff8ed5e747 100644 --- a/3rdparty/bx/include/bx/timer.h +++ b/3rdparty/bx/include/bx/timer.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/include/bx/uint32_t.h b/3rdparty/bx/include/bx/uint32_t.h index 3eb8bdfd3c8..6053cdfdab6 100644 --- a/3rdparty/bx/include/bx/uint32_t.h +++ b/3rdparty/bx/include/bx/uint32_t.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -251,6 +251,42 @@ namespace bx template<uint32_t Min> BX_CONSTEXPR_FUNC uint32_t strideAlign(uint32_t _offset, uint32_t _stride); + /// + template <typename Ty> + bool isAligned(Ty _a, int32_t _align); + + /// + template <typename Ty> + bool isAligned(void* _ptr, int32_t _align); + + /// + template <typename Ty> + bool isAligned(const void* _ptr, int32_t _align); + + /// + template <typename Ty> + Ty alignDown(Ty _a, int32_t _align); + + /// + template <typename Ty> + Ty* alignDown(Ty* _ptr, int32_t _align); + + /// + template <typename Ty> + const Ty* alignDown(const Ty* _ptr, int32_t _align); + + /// + template <typename Ty> + Ty alignUp(Ty _a, int32_t _align); + + /// + template <typename Ty> + Ty* alignUp(Ty* _ptr, int32_t _align); + + /// + template <typename Ty> + const Ty* alignUp(const Ty* _ptr, int32_t _align); + /// Convert float to half-float. /// BX_CONST_FUNC uint16_t halfFromFloat(float _a); diff --git a/3rdparty/bx/include/bx/url.h b/3rdparty/bx/include/bx/url.h index 320db14e398..769b3c8db84 100644 --- a/3rdparty/bx/include/bx/url.h +++ b/3rdparty/bx/include/bx/url.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/makefile b/3rdparty/bx/makefile index 985c94b83f4..43675305b7f 100644 --- a/3rdparty/bx/makefile +++ b/3rdparty/bx/makefile @@ -1,24 +1,25 @@ # -# Copyright 2011-2019 Branimir Karadzic. All rights reserved. +# Copyright 2011-2021 Branimir Karadzic. All rights reserved. # License: https://github.com/bkaradzic/bx#license-bsd-2-clause # GENIE=../bx/tools/bin/$(OS)/genie all: - $(GENIE) vs2017 - $(GENIE) --gcc=android-arm gmake - $(GENIE) --gcc=android-arm64 gmake - $(GENIE) --gcc=android-mips gmake - $(GENIE) --gcc=android-x86 gmake - $(GENIE) --gcc=mingw-gcc gmake - $(GENIE) --gcc=linux-gcc gmake - $(GENIE) --gcc=haiku gmake - $(GENIE) --gcc=osx gmake - $(GENIE) --gcc=ios-arm gmake - $(GENIE) --gcc=ios-simulator gmake + $(GENIE) vs2017 + $(GENIE) vs2019 + $(GENIE) --gcc=android-arm gmake + $(GENIE) --gcc=android-arm64 gmake + $(GENIE) --gcc=android-x86 gmake + $(GENIE) --gcc=mingw-gcc gmake + $(GENIE) --gcc=linux-gcc gmake + $(GENIE) --gcc=haiku gmake + $(GENIE) --gcc=osx-x64 gmake + $(GENIE) --gcc=osx-arm64 gmake + $(GENIE) --gcc=ios-arm gmake + $(GENIE) --gcc=ios-simulator gmake $(GENIE) --gcc=ios-simulator64 gmake - $(GENIE) xcode8 + $(GENIE) xcode8 .build/projects/gmake-android-arm: $(GENIE) --gcc=android-arm gmake @@ -36,14 +37,6 @@ android-arm64-release: .build/projects/gmake-android-arm64 make -R -C .build/projects/gmake-android-arm64 config=release android-arm64: android-arm64-debug android-arm64-release -.build/projects/gmake-android-mips: - $(GENIE) --gcc=android-mips gmake -android-mips-debug: .build/projects/gmake-android-mips - make -R -C .build/projects/gmake-android-mips config=debug -android-mips-release: .build/projects/gmake-android-mips - make -R -C .build/projects/gmake-android-mips config=release -android-mips: android-mips-debug android-mips-release - .build/projects/gmake-android-x86: $(GENIE) --gcc=android-x86 gmake android-x86-debug: .build/projects/gmake-android-x86 @@ -95,13 +88,13 @@ mingw-clang: mingw-clang-debug32 mingw-clang-release32 mingw-clang-debug64 mingw .build/projects/vs2017: $(GENIE) vs2017 -.build/projects/gmake-osx: - $(GENIE) --gcc=osx gmake -osx-debug64: .build/projects/gmake-osx - make -C .build/projects/gmake-osx config=debug64 -osx-release64: .build/projects/gmake-osx - make -C .build/projects/gmake-osx config=release64 -osx: osx-debug64 osx-release64 +.build/projects/gmake-osx-x64: + $(GENIE) --gcc=osx-x64 gmake +osx-x64-debug: .build/projects/gmake-osx-x64 + make -C .build/projects/gmake-osx config=debug +osx-x64-release: .build/projects/gmake-osx-x64 + make -C .build/projects/gmake-osx config=release +osx-x64: osx-x64-debug osx-x64-release .build/projects/gmake-ios-arm: $(GENIE) --gcc=ios-arm gmake @@ -152,9 +145,9 @@ ifeq ($(UNAME),$(filter $(UNAME),Linux GNU Darwin Haiku)) ifeq ($(UNAME),$(filter $(UNAME),Darwin Haiku)) ifeq ($(UNAME),$(filter $(UNAME),Darwin)) OS=darwin -BUILD_PROJECT_DIR=gmake-osx -BUILD_OUTPUT_DIR=osx64_clang -BUILD_TOOLS_CONFIG=release64 +BUILD_PROJECT_DIR=gmake-osx-x64 +BUILD_OUTPUT_DIR=osx-x64 +BUILD_TOOLS_CONFIG=release EXE= else OS=haiku @@ -179,10 +172,10 @@ EXE=.exe endif # bin2c -.build/osx64_clang/bin/bin2cRelease: .build/projects/gmake-osx - $(SILENT) make -C .build/projects/gmake-osx bin2c config=$(BUILD_TOOLS_CONFIG) +.build/osx-x64/bin/bin2cRelease: .build/projects/gmake-osx-x64 + $(SILENT) make -C .build/projects/gmake-osx-x64 bin2c config=$(BUILD_TOOLS_CONFIG) -tools/bin/darwin/bin2c: .build/osx64_clang/bin/bin2cRelease +tools/bin/darwin/bin2c: .build/osx-x64/bin/bin2cRelease $(SILENT) cp $(<) $(@) .build/linux64_gcc/bin/bin2cRelease: .build/projects/gmake-linux @@ -206,10 +199,10 @@ tools/bin/windows/bin2c.exe: .build/win64_mingw-gcc/bin/bin2cRelease.exe bin2c: tools/bin/$(OS)/bin2c$(EXE) # lemon -.build/osx64_clang/bin/lemonRelease: .build/projects/gmake-osx - $(SILENT) make -C .build/projects/gmake-osx lemon config=$(BUILD_TOOLS_CONFIG) +.build/osx-x64/bin/lemonRelease: .build/projects/gmake-osx-x64 + $(SILENT) make -C .build/projects/gmake-osx-x64 lemon config=$(BUILD_TOOLS_CONFIG) -tools/bin/darwin/lemon: .build/osx64_clang/bin/lemonRelease +tools/bin/darwin/lemon: .build/osx-x64/bin/lemonRelease $(SILENT) cp $(<) $(@) .build/linux64_gcc/bin/lemonRelease: .build/projects/gmake-linux diff --git a/3rdparty/bx/scripts/bin2c.lua b/3rdparty/bx/scripts/bin2c.lua index f81031879ca..3ebc0014629 100644 --- a/3rdparty/bx/scripts/bin2c.lua +++ b/3rdparty/bx/scripts/bin2c.lua @@ -1,5 +1,5 @@ -- --- Copyright 2010-2019 Branimir Karadzic. All rights reserved. +-- Copyright 2010-2021 Branimir Karadzic. All rights reserved. -- License: https://github.com/bkaradzic/bx#license-bsd-2-clause -- diff --git a/3rdparty/bx/scripts/bx.lua b/3rdparty/bx/scripts/bx.lua index 60f67641362..1e54ac521fc 100644 --- a/3rdparty/bx/scripts/bx.lua +++ b/3rdparty/bx/scripts/bx.lua @@ -1,8 +1,20 @@ -- --- Copyright 2010-2019 Branimir Karadzic. All rights reserved. +-- Copyright 2010-2021 Branimir Karadzic. All rights reserved. -- License: https://github.com/bkaradzic/bx#license-bsd-2-clause -- +local function userdefines() + local defines = {} + local BX_CONFIG = os.getenv("BX_CONFIG") + if BX_CONFIG then + for def in BX_CONFIG:gmatch "[^%s:]+" do + table.insert(defines, "BX_CONFIG_" .. def) + end + end + + return defines +end + project "bx" kind "StaticLib" @@ -18,6 +30,8 @@ project "bx" path.join(BX_DIR, "scripts/**.natvis"), } + defines (userdefines()) + configuration { "Debug" } defines { "BX_CONFIG_DEBUG=1", diff --git a/3rdparty/bx/scripts/genie.lua b/3rdparty/bx/scripts/genie.lua index 600bd7fab9c..8801b224ad2 100644 --- a/3rdparty/bx/scripts/genie.lua +++ b/3rdparty/bx/scripts/genie.lua @@ -1,5 +1,5 @@ -- --- Copyright 2010-2019 Branimir Karadzic. All rights reserved. +-- Copyright 2010-2021 Branimir Karadzic. All rights reserved. -- License: https://github.com/bkaradzic/bx#license-bsd-2-clause -- @@ -81,7 +81,7 @@ project "bx.test" "pthread", } - configuration { "osx" } + configuration { "osx*" } links { "Cocoa.framework", } @@ -126,7 +126,7 @@ project "bx.bench" "pthread", } - configuration { "osx" } + configuration { "osx*" } links { "Cocoa.framework", } diff --git a/3rdparty/bx/scripts/lemon.lua b/3rdparty/bx/scripts/lemon.lua index 2759ea60972..b488896055d 100644 --- a/3rdparty/bx/scripts/lemon.lua +++ b/3rdparty/bx/scripts/lemon.lua @@ -1,5 +1,5 @@ -- --- Copyright 2010-2019 Branimir Karadzic. All rights reserved. +-- Copyright 2010-2021 Branimir Karadzic. All rights reserved. -- License: https://github.com/bkaradzic/bx#license-bsd-2-clause -- diff --git a/3rdparty/bx/scripts/toolchain.lua b/3rdparty/bx/scripts/toolchain.lua index e9b336e6e7d..cb91d3ac750 100644 --- a/3rdparty/bx/scripts/toolchain.lua +++ b/3rdparty/bx/scripts/toolchain.lua @@ -1,5 +1,5 @@ -- --- Copyright 2010-2019 Branimir Karadzic. All rights reserved. +-- Copyright 2010-2021 Branimir Karadzic. All rights reserved. -- License: https://github.com/bkaradzic/bx#license-bsd-2-clause -- @@ -52,7 +52,8 @@ function toolchain(_buildDir, _libDir) { "android-arm", "Android - ARM" }, { "android-arm64", "Android - ARM64" }, { "android-x86", "Android - x86" }, - { "asmjs", "Emscripten/asm.js" }, + { "wasm2js", "Emscripten/Wasm2JS" }, + { "wasm", "Emscripten/Wasm" }, { "freebsd", "FreeBSD" }, { "linux-gcc", "Linux (GCC compiler)" }, { "linux-gcc-afl", "Linux (GCC + AFL fuzzer)" }, @@ -70,11 +71,11 @@ function toolchain(_buildDir, _libDir) { "mingw-gcc", "MinGW" }, { "mingw-clang", "MinGW (clang compiler)" }, { "netbsd", "NetBSD" }, - { "osx", "OSX" }, + { "osx-x64", "OSX - x64" }, + { "osx-arm64", "OSX - ARM64" }, { "orbis", "Orbis" }, { "riscv", "RISC-V" }, { "rpi", "RaspberryPi" }, - { "haiku", "Haiku" }, }, } @@ -251,17 +252,18 @@ function toolchain(_buildDir, _libDir) premake.gcc.llvm = true location (path.join(_buildDir, "projects", _ACTION .. "-android-x86")) - elseif "asmjs" == _OPTIONS["gcc"] then + elseif "wasm2js" == _OPTIONS["gcc"] or "wasm" == _OPTIONS["gcc"] then - if not os.getenv("EMSDK") then - print("Set EMSDK environment variable.") + if not os.getenv("EMSCRIPTEN") then + print("Set EMSCRIPTEN environment variable to root directory of your Emscripten installation. (e.g. by entering the EMSDK command prompt)") end - premake.gcc.cc = "\"$(EMSDK)/fastcomp/bin/emcc\"" - premake.gcc.cxx = "\"$(EMSDK)/fastcomp/bin/em++\"" - premake.gcc.ar = "\"$(EMSDK)/fastcomp/bin/emar\"" + premake.gcc.cc = "\"$(EMSCRIPTEN)/emcc\"" + premake.gcc.cxx = "\"$(EMSCRIPTEN)/em++\"" + premake.gcc.ar = "\"$(EMSCRIPTEN)/emar\"" premake.gcc.llvm = true - location (path.join(_buildDir, "projects", _ACTION .. "-asmjs")) + premake.gcc.namestyle = "Emscripten" + location (path.join(_buildDir, "projects", _ACTION .. "-" .. _OPTIONS["gcc"])) elseif "freebsd" == _OPTIONS["gcc"] then location (path.join(_buildDir, "projects", _ACTION .. "-freebsd")) @@ -330,16 +332,6 @@ function toolchain(_buildDir, _libDir) elseif "linux-arm-gcc" == _OPTIONS["gcc"] then location (path.join(_buildDir, "projects", _ACTION .. "-linux-arm-gcc")) - elseif "linux-steamlink" == _OPTIONS["gcc"] then - if not os.getenv("MARVELL_SDK_PATH") then - print("Set MARVELL_SDK_PATH environment variable.") - end - - premake.gcc.cc = "$(MARVELL_SDK_PATH)/toolchain/bin/armv7a-cros-linux-gnueabi-gcc" - premake.gcc.cxx = "$(MARVELL_SDK_PATH)/toolchain/bin/armv7a-cros-linux-gnueabi-g++" - premake.gcc.ar = "$(MARVELL_SDK_PATH)/toolchain/bin/armv7a-cros-linux-gnueabi-ar" - location (path.join(_buildDir, "projects", _ACTION .. "-linux-steamlink")) - elseif "mingw-gcc" == _OPTIONS["gcc"] then if not os.getenv("MINGW") then print("Set MINGW environment variable.") @@ -370,7 +362,9 @@ function toolchain(_buildDir, _libDir) elseif "netbsd" == _OPTIONS["gcc"] then location (path.join(_buildDir, "projects", _ACTION .. "-netbsd")) - elseif "osx" == _OPTIONS["gcc"] then + elseif "osx-x64" == _OPTIONS["gcc"] + or "osx-arm64" == _OPTIONS["gcc"] then + if os.is("linux") then if not os.getenv("OSXCROSS") then @@ -382,7 +376,8 @@ function toolchain(_buildDir, _libDir) premake.gcc.cxx = "$(OSXCROSS)/target/bin/" .. osxToolchain .. "clang++" premake.gcc.ar = "$(OSXCROSS)/target/bin/" .. osxToolchain .. "ar" end - location (path.join(_buildDir, "projects", _ACTION .. "-osx")) + + location (path.join(_buildDir, "projects", _ACTION .. "-" .. _OPTIONS["gcc"])) elseif "orbis" == _OPTIONS["gcc"] then @@ -471,9 +466,7 @@ function toolchain(_buildDir, _libDir) end - elseif _ACTION == "xcode4" - or _ACTION == "xcode8" - or _ACTION == "xcode9" then + elseif _ACTION and _ACTION:match("^xcode.+$") then local action = premake.action.current() local str_or = function(str, def) return #str > 0 and str or def @@ -556,8 +549,6 @@ function toolchain(_buildDir, _libDir) "WIN32", "_WIN32", "_HAS_EXCEPTIONS=0", - "_HAS_ITERATOR_DEBUGGING=0", - "_ITERATOR_DEBUG_LEVEL=0", "_SCL_SECURE=0", "_SECURE_SCL=0", "_SCL_SECURE_NO_WARNINGS", @@ -857,29 +848,6 @@ function toolchain(_buildDir, _libDir) "-Wl,-z,now", } - configuration { "linux-steamlink" } - targetdir (path.join(_buildDir, "steamlink/bin")) - objdir (path.join(_buildDir, "steamlink/obj")) - libdirs { path.join(_libDir, "lib/steamlink") } - includedirs { path.join(bxDir, "include/compat/linux") } - defines { - "__STEAMLINK__=1", -- There is no special prefedined compiler symbol to detect SteamLink, faking it. - } - buildoptions { - "-Wfatal-errors", - "-Wunused-value", - "-Wundef", - "-pthread", - "-marm", - "-mfloat-abi=hard", - "--sysroot=$(MARVELL_SDK_PATH)/rootfs", - } - linkoptions { - "-static-libgcc", - "-static-libstdc++", - "--sysroot=$(MARVELL_SDK_PATH)/rootfs", - } - configuration { "android-arm" } targetdir (path.join(_buildDir, "android-arm/bin")) objdir (path.join(_buildDir, "android-arm/obj")) @@ -907,7 +875,6 @@ function toolchain(_buildDir, _libDir) path.join("$(ANDROID_NDK_ROOT)/platforms", androidPlatform, "arch-arm/usr/lib/crtend_so.o"), "-target armv7-none-linux-androideabi", "-march=armv7-a", - "-Wl,--fix-cortex-a8", } configuration { "android-arm64" } @@ -934,7 +901,6 @@ function toolchain(_buildDir, _libDir) path.join("$(ANDROID_NDK_ROOT)/platforms", androidPlatform, "arch-arm64/usr/lib/crtend_so.o"), "-target aarch64-none-linux-androideabi", "-march=armv8-a", - "-Wl,--fix-cortex-a8", } configuration { "android-x86" } @@ -966,16 +932,29 @@ function toolchain(_buildDir, _libDir) "-target i686-none-linux-android", } - configuration { "asmjs" } - targetdir (path.join(_buildDir, "asmjs/bin")) - objdir (path.join(_buildDir, "asmjs/obj")) - libdirs { path.join(_libDir, "lib/asmjs") } + configuration { "wasm*" } buildoptions { - "-isystem \"$(EMSDK)/fastcomp/emscripten\"", "-Wunused-value", "-Wundef", } + linkoptions { + "-s MAX_WEBGL_VERSION=2" + } + + configuration { "wasm2js" } + targetdir (path.join(_buildDir, "wasm2js/bin")) + objdir (path.join(_buildDir, "wasm2js/obj")) + libdirs { path.join(_libDir, "lib/wasm2js") } + linkoptions { + "-s WASM=0" + } + + configuration { "wasm" } + targetdir (path.join(_buildDir, "wasm/bin")) + objdir (path.join(_buildDir, "wasm/obj")) + libdirs { path.join(_libDir, "lib/wasm") } + configuration { "freebsd" } targetdir (path.join(_buildDir, "freebsd/bin")) objdir (path.join(_buildDir, "freebsd/obj")) @@ -1011,33 +990,35 @@ function toolchain(_buildDir, _libDir) path.join(bxDir, "include/compat/freebsd"), } - configuration { "osx", "x32" } - targetdir (path.join(_buildDir, "osx32_clang/bin")) - objdir (path.join(_buildDir, "osx32_clang/obj")) - --libdirs { path.join(_libDir, "lib/osx32_clang") } + configuration { "osx-x64" } + targetdir (path.join(_buildDir, "osx-x64/bin")) + objdir (path.join(_buildDir, "osx-x64/obj")) + linkoptions { + "-arch x86_64", + } buildoptions { - "-m32", + "-arch x86_64", + "-msse2", + "-target x86_64-apple-macos" .. (#macosPlatform > 0 and macosPlatform or "10.11"), } - configuration { "osx", "x64" } - targetdir (path.join(_buildDir, "osx64_clang/bin")) - objdir (path.join(_buildDir, "osx64_clang/obj")) - --libdirs { path.join(_libDir, "lib/osx64_clang") } + configuration { "osx-arm64" } + targetdir (path.join(_buildDir, "osx-arm64/bin")) + objdir (path.join(_buildDir, "osx-arm64/obj")) + linkoptions { + "-arch arm64", + } buildoptions { - "-m64", + "-arch arm64", + "-Wno-error=unused-command-line-argument", + "-Wno-unused-command-line-argument", } - configuration { "osx", "Universal" } - targetdir (path.join(_buildDir, "osx_universal/bin")) - objdir (path.join(_buildDir, "osx_universal/bin")) - - configuration { "osx" } + configuration { "osx*" } buildoptions { "-Wfatal-errors", - "-msse2", "-Wunused-value", "-Wundef", - "-target x86_64-apple-macos" .. (#macosPlatform > 0 and macosPlatform or "10.11"), } includedirs { path.join(bxDir, "include/compat/osx") } @@ -1080,14 +1061,14 @@ function toolchain(_buildDir, _libDir) configuration { "ios-arm*" } linkoptions { - "-miphoneos-version-min=7.0", + "-miphoneos-version-min=9.0", "--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" ..iosPlatform .. ".sdk", "-L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" ..iosPlatform .. ".sdk/usr/lib/system", "-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" ..iosPlatform .. ".sdk/System/Library/Frameworks", "-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" ..iosPlatform .. ".sdk/System/Library/PrivateFrameworks", } buildoptions { - "-miphoneos-version-min=7.0", + "-miphoneos-version-min=9.0", "--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" ..iosPlatform .. ".sdk", "-fembed-bitcode", } @@ -1097,7 +1078,7 @@ function toolchain(_buildDir, _libDir) objdir (path.join(_buildDir, "ios-simulator/obj")) libdirs { path.join(_libDir, "lib/ios-simulator") } linkoptions { - "-mios-simulator-version-min=7.0", + "-mios-simulator-version-min=9.0", "-arch i386", "--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk", "-L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk/usr/lib/system", @@ -1105,7 +1086,7 @@ function toolchain(_buildDir, _libDir) "-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk/System/Library/PrivateFrameworks", } buildoptions { - "-mios-simulator-version-min=7.0", + "-mios-simulator-version-min=9.0", "-arch i386", "--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk", } @@ -1115,7 +1096,7 @@ function toolchain(_buildDir, _libDir) objdir (path.join(_buildDir, "ios-simulator64/obj")) libdirs { path.join(_libDir, "lib/ios-simulator64") } linkoptions { - "-mios-simulator-version-min=7.0", + "-mios-simulator-version-min=9.0", "-arch x86_64", "--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk", "-L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk/usr/lib/system", @@ -1123,7 +1104,7 @@ function toolchain(_buildDir, _libDir) "-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk/System/Library/PrivateFrameworks", } buildoptions { - "-mios-simulator-version-min=7.0", + "-mios-simulator-version-min=9.0", "-arch x86_64", "--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" ..iosPlatform .. ".sdk", } @@ -1259,13 +1240,7 @@ function strip() "$(SILENT) $(ANDROID_NDK_X86)/bin/i686-linux-android-strip -s \"$(TARGET)\"" } - configuration { "linux-steamlink", "Release" } - postbuildcommands { - "$(SILENT) echo Stripping symbols.", - "$(SILENT) $(MARVELL_SDK_PATH)/toolchain/bin/armv7a-cros-linux-gnueabi-strip -s \"$(TARGET)\"" - } - - configuration { "linux-* or rpi", "not linux-steamlink", "Release" } + configuration { "linux-* or rpi", "Release" } postbuildcommands { "$(SILENT) echo Stripping symbols.", "$(SILENT) strip -s \"$(TARGET)\"" @@ -1277,24 +1252,6 @@ function strip() "$(SILENT) $(MINGW)/bin/strip -s \"$(TARGET)\"" } - configuration { "asmjs" } - postbuildcommands { - "$(SILENT) echo Running asmjs finalize.", - "$(SILENT) \"$(EMSDK)/fastcomp/bin/emcc\" -O2 " - --- .. "-s ALLOW_MEMORY_GROWTH=1 " --- .. "-s ASSERTIONS=2 " --- .. "-s EMTERPRETIFY=1 " --- .. "-s EMTERPRETIFY_ASYNC=1 " - .. "-s PRECISE_F32=1 " - .. "-s TOTAL_MEMORY=268435456 " --- .. "-s USE_WEBGL2=1 " - - .. "--memory-init-file 1 " - .. "\"$(TARGET)\" -o \"$(TARGET)\".html " --- .. "--preload-file ../../../examples/runtime@/ " - } - configuration { "riscv" } postbuildcommands { "$(SILENT) echo Stripping symbols.", diff --git a/3rdparty/bx/src/allocator.cpp b/3rdparty/bx/src/allocator.cpp index 50c1505874c..0bcf2cd43c7 100644 --- a/3rdparty/bx/src/allocator.cpp +++ b/3rdparty/bx/src/allocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/amalgamated.cpp b/3rdparty/bx/src/amalgamated.cpp index e274b69019d..4aeac822870 100644 --- a/3rdparty/bx/src/amalgamated.cpp +++ b/3rdparty/bx/src/amalgamated.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/bx.cpp b/3rdparty/bx/src/bx.cpp index ab28bc25d2f..d6bdbf026c3 100644 --- a/3rdparty/bx/src/bx.cpp +++ b/3rdparty/bx/src/bx.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/bx_p.h b/3rdparty/bx/src/bx_p.h index de02ccce2da..d44901c58ee 100644 --- a/3rdparty/bx/src/bx_p.h +++ b/3rdparty/bx/src/bx_p.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -13,7 +13,7 @@ #if BX_CONFIG_DEBUG # define BX_TRACE _BX_TRACE # define BX_WARN _BX_WARN -# define BX_CHECK _BX_CHECK +# define BX_ASSERT _BX_ASSERT # define BX_CONFIG_ALLOCATOR_DEBUG 1 #endif // BX_CONFIG_DEBUG @@ -30,7 +30,7 @@ } \ BX_MACRO_BLOCK_END -#define _BX_CHECK(_condition, _format, ...) \ +#define _BX_ASSERT(_condition, _format, ...) \ BX_MACRO_BLOCK_BEGIN \ if (!BX_IGNORE_C4127(_condition) ) \ { \ diff --git a/3rdparty/bx/src/commandline.cpp b/3rdparty/bx/src/commandline.cpp index d9f6fb4e8de..2ff57f6dbd1 100644 --- a/3rdparty/bx/src/commandline.cpp +++ b/3rdparty/bx/src/commandline.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/crtnone.cpp b/3rdparty/bx/src/crtnone.cpp index 72dd8747eaa..7852f374f44 100644 --- a/3rdparty/bx/src/crtnone.cpp +++ b/3rdparty/bx/src/crtnone.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -100,7 +100,7 @@ extern "C" const char* strstr(const char* _str, const char* _find) extern "C" void qsort(void* _base, size_t _num, size_t _size, bx::ComparisonFn _fn) { - BX_CHECK(_num <= UINT32_MAX && _size <= UINT32_MAX, ""); + BX_ASSERT(_num <= UINT32_MAX && _size <= UINT32_MAX, ""); return bx::quickSort(_base, _num, _size, _fn); } diff --git a/3rdparty/bx/src/debug.cpp b/3rdparty/bx/src/debug.cpp index 623a2213b47..b02e53f1380 100644 --- a/3rdparty/bx/src/debug.cpp +++ b/3rdparty/bx/src/debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -142,7 +142,7 @@ namespace bx if (NULL != _data) { - const uint8_t* data = reinterpret_cast<const uint8_t*>(_data); + const uint8_t* data = (const uint8_t*)_data; char hex[HEX_DUMP_WIDTH*3+1]; char ascii[HEX_DUMP_WIDTH+1]; uint32_t hexPos = 0; diff --git a/3rdparty/bx/src/dtoa.cpp b/3rdparty/bx/src/dtoa.cpp index 686d5c6a12d..99b27a5a36c 100644 --- a/3rdparty/bx/src/dtoa.cpp +++ b/3rdparty/bx/src/dtoa.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -74,8 +74,8 @@ namespace bx DiyFp operator-(const DiyFp& rhs) const { - BX_CHECK(e == rhs.e, ""); - BX_CHECK(f >= rhs.f, ""); + BX_ASSERT(e == rhs.e, ""); + BX_ASSERT(f >= rhs.f, ""); return DiyFp(f - rhs.f, e); } @@ -224,7 +224,7 @@ namespace bx uint32_t index = static_cast<uint32_t>( (k >> 3) + 1); *K = -(-348 + static_cast<int32_t>(index << 3) ); // decimal exponent no need lookup table - BX_CHECK(index < sizeof(s_kCachedPowers_F) / sizeof(s_kCachedPowers_F[0]), ""); + BX_ASSERT(index < sizeof(s_kCachedPowers_F) / sizeof(s_kCachedPowers_F[0]), ""); return DiyFp(s_kCachedPowers_F[index], s_kCachedPowers_E[index]); } diff --git a/3rdparty/bx/src/easing.cpp b/3rdparty/bx/src/easing.cpp index 8984abccd0c..ec4c4517196 100644 --- a/3rdparty/bx/src/easing.cpp +++ b/3rdparty/bx/src/easing.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/file.cpp b/3rdparty/bx/src/file.cpp index aea285ea23f..c47eb37a0b6 100644 --- a/3rdparty/bx/src/file.cpp +++ b/3rdparty/bx/src/file.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -100,18 +100,18 @@ namespace bx virtual bool open(const FilePath& _filePath, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } m_file = fopen(_filePath.getCPtr(), "rb"); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileReader: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileReader: Failed to open file."); return false; } @@ -131,26 +131,26 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); fseeko64(m_file, _offset, _whence); return ftello64(m_file); } virtual int32_t read(void* _data, int32_t _size, Error* _err) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = (int32_t)fread(_data, 1, _size, m_file); if (size != _size) { if (0 != feof(m_file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "FileReader: EOF."); + BX_ERROR_SET(_err, kErrorReaderWriterEof, "FileReader: EOF."); } else if (0 != ferror(m_file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "FileReader: read error."); + BX_ERROR_SET(_err, kErrorReaderWriterRead, "FileReader: read error."); } return size >= 0 ? size : 0; @@ -180,11 +180,11 @@ namespace bx virtual bool open(const FilePath& _filePath, bool _append, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } @@ -192,7 +192,7 @@ namespace bx if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileWriter: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileWriter: Failed to open file."); return false; } @@ -212,20 +212,20 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); fseeko64(m_file, _offset, _whence); return ftello64(m_file); } virtual int32_t write(const void* _data, int32_t _size, Error* _err) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = (int32_t)fwrite(_data, 1, _size, m_file); if (size != _size) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "FileWriter: write failed."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "FileWriter: write failed."); return size >= 0 ? size : 0; } @@ -272,11 +272,11 @@ namespace bx virtual bool open(const FilePath& _filePath, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (0 != m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } @@ -284,7 +284,7 @@ namespace bx if (0 >= m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileReader: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileReader: Failed to open file."); return false; } @@ -304,14 +304,14 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); return crt0::seek(m_fd, _offset, crt0::Whence::Enum(_whence) ); } virtual int32_t read(void* _data, int32_t _size, Error* _err) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = crt0::read(m_fd, _data, _size); if (size != _size) @@ -319,11 +319,11 @@ namespace bx BX_UNUSED(_err); // if (0 != feof(m_file) ) // { -// BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "FileReader: EOF."); +// BX_ERROR_SET(_err, kErrorReaderWriterEof, "FileReader: EOF."); // } // else if (0 != ferror(m_file) ) // { -// BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "FileReader: read error."); +// BX_ERROR_SET(_err, kErrorReaderWriterRead, "FileReader: read error."); // } return size >= 0 ? size : 0; @@ -353,11 +353,11 @@ namespace bx virtual bool open(const FilePath& _filePath, bool _append, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (0 != m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } @@ -365,7 +365,7 @@ namespace bx if (0 >= m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileWriter: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileWriter: Failed to open file."); return false; } @@ -385,19 +385,19 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); return crt0::seek(m_fd, _offset, crt0::Whence::Enum(_whence) ); } virtual int32_t write(const void* _data, int32_t _size, Error* _err) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = crt0::write(m_fd, _data, _size); if (size != _size) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "FileWriter: write failed."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "FileWriter: write failed."); return size >= 0 ? size : 0; } @@ -582,13 +582,13 @@ namespace bx virtual bool open(const FilePath& _filePath, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); m_dir = opendir(_filePath.getCPtr() ); if (NULL == m_dir) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "DirectoryReader: Failed to open directory."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "DirectoryReader: Failed to open directory."); return false; } @@ -608,7 +608,7 @@ namespace bx virtual int32_t read(void* _data, int32_t _size, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t total = 0; @@ -620,7 +620,7 @@ namespace bx { if (!fetch(m_cache, m_dir) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "DirectoryReader: EOF."); + BX_ERROR_SET(_err, kErrorReaderWriterEof, "DirectoryReader: EOF."); return total; } } @@ -690,7 +690,7 @@ namespace bx virtual bool open(const FilePath& _filePath, Error* _err) override { BX_UNUSED(_filePath); - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "DirectoryReader: Failed to open directory."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "DirectoryReader: Failed to open directory."); return false; } @@ -701,8 +701,8 @@ namespace bx virtual int32_t read(void* _data, int32_t _size, Error* _err) override { BX_UNUSED(_data, _size); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "DirectoryReader: EOF."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ERROR_SET(_err, kErrorReaderWriterEof, "DirectoryReader: EOF."); return 0; } }; @@ -811,7 +811,7 @@ namespace bx if (0 != result) { - BX_ERROR_SET(_err, BX_ERROR_ACCESS, "The parent directory does not allow write permission to the process."); + BX_ERROR_SET(_err, kErrorAccess, "The parent directory does not allow write permission to the process."); return false; } @@ -836,7 +836,7 @@ namespace bx return true; } - BX_ERROR_SET(_err, BX_ERROR_NOT_DIRECTORY, "File already exist, and is not directory."); + BX_ERROR_SET(_err, kErrorNotDirectory, "File already exist, and is not directory."); return false; } @@ -888,7 +888,7 @@ namespace bx if (0 != result) { - BX_ERROR_SET(_err, BX_ERROR_ACCESS, "The parent directory does not allow write permission to the process."); + BX_ERROR_SET(_err, kErrorAccess, "The parent directory does not allow write permission to the process."); return false; } @@ -910,13 +910,13 @@ namespace bx if (!stat(fi, _filePath) ) { - BX_ERROR_SET(_err, BX_ERROR_ACCESS, "The parent directory does not allow write permission to the process."); + BX_ERROR_SET(_err, kErrorAccess, "The parent directory does not allow write permission to the process."); return false; } if (FileType::Dir != fi.type) { - BX_ERROR_SET(_err, BX_ERROR_NOT_DIRECTORY, "File already exist, and is not directory."); + BX_ERROR_SET(_err, kErrorNotDirectory, "File already exist, and is not directory."); return false; } @@ -925,7 +925,7 @@ namespace bx if (!bx::open(&dr, _filePath) ) { - BX_ERROR_SET(_err, BX_ERROR_NOT_DIRECTORY, "File already exist, and is not directory."); + BX_ERROR_SET(_err, kErrorNotDirectory, "File already exist, and is not directory."); return false; } diff --git a/3rdparty/bx/src/filepath.cpp b/3rdparty/bx/src/filepath.cpp index 28149403aba..14b34782705 100644 --- a/3rdparty/bx/src/filepath.cpp +++ b/3rdparty/bx/src/filepath.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/hash.cpp b/3rdparty/bx/src/hash.cpp index d48a1e22f28..bdef60796c0 100644 --- a/3rdparty/bx/src/hash.cpp +++ b/3rdparty/bx/src/hash.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/math.cpp b/3rdparty/bx/src/math.cpp index 4e3380a3774..71f96c5ac20 100644 --- a/3rdparty/bx/src/math.cpp +++ b/3rdparty/bx/src/math.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/mutex.cpp b/3rdparty/bx/src/mutex.cpp index 2fe5eaf33d4..b3e9677e62b 100644 --- a/3rdparty/bx/src/mutex.cpp +++ b/3rdparty/bx/src/mutex.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -158,4 +158,26 @@ namespace bx } // namespace bx -#endif // BX_MUTEX_H_HEADER_GUARD +#else + +namespace bx +{ + Mutex::Mutex() + { + } + + Mutex::~Mutex() + { + } + + void Mutex::lock() + { + } + + void Mutex::unlock() + { + } + +} // namespace bx + +#endif // BX_CONFIG_SUPPORTS_THREADING diff --git a/3rdparty/bx/src/os.cpp b/3rdparty/bx/src/os.cpp index ab5d6bd0935..12586aa8862 100644 --- a/3rdparty/bx/src/os.cpp +++ b/3rdparty/bx/src/os.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -27,15 +27,13 @@ || BX_PLATFORM_NX \ || BX_PLATFORM_OSX \ || BX_PLATFORM_PS4 \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK + || BX_PLATFORM_RPI # include <sched.h> // sched_yield # if BX_PLATFORM_BSD \ || BX_PLATFORM_HAIKU \ || BX_PLATFORM_IOS \ || BX_PLATFORM_OSX \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_STEAMLINK + || BX_PLATFORM_PS4 # include <pthread.h> // mach_port_t # endif // BX_PLATFORM_* @@ -47,8 +45,7 @@ # if BX_PLATFORM_ANDROID # include <malloc.h> // mallinfo # elif BX_PLATFORM_LINUX \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK + || BX_PLATFORM_RPI # include <stdio.h> // fopen # include <unistd.h> // syscall # include <sys/syscall.h> @@ -101,8 +98,7 @@ namespace bx #if BX_PLATFORM_WINDOWS return ::GetCurrentThreadId(); #elif BX_PLATFORM_LINUX \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK + || BX_PLATFORM_RPI return (pid_t)::syscall(SYS_gettid); #elif BX_PLATFORM_IOS \ || BX_PLATFORM_OSX diff --git a/3rdparty/bx/src/process.cpp b/3rdparty/bx/src/process.cpp index b079bbc77e5..8dc2a6b0717 100644 --- a/3rdparty/bx/src/process.cpp +++ b/3rdparty/bx/src/process.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -34,16 +34,16 @@ namespace bx ProcessReader::~ProcessReader() { - BX_CHECK(NULL == m_file, "Process not closed!"); + BX_ASSERT(NULL == m_file, "Process not closed!"); } bool ProcessReader::open(const FilePath& _filePath, const StringView& _args, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "ProcessReader: File is already open."); return false; } @@ -55,7 +55,7 @@ namespace bx m_file = popen(tmp, "r"); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessReader: Failed to open process."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "ProcessReader: Failed to open process."); return false; } @@ -64,7 +64,7 @@ namespace bx void ProcessReader::close() { - BX_CHECK(NULL != m_file, "Process not open!"); + BX_ASSERT(NULL != m_file, "Process not open!"); FILE* file = (FILE*)m_file; m_exitCode = pclose(file); m_file = NULL; @@ -72,7 +72,7 @@ namespace bx int32_t ProcessReader::read(void* _data, int32_t _size, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); FILE* file = (FILE*)m_file; int32_t size = (int32_t)fread(_data, 1, _size, file); @@ -80,11 +80,11 @@ namespace bx { if (0 != feof(file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "ProcessReader: EOF."); + BX_ERROR_SET(_err, kErrorReaderWriterEof, "ProcessReader: EOF."); } else if (0 != ferror(file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "ProcessReader: read error."); + BX_ERROR_SET(_err, kErrorReaderWriterRead, "ProcessReader: read error."); } return size >= 0 ? size : 0; @@ -105,16 +105,16 @@ namespace bx ProcessWriter::~ProcessWriter() { - BX_CHECK(NULL == m_file, "Process not closed!"); + BX_ASSERT(NULL == m_file, "Process not closed!"); } bool ProcessWriter::open(const FilePath& _filePath, const StringView& _args, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessWriter: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "ProcessWriter: File is already open."); return false; } @@ -126,7 +126,7 @@ namespace bx m_file = popen(tmp, "w"); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessWriter: Failed to open process."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "ProcessWriter: Failed to open process."); return false; } @@ -135,7 +135,7 @@ namespace bx void ProcessWriter::close() { - BX_CHECK(NULL != m_file, "Process not open!"); + BX_ASSERT(NULL != m_file, "Process not open!"); FILE* file = (FILE*)m_file; m_exitCode = pclose(file); m_file = NULL; @@ -143,7 +143,7 @@ namespace bx int32_t ProcessWriter::write(const void* _data, int32_t _size, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); FILE* file = (FILE*)m_file; int32_t size = (int32_t)fwrite(_data, 1, _size, file); @@ -151,7 +151,7 @@ namespace bx { if (0 != ferror(file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "ProcessWriter: write error."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "ProcessWriter: write error."); } return size >= 0 ? size : 0; diff --git a/3rdparty/bx/src/semaphore.cpp b/3rdparty/bx/src/semaphore.cpp index f4e99c66637..3e3083d3254 100644 --- a/3rdparty/bx/src/semaphore.cpp +++ b/3rdparty/bx/src/semaphore.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -76,7 +76,7 @@ namespace bx SemaphoreInternal* si = (SemaphoreInternal*)m_internal; si->m_handle = dispatch_semaphore_create(0); - BX_CHECK(NULL != si->m_handle, "dispatch_semaphore_create failed."); + BX_ASSERT(NULL != si->m_handle, "dispatch_semaphore_create failed."); } Semaphore::~Semaphore() @@ -140,10 +140,10 @@ namespace bx int result; result = pthread_mutex_init(&si->m_mutex, NULL); - BX_CHECK(0 == result, "pthread_mutex_init %d", result); + BX_ASSERT(0 == result, "pthread_mutex_init %d", result); result = pthread_cond_init(&si->m_cond, NULL); - BX_CHECK(0 == result, "pthread_cond_init %d", result); + BX_ASSERT(0 == result, "pthread_cond_init %d", result); BX_UNUSED(result); } @@ -154,10 +154,10 @@ namespace bx int result; result = pthread_cond_destroy(&si->m_cond); - BX_CHECK(0 == result, "pthread_cond_destroy %d", result); + BX_ASSERT(0 == result, "pthread_cond_destroy %d", result); result = pthread_mutex_destroy(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_destroy %d", result); + BX_ASSERT(0 == result, "pthread_mutex_destroy %d", result); BX_UNUSED(result); } @@ -167,18 +167,18 @@ namespace bx SemaphoreInternal* si = (SemaphoreInternal*)m_internal; int result = pthread_mutex_lock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_lock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_lock %d", result); for (uint32_t ii = 0; ii < _count; ++ii) { result = pthread_cond_signal(&si->m_cond); - BX_CHECK(0 == result, "pthread_cond_signal %d", result); + BX_ASSERT(0 == result, "pthread_cond_signal %d", result); } si->m_count += _count; result = pthread_mutex_unlock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_unlock %d", result); BX_UNUSED(result); } @@ -188,7 +188,7 @@ namespace bx SemaphoreInternal* si = (SemaphoreInternal*)m_internal; int result = pthread_mutex_lock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_lock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_lock %d", result); if (-1 == _msecs) { @@ -219,7 +219,7 @@ namespace bx } result = pthread_mutex_unlock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_unlock %d", result); BX_UNUSED(result); @@ -240,7 +240,7 @@ namespace bx #else si->m_handle = CreateSemaphoreA(NULL, 0, LONG_MAX, NULL); #endif - BX_CHECK(NULL != si->m_handle, "Failed to create Semaphore!"); + BX_ASSERT(NULL != si->m_handle, "Failed to create Semaphore!"); } Semaphore::~Semaphore() diff --git a/3rdparty/bx/src/settings.cpp b/3rdparty/bx/src/settings.cpp index 49bcc596817..daed2f1b90a 100644 --- a/3rdparty/bx/src/settings.cpp +++ b/3rdparty/bx/src/settings.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/sort.cpp b/3rdparty/bx/src/sort.cpp index 56cb7d48a98..ce1b3e3a8a4 100644 --- a/3rdparty/bx/src/sort.cpp +++ b/3rdparty/bx/src/sort.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/src/string.cpp b/3rdparty/bx/src/string.cpp index 678af6664ce..0c5f06d0301 100644 --- a/3rdparty/bx/src/string.cpp +++ b/3rdparty/bx/src/string.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -310,9 +310,9 @@ namespace bx inline int32_t strCopy(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) { - BX_CHECK(NULL != _dst, "_dst can't be NULL!"); - BX_CHECK(NULL != _src, "_src can't be NULL!"); - BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); + BX_ASSERT(NULL != _dst, "_dst can't be NULL!"); + BX_ASSERT(NULL != _src, "_src can't be NULL!"); + BX_ASSERT(0 < _dstSize, "_dstSize can't be 0!"); const int32_t len = strLen(_src, _num); const int32_t max = _dstSize-1; @@ -330,9 +330,9 @@ namespace bx inline int32_t strCat(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) { - BX_CHECK(NULL != _dst, "_dst can't be NULL!"); - BX_CHECK(NULL != _src, "_src can't be NULL!"); - BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); + BX_ASSERT(NULL != _dst, "_dst can't be NULL!"); + BX_ASSERT(NULL != _src, "_src can't be NULL!"); + BX_ASSERT(0 < _dstSize, "_dstSize can't be 0!"); const int32_t max = _dstSize; const int32_t len = strLen(_dst, max); @@ -420,18 +420,9 @@ namespace bx } } - // Set pointers. - const char* string = ptr; - const char* search = _find; - - // Start comparing. - while (fn(*string++) == fn(*search++) ) + if (0 == strCmp<fn>(ptr, _findMax, _find, _findMax) ) { - // If end of the 'search' string is reached, all characters match. - if ('\0' == *search) - { - return ptr; - } + return ptr; } } @@ -539,34 +530,47 @@ namespace bx return _str; } + StringView strRTrimSpace(const StringView& _str) + { + if (!_str.isEmpty() ) + { + const char* ptr = _str.getPtr(); + + for (int32_t len = _str.getLength(), ii = len - 1; 0 <= ii; --ii) + { + if (!isSpace(ptr[ii]) ) + { + return StringView(ptr, ii + 1); + } + } + } + + return _str; + } + StringView strTrim(const StringView& _str, const StringView& _chars) { return strLTrim(strRTrim(_str, _chars), _chars); } + StringView strTrimSpace(const StringView& _str) + { + return strLTrimSpace(strRTrimSpace(_str) ); + } + constexpr uint32_t kFindStep = 1024; StringView strFindNl(const StringView& _str) { StringView str(_str); - for (; str.getPtr() != _str.getTerm() - ; str = StringView(min(str.getPtr() + kFindStep, _str.getTerm() ), min(str.getPtr() + kFindStep*2, _str.getTerm() ) ) - ) + // This method returns the character past the \n, so + // there is no need to look for he \r which preceedes it. + StringView eol = strFind(str, "\n"); + if (!eol.isEmpty() ) { - StringView eol = strFind(str, "\r\n"); - if (!eol.isEmpty() ) - { - return StringView(eol.getTerm(), _str.getTerm() ); - } - - eol = strFind(str, '\n'); - if (!eol.isEmpty() ) - { - return StringView(eol.getTerm(), _str.getTerm() ); - } + return StringView(eol.getTerm(), str.getTerm() ); } - return StringView(_str.getTerm(), _str.getTerm() ); } @@ -674,7 +678,7 @@ namespace bx StringView ptr = strFind(_str, _word); for (; !ptr.isEmpty(); ptr = strFind(StringView(ptr.getPtr() + len, _str.getTerm() ), _word) ) { - char ch = *(ptr.getPtr() - 1); + char ch = ptr.getPtr() != _str.getPtr() ? *(ptr.getPtr() - 1) : ' '; if (isAlphaNum(ch) || '_' == ch) { continue; @@ -739,13 +743,40 @@ namespace bx { int32_t size = 0; int32_t len = (int32_t)strLen(_str, _len); - int32_t padding = _param.width > len ? _param.width - len : 0; - bool sign = _param.sign && len > 1 && _str[0] != '-'; - padding = padding > 0 ? padding - sign : 0; + + if (_param.width > 0) + { + len = min(_param.width, len); + } + + const bool hasMinus = (NULL != _str && '-' == _str[0]); + const bool hasSign = _param.sign || hasMinus; + char sign = hasSign ? hasMinus ? '-' : '+' : '\0'; + + const char* str = _str; + if (hasMinus) + { + str++; + len--; + } + + int32_t padding = _param.width > len ? _param.width - len - hasSign: 0; if (!_param.left) { - size += writeRep(_writer, _param.fill, padding, _err); + if (' ' != _param.fill + && '\0' != sign) + { + size += write(_writer, sign, _err); + sign = '\0'; + } + + size += writeRep(_writer, _param.fill, max(0, padding), _err); + } + + if ('\0' != sign) + { + size += write(_writer, sign, _err); } if (NULL == _str) @@ -756,17 +787,12 @@ namespace bx { for (int32_t ii = 0; ii < len; ++ii) { - size += write(_writer, toUpper(_str[ii]), _err); + size += write(_writer, toUpper(str[ii]), _err); } } - else if (sign) - { - size += write(_writer, '+', _err); - size += write(_writer, _str, len, _err); - } else { - size += write(_writer, _str, len, _err); + size += write(_writer, str, len, _err); } if (_param.left) diff --git a/3rdparty/bx/src/thread.cpp b/3rdparty/bx/src/thread.cpp index 952510569b1..17ace0927e7 100644 --- a/3rdparty/bx/src/thread.cpp +++ b/3rdparty/bx/src/thread.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ #include "bx_p.h" +#include <bx/os.h> #include <bx/thread.h> #if BX_CONFIG_SUPPORTS_THREADING @@ -31,15 +32,11 @@ # endif // BX_PLATFORM_ #elif BX_PLATFORM_WINDOWS \ || BX_PLATFORM_WINRT \ - || BX_PLATFORM_XBOXONE + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT # include <windows.h> # include <limits.h> # include <errno.h> -# if BX_PLATFORM_WINRT -using namespace Platform; -using namespace Windows::Foundation; -using namespace Windows::System::Threading; -# endif // BX_PLATFORM_WINRT #endif // BX_PLATFORM_ namespace bx @@ -128,20 +125,25 @@ namespace bx } } - void Thread::init(ThreadFn _fn, void* _userData, uint32_t _stackSize, const char* _name) + bool Thread::init(ThreadFn _fn, void* _userData, uint32_t _stackSize, const char* _name) { - BX_CHECK(!m_running, "Already running!"); + BX_ASSERT(!m_running, "Already running!"); m_fn = _fn; m_userData = _userData; m_stackSize = _stackSize; - m_running = true; ThreadInternal* ti = (ThreadInternal*)m_internal; #if BX_CRT_NONE ti->m_handle = crt0::threadCreate(&ti->threadFunc, _userData, m_stackSize, _name); + + if (NULL == ti->m_handle) + { + return false; + } #elif BX_PLATFORM_WINDOWS \ - || BX_PLATFORM_XBOXONE + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT ti->m_handle = ::CreateThread(NULL , m_stackSize , (LPTHREAD_START_ROUTINE)ti->threadFunc @@ -149,48 +151,57 @@ namespace bx , 0 , NULL ); -#elif BX_PLATFORM_WINRT - ti->m_handle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); - auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^) - { - m_exitCode = ti->threadFunc(this); - SetEvent(ti->m_handle); - } - , CallbackContext::Any - ); - - ThreadPool::RunAsync(workItemHandler, WorkItemPriority::Normal, WorkItemOptions::TimeSliced); + if (NULL == ti->m_handle) + { + return false; + } #elif BX_PLATFORM_POSIX int result; BX_UNUSED(result); pthread_attr_t attr; result = pthread_attr_init(&attr); - BX_CHECK(0 == result, "pthread_attr_init failed! %d", result); + BX_WARN(0 == result, "pthread_attr_init failed! %d", result); + if (0 != result) + { + return false; + } if (0 != m_stackSize) { result = pthread_attr_setstacksize(&attr, m_stackSize); - BX_CHECK(0 == result, "pthread_attr_setstacksize failed! %d", result); + BX_WARN(0 == result, "pthread_attr_setstacksize failed! %d", result); + + if (0 != result) + { + return false; + } } result = pthread_create(&ti->m_handle, &attr, &ti->threadFunc, this); - BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result); + BX_WARN(0 == result, "pthread_attr_setschedparam failed! %d", result); + if (0 != result) + { + return false; + } #else # error "Not implemented!" #endif // BX_PLATFORM_ + m_running = true; m_sem.wait(); if (NULL != _name) { setThreadName(_name); } + + return true; } void Thread::shutdown() { - BX_CHECK(m_running, "Not running!"); + BX_ASSERT(m_running, "Not running!"); ThreadInternal* ti = (ThreadInternal*)m_internal; #if BX_CRT_NONE crt0::threadJoin(ti->m_handle, NULL); @@ -249,8 +260,9 @@ namespace bx #elif BX_PLATFORM_WINDOWS // Try to use the new thread naming API from Win10 Creators update onwards if we have it typedef HRESULT (WINAPI *SetThreadDescriptionProc)(HANDLE, PCWSTR); - SetThreadDescriptionProc SetThreadDescription = (SetThreadDescriptionProc)(GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetThreadDescription")); - if (SetThreadDescription) + SetThreadDescriptionProc SetThreadDescription = dlsym<SetThreadDescriptionProc>((void*)GetModuleHandleA("Kernel32.dll"), "SetThreadDescription"); + + if (NULL != SetThreadDescription) { uint32_t length = (uint32_t)bx::strLen(_name)+1; uint32_t size = length*sizeof(wchar_t); @@ -358,14 +370,14 @@ namespace bx TlsDataInternal* ti = (TlsDataInternal*)m_internal; ti->m_id = TlsAlloc(); - BX_CHECK(TLS_OUT_OF_INDEXES != ti->m_id, "Failed to allocated TLS index (err: 0x%08x).", GetLastError() ); + BX_ASSERT(TLS_OUT_OF_INDEXES != ti->m_id, "Failed to allocated TLS index (err: 0x%08x).", GetLastError() ); } TlsData::~TlsData() { TlsDataInternal* ti = (TlsDataInternal*)m_internal; BOOL result = TlsFree(ti->m_id); - BX_CHECK(0 != result, "Failed to free TLS index (err: 0x%08x).", GetLastError() ); BX_UNUSED(result); + BX_ASSERT(0 != result, "Failed to free TLS index (err: 0x%08x).", GetLastError() ); BX_UNUSED(result); } void* TlsData::get() const @@ -388,14 +400,14 @@ namespace bx TlsDataInternal* ti = (TlsDataInternal*)m_internal; int result = pthread_key_create(&ti->m_id, NULL); - BX_CHECK(0 == result, "pthread_key_create failed %d.", result); BX_UNUSED(result); + BX_ASSERT(0 == result, "pthread_key_create failed %d.", result); BX_UNUSED(result); } TlsData::~TlsData() { TlsDataInternal* ti = (TlsDataInternal*)m_internal; int result = pthread_key_delete(ti->m_id); - BX_CHECK(0 == result, "pthread_key_delete failed %d.", result); BX_UNUSED(result); + BX_ASSERT(0 == result, "pthread_key_delete failed %d.", result); BX_UNUSED(result); } void* TlsData::get() const @@ -408,7 +420,7 @@ namespace bx { TlsDataInternal* ti = (TlsDataInternal*)m_internal; int result = pthread_setspecific(ti->m_id, _ptr); - BX_CHECK(0 == result, "pthread_setspecific failed %d.", result); BX_UNUSED(result); + BX_ASSERT(0 == result, "pthread_setspecific failed %d.", result); BX_UNUSED(result); } #endif // BX_PLATFORM_* diff --git a/3rdparty/bx/src/timer.cpp b/3rdparty/bx/src/timer.cpp index 80bc28a8448..45806b10777 100644 --- a/3rdparty/bx/src/timer.cpp +++ b/3rdparty/bx/src/timer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -41,7 +41,7 @@ namespace bx gettimeofday(&now, 0); int64_t i64 = now.tv_sec*INT64_C(1000000) + now.tv_usec; #else - BX_CHECK(false, "Not implemented!"); + BX_ASSERT(false, "Not implemented!"); int64_t i64 = UINT64_MAX; #endif // BX_PLATFORM_ return i64; diff --git a/3rdparty/bx/src/url.cpp b/3rdparty/bx/src/url.cpp index b64a50b43b3..ce02bd35bd8 100644 --- a/3rdparty/bx/src/url.cpp +++ b/3rdparty/bx/src/url.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bnet#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/atomic_test.cpp b/3rdparty/bx/tests/atomic_test.cpp index 219b0959d27..43d87b63589 100644 --- a/3rdparty/bx/tests/atomic_test.cpp +++ b/3rdparty/bx/tests/atomic_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/crt_test.cpp b/3rdparty/bx/tests/crt_test.cpp index bddcb2b2d76..d40270641b8 100644 --- a/3rdparty/bx/tests/crt_test.cpp +++ b/3rdparty/bx/tests/crt_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/dbg.h b/3rdparty/bx/tests/dbg.h index 2fb211862d1..880b0188de4 100644 --- a/3rdparty/bx/tests/dbg.h +++ b/3rdparty/bx/tests/dbg.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/easing_test.cpp b/3rdparty/bx/tests/easing_test.cpp index 4556c3ad19c..ff0a81934c8 100644 --- a/3rdparty/bx/tests/easing_test.cpp +++ b/3rdparty/bx/tests/easing_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/filepath_test.cpp b/3rdparty/bx/tests/filepath_test.cpp index fa912105569..afd46f6bf58 100644 --- a/3rdparty/bx/tests/filepath_test.cpp +++ b/3rdparty/bx/tests/filepath_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/handle_bench.cpp b/3rdparty/bx/tests/handle_bench.cpp index 082bee0e182..a7c88a864b8 100644 --- a/3rdparty/bx/tests/handle_bench.cpp +++ b/3rdparty/bx/tests/handle_bench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/handle_test.cpp b/3rdparty/bx/tests/handle_test.cpp index 5c367f34531..80ff28cda01 100644 --- a/3rdparty/bx/tests/handle_test.cpp +++ b/3rdparty/bx/tests/handle_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/hash_test.cpp b/3rdparty/bx/tests/hash_test.cpp index 5c2d258dcc9..56556e9d91e 100644 --- a/3rdparty/bx/tests/hash_test.cpp +++ b/3rdparty/bx/tests/hash_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/macros_test.cpp b/3rdparty/bx/tests/macros_test.cpp index 3576b1cf2a9..afcc75788bd 100644 --- a/3rdparty/bx/tests/macros_test.cpp +++ b/3rdparty/bx/tests/macros_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -24,20 +24,6 @@ BX_STATIC_ASSERT(4 == BX_VA_ARGS_COUNT(1, 2, 3, 4) ); BX_STATIC_ASSERT(5 == BX_VA_ARGS_COUNT(1, 2, 3, 4, 5) ); BX_STATIC_ASSERT(6 == BX_VA_ARGS_COUNT(1, 2, 3, 4, 5, 6) ); -BX_STATIC_ASSERT( 0 == BX_ALIGN_16( 0) ); -BX_STATIC_ASSERT( 16 == BX_ALIGN_16( 1) ); -BX_STATIC_ASSERT( 16 == BX_ALIGN_16( 15) ); -BX_STATIC_ASSERT( 16 == BX_ALIGN_16( 16) ); -BX_STATIC_ASSERT(256 == BX_ALIGN_16(255) ); - -BX_STATIC_ASSERT( 0 == BX_ALIGN_256( 0) ); -BX_STATIC_ASSERT(256 == BX_ALIGN_256( 1) ); -BX_STATIC_ASSERT(256 == BX_ALIGN_256( 15) ); -BX_STATIC_ASSERT(256 == BX_ALIGN_256(255) ); -BX_STATIC_ASSERT(256 == BX_ALIGN_256(256) ); -BX_STATIC_ASSERT(256 == BX_ALIGN_256(256) ); -BX_STATIC_ASSERT(512 == BX_ALIGN_256(511) ); - BX_NO_INLINE void unusedFunction() { CHECK(false); diff --git a/3rdparty/bx/tests/main_test.cpp b/3rdparty/bx/tests/main_test.cpp index 2e0fbe2b431..251d45cb142 100644 --- a/3rdparty/bx/tests/main_test.cpp +++ b/3rdparty/bx/tests/main_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/math_bench.cpp b/3rdparty/bx/tests/math_bench.cpp index e9e083e385c..7a9fb9af613 100644 --- a/3rdparty/bx/tests/math_bench.cpp +++ b/3rdparty/bx/tests/math_bench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/math_test.cpp b/3rdparty/bx/tests/math_test.cpp index 00a73b283ce..d2a36420974 100644 --- a/3rdparty/bx/tests/math_test.cpp +++ b/3rdparty/bx/tests/math_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -196,6 +196,13 @@ TEST_CASE("ToBits", "") REQUIRE(UINT64_C(0x123456789abcdef0) == bx::doubleToBits(bx::bitsToDouble(UINT32_C(0x123456789abcdef0) ) ) ); } +TEST_CASE("lerp", "") +{ + REQUIRE(1389.0f == bx::lerp(1389.0f, 1453.0f, 0.0f) ); + REQUIRE(1453.0f == bx::lerp(1389.0f, 1453.0f, 1.0f) ); + REQUIRE(0.5f == bx::lerp(0.0f, 1.0f, 0.5f) ); +} + void mtxCheck(const float* _a, const float* _b) { if (!bx::equal(_a, _b, 16, 0.01f) ) diff --git a/3rdparty/bx/tests/nlalloc_test.cpp b/3rdparty/bx/tests/nlalloc_test.cpp index 14c44e5f23f..dd44b3bacaf 100644 --- a/3rdparty/bx/tests/nlalloc_test.cpp +++ b/3rdparty/bx/tests/nlalloc_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -90,7 +90,7 @@ namespace bx Blk remove() { - BX_CHECK(0 == m_used, ""); + BX_ASSERT(0 == m_used, ""); if (0 < m_free.size() ) { @@ -134,7 +134,7 @@ namespace bx void free(const Blk& _blk) { - BX_CHECK(isValid(_blk), "Freeing invalid block!"); + BX_ASSERT(isValid(_blk), "Freeing invalid block!"); m_used -= _blk.size; diff --git a/3rdparty/bx/tests/os_test.cpp b/3rdparty/bx/tests/os_test.cpp index bd28bf51d2d..5d72aa68af7 100644 --- a/3rdparty/bx/tests/os_test.cpp +++ b/3rdparty/bx/tests/os_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/queue_test.cpp b/3rdparty/bx/tests/queue_test.cpp index c035dcc8db1..b68fe5fc66f 100644 --- a/3rdparty/bx/tests/queue_test.cpp +++ b/3rdparty/bx/tests/queue_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/readerwriter_test.cpp b/3rdparty/bx/tests/readerwriter_test.cpp index 53fa3f80cd3..b82238a53a5 100644 --- a/3rdparty/bx/tests/readerwriter_test.cpp +++ b/3rdparty/bx/tests/readerwriter_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/ringbuffer_test.cpp b/3rdparty/bx/tests/ringbuffer_test.cpp index fb78b0862d7..cc2ac02920b 100644 --- a/3rdparty/bx/tests/ringbuffer_test.cpp +++ b/3rdparty/bx/tests/ringbuffer_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/rng_test.cpp b/3rdparty/bx/tests/rng_test.cpp index c6586275e47..3b13284a6a2 100644 --- a/3rdparty/bx/tests/rng_test.cpp +++ b/3rdparty/bx/tests/rng_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/run_test.cpp b/3rdparty/bx/tests/run_test.cpp index 1f7e0509273..91f40c6b89f 100644 --- a/3rdparty/bx/tests/run_test.cpp +++ b/3rdparty/bx/tests/run_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/settings_test.cpp b/3rdparty/bx/tests/settings_test.cpp index fbf6c9a1112..85b72c44eb6 100644 --- a/3rdparty/bx/tests/settings_test.cpp +++ b/3rdparty/bx/tests/settings_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/simd_bench.cpp b/3rdparty/bx/tests/simd_bench.cpp index 5e77d4190d3..50ea99f9706 100644 --- a/3rdparty/bx/tests/simd_bench.cpp +++ b/3rdparty/bx/tests/simd_bench.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/simd_test.cpp b/3rdparty/bx/tests/simd_test.cpp index 8b959c8dffb..39459dcf9a4 100644 --- a/3rdparty/bx/tests/simd_test.cpp +++ b/3rdparty/bx/tests/simd_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/sort_test.cpp b/3rdparty/bx/tests/sort_test.cpp index a46a80b64f8..dc565aeaf33 100644 --- a/3rdparty/bx/tests/sort_test.cpp +++ b/3rdparty/bx/tests/sort_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/string_test.cpp b/3rdparty/bx/tests/string_test.cpp index c1c4b85f546..40f58cf636e 100644 --- a/3rdparty/bx/tests/string_test.cpp +++ b/3rdparty/bx/tests/string_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -226,6 +226,18 @@ TEST_CASE("strFind", "") REQUIRE(bx::strFind("vgd", 'a').isEmpty() ); } + + { + bx::StringView test = bx::strFind("a", "a"); + REQUIRE(test.getLength() == 1); + REQUIRE(*test.getPtr() == 'a'); + } + + { + bx::StringView test = bx::strFind("a", bx::StringView("a ", 1) ); + REQUIRE(test.getLength() == 1); + REQUIRE(*test.getPtr() == 'a'); + } } TEST_CASE("strSkip", "") @@ -482,6 +494,33 @@ TEST_CASE("Trim", "") REQUIRE(0 == bx::strCmp(bx::strTrim(uri.getPath(), "/"), "555333/podmac") ); } +TEST_CASE("TrimSpace", "") +{ + REQUIRE(bx::strLTrimSpace("").isEmpty() ); + REQUIRE(bx::strRTrimSpace("").isEmpty() ); + REQUIRE(bx::strTrimSpace( "").isEmpty() ); + + const bx::StringView t0("1389"); + const bx::StringView t1(" 1389"); + const bx::StringView t2("1389 "); + const bx::StringView t3(" 1389 "); + + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t0), t0) ); + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t1), t0) ); + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t2), t2) ); + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t3), "1389 ") ); + + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t0), t0) ); + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t1), t1) ); + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t2), t0) ); + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t3), " 1389") ); + + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t0), t0) ); + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t1), t0) ); + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t2), t0) ); + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t3), t0) ); +} + TEST_CASE("strWord", "") { REQUIRE(bx::strWord(" abvgd-1389.0").isEmpty() ); diff --git a/3rdparty/bx/tests/test.h b/3rdparty/bx/tests/test.h index b7654aba1e2..88c39f8f5b7 100644 --- a/3rdparty/bx/tests/test.h +++ b/3rdparty/bx/tests/test.h @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/thread_test.cpp b/3rdparty/bx/tests/thread_test.cpp index a174e9f86d6..3c935fa6323 100644 --- a/3rdparty/bx/tests/thread_test.cpp +++ b/3rdparty/bx/tests/thread_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -42,7 +42,9 @@ TEST_CASE("Thread", "") REQUIRE(!th.isRunning() ); - th.init(threadExit0); + bool init = th.init(threadExit0, NULL, 0, NULL); + REQUIRE(init); + REQUIRE(th.isRunning() ); th.push(NULL); th.shutdown(); diff --git a/3rdparty/bx/tests/tokenizecmd_test.cpp b/3rdparty/bx/tests/tokenizecmd_test.cpp index c453ddaf1d9..569d14898c7 100644 --- a/3rdparty/bx/tests/tokenizecmd_test.cpp +++ b/3rdparty/bx/tests/tokenizecmd_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 Branimir Karadzic. All rights reserved. + * Copyright 2012-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/uint32_test.cpp b/3rdparty/bx/tests/uint32_test.cpp index b209219cd56..663ac3f1dd1 100644 --- a/3rdparty/bx/tests/uint32_test.cpp +++ b/3rdparty/bx/tests/uint32_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -117,3 +117,35 @@ TEST_CASE("uint64_roX", "") REQUIRE(bx::uint64_rol(0x8000000000000000, 1) == 1); REQUIRE(bx::uint64_ror(1, 1) == 0x8000000000000000); } + +TEST_CASE("align", "") +{ + REQUIRE( bx::isAligned(0, 8) ); + REQUIRE(!bx::isAligned(7, 8) ); + REQUIRE( bx::isAligned(64, 8) ); + REQUIRE(!bx::isAligned(63, 8) ); + + REQUIRE( 0 == bx::alignUp( 0, 16) ); + REQUIRE( 16 == bx::alignUp( 1, 16) ); + REQUIRE( 16 == bx::alignUp( 15, 16) ); + REQUIRE( 16 == bx::alignUp( 16, 16) ); + REQUIRE(256 == bx::alignUp(255, 16) ); + REQUIRE( 0 == bx::alignUp(-1, 16) ); + REQUIRE(-16 == bx::alignUp(-31, 16) ); + + REQUIRE( 0 == bx::alignUp( 0, 256) ); + REQUIRE(256 == bx::alignUp( 1, 256) ); + REQUIRE(256 == bx::alignUp( 15, 256) ); + REQUIRE(256 == bx::alignUp(255, 256) ); + REQUIRE(256 == bx::alignUp(256, 256) ); + REQUIRE(256 == bx::alignUp(256, 256) ); + REQUIRE(512 == bx::alignUp(511, 256) ); + + REQUIRE( 0 == bx::alignDown( 0, 16) ); + REQUIRE( 0 == bx::alignDown( 1, 16) ); + REQUIRE( 0 == bx::alignDown( 15, 16) ); + REQUIRE( 16 == bx::alignDown( 16, 16) ); + REQUIRE(240 == bx::alignDown(255, 16) ); + REQUIRE(-16 == bx::alignDown(-1, 16) ); + REQUIRE(-32 == bx::alignDown(-31, 16) ); +} diff --git a/3rdparty/bx/tests/url_test.cpp b/3rdparty/bx/tests/url_test.cpp index b43488c157e..c0a9f62d1b4 100644 --- a/3rdparty/bx/tests/url_test.cpp +++ b/3rdparty/bx/tests/url_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ diff --git a/3rdparty/bx/tests/vsnprintf_test.cpp b/3rdparty/bx/tests/vsnprintf_test.cpp index 50bf5449ff7..8d09210825f 100644 --- a/3rdparty/bx/tests/vsnprintf_test.cpp +++ b/3rdparty/bx/tests/vsnprintf_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 Branimir Karadzic. All rights reserved. + * Copyright 2010-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -66,6 +66,18 @@ TEST_CASE("vsnprintf f") REQUIRE(test(" inf", "%8f", std::numeric_limits<double>::infinity() ) ); REQUIRE(test("inf ", "%-8f", std::numeric_limits<double>::infinity() ) ); REQUIRE(test(" -INF", "%8F", -std::numeric_limits<double>::infinity() ) ); + + REQUIRE(test(" 1.0", "%4.1f", 1.0) ); + REQUIRE(test(" 1.500", "%6.3f", 1.5) ); + REQUIRE(test("0001.500", "%08.3f", 1.5) ); + REQUIRE(test("+001.500", "%+08.3f", 1.5) ); + REQUIRE(test("-001.500", "%+08.3f", -1.5) ); + REQUIRE(test("0.003906", "%f", 0.00390625) ); + REQUIRE(test("0.0039", "%.4f", 0.00390625) ); + + REQUIRE(test("0.00390625", "%.8f", 0.00390625) ); + REQUIRE(test("-0.00390625", "%.8f", -0.00390625) ); + REQUIRE(test("1.50000000000000000", "%.17f", 1.5) ); } TEST_CASE("vsnprintf d/i/o/u/x") @@ -82,6 +94,8 @@ TEST_CASE("vsnprintf d/i/o/u/x") REQUIRE(test("2471", "%o", 1337) ); REQUIRE(test("1337 ", "%-20o", 01337) ); REQUIRE(test("37777776441 ", "%-20o", -01337) ); + REQUIRE(test(" 2471", "%20o", 1337) ); + REQUIRE(test("00000000000000002471", "%020o", 1337) ); REQUIRE(test("1337", "%u", 1337) ); REQUIRE(test("1337 ", "%-20u", 1337) ); @@ -92,11 +106,40 @@ TEST_CASE("vsnprintf d/i/o/u/x") REQUIRE(test("1234ABCD ", "%-20X", 0x1234abcd) ); REQUIRE(test("edcb5433 ", "%-20x", -0x1234abcd) ); REQUIRE(test("EDCB5433 ", "%-20X", -0x1234abcd) ); + REQUIRE(test(" 1234abcd", "% 20x", 0x1234abcd) ); + REQUIRE(test(" 1234ABCD", "% 20X", 0x1234abcd) ); + REQUIRE(test(" edcb5433", "% 20x", -0x1234abcd) ); + REQUIRE(test(" EDCB5433", "% 20X", -0x1234abcd) ); REQUIRE(test("0000000000001234abcd", "%020x", 0x1234abcd) ); REQUIRE(test("0000000000001234ABCD", "%020X", 0x1234abcd) ); REQUIRE(test("000000000000edcb5433", "%020x", -0x1234abcd) ); REQUIRE(test("000000000000EDCB5433", "%020X", -0x1234abcd) ); + REQUIRE(test("0xf", "0x%01x", -1) ); + REQUIRE(test("0xff", "0x%02x", -1) ); + REQUIRE(test("0xfff", "0x%03x", -1) ); + REQUIRE(test("0xffff", "0x%04x", -1) ); + REQUIRE(test("0xfffff", "0x%05x", -1) ); + REQUIRE(test("0xffffff", "0x%06x", -1) ); + REQUIRE(test("0xfffffff", "0x%07x", -1) ); + REQUIRE(test("0xffffffff", "0x%08x", -1) ); + + REQUIRE(test(" -1", "% 4i", -1) ); + REQUIRE(test(" -1", "% 4i", -1) ); + REQUIRE(test(" 0", "% 4i", 0) ); + REQUIRE(test(" 1", "% 4i", 1) ); + REQUIRE(test(" 1", "% 4o", 1) ); + REQUIRE(test(" +1", "%+4i", 1) ); + REQUIRE(test(" +1", "%+4o", 1) ); + REQUIRE(test(" +0", "%+4i", 0) ); + REQUIRE(test(" -1", "%+4i", -1) ); + REQUIRE(test("0001", "%04i", 1) ); + REQUIRE(test("0001", "%04o", 1) ); + REQUIRE(test("0000", "%04i", 0) ); + REQUIRE(test("0000", "%04o", 0) ); + REQUIRE(test("-001", "%04i", -1) ); + REQUIRE(test("+001", "%+04i", 1) ); + if (BX_ENABLED(BX_ARCH_32BIT) ) { REQUIRE(test("2147483647", "%jd", INTMAX_MAX) ); @@ -152,6 +195,12 @@ TEST_CASE("vsnprintf") REQUIRE(test("hello ", "%-20s", "hello") ); REQUIRE(test("hello, world!", "%s, %s!", "hello", "world") ); + REQUIRE(test("h", "%1s", "hello") ); + REQUIRE(test("he", "%2s", "hello") ); + REQUIRE(test("hel", "%3s", "hello") ); + REQUIRE(test("hell", "%4s", "hello") ); + REQUIRE(test("hello", "%5s", "hello") ); + bx::StringView str("0hello1world2"); bx::StringView hello(str, 1, 5); bx::StringView world(str, 7, 5); diff --git a/3rdparty/bx/tools/bin/darwin/bin2c b/3rdparty/bx/tools/bin/darwin/bin2c Binary files differindex 7aa45d00061..7aa45d00061 100644..100755 --- a/3rdparty/bx/tools/bin/darwin/bin2c +++ b/3rdparty/bx/tools/bin/darwin/bin2c diff --git a/3rdparty/bx/tools/bin/darwin/genie b/3rdparty/bx/tools/bin/darwin/genie Binary files differindex 7ebe0a3cf11..d12f53ec4c1 100755 --- a/3rdparty/bx/tools/bin/darwin/genie +++ b/3rdparty/bx/tools/bin/darwin/genie diff --git a/3rdparty/bx/tools/bin/darwin/lemon b/3rdparty/bx/tools/bin/darwin/lemon Binary files differindex c00a276b405..c00a276b405 100644..100755 --- a/3rdparty/bx/tools/bin/darwin/lemon +++ b/3rdparty/bx/tools/bin/darwin/lemon diff --git a/3rdparty/bx/tools/bin/darwin/ninja b/3rdparty/bx/tools/bin/darwin/ninja Binary files differindex d26afc28e73..d26afc28e73 100644..100755 --- a/3rdparty/bx/tools/bin/darwin/ninja +++ b/3rdparty/bx/tools/bin/darwin/ninja diff --git a/3rdparty/bx/tools/bin/linux/bin2c b/3rdparty/bx/tools/bin/linux/bin2c Binary files differindex d825698d97a..39015b9b40e 100644..100755 --- a/3rdparty/bx/tools/bin/linux/bin2c +++ b/3rdparty/bx/tools/bin/linux/bin2c diff --git a/3rdparty/bx/tools/bin/linux/genie b/3rdparty/bx/tools/bin/linux/genie Binary files differindex f61c3ee0039..996d64acd06 100755 --- a/3rdparty/bx/tools/bin/linux/genie +++ b/3rdparty/bx/tools/bin/linux/genie diff --git a/3rdparty/bx/tools/bin/linux/lemon b/3rdparty/bx/tools/bin/linux/lemon Binary files differindex 79e1aa9213d..be869ab1886 100644..100755 --- a/3rdparty/bx/tools/bin/linux/lemon +++ b/3rdparty/bx/tools/bin/linux/lemon diff --git a/3rdparty/bx/tools/bin/linux/ninja b/3rdparty/bx/tools/bin/linux/ninja Binary files differindex 189832fdb4b..189832fdb4b 100644..100755 --- a/3rdparty/bx/tools/bin/linux/ninja +++ b/3rdparty/bx/tools/bin/linux/ninja diff --git a/3rdparty/bx/tools/bin/windows/bin2c.exe b/3rdparty/bx/tools/bin/windows/bin2c.exe Binary files differindex d93eff18e60..d93eff18e60 100644..100755 --- a/3rdparty/bx/tools/bin/windows/bin2c.exe +++ b/3rdparty/bx/tools/bin/windows/bin2c.exe diff --git a/3rdparty/bx/tools/bin/windows/genie.exe b/3rdparty/bx/tools/bin/windows/genie.exe Binary files differindex c8cecc1559c..cd5ebbb2eed 100644 --- a/3rdparty/bx/tools/bin/windows/genie.exe +++ b/3rdparty/bx/tools/bin/windows/genie.exe diff --git a/3rdparty/bx/tools/bin/windows/ninja.exe b/3rdparty/bx/tools/bin/windows/ninja.exe Binary files differindex 1b30c1eb432..1b30c1eb432 100644..100755 --- a/3rdparty/bx/tools/bin/windows/ninja.exe +++ b/3rdparty/bx/tools/bin/windows/ninja.exe diff --git a/3rdparty/bx/tools/bin2c/bin2c.cpp b/3rdparty/bx/tools/bin2c/bin2c.cpp index afc64385be9..066d9e25f8d 100644 --- a/3rdparty/bx/tools/bin2c/bin2c.cpp +++ b/3rdparty/bx/tools/bin2c/bin2c.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. + * Copyright 2011-2021 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ @@ -27,20 +27,21 @@ public: virtual int32_t write(const void* _data, int32_t _size, bx::Error* _err) override { - m_outputAsCStr = true; + bool asCStr = true; const char* data = (const char*)_data; - for (int32_t ii = 0; ii < _size; ++ii) + for (int32_t ii = 0; ii < _size && asCStr; ++ii) { char ch = data[ii]; - if (!bx::isPrint(ch) - && !bx::isSpace(ch) ) - { - m_outputAsCStr = false; - break; - } + + asCStr &= false + | bx::isPrint(ch) + | bx::isSpace(ch) + ; } + m_outputAsCStr = asCStr; + return bx::write(&m_mw, _data, _size, _err); } @@ -58,7 +59,7 @@ public: void outputString(bx::WriterI* _writer) { - const char* data = (const char*)m_mb.more(0); + const uint8_t* data = (const uint8_t*)m_mb.more(0); uint32_t size = uint32_t(bx::seek(&m_mw) ); bx::Error err; @@ -77,7 +78,7 @@ public: for (uint32_t ii = 0; ii < size; ++ii) { - char ch = data[ii]; + const char ch = char(data[ii]); if (!escaped) { @@ -113,7 +114,7 @@ public: #define HEX_DUMP_WIDTH 16 #define HEX_DUMP_SPACE_WIDTH 96 #define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s" - const char* data = (const char*)m_mb.more(0); + const uint8_t* data = (const uint8_t*)m_mb.more(0); uint32_t size = uint32_t(bx::seek(&m_mw) ); bx::Error err; @@ -170,6 +171,19 @@ public: bool m_outputAsCStr; }; +void error(const char* _format, ...) +{ + bx::WriterI* stdOut = bx::getStdOut(); + bx::Error err; + + va_list argList; + va_start(argList, _format); + bx::write(stdOut, &err, "Error:\n"); + bx::write(stdOut, _format, argList, &err); + bx::write(stdOut, &err, "\n\n"); + va_end(argList); +} + void help(const char* _error = NULL) { bx::WriterI* stdOut = bx::getStdOut(); @@ -177,12 +191,12 @@ void help(const char* _error = NULL) if (NULL != _error) { - bx::write(stdOut, &err, "Error:\n%s\n\n", _error); + error(_error); } bx::write(stdOut, &err , "bin2c, binary to C\n" - "Copyright 2011-2019 Branimir Karadzic. All rights reserved.\n" + "Copyright 2011-2021 Branimir Karadzic. All rights reserved.\n" "License: https://github.com/bkaradzic/bx#license-bsd-2-clause\n\n" ); @@ -250,9 +264,19 @@ int main(int _argc, const char* _argv[]) writer.output(&fw); bx::close(&fw); } + else + { + bx::StringView path = outFilePath; + error("Failed to open output file '%.*s'.\n", path.getLength(), path.getPtr() ); + } BX_FREE(&allocator, data); } + else + { + bx::StringView path = filePath; + error("Failed to open input file '%.*s'.\n", path.getLength(), path.getPtr() ); + } return 0; } |