diff --git a/.clang-format b/.clang-format index 8a50165c0..6b092066a 100644 --- a/.clang-format +++ b/.clang-format @@ -6,8 +6,9 @@ AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: Always AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: false AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: "false" +AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakBeforeMultilineStrings: true @@ -42,7 +43,7 @@ PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right -RequiresClausePosition: OwnLine +RequiresClausePosition: OwnLineWithBrace SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: false SpaceBeforeAssignmentOperators: true diff --git a/.github/workflows/ci_ubuntu.yml b/.github/workflows/ci_ubuntu.yml index 3fa5d68b9..5d2082aa5 100644 --- a/.github/workflows/ci_ubuntu.yml +++ b/.github/workflows/ci_ubuntu.yml @@ -25,7 +25,7 @@ jobs: cpp_version: [ 17, 20 ] build_type: [ Debug, Release ] os: [ ubuntu-24.04 ] - toolset: [ g++-12, g++-13, clang++-13, clang++-14, clang++-15, clang++-16, clang++-17, clang++-18, clang++-19, clang++-20 ] + toolset: [ g++-12, g++-13, clang++-19, clang++-20 ] exclude: - toolset: g++-12 cpp_version: 20 @@ -43,15 +43,9 @@ jobs: if: endsWith( matrix.os, '24.04' ) run: | sudo wget -O /etc/apt/trusted.gpg.d/llvm.asc https://apt.llvm.org/llvm-snapshot.gpg.key - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-13 main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-14 main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main' - sudo apt-add-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main' + sudo apt-add-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble main' + sudo apt-add-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main' + sudo apt-add-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-20 main' sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt update sudo apt install ninja-build libunwind-dev diff --git a/.github/workflows/ci_windows.yml b/.github/workflows/ci_windows.yml index 74d74c1fd..4e96f8b42 100644 --- a/.github/workflows/ci_windows.yml +++ b/.github/workflows/ci_windows.yml @@ -1,19 +1,72 @@ name: Windows - on: + schedule: + - cron: '10 5 * * *' push: - branches-ignore: dev + branches: [ release, develop ] pull_request: - branches-ignore: dev + push: + branches-ignore: develop + pull_request: + branches-ignore: develop jobs: - build: - runs-on: [windows-2019] + Windows: + permissions: + actions: none + checks: none + contents: none + deployments: none + issues: none + packages: none + pull-requests: none + repository-projects: none + security-events: none + statuses: none + defaults: + run: + shell: cmd + strategy: + fail-fast: false + matrix: + config: + - { cpp_version: 17, build_type: Debug, arch: x64, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 17, build_type: Release, arch: x64, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 20, build_type: Debug, arch: x64, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 20, build_type: Release, arch: x64, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 17, build_type: Debug, arch: Win32, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 17, build_type: Release, arch: Win32, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 20, build_type: Debug, arch: Win32, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 20, build_type: Release, arch: Win32, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 23, build_type: Debug, arch: Win32, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 23, build_type: Release, arch: Win32, os: windows-2022, toolset: MSVC, cmake_flags: "-GNinja" } + - { cpp_version: 23, build_type: Debug, arch: Win32, os: windows-2022, toolset: ClangCL, cmake_flags: " -T ClangCL -DCMAKE_C_COMPILER=clang-cl.exe -DCMAKE_CXX_COMPILER=clang-cl.exe" } + - { cpp_version: 23, build_type: Release, arch: Win32, os: windows-2022, toolset: ClangCL, cmake_flags: " -T ClangCL -DCMAKE_C_COMPILER=clang-cl.exe -DCMAKE_CXX_COMPILER=clang-cl.exe" } + runs-on: ${{ matrix.config.os }} + name: "${{ matrix.config.os }} ${{ matrix.config.toolset }} ${{ matrix.config.cpp_version }} ${{ matrix.config.arch }} ${{ matrix.config.build_type }}" + env: + DAW_BUILD_DIR: "build_${{ matrix.config.cpp_version }}_${{ matrix.config.arch }}_${{ matrix.config.build_type }}_${{ matrix.config.toolset }}" steps: - uses: actions/checkout@v1 + - uses: beached/msvc-dev-cmd@285e7c0b9b57a02c900951da93a77e656425d783 + with: + arch: ${{ matrix.config.arch }} + - name: Setup Build Environment + run: md ${{ env.DAW_BUILD_DIR }} + - name: CMake Config + run: cmake.exe ${{ matrix.config.cmake_flags }} -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.config.cpp_version }} -DDAW_ENABLE_TESTING=On -B${{ env.DAW_BUILD_DIR }}/ . - name: Build - run: .\ci_scripts\ci_windows_build.cmd + run: cmake.exe --build ${{ env.DAW_BUILD_DIR }}/ --target daw-header-libraries_full --config ${{ matrix.config.build_type }} + continue-on-error: true - name: Test - run: .\ci_scripts\ci_windows_test.cmd - - name: InstallTest - run: .\ci_scripts\ci_windows_install_test.cmd + run: ctest.exe -C ${{ matrix.config.build_type }} -j2 -VV --timeout 1200 --test-dir ${{ env.DAW_BUILD_DIR }}/ + - name: Archive any crashes as an artifact + uses: actions/upload-artifact@v4 + if: always( ) + with: + name: crashes + path: | + crash-* + leak-* + timeout-* + if-no-files-found: ignore diff --git a/.github/workflows/ci_windows_clangcl.yml b/.github/workflows/ci_windows_clangcl.yml deleted file mode 100644 index 25a8e13b2..000000000 --- a/.github/workflows/ci_windows_clangcl.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Windows_ClangCl - -on: - push: - branches-ignore: dev - pull_request: - branches-ignore: dev - -jobs: - build: - runs-on: [windows-2019] - steps: - - uses: actions/checkout@v1 - - name: Build - run: .\ci_scripts\ci_windows_build_clangcl.cmd - - name: Test - run: .\ci_scripts\ci_windows_test.cmd - diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f1b2a525..df2c838a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ cmake_minimum_required( VERSION 3.14 ) project( "daw-header-libraries" - VERSION "2.124.1" + VERSION "2.127.0" DESCRIPTION "Various headers" HOMEPAGE_URL "https://github.com/beached/header_libraries" LANGUAGES C CXX diff --git a/ci_scripts/ci_windows_build.cmd b/ci_scripts/ci_windows_build.cmd deleted file mode 100755 index 6ea9172e5..000000000 --- a/ci_scripts/ci_windows_build.cmd +++ /dev/null @@ -1,22 +0,0 @@ -@ECHO OFF - -ECHO "##############################" -ECHO "Installing Ninja" -vcpkg upgrade -REM vcpkg install ninja - -md build -cd build - -ECHO "##############################" -ECHO "Setting VCVars" -@call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64 - -ECHO "##############################" -ECHO "Running cmake" -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_COMPILER=cl.exe -DCMAKE_C_COMPILER=cl.exe -DDAW_ENABLE_TESTING=On .. - - -ECHO "##############################" -ECHO "Building" -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" --build . --config Debug --target daw-header-libraries_full -j 2 -- -k 1000 diff --git a/ci_scripts/ci_windows_build_clangcl.cmd b/ci_scripts/ci_windows_build_clangcl.cmd deleted file mode 100755 index f0051cda0..000000000 --- a/ci_scripts/ci_windows_build_clangcl.cmd +++ /dev/null @@ -1,16 +0,0 @@ -@ECHO OFF - -md build -cd build - -ECHO "##############################" -ECHO "Setting VCVars" -@call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64 - -ECHO "##############################" -ECHO "Running cmake" -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe" -DCMAKE_C_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe" -DDAW_ENABLE_TESTING=On .. - -ECHO "##############################" -ECHO "Building" -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" --build . --config Debug --target daw-header-libraries_full -j 2 -- -k 1000 diff --git a/ci_scripts/ci_windows_install_test.cmd b/ci_scripts/ci_windows_install_test.cmd deleted file mode 100755 index f2e1595b9..000000000 --- a/ci_scripts/ci_windows_install_test.cmd +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -cd build - - -ECHO "##############################" -ECHO "Setting VCVars" -@call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64 - -echo "#################################" -echo "Starting Install Tests" -cmake --install . -cd ../cmake/test_project/ -md build -cd build -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_COMPILER=cl.exe -DCMAKE_C_COMPILER=cl.exe .. -IF %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" --build . --config Debug -IF %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/ctest.exe" -C Debug -VV -IF %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% diff --git a/ci_scripts/ci_windows_install_test_clangcl.cmd b/ci_scripts/ci_windows_install_test_clangcl.cmd deleted file mode 100755 index 75e556cd3..000000000 --- a/ci_scripts/ci_windows_install_test_clangcl.cmd +++ /dev/null @@ -1,20 +0,0 @@ -@ECHO OFF - -cd build - -ECHO "##############################" -ECHO "Setting VCVars" -@call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64 - -echo "#################################" -echo "Starting Install Tests" -cmake --install . -cd ../cmake/test_project/ -md build -cd build -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe" -DCMAKE_C_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe" .. -IF %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/cmake.exe" --build . --config Debug -IF %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/ctest.exe" -C Debug -VV -IF %ERRORLEVEL% NEQ 0 EXIT %ERRORLEVEL% diff --git a/ci_scripts/ci_windows_test.cmd b/ci_scripts/ci_windows_test.cmd deleted file mode 100755 index 780823aa8..000000000 --- a/ci_scripts/ci_windows_test.cmd +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -cd build - -ECHO "#################################3" -ECHO "Starting Tests" -"C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2019/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/CMAKE/CMake/bin/ctest.exe" -C Debug --target daw-header-libraries_full -j 2 -VV --timeout 300 diff --git a/include/daw/daw_ascii.h b/include/daw/daw_ascii.h new file mode 100644 index 000000000..28750ba40 --- /dev/null +++ b/include/daw/daw_ascii.h @@ -0,0 +1,98 @@ +// Copyright (c) Darrell Wright +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/beached/header_libraries +// + +#pragma once + +#include "daw/daw_attributes.h" +#include "daw/daw_cpp_feature_check.h" +#include "daw/impl/daw_make_trait.h" + +#include + +namespace daw { + struct is_ascii_digit_t { + explicit is_ascii_digit_t( ) = default; + + template, + std::nullptr_t> = nullptr> + DAW_ATTRIB_INLINE DAW_CPP23_STATIC_CALL_OP constexpr bool + operator( )( Integer c ) DAW_CPP23_STATIC_CALL_OP_CONST { + // '0' <= c <= '9' + return Integer{ 48 } <= c and c <= Integer{ 57 }; + } + }; + inline constexpr auto is_ascii_digit = is_ascii_digit_t{ }; + + struct is_ascii_alpha_t { + explicit is_ascii_alpha_t( ) = default; + + template, + std::nullptr_t> = nullptr> + DAW_ATTRIB_INLINE DAW_CPP23_STATIC_CALL_OP constexpr bool + operator( )( Integer c ) DAW_CPP23_STATIC_CALL_OP_CONST { + // ( 'A' <= c <= 'Z' ) or ( 'a' <= c <= 'z' ) + return ( Integer{ 65 } <= c and c <= Integer{ 90 } ) or + ( Integer{ 97 } <= c and c <= Integer{ 122 } ); + } + }; + inline constexpr auto is_ascii_alpha = is_ascii_alpha_t{ }; + + struct is_ascii_alphanum_t { + explicit is_ascii_alphanum_t( ) = default; + + template, + std::nullptr_t> = nullptr> + DAW_ATTRIB_INLINE DAW_CPP23_STATIC_CALL_OP constexpr bool + operator( )( Integer c ) DAW_CPP23_STATIC_CALL_OP_CONST { + return is_ascii_digit( c ) or is_ascii_alpha( c ); + } + }; + inline constexpr auto is_ascii_alphanum = is_ascii_alphanum_t{ }; + + struct is_ascii_printable_t { + explicit is_ascii_printable_t( ) = default; + + template, + std::nullptr_t> = nullptr> + DAW_ATTRIB_INLINE DAW_CPP23_STATIC_CALL_OP constexpr bool + operator( )( Integer c ) DAW_CPP23_STATIC_CALL_OP_CONST { + return Integer{ 32 } <= c and c < Integer{ 127 }; + } + }; + inline constexpr auto is_ascii_printable = is_ascii_printable_t{ }; + + struct to_upper_ascii_t { + explicit to_upper_ascii_t( ) = default; + + template, + std::nullptr_t> = nullptr> + DAW_ATTRIB_INLINE DAW_CPP23_STATIC_CALL_OP constexpr Integer + operator( )( Integer c ) DAW_CPP23_STATIC_CALL_OP_CONST { + if( Integer{ 97 } <= c and c <= Integer{ 122 } ) { + return static_cast( c - Integer{ 32 } ); + } + return c; + } + }; + inline constexpr auto to_upper_ascii = to_upper_ascii_t{ }; + + struct to_lower_ascii_t { + explicit to_lower_ascii_t( ) = default; + + template, + std::nullptr_t> = nullptr> + DAW_ATTRIB_INLINE DAW_CPP23_STATIC_CALL_OP constexpr Integer + operator( )( Integer c ) DAW_CPP23_STATIC_CALL_OP_CONST { + if( Integer{ 65 } <= c and c <= Integer{ 90 } ) { + return static_cast( c + Integer{ 32 } ); + } + return c; + } + }; + inline constexpr auto to_lower_ascii = to_lower_ascii_t{ }; +} // namespace daw diff --git a/include/daw/daw_attributes.h b/include/daw/daw_attributes.h index 90486f533..a78491b02 100644 --- a/include/daw/daw_attributes.h +++ b/include/daw/daw_attributes.h @@ -104,7 +104,7 @@ #endif -#if defined( DAW_HAS_MSVC ) +#if defined( DAW_HAS_MSVC_LIKE ) #define DAW_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] #else #define DAW_NO_UNIQUE_ADDRESS [[no_unique_address]] diff --git a/include/daw/daw_contract.h b/include/daw/daw_contract.h new file mode 100644 index 000000000..05bf33eb6 --- /dev/null +++ b/include/daw/daw_contract.h @@ -0,0 +1,96 @@ +// Copyright (c) Darrell Wright +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/beached/header_libraries +// + +#pragma once + +#include "daw/daw_assume.h" +#include "daw/daw_attributes.h" +#include "daw/daw_check_exceptions.h" +#include "daw/daw_consteval.h" +#include "daw/daw_cpp_feature_check.h" +#include "daw/daw_function_ref.h" + +#include +#include +#include +#include +#include + +namespace daw { +#if defined( DAW_USE_EXCEPTIONS ) + struct daw_contract_violation : std::exception {}; + [[noreturn]] inline void default_contract_failure( ) { + throw daw_contract_violation{ }; + } +#else + [[noreturn]] inline void default_contract_failure( ) { + std::abort( ); + } +#endif + constinit static thread_local daw::function_ref + contract_failure_handler = default_contract_failure; + + DAW_ATTRIB_NOINLINE inline void contract_failure( ) { + contract_failure_handler( ); + } + + template + requires( std::is_invocable_r_v and... ) // + class contract { + T value; + + static constexpr bool validate( T value ) { + return ( Preconditions{ }( value ) and ... ); + } + + public: + DAW_ATTRIB_FLATINLINE constexpr contract( T v ) + : value( std::move( v ) ) { + if( not validate( value ) ) { + contract_failure( ); + } + } + + DAW_ATTRIB_FLATINLINE constexpr T extract( ) { + DAW_ASSUME( validate( value ) ); + return std::move( value ); + } + + DAW_ATTRIB_FLATINLINE constexpr T &operator*( ) { + DAW_ASSUME( validate( value ) ); + return value; + } + + DAW_ATTRIB_FLATINLINE constexpr T const &operator*( ) const { + DAW_ASSUME( validate( value ) ); + return value; + } + + DAW_ATTRIB_FLATINLINE constexpr operator T const &( ) const { + DAW_ASSUME( validate( value ) ); + return value; + } + + template + using add_precondition_t = contract; + + template + DAW_ATTRIB_FLATINLINE constexpr operator contract( ) const { + DAW_ASSUME( validate( value ) ); + return contract( value ); + } + + template + requires( std::is_invocable_r_v and... ) // + constexpr auto add_condition( Pre2s... ) const { + + DAW_ASSUME( validate( value ) ); + return contract{ value }; + } + }; +} // namespace daw diff --git a/include/daw/daw_cxmath.h b/include/daw/daw_cxmath.h index 75add3777..a8321713c 100644 --- a/include/daw/daw_cxmath.h +++ b/include/daw/daw_cxmath.h @@ -463,6 +463,16 @@ namespace daw::cxmath { } } +#if DAW_HAS_BUILTIN( __builtin_clzg ) + template, + std::nullptr_t> = nullptr> + [[nodiscard]] DAW_ATTRIB_INLINE constexpr std::uint32_t + count_leading_zeroes( Unsigned u ) { + return static_cast( + __builtin_clzg( u, static_cast( daw::bit_count_v ) ) ); + } +#else + #if DAW_HAS_BUILTIN( __builtin_clz ) [[nodiscard]] DAW_ATTRIB_INLINE constexpr unsigned count_leading_zeroes( unsigned v ) noexcept { @@ -480,11 +490,6 @@ namespace daw::cxmath { return static_cast( bit_count_v ); } - [[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr unsigned - count_leading_zeroes( daw::UInt32 v ) noexcept { - return count_leading_zeroes( static_cast( v ) ); - } - #if DAW_HAS_BUILTIN( __builtin_clzll ) [[nodiscard]] DAW_ATTRIB_INLINE constexpr unsigned count_leading_zeroes( unsigned long long v ) noexcept { @@ -512,11 +517,6 @@ namespace daw::cxmath { #endif - [[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr unsigned - count_leading_zeroes( daw::UInt64 v ) noexcept { - return count_leading_zeroes( static_cast( v ) ); - } - #else // Based on code from // https://graphics.stanford.edu/~seander/bithacks.html @@ -542,18 +542,32 @@ namespace daw::cxmath { return 63U - static_cast( bit_position[( v * 0x021'8a39'2cd3'd5dbf ) >> 58U] ); // [3] } +#endif +#if defined( DAW_HAS_INT128 ) + [[nodiscard]] DAW_ATTRIB_FLATTEN constexpr std::uint32_t + count_leading_zeros( daw::uint128_t v ) { + if( v == 0 ) { + return 128U; + } + auto const h = + count_leading_zeros( static_cast( v >> 64ULL ) ); + if( h == 64U ) { + return count_leading_zeros( static_cast( v ) ); + } + return h; + } +#endif +#endif + [[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr unsigned + count_leading_zeroes( daw::UInt32 v ) noexcept { + return count_leading_zeroes( static_cast( v ) ); + } - [[nodiscard]] constexpr std::uint32_t + [[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr unsigned count_leading_zeroes( daw::UInt64 v ) noexcept { return count_leading_zeroes( static_cast( v ) ); } - [[nodiscard]] constexpr std::uint32_t - count_leading_zeroes( daw::UInt32 v ) noexcept { - return count_leading_zeroes( static_cast( v ) << 32U ); - } -#endif - namespace cxmath_impl { [[nodiscard]] DAW_ATTRIB_INLINE constexpr std::uint32_t count_trailing_zeros_cx32( std::uint32_t v ) noexcept { @@ -1372,9 +1386,11 @@ namespace daw::cxmath { 10'000'000'000'000'000'000ull }; constexpr int count_digits( std::uint64_t value ) { - auto b = -( value > 0 ) & ( 63 - count_leading_zeroes( value ) ); + auto b = -static_cast( value > 0 ) & + ( 63 - count_leading_zeroes( value ) ); auto a = ( b * 77 ) / 256; - return static_cast( 1 + a + ( value >= powers_of_ten[a] ) ); + return static_cast( + 1 + a + static_cast( value >= powers_of_ten[a] ) ); } static_assert( count_digits( 1'000'000ULL ) == 7 ); } // namespace daw::cxmath diff --git a/include/daw/daw_fnv1a_hash.h b/include/daw/daw_fnv1a_hash.h index e7f72642b..462250026 100644 --- a/include/daw/daw_fnv1a_hash.h +++ b/include/daw/daw_fnv1a_hash.h @@ -68,11 +68,12 @@ namespace daw { std::nullptr_t> = nullptr> [[nodiscard]] static constexpr fnv1a_uint_t append_hash( fnv1a_uint_t current_hash, Value const &value ) noexcept { + struct array_t { + unsigned char values[sizeof( Value )]; + }; + auto const chars = DAW_BIT_CAST( array_t, value ); for( fnv1a_uint_t n = 0; n < sizeof( Value ); ++n ) { - current_hash ^= static_cast( - ( static_cast( value ) & - ( fnv1a_uint_t{ 0xFFU } << (n * bit_count_v)) ) >> - (n * bit_count_v)); + current_hash ^= chars.values[n]; current_hash *= fnv1a_impl::fnv_prime; } return current_hash; diff --git a/include/daw/daw_function_ref.h b/include/daw/daw_function_ref.h index 83dd4f4be..7169c3f53 100644 --- a/include/daw/daw_function_ref.h +++ b/include/daw/daw_function_ref.h @@ -84,19 +84,22 @@ namespace daw { constexpr function_ref( Result ( *ptr )( Params... ) ) noexcept : m_data( ptr ) - , m_thunk( fp_thunk ) { + , m_thunk( nullptr ) { assert( ptr ); } constexpr function_ref &operator=( Result ( *ptr )( Params... ) ) noexcept { m_data = ptr; - m_thunk = fp_thunk; + m_thunk = nullptr; assert( ptr ); return *this; } constexpr Result operator( )( Params... params ) const { - return m_thunk( m_data, params... ); + if( not m_thunk ) { + return m_data.func_ptr( std::forward( params )... ); + } + return m_thunk( m_data, std::forward( params )... ); } }; diff --git a/include/daw/daw_read_file.h b/include/daw/daw_read_file.h index c4b7a2440..40b0bd26d 100644 --- a/include/daw/daw_read_file.h +++ b/include/daw/daw_read_file.h @@ -36,10 +36,18 @@ namespace daw { } auto result = std::basic_string( static_cast( fsize ), CharT{ } ); +#if defined( _MSC_VER ) + FILE * f = nullptr; + auto err = fopen_s( &f, path.c_str( ), "rb" ); + if( err ) { + return std::nullopt; + } +#else auto *f = fopen( path.c_str( ), "rb" ); if( not f ) { return std::nullopt; } +#endif auto num_read = fread( result.data( ), sizeof( CharT ), result.size( ), f ); if( num_read != ( result.size( ) / sizeof( CharT ) ) ) { return std::nullopt; @@ -76,8 +84,9 @@ namespace daw { } auto result = std::basic_string( static_cast( fsize ), CharT{ } ); - auto *f = _wfopen( path.c_str( ), L"rb" ); - if( not f ) { + FILE * f = nullptr; + auto err = _wfopen_s( &f, path.c_str( ), L"rb" ); + if( err ) { return std::nullopt; } auto num_read = fread( result.data( ), sizeof( CharT ), result.size( ), f ); diff --git a/include/daw/daw_size_literals.h b/include/daw/daw_size_literals.h index a10d61ae1..9f1cba752 100644 --- a/include/daw/daw_size_literals.h +++ b/include/daw/daw_size_literals.h @@ -8,55 +8,53 @@ #pragma once -#include - namespace daw::size_literals { - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_KB( unsigned long long val ) noexcept { return val * 1024ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_MB( unsigned long long val ) noexcept { return val * 1024ull * 1024ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_GB( unsigned long long val ) noexcept { return val * 1024ull * 1024ull * 1024ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_TB( unsigned long long val ) noexcept { return val * 1024ull * 1024ull * 1024ull * 1024ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_PB( unsigned long long val ) noexcept { return val * 1024ull * 1024ull * 1024ull * 1024ull * 1024ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_KiB( unsigned long long val ) noexcept { return val * 1000ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_MiB( unsigned long long val ) noexcept { return val * 1000ull * 1000ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_GiB( unsigned long long val ) noexcept { return val * 1000ull * 1000ull * 1000ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_TiB( unsigned long long val ) noexcept { return val * 1000ull * 1000ull * 1000ull * 1000ull; } - [[nodiscard]] constexpr size_t + [[nodiscard]] constexpr unsigned long long operator""_PiB( unsigned long long val ) noexcept { return val * 1000ull * 1000ull * 1000ull * 1000ull * 1000ull; } diff --git a/include/daw/daw_string_view.h b/include/daw/daw_string_view.h index f3b5da826..b78110e75 100644 --- a/include/daw/daw_string_view.h +++ b/include/daw/daw_string_view.h @@ -536,8 +536,8 @@ namespace daw { /// refer to a constant contiguous sequence of char-like objects with the /// first element of the sequence at position zero. template - struct [[DAW_PREF_NAME( string_view ), - DAW_PREF_NAME( wstring_view )]] basic_string_view { + struct [[DAW_PREF_NAME( string_view ), DAW_PREF_NAME( wstring_view )]] + basic_string_view { using value_type = CharT; using pointer = CharT *; using const_pointer = std::add_const_t *; diff --git a/include/daw/daw_to_underlying_type.h b/include/daw/daw_to_underlying_type.h new file mode 100644 index 000000000..fa72eeec6 --- /dev/null +++ b/include/daw/daw_to_underlying_type.h @@ -0,0 +1,19 @@ +// Copyright (c) Darrell Wright +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/beached/header_libraries +// + +#pragma once + +#include + +namespace daw { + template, std::nullptr_t> = nullptr> + constexpr auto to_underlying( Enum e ) { + return static_cast>( e ); + } +} // namespace daw diff --git a/include/daw/daw_uninitialized_storage.h b/include/daw/daw_uninitialized_storage.h index f69150446..17363d8a4 100644 --- a/include/daw/daw_uninitialized_storage.h +++ b/include/daw/daw_uninitialized_storage.h @@ -39,7 +39,7 @@ namespace daw { void construct( Args &&...args ) noexcept( std::is_nothrow_constructible_v ) { - if constexpr( std::is_aggregate_v ) { + if constexpr( std::is_class_v and std::is_aggregate_v ) { new( m_data ) T{ DAW_FWD( args )... }; } else { new( m_data ) T( std ::forward( args )... ); diff --git a/include/daw/pipelines/enumerate.h b/include/daw/pipelines/enumerate.h index 83a91ea0a..2279da1c3 100644 --- a/include/daw/pipelines/enumerate.h +++ b/include/daw/pipelines/enumerate.h @@ -20,10 +20,9 @@ namespace daw::pipelines::pimpl { template struct Enumerate_t { - template + template [[nodiscard]] DAW_CPP23_STATIC_CALL_OP constexpr auto operator( )( R &&r ) DAW_CPP23_STATIC_CALL_OP_CONST { - static_assert( Range ); return zip_view, daw::remove_cvref_t>( iota_view( 0, max_value ), DAW_FWD( r ) ); } @@ -32,9 +31,8 @@ namespace daw::pipelines::pimpl { template struct EnumerateFrom_t { EnumType offset = EnumType{ }; - template + template [[nodiscard]] constexpr auto operator( )( R &&r ) const { - static_assert( Range ); return zip_view, daw::remove_cvref_t>( iota_view( offset, max_value ), DAW_FWD( r ) ); } @@ -42,7 +40,7 @@ namespace daw::pipelines::pimpl { template struct EnumerateApply_t { - template + template [[nodiscard]] DAW_CPP23_STATIC_CALL_OP constexpr auto operator( )( R &&r ) DAW_CPP23_STATIC_CALL_OP_CONST { if constexpr( RandomRange ) { @@ -59,7 +57,7 @@ namespace daw::pipelines::pimpl { template struct EnumerateApplyFrom_t { EnumType offset = EnumType{ }; - template + template [[nodiscard]] constexpr auto operator( )( R &&r ) const { if constexpr( RandomRange ) { auto const sz = static_cast( diff --git a/include/daw/pipelines/every.h b/include/daw/pipelines/every.h index d94f7c7bc..7c22d7b61 100644 --- a/include/daw/pipelines/every.h +++ b/include/daw/pipelines/every.h @@ -15,11 +15,7 @@ namespace daw::pipelines::pimpl { struct Every_t { std::size_t m_select_every; - template - [[nodiscard]] constexpr auto operator( )( R &&r ) const { - static_assert( Range, - "Every requires the previous algorithm in the pipeline " - "to return a range" ); + [[nodiscard]] constexpr auto operator( )( Range auto &&r ) const { return filter_view{ std::begin( DAW_FWD( r ) ), std::end( DAW_FWD( r ) ), [select_every = m_select_every, n = m_select_every]( auto const & ) mutable { diff --git a/include/daw/pipelines/iota.h b/include/daw/pipelines/iota.h index 3647d192e..6183f0f62 100644 --- a/include/daw/pipelines/iota.h +++ b/include/daw/pipelines/iota.h @@ -177,6 +177,6 @@ namespace daw::pipelines { iota_view( T, T ) -> iota_view; inline constexpr auto ToIota = []( I last ) { - return iota_view{ 0, last }; + return iota_view{ I{}, last }; }; } // namespace daw::pipelines diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 33c02df95..35408eedf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,6 +21,7 @@ set( TEST_SOURCES daw_arith_traits_test.cpp daw_array_compare_test.cpp daw_array_test.cpp + daw_ascii_test.cpp daw_assume_test.cpp daw_attributes_test.cpp daw_benchmark_test.cpp @@ -152,6 +153,7 @@ set( CPP20_TEST_SOURCES ) set( CPP20_NOT_MSVC_TEST_SOURCES + daw_contract_test.cpp daw_pipelines_test.cpp vector_test.cpp ) diff --git a/tests/cmake/test_compiler_options.cmake b/tests/cmake/test_compiler_options.cmake index 34e857bf7..34dde0bb4 100644 --- a/tests/cmake/test_compiler_options.cmake +++ b/tests/cmake/test_compiler_options.cmake @@ -16,6 +16,7 @@ if( ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQU if( DAW_WERROR ) add_compile_options( /WX ) endif() + add_compile_options( -Wno-missing-braces ) else() message( STATUS "Clang ${CMAKE_CXX_COMPILER_VERSION} detected" ) add_compile_options( diff --git a/tests/daw_ascii_test.cpp b/tests/daw_ascii_test.cpp new file mode 100644 index 000000000..ab65233da --- /dev/null +++ b/tests/daw_ascii_test.cpp @@ -0,0 +1,20 @@ +// Copyright (c) Darrell Wright +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/beached/header_libraries +// + +#include +#include + +int main( ) { + daw_ensure( daw::is_ascii_alpha( 'a' ) ); + daw_ensure( not daw::is_ascii_alpha( '0' ) ); + daw_ensure( daw::is_ascii_digit( '0' ) ); + daw_ensure( not daw::is_ascii_digit( 'a' ) ); + daw_ensure( daw::is_ascii_alphanum( 'a' ) ); + daw_ensure( not daw::is_ascii_alphanum( ' ' ) ); + daw_ensure( daw::is_ascii_printable( '!' ) ); +} \ No newline at end of file diff --git a/tests/daw_contract_test.cpp b/tests/daw_contract_test.cpp new file mode 100644 index 000000000..b6617c5eb --- /dev/null +++ b/tests/daw_contract_test.cpp @@ -0,0 +1,28 @@ +// Copyright (c) Darrell Wright +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/beached/header_libraries +// + +#include +#include + +int main( ) { + using positive_integral = decltype( []( T const &value ) { + return value >= T{ }; + } ); + using pos_int = daw::contract; + static constexpr auto v0 = pos_int( 42 ); + constexpr int const &v0cr = v0; + (void)v0cr; +#if defined( DAW_USE_EXCEPTIONS ) + bool has_error = false; + try { + auto v1 = pos_int{ -1 }; + (void)v1; + } catch( daw::daw_contract_violation const & ) { has_error = true; } + daw_ensure( has_error ); +#endif +} diff --git a/tests/daw_function_ref_test.cpp b/tests/daw_function_ref_test.cpp index a9e1c0673..325610b18 100644 --- a/tests/daw_function_ref_test.cpp +++ b/tests/daw_function_ref_test.cpp @@ -34,7 +34,7 @@ inline constexpr int add( int a, int b, int c ) { } DAW_CONSTEVAL void test2( ) { - auto const r = func( add ); + constexpr auto const r = func( add ); daw_ensure( r == 96 ); } diff --git a/tests/daw_size_literals_test.cpp b/tests/daw_size_literals_test.cpp index ae6b95542..be0b27f69 100644 --- a/tests/daw_size_literals_test.cpp +++ b/tests/daw_size_literals_test.cpp @@ -13,8 +13,8 @@ namespace daw_size_literals_001 { static_assert( 1_KB == 1024ull ); static_assert( 1_MB == 1024ull * 1024u ); static_assert( 1_GB == 1024ull * 1024u * 1024u ); - static_assert( 1_TB == 1024ull * 1024u * 1024u * 1024u ); - static_assert( 1_PB == 1024ull * 1024u * 1024u * 1024u * 1024u ); + static_assert( 1_TB == 1024ull * 1024ull * 1024ull * 1024ull ); + static_assert( 1_PB == 1024ull * 1024ull * 1024ull * 1024ull * 1024ull ); } // namespace daw_size_literals_001 int main( ) {}