diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 718317c..3ea3c78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ # Copyright 2020-2021 Peter Dimov -# Copyright 2021 Andrey Semashev +# Copyright 2021-2022 Andrey Semashev # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) @@ -14,10 +14,6 @@ on: - develop - feature/** -concurrency: - group: ${{format('{0}:{1}', github.repository, github.ref)}} - cancel-in-progress: true - env: GIT_FETCH_JOBS: 8 NET_RETRY_COUNT: 5 @@ -36,7 +32,7 @@ jobs: # Linux, gcc - toolset: gcc-4.4 cxxstd: "98,0x" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.4 @@ -44,7 +40,7 @@ jobs: - "ppa:ubuntu-toolchain-r/test" - toolset: gcc-4.6 cxxstd: "03,0x" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.6 @@ -52,45 +48,49 @@ jobs: - "ppa:ubuntu-toolchain-r/test" - toolset: gcc-4.7 cxxstd: "03,11" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.7 - toolset: gcc-4.8 cxxstd: "03,11" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-4.8 - toolset: gcc-4.9 cxxstd: "03,11" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-4.9 - toolset: gcc-5 cxxstd: "03,11,14,1z" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - g++-5 - toolset: gcc-6 cxxstd: "03,11,14,1z" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-6 - toolset: gcc-7 cxxstd: "03,11,14,17" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-7 - toolset: gcc-8 cxxstd: "03,11,14,17,2a" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - g++-8 - toolset: gcc-9 cxxstd: "03,11,14,17,2a" - os: ubuntu-18.04 + os: ubuntu-20.04 install: - g++-9 - toolset: gcc-10 @@ -99,86 +99,93 @@ jobs: install: - g++-10 - toolset: gcc-11 - cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + cxxstd: "03,11,14,17,20,23" + os: ubuntu-22.04 install: - g++-11 - sources: - - "ppa:ubuntu-toolchain-r/test" + - toolset: gcc-12 + cxxstd: "03,11,14,17,20,23" + os: ubuntu-22.04 + install: + - g++-12 - name: UBSAN - toolset: gcc-11 - cxxstd: "03,11,14,17,20" + toolset: gcc-12 + cxxstd: "03,11,14,17,20,23" ubsan: 1 - os: ubuntu-20.04 + os: ubuntu-22.04 install: - - g++-11 - sources: - - "ppa:ubuntu-toolchain-r/test" + - g++-12 # Linux, clang - toolset: clang compiler: clang++-3.5 cxxstd: "03,11" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.5 - toolset: clang compiler: clang++-3.6 cxxstd: "03,11,14" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.6 - toolset: clang compiler: clang++-3.7 cxxstd: "03,11,14" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.7 - toolset: clang compiler: clang++-3.8 cxxstd: "03,11,14" - os: ubuntu-20.04 + os: ubuntu-latest container: ubuntu:16.04 install: - clang-3.8 - toolset: clang compiler: clang++-3.9 cxxstd: "03,11,14" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-3.9 - toolset: clang compiler: clang++-4.0 cxxstd: "03,11,14" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-4.0 - toolset: clang compiler: clang++-5.0 cxxstd: "03,11,14,1z" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-5.0 - toolset: clang compiler: clang++-6.0 cxxstd: "03,11,14,17" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-6.0 - toolset: clang compiler: clang++-7 cxxstd: "03,11,14,17" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-7 # Note: clang-8 does not fully support C++20, so it is not compatible with libstdc++-8 in this mode - toolset: clang compiler: clang++-8 cxxstd: "03,11,14,17,2a" - os: ubuntu-18.04 + os: ubuntu-latest + container: ubuntu:18.04 install: - clang-8 - g++-7 @@ -198,45 +205,67 @@ jobs: - toolset: clang compiler: clang++-11 cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + os: ubuntu-22.04 install: - clang-11 - toolset: clang compiler: clang++-12 - cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 install: - clang-12 - toolset: clang - compiler: clang++-12 - cxxstd: "03,11,14,17,20" + compiler: clang++-13 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-13 + - toolset: clang + compiler: clang++-14 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-14 + - toolset: clang + compiler: clang++-15 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-15 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-15 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-15 + - libc++-15-dev + - libc++abi-15-dev + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" cxxflags: -stdlib=libc++ linkflags: -stdlib=libc++ - os: ubuntu-20.04 - install: - - clang-12 - - libc++-12-dev - - libc++abi-12-dev - name: UBSAN toolset: clang - compiler: clang++-12 - cxxstd: "03,11,14,17,20" + compiler: clang++-14 + cxxstd: "03,11,14,17,20,2b" cxxflags: -stdlib=libc++ linkflags: -stdlib=libc++ ubsan: 1 - os: ubuntu-20.04 + os: ubuntu-22.04 install: - - clang-12 - - libc++-12-dev - - libc++abi-12-dev + - clang-14 + - libc++-14-dev + - libc++abi-14-dev - toolset: clang cxxstd: "03,11,14,17,2a" - os: macos-10.15 - - - name: CMake tests - cmake_tests: 1 - os: ubuntu-20.04 + os: macos-11 timeout-minutes: 120 runs-on: ${{matrix.os}} @@ -256,38 +285,48 @@ jobs: if [ -f "/etc/debian_version" ] then apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ python python3 git cmake + if [ "$(apt-cache search "^python-is-python3$" | wc -l)" -ne 0 ] + then + PYTHON_PACKAGE="python-is-python3" + else + PYTHON_PACKAGE="python" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ $PYTHON_PACKAGE python3 perl git cmake fi fi git config --global pack.threads 0 - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install packages if: matrix.install run: | - SOURCE_KEYS=(${{join(matrix.source_keys, ' ')}}) - SOURCES=(${{join(matrix.sources, ' ')}}) + declare -a SOURCE_KEYS SOURCES + if [ -n "${{join(matrix.source_keys, ' ')}}" ] + then + SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}") + fi + if [ -n "${{join(matrix.sources, ' ')}}" ] + then + SOURCES=("${{join(matrix.sources, '" "')}}") + fi for key in "${SOURCE_KEYS[@]}" do for i in {1..$NET_RETRY_COUNT} do + echo "Adding key: $key" wget -O - "$key" | sudo apt-key add - && break || sleep 2 done done if [ ${#SOURCES[@]} -gt 0 ] then APT_ADD_REPO_COMMON_ARGS=("-y") - APT_ADD_REPO_HAS_SOURCE_ARGS=0 - SOFTWARE_PROPERTIES_VERSION="$(dpkg-query --showformat='${Version}' --show software-properties-common)" - if dpkg --compare-versions "$SOFTWARE_PROPERTIES_VERSION" ge "0.96.24.20" + APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')" + if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ] then APT_ADD_REPO_COMMON_ARGS+=("-n") fi - if dpkg --compare-versions "$SOFTWARE_PROPERTIES_VERSION" ge "0.98.10" - then - APT_ADD_REPO_HAS_SOURCE_ARGS=1 - fi + APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)" for source in "${SOURCES[@]}" do for i in {1..$NET_RETRY_COUNT} @@ -308,6 +347,7 @@ jobs: esac fi APT_ADD_REPO_ARGS+=("$source") + echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}" sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2 done done @@ -338,7 +378,7 @@ jobs: REF=${GITHUB_BASE_REF:-$GITHUB_REF} REF=${REF#refs/heads/} echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true echo BOOST_BRANCH: $BOOST_BRANCH BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV @@ -380,19 +420,16 @@ jobs: git submodule update --init tools/boostdep DEPINST_ARGS+=("$LIBRARY") python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}" - if [ -z "${{matrix.cmake_tests}}" ] + ./bootstrap.sh + ./b2 headers + if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] then - ./bootstrap.sh - ./b2 headers - if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] + echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam + if [ -n "$GCC_TOOLCHAIN_ROOT" ] then - echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam - if [ -n "$GCC_TOOLCHAIN_ROOT" ] - then - echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam - fi - echo " ;" >> ~/user-config.jam + echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam fi + echo " ;" >> ~/user-config.jam fi - name: Run tests @@ -426,50 +463,27 @@ jobs: B2_ARGS+=("libs/$LIBRARY/test") ./b2 "${B2_ARGS[@]}" - - name: Run CMake tests - if: matrix.cmake_tests != '' - run: | - cd ../boost-root - mkdir __build_cmake_test__ && cd __build_cmake_test__ - cmake -DBUILD_TESTING=ON -DBOOST_INCLUDE_LIBRARIES=$LIBRARY .. - cmake --build . --target tests - ctest --output-on-failure - - - name: Run CMake subdir tests - if: matrix.cmake_tests != '' - run: | - cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test - mkdir __build_cmake_subdir_test__ && cd __build_cmake_subdir_test__ - cmake .. - cmake --build . - cmake --build . --target check - - - name: Run CMake install tests - if: matrix.cmake_tests != '' - run: | - cd ../boost-root - mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__ - cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. - cmake --build . --target install - cd ../libs/$LIBRARY/test/cmake_install_test - mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__ - cmake -DCMAKE_INSTALL_PREFIX=~/.local .. - cmake --build . - cmake --build . --target check - windows: strategy: fail-fast: false matrix: include: - - toolset: msvc-14.1 - cxxstd: "14,17,latest" - addrmd: 32,64 - os: windows-2016 - - toolset: msvc-14.2 - cxxstd: "14,17,latest" + - toolset: msvc-14.0 + cxxstd: "14" addrmd: 32,64 os: windows-2019 + - toolset: msvc-14.2 + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2019 + - toolset: msvc-14.3 + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2022 + - toolset: clang-win + cxxstd: "14,17,latest" + addrmd: 32,64 + os: windows-2022 - toolset: gcc cxxstd: "03,11,14,17,2a" addrmd: 64 @@ -478,7 +492,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Boost shell: cmd @@ -506,4 +520,160 @@ jobs: shell: cmd run: | cd ../boost-root - b2 -j %NUMBER_OF_PROCESSORS% libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release + b2 -j %NUMBER_OF_PROCESSORS% libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker + + posix-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-11 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" $LIBRARY + + - name: Use library with add_subdirectory + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . -- -j $BUILD_JOBS + ctest --output-on-failure --no-tests=error + + posix-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-11 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. + + - name: Install + run: | + cd ../boost-root/__build__ + cmake --build . --target install -- -j $BUILD_JOBS + + - name: Use the installed library + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=~/.local .. + cmake --build . -- -j $BUILD_JOBS + ctest --output-on-failure --no-tests=error + + posix-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-11 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs $GIT_FETCH_JOBS" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. + + - name: Build tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests -- -j $BUILD_JOBS + + - name: Run tests + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error diff --git a/CMakeLists.txt b/CMakeLists.txt index 2110bcc..4a0d81a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ -# Copyright 2018, 2019 Peter Dimov +# Generated by `boostdep --cmake core` +# Copyright 2020, 2021 Peter Dimov # 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 +# https://www.boost.org/LICENSE_1_0.txt -cmake_minimum_required(VERSION 3.5...3.16) +cmake_minimum_required(VERSION 3.5...3.20) project(boost_core VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) @@ -15,9 +16,11 @@ target_link_libraries(boost_core INTERFACE Boost::assert Boost::config + Boost::static_assert + Boost::throw_exception ) -if(BUILD_TESTING) +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") add_subdirectory(test) diff --git a/appveyor.yml b/appveyor.yml index c25fb9e..ae3ed65 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -# Copyright 2016-2019 Peter Dimov +# Copyright 2016-2021 Peter Dimov # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) @@ -27,14 +27,11 @@ environment: ADDRMD: 32,64 CXXSTD: 14,17 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - TOOLSET: msvc-14.2 - ADDRMD: 32,64 - CXXSTD: 14,17,latest + # clang-win 32 bit fails to link with "unable to load mspdbcore.dll (error code: 126)" - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 TOOLSET: clang-win - ADDRMD: 32,64 + ADDRMD: 64 CXXSTD: 14,17,latest - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -63,22 +60,15 @@ environment: CXXSTD: 03,11,14,1z install: + - set GIT_FETCH_JOBS=8 - set BOOST_BRANCH=develop - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master - cd .. - git clone -b %BOOST_BRANCH% https://github.com/boostorg/boost.git boost-root - cd boost-root - - git submodule init libs/headers - - git submodule init libs/assert - - git submodule init libs/config - - git submodule init libs/predef - - git submodule init libs/static_assert - - git submodule init libs/throw_exception - - git submodule init libs/type_traits - - git submodule init tools/build - - git submodule init tools/boost_install - - git submodule update --jobs 4 + - git submodule update --init tools/boostdep - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\core\ + - python tools/boostdep/depinst/depinst.py --git_args "--jobs %GIT_FETCH_JOBS%" core - cmd /c bootstrap - b2 headers diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index d73d31d..cce135f 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -5,12 +5,15 @@ # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://boost.org/LICENSE_1_0.txt) +import project ; import doxygen ; import quickbook ; +path-constant INCLUDES : ../../.. ; + doxygen ref_reference : - [ glob ../../../boost/core/ref.hpp ] + $(INCLUDES)/boost/core/ref.hpp : ENABLE_PREPROCESSING=YES EXPAND_ONLY_PREDEF=YES diff --git a/doc/alloc_construct.qbk b/doc/alloc_construct.qbk deleted file mode 100644 index 2342367..0000000 --- a/doc/alloc_construct.qbk +++ /dev/null @@ -1,149 +0,0 @@ -[/ -Copyright 2019 Glen Joseph Fernandes -(glenjofe@gmail.com) - -Distributed under the Boost Software License, Version 1.0. -(http://www.boost.org/LICENSE_1_0.txt) -] - -[section:alloc_construct alloc_construct, alloc_destroy] - -[simplesect Authors] - -* Glen Fernandes - -[endsimplesect] - -[section Overview] - -The header provides function templates -`alloc_construct`, `alloc_construct_n`, `alloc_destroy`, and `alloc_destroy_n` -for allocator aware and exception safe construction and destruction of objects -and arrays. - -[endsect] - -[section Example] - -The following example allocates storage for an array of `n` elements of `T` -using an allocator `a` and constructs `T` elements in that storage. If any -exception was thrown during construction of an element, the constructed -elements are destroyed in reverse order. - -``` -template -auto create(A& a, std::size_t n) -{ - auto p = a.allocate(n); - try { - boost::alloc_construct_n(a, boost::to_address(p), n); - } catch (...) { - a.deallocate(p, n); - throw; - } - return p; -} -``` - -[endsect] - -[section Reference] - -``` -namespace boost { - -template -void alloc_destroy(A& a, T* p); - -template -void alloc_destroy_n(A& a, T* p, std::size_t n); - -template -void alloc_construct(A& a, T* p, Args&&... args); - -template -void alloc_construct_n(A& a, T* p, std::size_t n); - -template -void alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m); - -template -void alloc_construct_n(A& a, T* p, std::size_t n, I begin); - -} /* boost */ -``` - -[section Functions] - -[variablelist -[[`template void alloc_destroy(A& a, T* p);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects][`std::allocator_traits::destroy(a, p)`.]]]]] -[[`template void alloc_destroy_n(A& a, T* p, -std::size_t n);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[Destroys each `i`-th element in reverse order by calling -`std::allocator_traits::destroy(a, &p[i])`.]]]]] -[[`template void alloc_construct(A& a, T* p, -Args&&... args);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[`std::allocator_traits::construct(a, p, std::forward(args)...)`.]]]]] -[[`template void alloc_construct_n(A& a, T* p, -std::size_t n);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[Constructs each `i`-th element in order by calling -`std::allocator_traits::construct(a, &p[i])`.]] -[[Remarks] -[If an exception is thrown destroys each already constructed `j`-th element in -reverse order by calling `std::allocator_traits::destroy(a, &p[j])`.]]]]] -[[`template void alloc_construct_n(A& a, T* p, std::size_t n, -const T* l, std::size_t m);`] -[[variablelist -[[Requires][`A` is an /Allocator/]] -[[Effects] -[Constructs each `i`-th element in order by calling -`std::allocator_traits::construct(a, &p[i], l[i % m])`.]] -[[Remarks] -[If an exception is thrown destroys each already constructed `j`-th element in -reverse order by calling `std::allocator_traits::destroy(a, &p[j])`.]]]]] -[[`template void alloc_construct_n(A& a, T* p, -std::size_t n, I begin);`] -[[variablelist -[[Requires] -[[itemized_list -[`A` is an /Allocator/][`I` is an /InputIterator/]]]] -[[Effects] -[Constructs each `i`-th element in order by calling -`std::allocator_traits::construct(a, &p[i], *begin++])`.]] -[[Remarks] -[If an exception is thrown destroys each already constructed `j`-th element in -reverse order by calling `std::allocator_traits::destroy(a, &p[j])`.]]]]]] - -[endsect] - -[endsect] - -[section Compatibility] - -When `BOOST_NO_CXX11_ALLOCATOR` is defined, and the C++11 allocator model is -not supported, these functions invoke constructors and destructors directly -without going through the supplied allocator. - -[endsect] - -[section Acknowledgments] - -Glen Fernandes originally implemented this functionality in Boost.Smart_Ptr and -later moved these functions to Boost.Core for use in other Boost libraries, -such as Boost.Multi_Array and Boost.Histogram. - -[endsect] - -[endsect] diff --git a/doc/allocator_access.qbk b/doc/allocator_access.qbk index 6b649e7..afde7d3 100644 --- a/doc/allocator_access.qbk +++ b/doc/allocator_access.qbk @@ -1,12 +1,12 @@ [/ -Copyright 2020 Glen Joseph Fernandes +Copyright 2020-2022 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) ] -[section Allocator Access] +[section allocator_access] [simplesect Authors] @@ -21,6 +21,9 @@ templates to simplify allocator use. It provides the same functionality as the C++ standard library `std::allocator_traits` but with individual templates for each allocator feature. +It also adds additional functionality for allocator aware exception safe +construction and destruction of arrays. + These facilities also simplify existing libraries by avoiding having to check for `BOOST_NO_CXX11_ALLOCATOR` and conditionally use `std::allocator_traits`. @@ -51,6 +54,26 @@ public: In C++11 or above, aliases such as `boost::allocator_pointer_t` can be used instead of `typename boost::allocator_pointer::type`. +The following example allocates storage for an array of `n` elements of `T` +using an allocator `a` and constructs `T` elements in that storage. If any +exception was thrown during construction of an element, the constructed +elements are destroyed in reverse order. + +``` +template +auto create(A& a, std::size_t n) +{ + auto p = a.allocate(n); + try { + boost::allocator_construct_n(a, boost::to_address(p), n); + } catch (...) { + a.deallocate(p, n); + throw; + } + return p; +} +``` + [endsect] [section Reference] @@ -150,9 +173,22 @@ void allocator_deallocate(A& a, allocator_pointer_t p, template void allocator_construct(A& a, T* p, Args&&... args); +template +void allocator_construct_n(A& a, T* p, std::size_t n); + +template +void allocator_construct_n(A& a, T* p, std::size_t n, const T* l, + std::size_t m); + +template +void allocator_construct_n(A& a, T* p, std::size_t n, I begin); + template void allocator_destroy(A& a, T* p); +template +void allocator_destroy_n(A& a, T* p, std::size_t n); + template allocator_size_type_t allocator_max_size(const A& a); @@ -168,7 +204,8 @@ A allocator_select_on_container_copy_construction(const A& a); [[`template struct allocator_value_type;`] [The member `type` is `A::value_type`.]] [[`template struct allocator_pointer;`] -[The member `type` is `A::pointer` if valid, otherwise `A::value_type*`.]] +[The member `type` is `A::pointer` if valid, otherwise +`allocator_value_type_t*`.]] [[`template struct allocator_const_pointer;`] [The member `type` is `A::const_pointer` if valid, otherwise `pointer_traits >::rebind n);`] void allocator_construct(A& a, T*p, Args&&... args);`] [Calls `a.construct(p, std::forward(args)...)` if valid, otherwise calls `::new(static_cast(p)) T(std::forward(args)...)`.]] +[[`template +void alloc_construct_n(A& a, T* p, std::size_t n);`] +[Constructs each `i`-th element in order by calling +`boost::allocator_construct(a, &p[i])`. +If an exception is thrown destroys each already constructed `j`-th element in +reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] +[[`template +void alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m);`] +[Constructs each `i`-th element in order by calling +`boost::allocator_construct(a, &p[i], l[i % m])`. +If an exception is thrown destroys each already constructed `j`-th element in +reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] +[[`template +void alloc_construct_n(A& a, T* p, std::size_t n, I begin);`] +[Constructs each `i`-th element in order by calling +`boost::allocator_construct(a, &p[i], *begin++)`. +If an exception is thrown destroys each already constructed `j`-th element in +reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] [[`template void allocator_destroy(A& a, T* p);`] [Calls `a.destroy(p)` if valid, otherwise calls `p->~T()`.]] +[[`template +void allocator_destroy_n(A& a, T* p, std::size_t n);`] +[Destroys each `i`-th element in reverse order by calling +`boost::allocator_destroy(a, &p[i])`.]] [[`template allocator_size_type_t allocator_max_size(const A& a);`] [Returns `a.max_size()` if valid, otherwise returns `std::numeric_limits >::max() / -sizeof(A::value_type)`.]] +sizeof(allocator_value_type_t)`.]] [[`template A allocator_select_on_container_copy_construction(const A& a);`] [Returns `a.select_on_container_copy_construction()` if valid, otherwise @@ -234,7 +293,7 @@ returns `a`.]]] [endsect] -[section Acknowledgments] +[section Acknowledgements] Glen Fernandes implemented the allocator access utilities. diff --git a/doc/allocator_traits.qbk b/doc/allocator_traits.qbk new file mode 100644 index 0000000..f16cc70 --- /dev/null +++ b/doc/allocator_traits.qbk @@ -0,0 +1,116 @@ +[/ +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +] + +[section:allocator_traits allocator_traits] + +[simplesect Authors] + +* Glen Fernandes + +[endsimplesect] + +[section Overview] + +This header provides an implementation of the +C++ standard library class template `allocator_traits` based on the facilities +in [link core.allocator_access Allocator Access]. Users should still prefer the +individual traits, but this utility exists to simplify migration. + +[endsect] + +[section Reference] + +``` +namespace boost { + +template +struct allocator_traits { + using allocator_type = A; + + using value_type = allocator_value_type_t; + + using pointer = allocator_pointer_t; + + using const_pointer = allocator_const_pointer_t; + + using void_pointer = allocator_void_pointer_t; + + using const_pointer = allocator_const_void_pointer_t; + + using difference_type = allocator_difference_type_t; + + using size_type = allocator_size_type_t; + + using propagate_on_container_copy_assignment = + allocator_propagate_on_container_copy_assignment_t; + + using propagate_on_container_move_assignment = + allocator_propagate_on_container_move_assignment_t; + + using propagate_on_container_swap = + allocator_propagate_on_container_swap_t; + + using is_always_equal = allocator_is_always_equal_t; + + template + using rebind_traits = allocator_traits >; + + static pointer allocate(A& a, size_type n); + + static pointer allocate(A& a, size_type n, const_void_pointer h); + + static void deallocate(A& a, pointer p, size_type n); + + template + static void construct(A& a, T* p, Args&&... args); + + static void destroy(A& a, T* p); + + static size_type max_size(const A& a) noexcept; + + static A select_on_container_copy_construction(const A& a); +}; + +} /* boost */ +``` + +[section Static member functions] + +[variablelist +[[`static pointer allocate(A& a, size_type n);`] +[Equivalent to: `return boost::allocator_allocate(a, n);`]] +[[`static pointer allocate(A& a, size_type n, const_void_pointer h);`] +[Equivalent to: `return boost::allocator_allocate(a, n, h);`]] +[[`static void deallocate(A& a, pointer p, size_type n);`] +[Equivalent to: `boost::allocator_deallocate(a, n, h);`]] +[[`template +static void construct(A& a, T* p, Args&&... args);`] +[Equivalent to: +`boost::allocator_construct(a, p, std::forward(args)...);`]] +[[`static void destroy(A& a, T* p);`] +[Equivalent to: `boost::allocator_destroy(a, p);`]] +[[`static size_type max_size(const A& a) noexcept;`] +[Equivalent to: `return boost::allocator_max_size(a);`]] +[[`static A select_on_container_copy_construction(const A& a);`] +[Equivalent to: +`return boost::allocator_select_on_container_copy_construction(a);`]]] + +[endsect] + +[endsect] + +[section Notes] + +# The member `rebind_alloc` is not provided for parity with C++03 where it is +unimplementable. Instead of `allocator_traits::rebind_alloc` you can +express the same with `allocator_traits::rebind_traits::allocator_type` +or more simply with `allocator_rebind_t`. + +[endsect] + +[endsect] diff --git a/doc/bit.qbk b/doc/bit.qbk index e8d5fce..81b9536 100644 --- a/doc/bit.qbk +++ b/doc/bit.qbk @@ -45,7 +45,7 @@ template constexpr T bit_floor(T x) noexcept; template -constexpr T bit_width(T x) noexcept; +constexpr int bit_width(T x) noexcept; // Rotating @@ -119,7 +119,7 @@ constant expression context. * *Requires:* `T` must be an unsigned integer type. * *Returns:* If `x == 0`, 0; otherwise the maximal value `y` such that `has_single_bit(y)` is `true` and `y <= x`. -`template constexpr T bit_width(T x) noexcept;` +`template constexpr int bit_width(T x) noexcept;` * *Requires:* `T` must be an unsigned integer type. * *Returns:* If `x == 0`, 0; otherwise one plus the base-2 logarithm of `x`, with any fractional part discarded. diff --git a/doc/changes.qbk b/doc/changes.qbk new file mode 100644 index 0000000..1069b78 --- /dev/null +++ b/doc/changes.qbk @@ -0,0 +1,142 @@ +[/ + Copyright 2021 Peter Dimov + Copyright 2022 Andrey Semashev + Distributed under the Boost Software License, Version 1.0. + https://boost.org/LICENSE_1_0.txt) +] + +[section Revision History] + +[section Changes in 1.82.0] + +* Added [link core.snprintf `boost/core/snprintf.hpp`] header with portable definitions of `snprintf`, `vsnprintf` and + their `wchar_t` counterparts. +* Deprecated `boost/core/is_same.hpp` and `boost::core::is_same`. The header will be removed in a future release. + Users are advised to use [@http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/index.html Boost.TypeTraits] + or C++ standard library type traits instead. +* Marked `boost::ref` member functions and associated methods with `noexcept`. +* Marked `boost::swap` function with `noexcept`, depending on whether the type supports a non-throwing swap operation. + +[endsect] + +[section Changes in 1.81.0] + +* [link core.empty_value `empty_value`] members are now marked as `constexpr`. +* Added [link core.fclose_deleter `fclose_deleter`], a deleter that calls `std::fclose` on a pointer to `std::FILE`. +* Bit manipulation utilities in [link core.bit `boost/core/bit.hpp`] now explicitly require unsigned integers on input. + ([@https://github.com/boostorg/core/issues/129 #129]) +* `bit_width` now returns `int` instead of a value of the input argument type. This follows the + resolution of [@https://cplusplus.github.io/LWG/issue3656 LWG3656]. + +[endsect] + +[section Changes in 1.80.0] + +* In [link core.allocator_access `boost/core/allocator_access.hpp`], added detection of `construct` and `destroy` + members of an allocator. +* `boost/core/alloc_construct.hpp` header is now deprecated and will be removed in a future release. Its functionality + was moved to [link core.allocator_access `boost/core/allocator_access.hpp`]. In particular, new methods + `allocator_construct_n` and `allocator_destroy_n` were added for allocating and destroying arrays. +* Worked around MSVC bug that failed to compile [link core.span `span`] in C++17 mode when Boost.Range headers were included. + ([@https://github.com/boostorg/core/issues/105 #105], [@https://github.com/boostorg/core/pull/115 PR#115]) +* Added support for 128-bit integer types in [link core.type_name `type_name`]. +* In [link core.pointer_traits `pointer_traits`], pointer rebinding now supports C++03 compilers. + +[endsect] + +[section Changes in 1.79.0] + +* Added `boost::allocator_traits`, an implementation of `std::allocator_traits`. +* Made `boost::pointer_traits` SFINAE friendly. +* `boost/iterator.hpp` is deprecated and will be removed in a future release. The header defines the + `boost::iterator` template, which is equivalent to `std::iterator` in the `` header. However, + since `std::iterator` is itself deprecated in C++17, users are advised to remove the use of `boost::iterator` + or `std::iterator` from their code. +* Added `boost::core::verbose_terminate_handler`, a utility function intended + to be passed to `std::set_terminate` that prints information about the + uncaught exception to `stderr`. + +[endsect] + +[section Changes in 1.78.0] + +* Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH` + is defined or when the platform does not provide the necessary facilities in ``. +* Added `boost::core::type_name`, a utility function that returns the name of a type as a string. +* Added `boost::span`, a C++11 implementation of C++20's `std::span`. + +[endsect] + +[section Changes in 1.77.0] + +* `boost/core/uncaught_exceptions.hpp` has been modified for compatibility with Mac OS 10.4 and older. + +[endsect] + +[section Changes in 1.76.0] + +* Added implicit conversion between compatible reference wrappers. +* Added `boost/core/cmath.hpp`, a portable implementation of the floating point classification functions from ``. +* Added `boost/core/bit.hpp`, a portable implementation of the C++20 standard header ``. +* Fixed `BOOST_TEST_EQ`, `BOOST_TEST_NE` for character types under C++20. +* Revised allocator access utilities (now support VS2013, and no workarounds use `allocator_traits`.) + +[endsect] + +[section Changes in 1.74.0] + +* Implemented the allocator access utilities which provide a replacement for `allocator_traits` + with individual traits and functions for each facility. They support the C++11 allocator model + when possible and provide a fallback for C++98 compatibility. +* Added `BOOST_TEST_WITH` to Lightweight Test. + +[endsect] + +[section Changes in 1.71.0] + +* Added functions `alloc_construct`, `alloc_construct_n`, `alloc_destroy`, and `alloc_destroy_n` + in `` for allocator aware and exception safe construction and + destruction of objects and arrays. +* Added constexpr functions `first_scalar` in `` for obtaining a pointer + to the first scalar element of an array. Given a pointer of type `T*` they return a pointer of type + `remove_all_extents_t*`. +* Added class template `noinit_adaptor` in `` which is an allocator adaptor + that converts any allocator into one whose `construct(ptr)` performs default initialization via placement + `new`, and whose `destroy(ptr)` invokes the `value_type` destructor directly. +* Added class template `default_allocator` in ``, which can serve as a minimal + default allocator that has interface similar to C++20 `std::allocator`, supports configurations with disabled + exceptions and does not have `std` as an associated namespace. The allocator uses `operator new` and + `operator delete` for allocation. +* In `` header, added workarounds for better compatibility with QNX SDP 7.0 + when libc++/libc++abi libraries are used. +* The `` header is now marked as deprecated and will be removed in a future release. + `` should be used instead. + +[endsect] + +[section Changes in 1.69.0] + +* Implemented `boost::empty_value`, for library authors to conveniently leverage the Empty Base Optimization to + store objects of potentially empty types. +* Implemented `boost::quick_exit` to provide the C++11 standard library facility `std::quick_exit` functionality. +* Reduced the number of statics in Lightweight Test, and employ lighter abort behavior for MSVC compilers upon + failure to call `boost::report_errors`. + +[endsect] + +[section Changes in 1.67.0] + +* Updated `to_address` and `pointer_traits` to reflect the design adopted for C++20 in + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0653r2.html P0653R2]. + +[endsect] + +[section Changes in 1.65.0] + +* Implemented `pointer_traits` for C++03 and higher, that implements + [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0653r0.html P0653r0]. +* Added `BOOST_TEST_GT` and `BOOST_TEST_GE` to Lightweight Test. + +[endsect] + +[endsect] diff --git a/doc/core.qbk b/doc/core.qbk index 9c20459..a7943f7 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -34,13 +34,15 @@ criteria for inclusion is that the utility component be: * simple, * used by other Boost libraries, and * not dependent on any other Boost modules except Core - itself, Config, Assert, Static Assert, or Predef. + itself, Config, Assert, StaticAssert, or ThrowException. [endsect] +[include changes.qbk] + [include addressof.qbk] [include allocator_access.qbk] -[include alloc_construct.qbk] +[include allocator_traits.qbk] [include bit.qbk] [include checked_delete.qbk] [include cmath.qbk] @@ -58,13 +60,17 @@ criteria for inclusion is that the utility component be: [include noinit_adaptor.qbk] [include noncopyable.qbk] [include null_deleter.qbk] +[include fclose_deleter.qbk] [include nvp.qbk] [include pointer_traits.qbk] [include quick_exit.qbk] [include ref.qbk] [include scoped_enum.qbk] +[include span.qbk] [include swap.qbk] [include typeinfo.qbk] [include type_name.qbk] +[include snprintf.qbk] [include uncaught_exceptions.qbk] [include use_default.qbk] +[include verbose_terminate_handler.qbk] diff --git a/doc/demangle.qbk b/doc/demangle.qbk index 16bd65e..cd0febc 100644 --- a/doc/demangle.qbk +++ b/doc/demangle.qbk @@ -125,7 +125,7 @@ return `nullptr` if demangling failed. [endsect] -[section Acknowledgments] +[section Acknowledgements] The implementation of `core::demangle` was taken from `boost/exception/detail/type_info.hpp`, which in turn was adapted diff --git a/doc/empty_value.qbk b/doc/empty_value.qbk index f693aeb..ef82f20 100644 --- a/doc/empty_value.qbk +++ b/doc/empty_value.qbk @@ -90,11 +90,11 @@ public: empty_value() = default; template - empty_value(empty_init_t, Args&&... args); + constepxr empty_value(empty_init_t, Args&&... args); - const T& get() const noexcept; + constepxr const T& get() const noexcept; - T& get() noexcept; + constepxr T& get() noexcept; }; inline constexpr empty_init_t empty_init{ }; @@ -121,8 +121,9 @@ inline constexpr empty_init_t empty_init{ }; [section Constructors] [variablelist -[[`empty_value() = default;`][Default initialize the value]] -[[`template empty_value(empty_init_t, Args&&... args);`] +[[`constepxr empty_value() = default;`][Default initialize the value]] +[[`template +constepxr empty_value(empty_init_t, Args&&... args);`] [Initialize the value with `std::forward(args)...`]]] [endsect] @@ -130,8 +131,8 @@ inline constexpr empty_init_t empty_init{ }; [section Member functions] [variablelist -[[`const T& get() const noexcept;`][Returns the value]] -[[`T& get() noexcept;`][Returns the value]]] +[[`constepxr const T& get() const noexcept;`][Returns the value]] +[[`constepxr T& get() noexcept;`][Returns the value]]] [endsect] diff --git a/doc/enable_if.qbk b/doc/enable_if.qbk index a64a2b1..6562d0b 100644 --- a/doc/enable_if.qbk +++ b/doc/enable_if.qbk @@ -304,8 +304,8 @@ depends on the template arguments of the class. Note that again, the second argument to `enable_if` is not needed; the default (`void`) is the correct value. -The `enable_if_has_type` template is usable this scenario but instead of -using a type traits to enable or disable a specialization, it use a +The `enable_if_has_type` template is usable in this scenario but instead of +using a type trait to enable or disable a specialization, it uses a SFINAE context to check for the existence of a dependent type inside its parameter. For example, the following structure extracts a dependent `value_type` from T if and only if `T::value_type` exists. diff --git a/doc/fclose_deleter.qbk b/doc/fclose_deleter.qbk new file mode 100644 index 0000000..30dd913 --- /dev/null +++ b/doc/fclose_deleter.qbk @@ -0,0 +1,34 @@ +[/ + / Copyright (c) 2022 Andrey Semashev + / + / 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) + /] + +[section:fclose_deleter fclose_deleter] + +[simplesect Authors] + +* Andrey Semashev + +[endsimplesect] + +[section Header ] + +The header `` defines the `boost::fclose_deleter` function object, +which can be used as a deleter with smart pointers such as `unique_ptr` or `shared_ptr` pointing to `std::FILE`. +structures returned by `std::fopen` calls. The deleter calls `std::fclose` on the passed pointer, causing +the file stream to be flushed and closed. + +[section Example] +`` +std::unique_ptr< std::FILE, boost::fclose_deleter > make_file(const char* filename, const char* open_mode) +{ + return { std::fopen(filename, open_mode) }; +} +`` +[endsect] + +[endsect] + +[endsect] diff --git a/doc/ignore_unused.qbk b/doc/ignore_unused.qbk index e3bdc4c..bd018e8 100644 --- a/doc/ignore_unused.qbk +++ b/doc/ignore_unused.qbk @@ -51,7 +51,7 @@ int fun( int foo, int bar ) [endsect] -[section Acknowledgments] +[section Acknowledgements] `boost::ignore_unused()` was contributed by Adam Wulkiewicz. diff --git a/doc/is_same.qbk b/doc/is_same.qbk index 657c591..304ae4e 100644 --- a/doc/is_same.qbk +++ b/doc/is_same.qbk @@ -17,6 +17,11 @@ [section Header ] +[warning This component is deprecated and will be removed in a future release. +Users are recommended to use `boost::is_same` from +[@http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/index.html Boost.TypeTraits] +or `std::is_same` from C++ standard library `` instead.] + The header `` defines the class template `boost::core::is_same`. It defines a nested integral constant `value` which is `true` when `T1` and `T2` are the same type, and diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index 698485a..8c7fa4d 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -51,8 +51,16 @@ When using `lightweight_test.hpp`, *do not forget* to namespace boost { - int report_errors(); -} + +int report_errors(); + +namespace core +{ + +void lwt_init(); + +} // namespace core +} // namespace boost `` [endsect] @@ -246,6 +254,25 @@ Return the error count from `main`. [endsect] +[section lwt_init] + +`` +void boost::core::lwt_init() +`` + +Performs one-time initialization. Disables the interactive message +boxes displayed by the Microsoft Windows debug runtime library on +`abort`, failing `assert`, and other abnormal program terminations +(to facilitate unattended testing), and ensures that in case +`boost::report_errors` is not called (a common mistake), the program +ends with a nonzero exit code. + +`lwt_init` is automatically called by the test macros. There is +no need to call it explicitly, except in cases where a test fails due +to e.g. an assertion failure before the first test macro is invoked. + +[endsect] + [section Example] `` @@ -326,14 +353,14 @@ parentheses.) `` #include -#include +#include template struct X { typedef T type; }; -using boost::core::is_same; +using boost::is_same; int main() { diff --git a/doc/pointer_traits.qbk b/doc/pointer_traits.qbk index d0247fa..fb846b8 100644 --- a/doc/pointer_traits.qbk +++ b/doc/pointer_traits.qbk @@ -1,5 +1,5 @@ [/ -Copyright 2017-2018 Glen Joseph Fernandes +Copyright 2017-2021 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -47,68 +47,91 @@ void function(Allocator& a) ``` namespace boost { - template struct pointer_traits { + +template +struct pointer_traits { typedef T pointer; typedef ``['see below]`` element_type; typedef ``['see below]`` difference_type; - template struct rebind_to { typedef ``['see below]`` type; }; - template using rebind = typename rebind_to::type; + template + struct rebind_to { + typedef ``['see below]`` type; + }; - static pointer pointer_to(``['see below]`` v); - }; + template + using rebind = typename rebind_to::type; - template struct pointer_traits { + static pointer pointer_to(element_type& v); +}; + +template +struct pointer_traits { typedef T* pointer; typedef T element_type; typedef std::ptrdiff_t difference_type; - template struct rebind_to { typedef U* type; }; - template using rebind = typename rebind_to::type; + template + struct rebind_to { + typedef U* type; + }; + + template + using rebind = typename rebind_to::type; static pointer pointer_to(``['see below]`` v) noexcept; - }; +}; - template - constexpr T* to_address(T* v) noexcept; +template +constexpr T* to_address(T* v) noexcept; - template - auto to_address(const T& v) noexcept; -} +template +auto to_address(const T& v) noexcept; + +} // boost ``` +[section Overview] + +If the member type `element_type` is not defined, then all other members are +also not defined (`pointer_traits` is SFINAE-friendly). + +[endsect] + [section Member types] [variablelist [[`typedef` ['see below] `element_type;`] [`T::element_type` if such a type exists; otherwise `U` if `T` is a class template instantiation of the form `Pointer`, where `Args` is zero - or more type arguments; otherwise the specialization is ill-formed.]] + or more type arguments; otherwise the member is not defined.]] [[`typedef` ['see below] `difference_type;`] [`T::difference_type` if such a type exists; otherwise `std::ptrdiff_t`.]] [[`template struct rebind_to { typedef` ['see below] `type; };`] [`type` is `T::rebind` if such a type exists; otherwise, `Pointer` if `T` is a class template instantiation of the form `Pointer`, - where `Args` is zero or more type arguments; otherwise, the instantiation of - `rebind_to` is ill-formed.]]] + where `Args` is zero or more type arguments; otherwise, the member is not + defined.]]] + +[note When C++11 template aliases are not supported, the `type` for `rebind` is +`T::rebind::other` if such a type exists.] [endsect] [section Member functions] [variablelist -[[`static pointer pointer_traits::pointer_to(`['see below] `v);`] +[[`static pointer pointer_traits::pointer_to(element_type& v);`] [[variablelist [[Remark] -[If `element_type` is a void type, the type of `v` is unspecified; otherwise, - it is `element_type&`.]] +[If `element_type` is a void type, or if `T::pointer_to(v)` is not well-formed, + this member is not defined.]] [[Returns] [A pointer to `v` obtained by calling `T::pointer_to(v)`.]]]]] -[[`static pointer pointer_traits::pointer_to(`['see below] `v) noexcept;`] +[[`static pointer pointer_traits::pointer_to(element_type& v) noexcept;`] [[variablelist [[Remark] -[If `element_type` is a void type, the type of `v` is unspecified; otherwise, - it is `element_type&`.]] +[If `element_type` is a void type, this member is not defined.]] [[Returns][`addressof(v)`.]]]]]] [endsect] @@ -142,7 +165,7 @@ namespace boost { [endsect] -[section Acknowledgments] +[section Acknowledgements] Glen Fernandes implemented `pointer_traits` and `to_address` with reviews and guidance from Peter Dimov. diff --git a/doc/ref.qbk b/doc/ref.qbk index 454851b..3614497 100644 --- a/doc/ref.qbk +++ b/doc/ref.qbk @@ -68,7 +68,7 @@ The type-expression `boost::unwrap_reference::type` is [xinclude ref_reference.xml] -[section Acknowledgments] +[section Acknowledgements] `ref` and `cref` were originally part of the Tuple library by Jaakko J\u00E4rvi. They were "promoted to `boost::` status" by diff --git a/doc/scoped_enum.qbk b/doc/scoped_enum.qbk index a9e95f4..4c06f97 100644 --- a/doc/scoped_enum.qbk +++ b/doc/scoped_enum.qbk @@ -46,7 +46,7 @@ The user can portably declare such enumeration as follows: } BOOST_SCOPED_ENUM_DECLARE_END(future_errc) -These macros allows to use `future_errc` in almost all the cases as an scoped enum. +These macros allow using `future_errc` in almost all the cases as a scoped enum. future_errc ev = future_errc::no_state; @@ -179,7 +179,7 @@ such cases. [endsect] -[section Acknowledgments] +[section Acknowledgements] This scoped enum emulation was developed by Beman Dawes, Vicente J. Botet Escriba and Anthony Williams. diff --git a/doc/snprintf.qbk b/doc/snprintf.qbk new file mode 100644 index 0000000..814019a --- /dev/null +++ b/doc/snprintf.qbk @@ -0,0 +1,47 @@ +[/ + / Copyright (c) 2022 Andrey Semashev + / + / 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) + /] + +[section:snprintf snprintf] + +[simplesect Authors] + +* Andrey Semashev + +[endsimplesect] + +[section Header ] + +The header `` provides portable definition of [@https://en.cppreference.com/w/c/io/fprintf `snprintf`], +`vsnprintf` and their corresponding `wchar_t` counterparts. On a platform that supports these functions in the standard library, +these definitions are equivalent to the standard functions. On other platforms (mainly, older MSVC versions) these functions +are emulated through non-standard functions that have similar behavior. + +Depending on the standard library, certain implementation differences are exposed to the user: + +* Any non-standard behavior with respect to string format description are not hidden by the emulation. +* Returned value of `boost::core::snprintf` in case if the output buffer is too small may not be equal to the number of characters + that would have been written if the buffer was large enough. It is, however, equal or larger than the buffer size, + which still allows the caller to detect the buffer overflow condition. The formatted output is still properly null-terminated + in this case. + +[note Unlike `snprintf`, `swprintf` does not return the number of characters to be written if the output buffer is too small +but returns -1 instead. Furthermore, `swprintf` may or may not produce characters in the output buffer in this case.] + +[section Example] +`` +char buf[10]; +int n = boost::core::snprintf(buf, sizeof(buf), "%d", i); +if (n < 0) + throw std::runtime_error("Formatting error"); +if (n >= sizeof(buf)) + throw std::runtime_error("Formatting buffer overflow"); +`` +[endsect] + +[endsect] + +[endsect] diff --git a/doc/span.qbk b/doc/span.qbk new file mode 100644 index 0000000..e2a1425 --- /dev/null +++ b/doc/span.qbk @@ -0,0 +1,396 @@ +[/ +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +] + +[section:span span] + +[simplesect Authors] + +* Glen Fernandes + +[endsimplesect] + +[section Overview] + +This header provides class template `span`, which is a +view over a sequence of objects. It implements the C++20 standard library +`std::span` facility. This implementation supports C++11 and higher. + +In addition to referencing the sequence of objects, the span knows the count of +objects. There are two kinds of spans: + +* Dynamic size (`span` or `span`) +* Static size (`span`) + +Dynamic size spans have a count that can be a value known at run time. Static +size spans have a count that must be known at compile time. + +[endsect] + +[section Examples] + +The following snippet shows a function to compute a SHA1 hash whose parameters +and return type use spans. + +``` +auto sha1(boost::span input, + boost::span ouput) +{ + SHA_CTX context; + SHA1_Init(&context); + SHA1_Update(&context, input.data(), input.size()); + SHA1_Final(output.data(), &context); + return output; +} +``` + +[endsect] + +[section Reference] + +``` +namespace boost { + +constexpr std::size_t dynamic_extent = -1; + +template +class span { +public: + typedef T element_type; + typedef std::remove_cv_t value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T* iterator; + typedef const T* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + static constexpr std::size_t extent = E; + + constexpr span() noexcept; + + explicit(E != dynamic_extent) + template + constexpr span(I* f, size_type c); + + explicit(E != dynamic_extent) + template + constexpr span(I* f, L* l); + + template + constexpr span(type_identity_t (&a)[N]); + + template + constexpr span(std::array& a) noexcept; + + template + constexpr span(const std::array& a) noexcept; + + explicit(E != dynamic_extent) + template + constexpr span(R&& r); + + explicit(E != dynamic_extent && N == dynamic_extent) + template + constexpr span(const span& s) noexcept; + + template + constexpr span first() const; + + template + constexpr span last() const; + + template + constexpr span subspan() const; + + constexpr span first(size_type c) const; + constexpr span last(size_type c) const; + + constexpr span subspan(size_type o, + size_type c = dynamic_extent) const; + + constexpr size_type size() const noexcept; + constexpr size_type size_bytes() const noexcept; + constexpr bool empty() const noexcept; + + constexpr reference operator[](size_type i) const; + constexpr reference front() const; + constexpr reference back() const; + constexpr pointer data() const noexcept; + + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + constexpr reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; +}; + +template +span(I*, L) -> span; + +template +span(T(&)[N]) -> span; + +template +span(std::array&) -> span; + +template +span(const std::array&) -> span; + +template +span(R&&) -> span().data())> >; + +template +span +as_bytes(span s) noexcept; + +template +span +as_writable_bytes(span s) noexcept; + +} /* boost */ +``` + +[section Constructors] + +[variablelist +[[`constexpr span() noexcept;`] +[[variablelist +[[Constraints][`E == dynamic_extent || E == 0` is `true`.]] +[[Postconditions][`size() == 0 && data() == nullptr`.]]]]] +[[`explicit(E != dynamic_extent) +template +constexpr span(I* f, size_type c);`] +[[variablelist +[[Constraints] +[`is_convertible_v` is `true`.]] +[[Preconditions] +[[itemized_list +[`[f, f + c)` is a valid range.] +[If `E` is not equal to `dynamic_extent`, then `c` is equal to `E`.]]]] +[[Effects][Constructs a `span` with data `f` and size `c`.]] +[[Throws][Nothing.]]]]] +[[`explicit(E != dynamic_extent) +template +constexpr span(I* f, L* l);`] +[[variablelist +[[Constraints] +[`is_convertible_v` is `true`.]] +[[Preconditions] +[[itemized_list +[If `E` is not equal to `dynamic_extent`, then `l - f` is equal to `E`.] +[`[f, l)` is a valid range.]]]] +[[Effects][Constructs a `span` with data `f` and size `l - f`.]] +[[Throws][Nothing.]]]]] +[[`template +constexpr span(type_identity_t (&a)[N]);`] +[[variablelist +[[Constraints][`E == dynamic_extent || E == N` is `true`.]] +[[Effects][Constructs a `span` that is a view over the supplied array.]] +[[Postconditions][`size() == N && data() == &a[0]` is `true`.]]]]] +[[`template +constexpr span(std::array& a) noexcept;`] +[[variablelist +[[Constraints] +[[itemized_list +[`E == dynamic_extent || E == N` is `true`, and] +[`U(*)[]` is convertible to `T(*)[]`.]]]] +[[Effects][Constructs a `span` that is a view over the supplied array.]] +[[Postconditions][`size() == N && data() == a.data()` is `true`.]]]]] +[[`template +constexpr span(const std::array& a) noexcept;`] +[[variablelist +[[Constraints] +[[itemized_list +[`E == dynamic_extent || E == N` is `true`, and] +[`U(*)[]` is convertible to `T(*)[]`.]]]] +[[Effects][Constructs a `span` that is a view over the supplied array.]] +[[Postconditions][`size() == N && data() == a.data()` is `true`.]]]]] +[[`explicit(E != dynamic_extent) +template +constexpr span(R&& r);`] +[[variablelist +[[Constraints] +[[itemized_list +[`is_lvalue_reference_v || is_const_v` is `true`] +[`remove_cvref_t` is not a specialization of `span`,] +[`remove_cvref_t` is not a specialization of `array`,] +[`is_array_v>` is `false`,] +[`r.data()` is well-formed and +`is_convertible_v().data())>(*)[], +T(*)[]>` is `true`, and] +[`r.size()` is well-formed and +`is_convertible_v().size()), size_t>` is `true`.]]]] +[[Effects][Constructs a `span` with data `r.data()` and size `r.size()`.]] +[[Throws][What and when r.data() and r.size() throw.]]]]] +[[`explicit(E != dynamic_extent && N == dynamic_extent) +template +constexpr span(const span& s) noexcept;`] +[[variablelist +[[Constraints] +[[itemized_list +[`E == dynamic_extent || N == dynamic_extent || E == N` is `true`, and] +[`is_convertible_v` is `true`.]]]] +[[Preconditions] +[If `E` is not equal to `dynamic_extent`, then `s.size()` is equal to `E`.]] +[[Effects] +[Constructs a `span` that is a view over the range +`[s.data(), s.data() + s.size())`.]] +[[Postconditions][`size() == s.size() && data() == s.data()`.]]]]]] + +[endsect] + +[section Subviews] + +[variablelist +[[`template constexpr span first() const;`] +[[variablelist +[[Mandates][`C <= E` is `true`.]] +[[Preconditions][`C <= size()` is `true`.]] +[[Effects] +[Equivalent to `return R{data(), C};` where `R` is the return type.]]]]] +[[`template constexpr span last() const;`] +[[variablelist +[[Mandates][`C <= E` is `true`.]] +[[Preconditions][`C <= size()` is `true`.]] +[[Effects] +[Equivalent to `return R{data() + (size() - C), C};` where `R` is the return +type.]]]]] +[[`template +constexpr span subspan() const;`] +[[variablelist +[[Mandates][`O <= E && (C == dynamic_extent || C <= E - O)` is `true`.]] +[[Preconditions] +[`O <= size() && (C == dynamic_extent || C <= size() - O)` is `true`.]] +[[Effects] +[Equivalent to +`return span(data() + O, +C != dynamic_extent ? C : size() - O);`.]] +[[Remarks] +[The second template argument of the returned span type is: +`C != dynamic_extent ? C : (E != dynamic_extent ? E - O : +dynamic_extent)`]]]]] +[[`constexpr span first(size_type c) const;`] +[[variablelist +[[Preconditions][`c <= size()` is `true`.]] +[[Effects][Equivalent to: `return {data(), c};`]]]]] +[[`constexpr span last(size_type c) const;`] +[[variablelist +[[Preconditions][`c <= size()` is `true`.]] +[[Effects][Equivalent to: `return {data() + (size() - c), c};`]]]]] +[[`constexpr span subspan(size_type o, +size_type c = dynamic_extent) const;`] +[[variablelist +[[Preconditions] +[`o <= size() && (c == dynamic_extent || o + c <= size())` is `true`.]] +[[Effects] +[Equivalent to: +`return {data() + o, c == dynamic_extent ? size() - o : c};`]]]]]] + +[endsect] + +[section Observers] + +[variablelist +[[`constexpr size_type size() const noexcept;`] +[[variablelist +[[Returns][The number of elements in the span.]]]]] +[[`constexpr size_type size_bytes() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return size() * sizeof(T);`]]]]] +[[`constexpr bool empty() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return size() == 0;`]]]]]] + +[endsect] + +[section Element access] + +[variablelist +[[`constexpr reference operator[](size_type i) const;`] +[[variablelist +[[Preconditions][`i < size()` is `true`.]] +[[Effects][Equivalent to: `return *(data() + i);`]]]]] +[[`constexpr reference front() const;`] +[[variablelist +[[Preconditions][`empty()` is `false`.]] +[[Effects][Equivalent to: `return *data();`]]]]] +[[`constexpr reference back() const;`] +[[variablelist +[[Preconditions][`empty()` is `false`.]] +[[Effects][Equivalent to: `return *(data() + (size() - 1);`]]]]] +[[`constexpr pointer data() const noexcept;`] +[[variablelist +[[Returns][A pointer to the first element in the span.]]]]]] + +[endsect] + +[section Iterator support] + +[variablelist +[[`constexpr iterator begin() const noexcept;`] +[[variablelist +[[Returns][A constant iterator referring to the first element in the span. If `empty()`, +then it returns the same value as `cend()`.]]]]] +[[`constexpr iterator end() const noexcept;`] +[[variablelist +[[Returns][A constant iterator which is the past-the-end value.]]]]] +[[`constexpr reverse_iterator rbegin() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return reverse_iterator(end());`]]]]] +[[`constexpr reverse_iterator rend() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return reverse_iterator(begin());`]]]]] +[[`constexpr const_iterator cbegin() const noexcept;`] +[[variablelist +[[Returns] +[A constant iterator referring to the first element in the span. If `empty()`, +then it returns the same value as `cend()`.]]]]] +[[`constexpr const_iterator cend() const noexcept;`] +[[variablelist +[[Returns][A constant iterator which is the past-the-end value.]]]]] +[[`constexpr const_reverse_iterator crbegin() const noexcept;`] +[[variablelist +[[Effects][Equivalent to: `return const_reverse_iterator(cend());`]]]]] +[[`constexpr const_reverse_iterator crend() const noexcept;`] +[[variablelist +[[Effects] +[Equivalent to: `return const_reverse_iterator(cbegin());`]]]]]] + +[endsect] + +[section Views of object representation] + +[variablelist +[[`template +span +as_bytes(span s) noexcept;`] +[[variablelist +[[Effects] +[Equivalent to: +`return {reinterpret_cast(s.data()), s.size_bytes()};`.]]]]] +[[`template +span +as_writable_bytes(span s) noexcept;`] +[[variablelist +[[Constraints][`is_const_v` is `false`.]] +[[Effects] +[Equivalent to: `return R{reinterpret_cast(s.data()), s.size_bytes()};` +where `R` is the return type.]]]]]] + +[endsect] + +[endsect] + +[endsect] diff --git a/doc/string_view.qbk b/doc/string_view.qbk new file mode 100644 index 0000000..27edfeb --- /dev/null +++ b/doc/string_view.qbk @@ -0,0 +1,768 @@ +[/ + Copyright 2021 Peter Dimov + Distributed under the Boost Software License, Version 1.0. + https://boost.org/LICENSE_1_0.txt +] + +[section:string_view string_view] + +[simplesect Authors] + +* Peter Dimov + +[endsimplesect] + +[section Header ] + +The header `` defines `boost::core::string_view`, +a portable and interoperable implementation of `std::string_view`. + +Unlike `boost::string_view`, `boost::core::string_view` has implicit +conversions from and to `std::string_view`, which allows Boost libraries that +support C++11/C++14 to use it in interfaces without forcing users to forgo the +use of `std::string_view` in their code. + +[section Synopsis] + +`` +namespace boost +{ +namespace core +{ + +template class basic_string_view +{ +public: + + // types + + typedef std::char_traits traits_type; + typedef Ch value_type; + typedef Ch* pointer; + typedef Ch const* const_pointer; + typedef Ch& reference; + typedef Ch const& const_reference; + typedef Ch const* const_iterator; + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // npos + + static constexpr size_type npos = static_cast( -1 ); + +public: + + // construction and assignment + + constexpr basic_string_view() noexcept; + constexpr basic_string_view( basic_string_view const& ) noexcept = default; + constexpr basic_string_view& operator=( basic_string_view const& ) noexcept & = default; + constexpr basic_string_view( Ch const* str ) noexcept; + constexpr basic_string_view( Ch const* str, size_type len ) noexcept; + constexpr basic_string_view( Ch const* begin, Ch const* end ) noexcept; + template basic_string_view( std::basic_string, A> const& str ) noexcept; + basic_string_view( std::basic_string_view> const& str ) noexcept; + + // conversions + + template operator std::basic_string, A>() const; + template operator std::basic_string_view() const noexcept; + + // iterator support + + constexpr const_iterator begin() const noexcept; + constexpr const_iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr const_reverse_iterator rbegin() const noexcept; + constexpr const_reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + + // capacity + + constexpr size_type size() const noexcept; + constexpr size_type length() const noexcept; + constexpr size_type max_size() const noexcept; + constexpr bool empty() const noexcept; + + // element access + + constexpr const_reference operator[]( size_type pos ) const noexcept; + constexpr const_reference at( size_type pos ) const; + constexpr const_reference front() const noexcept; + constexpr const_reference back() const noexcept; + constexpr const_pointer data() const noexcept; + + // modifiers + + constexpr void remove_prefix( size_type n ) noexcept; + constexpr void remove_suffix( size_type n ) noexcept; + constexpr void swap( basic_string_view& s ) noexcept; + + // string operations + + constexpr size_type copy( Ch* s, size_type n, size_type pos = 0 ) const; + constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const; + + // compare + + constexpr int compare( basic_string_view str ) const noexcept; + constexpr int compare( size_type pos1, size_type n1, basic_string_view str ) const; + constexpr int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const; + constexpr int compare( Ch const* s ) const; + constexpr int compare( size_type pos1, size_type n1, Ch const* s ) const; + constexpr int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const; + + // starts_with + + constexpr bool starts_with( basic_string_view x ) const noexcept; + constexpr bool starts_with( Ch x ) const noexcept; + constexpr bool starts_with( Ch const* x ) const noexcept; + + // ends_with + + constexpr bool ends_with( basic_string_view x ) const noexcept; + constexpr bool ends_with( Ch x ) const noexcept; + constexpr bool ends_with( Ch const* x ) const noexcept; + + // find + + constexpr size_type find( basic_string_view str, size_type pos = 0 ) const noexcept; + constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept; + constexpr size_type find( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find( Ch const* s, size_type pos = 0 ) const noexcept; + + // rfind + + constexpr size_type rfind( basic_string_view str, size_type pos = npos ) const noexcept; + constexpr size_type rfind( Ch c, size_type pos = npos ) const noexcept; + constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type rfind( Ch const* s, size_type pos = npos ) const noexcept; + + // find_first_of + + constexpr size_type find_first_of( basic_string_view str, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_of( Ch c, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const noexcept; + + // find_last_of + + constexpr size_type find_last_of( basic_string_view str, size_type pos = npos ) const noexcept; + constexpr size_type find_last_of( Ch c, size_type pos = npos ) const noexcept; + constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const noexcept; + + // find_first_not_of + + constexpr size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_not_of( Ch c, size_type pos = 0 ) const noexcept; + constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const noexcept; + + // find_last_not_of + + constexpr size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const noexcept; + constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept; + constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const noexcept; + constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const noexcept; + + // contains + + constexpr bool contains( basic_string_view sv ) const noexcept; + constexpr bool contains( Ch c ) const noexcept; + constexpr bool contains( Ch const* s ) const noexcept; + + // relational operators + + constexpr friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) noexcept; + constexpr friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) noexcept; +}; + +// stream inserter + +template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ); + +// typedef names + +typedef basic_string_view string_view; +typedef basic_string_view wstring_view; +typedef basic_string_view u16string_view; +typedef basic_string_view u32string_view; +typedef basic_string_view u8string_view; + +} // namespace core +} // namespace boost +`` + +[endsect] + +[section Construction] + +[section `constexpr basic_string_view() noexcept;`] + +* *Ensures:* `data() == 0`; `size() == 0`. + +[endsect] + +[section `constexpr basic_string_view( Ch const* str ) noexcept;`] + +* *Ensures:* `data() == str`; `size() == traits_type::length( str )`. + +[endsect] + +[section `constexpr basic_string_view( Ch const* str, size_type len ) noexcept;`] + +* *Ensures:* `data() == str`; `size() == len`. + +[endsect] + +[section `constexpr basic_string_view( Ch const* begin, Ch const* end ) noexcept;`] + +* *Requires:* `end >= begin`. +* *Ensures:* `data() == begin`; `size() == end - begin`. + +[endsect] + +[section `template basic_string_view( std::basic_string, A> const& str ) noexcept;`] + +* *Ensures:* `data() == str.data()`; `size() == str.size()`. + +[endsect] + +[section `basic_string_view( std::basic_string_view> const& str ) noexcept;`] + +* *Ensures:* `data() == str.data()`; `size() == str.size()`. + +[endsect] + +[endsect] + +[section Conversions] + +[section `template operator std::basic_string, A>() const;`] + +* *Returns:* `std::basic_string, A>( data(), size() )`. + +[endsect] + +[section `template operator std::basic_string_view() const noexcept;`] + +* *Constraints:* `Ch2` is the same type as `Ch`. +* *Returns:* `std::basic_string_view( data(), size() )`. + +[endsect] + +[endsect] + +[section Iterator Support] + +[section `constexpr const_iterator begin() const noexcept;`] + +* *Returns:* `data()`. + +[endsect] + +[section `constexpr const_iterator end() const noexcept;`] + +* *Returns:* `data() + size()`. + +[endsect] + +[section `constexpr const_iterator cbegin() const noexcept;`] + +* *Returns:* `begin()`. + +[endsect] + +[section `constexpr const_iterator cend() const noexcept;`] + +* *Returns:* `end()`. + +[endsect] + +[section `constexpr const_reverse_iterator rbegin() const noexcept;`] + +* *Returns:* `const_reverse_iterator( end() )`. + +[endsect] + +[section `constexpr const_reverse_iterator rend() const noexcept;`] + +* *Returns:* `const_reverse_iterator( begin() )`. + +[endsect] + +[section `constexpr const_reverse_iterator crbegin() const noexcept;`] + +* *Returns:* `rbegin()`. + +[endsect] + +[section `constexpr const_reverse_iterator crend() const noexcept;`] + +* *Returns:* `rend()`. + +[endsect] + +[endsect] + +[section Capacity] + +[section `constexpr size_type size() const noexcept;`] + +* *Returns:* the length of the referenced character sequence. + +[endsect] + +[section `constexpr size_type length() const noexcept;`] + +* *Returns:* `size()`. + +[endsect] + +[section `constexpr size_type max_size() const noexcept;`] + +* *Returns:* `std::numeric_limits::max() / sizeof(Ch)`. + +[endsect] + +[section `constexpr bool empty() const noexcept;`] + +* *Returns:* `size() == 0`. + +[endsect] + +[endsect] + +[section Element Access] + +[section `constexpr const_reference operator[]( size_type pos ) const noexcept;`] + +* *Requires:* `pos < size()`. +* *Returns:* `data()[ pos ]`. + +[endsect] + +[section `constexpr const_reference at( size_type pos ) const;`] + +* *Returns:* `data()[ pos ]`. +* *Throws:* `std::out_of_range` when `pos >= size()`. + +[endsect] + +[section `constexpr const_reference front() const noexcept;`] + +* *Requires:* `!empty()`. +* *Returns:* `data()[ 0 ]`. + +[endsect] + +[section `constexpr const_reference back() const noexcept;`] + +* *Requires:* `!empty()`. +* *Returns:* `data()[ size() - 1 ]`. + +[endsect] + +[section `constexpr const_pointer data() const noexcept;`] + +* *Returns:* a pointer to the beginning of the referenced character sequence. + +[endsect] + +[endsect] + +[section Modifiers] + +[section `constexpr void remove_prefix( size_type n ) noexcept;`] + +* *Requires:* `n <= size()`. +* *Effects:* advances `data()` by `n` and decreases `size()` by `n`. + +[endsect] + +[section `constexpr void remove_suffix( size_type n ) noexcept;`] + +* *Requires:* `n <= size()`. +* *Effects:* decreases `size()` by `n`. + +[endsect] + +[section `constexpr void swap( basic_string_view& s ) noexcept;`] + +* *Effects:* exchanges the contents of `*this` and `s`. + +[endsect] + +[endsect] + +[section String Operations] + +[section copy] + +[section `constexpr size_type copy( Ch* s, size_type n, size_type pos = 0 ) const;`] + +* *Effects:* copies to `s` the contents of `substr( pos, n )`. +* *Throws:* `std::out_of_range` when `pos >= size()`. + +[endsect] + +[endsect] + +[section substr] + +[section `constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const;`] + +* *Returns:* `basic_string_view( data() + pos, std::min( size() - pos, n ) )`. +* *Throws:* `std::out_of_range` when `pos >= size()`. + +[endsect] + +[endsect] + +[section compare] + +[section `constexpr int compare( basic_string_view str ) const noexcept;`] + +* *Returns:* + * if `traits_type::compare( data(), str.data(), std::min( size(), str.size() ) )` is not zero, returns it. Otherwise, + * if `size() < str.size()`, returns a negative number. Otherwise, + * if `size() > str.size()`, returns a positive number. Otherwise, + * returns 0. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view str ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( str )`. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( str.substr( pos2, n2 ) )`. + +[endsect] + +[section `constexpr int compare( Ch const* s ) const noexcept;`] + +* *Returns:* `compare( basic_string_view( s ) )`. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, Ch const* s ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( basic_string_view( s ) )`. + +[endsect] + +[section `constexpr int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const;`] + +* *Returns:* `substr( pos1, n1 ).compare( basic_string_view( s, n2 ) )`. + +[endsect] + +[endsect] + +[section starts_with] + +[section `constexpr bool starts_with( basic_string_view x ) const noexcept;`] + +* *Returns:* `substr( 0, x.size() ) == x`. + +[endsect] + +[section `constexpr bool starts_with( Ch x ) const noexcept;`] + +* *Returns:* `starts_with( basic_string_view( &x, 1 ) )`. + +[endsect] + +[section `constexpr bool starts_with( Ch const* x ) const noexcept;`] + +* *Returns:* `starts_with( basic_string_view( x ) )`. + +[endsect] + +[endsect] + +[section ends_with] + +[section `constexpr bool ends_with( basic_string_view x ) const noexcept;`] + +* *Returns:* `size() >= x.size() && substr( size() - x.size(), x.size() ) == x`. + +[endsect] + +[section `constexpr bool ends_with( Ch x ) const noexcept;`] + +* *Returns:* `ends_with( basic_string_view( &x, 1 ) )`. + +[endsect] + +[section `constexpr bool ends_with( Ch const* x ) const noexcept;`] + +* *Returns:* `ends_with( basic_string_view( x ) )`. + +[endsect] + +[endsect] + +[endsect] + +[section Searching] + +[section find] + +[section `constexpr size_type find( basic_string_view str, size_type pos = 0 ) const noexcept;`] + +* *Returns:* The lowest position `i` such that `i >= pos` and `substr( i, str.size() ) == str`, or `npos` if such a position doesn't exist. + +[endsect] + +[section `constexpr size_type find( Ch c, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find( Ch const* s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find( basic_string_view( s ), pos )`. + +[endsect] + +[endsect] + +[section rfind] + +[section `constexpr size_type rfind( basic_string_view str, size_type pos = npos ) const noexcept;`] + +* *Returns:* The highest position `i` such that `i <= pos` and `substr( i, str.size() ) == str`, or `npos` if such a position doesn't exist. + +[endsect] + +[section `constexpr size_type rfind( Ch c, size_type pos = npos ) const noexcept;`] + +* *Returns:* `rfind( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type rfind( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `rfind( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type rfind( Ch const* s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `rfind( basic_string_view( s ), pos )`. + +[endsect] + +[endsect] + +[section find_first_of] + +[section `constexpr size_type find_first_of( basic_string_view str, size_type pos = 0 ) const noexcept;`] + +* *Returns:* The lowest position `i` such that `i >= pos` and the character at position `i` is equal to one of the characters in `str`, or `npos` if such a position doesn't exist. + +[endsect] + +[section `constexpr size_type find_first_of( Ch c, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_first_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_of( Ch const* s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_of( basic_string_view( s ), pos )`. + +[endsect] + +[endsect] + +[section find_last_of] + +[section `constexpr size_type find_last_of( basic_string_view str, size_type pos = npos ) const noexcept;`] + +* *Returns:* The highest position `i` such that `i <= pos` and the character at position `i` is equal to one of the characters in `str`, or `npos` if such a position doesn't exist. + +[endsect] + +[section `constexpr size_type find_last_of( Ch c, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_last_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_of( Ch const* s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_of( basic_string_view( s ), pos )`. + +[endsect] + +[endsect] + +[section find_first_not_of] + +[section `constexpr size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const noexcept;`] + +* *Returns:* The lowest position `i` such that `i >= pos` and the character at position `i` is not equal to one of the characters in `str`, or `npos` if such a position doesn't exist. + +[endsect] + +[section `constexpr size_type find_first_not_of( Ch c, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_not_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_first_not_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const noexcept;`] + +* *Returns:* `find_first_not_of( basic_string_view( s ), pos )`. + +[endsect] + +[endsect] + +[section find_last_not_of] + +[section `constexpr size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const noexcept;`] + +* *Returns:* The highest position `i` such that `i <= pos` and the character at position `i` is not equal to one of the characters in `str`, or `npos` if such a position doesn't exist. + +[endsect] + +[section `constexpr size_type find_last_not_of( Ch c, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_not_of( basic_string_view( &c, 1 ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const noexcept;`] + +* *Returns:* `find_last_not_of( basic_string_view( s, n ), pos )`. + +[endsect] + +[section `constexpr size_type find_last_not_of( Ch const* s, size_type pos = npos ) const noexcept;`] + +* *Returns:* `find_last_not_of( basic_string_view( s ), pos )`. + +[endsect] + +[endsect] + +[section contains] + +[section `constexpr bool contains( basic_string_view sv ) const noexcept;`] + +* *Returns:* `find( sv ) != npos`. + +[endsect] + +[section `constexpr bool contains( Ch c ) const noexcept;`] + +* *Returns:* `find( c ) != npos`. + +[endsect] + +[section `constexpr bool contains( Ch const* s ) const noexcept;`] + +* *Returns:* `find( s ) != npos`. + +[endsect] + +[endsect] + +[endsect] + +[section Relational Operators] + +[section `constexpr friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) == 0`. + +[endsect] + +[section `constexpr friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) != 0`. + +[endsect] + +[section `constexpr friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) < 0`. + +[endsect] + +[section `constexpr friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) <= 0`. + +[endsect] + +[section `constexpr friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) > 0`. + +[endsect] + +[section `constexpr friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) noexcept;`] + +* *Returns:* `sv1.compare( sv2 ) >= 0`. + +[endsect] + +[endsect] + +[section Stream Inserter] + +[section `template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str );`] + +* *Effects:* equivalent to `os << x`, where `x` is a pointer to a null-terminated character sequence with the same contents as `str`. + +[endsect] + +[endsect] + +[endsect] + +[endsect] diff --git a/doc/swap.qbk b/doc/swap.qbk index dc866fd..5770b9d 100644 --- a/doc/swap.qbk +++ b/doc/swap.qbk @@ -22,7 +22,7 @@ [section Header ] -`template void swap(T& left, T& right);` +[^template void swap(T& left, T& right) noexcept(['see below]);] [endsect] @@ -40,13 +40,14 @@ specialized swap function is available, `std::swap` is used. The generic `std::swap` function requires that the elements to be swapped are assignable and copy constructible. It is usually implemented using one copy construction and two -assignments - this is often both unnecessarily restrictive and -unnecessarily slow. In addition, where the generic swap -implementation provides only the basic guarantee, specialized -swap functions are often able to provide the no-throw exception -guarantee (and it is considered best practice to do so where -possible [footnote Scott Meyers, Effective C++ Third Edition, -Item 25: "Consider support for a non-throwing swap"]. +assignments (C++11 replaces copy operations with move) - this +is often both unnecessarily restrictive and unnecessarily slow. +In addition, where the generic swap implementation provides +only the basic guarantee, specialized swap functions are often +able to provide the no-throw exception guarantee (and it is +considered best practice to do so where possible[footnote Scott +Meyers, Effective C++ Third Edition, Item 25: "Consider support +for a non-throwing swap"]. The alternative to using argument dependent lookup in this situation is to provide a template specialization of @@ -59,12 +60,12 @@ in their own namespaces. `std::swap` originally did not do so, but a request to add an overload of `std::swap` for built-in arrays has been accepted by the C++ Standards Committee[footnote - [@http://open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809 + [@http://open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809 LWG Defect Report 809: std::swap should be overloaded for array types]]. [endsect] - + [section Exception Safety] `boost::swap` provides the same exception guarantee as the @@ -73,30 +74,33 @@ of type `T[n]`, where `n > 1` and the underlying swap function for `T` provides the strong exception guarantee, `boost::swap` provides only the basic exception guarantee. +In C++11 and later, `boost::swap` propagates the same `noexcept` +specification as the one specified in the underlying swap function. + [endsect] [section Requirements] Either: -* T must be assignable -* T must be copy constructible +* `T` must be copy assignable (/since C++11:/ move assignable) +* `T` must be copy constructible (/since C++11:/ move constructible) Or: -* A function with the signature `swap(T&,T&)` is available via +* A function with the signature `swap(T&, T&)` is available via argument dependent lookup Or: -* A template specialization of `std::swap` exists for T +* A template specialization of `std::swap` exists for `T` Or: -* T is a built-in array of swappable elements +* `T` is a built-in array of swappable elements [endsect] - + [section Portability] Several older compilers do not support argument dependent @@ -104,11 +108,11 @@ lookup. On these compilers `boost::swap` will call `std::swap`, ignoring any specialized swap functions that could be found as a result of argument dependent lookup. -[endsect] +[endsect] [section Credits] -* *Niels Dekker* - for implementing and documenting support for +* *Niels Dekker* - for implementing and documenting support for built-in arrays * *Joseph Gauterin* - for the initial idea, implementation, tests, and documentation diff --git a/doc/use_default.qbk b/doc/use_default.qbk index 2149161..63328ef 100644 --- a/doc/use_default.qbk +++ b/doc/use_default.qbk @@ -11,7 +11,7 @@ Distributed under the Boost Software License, Version 1.0. [section Overview] The header provides the type `boost::use_default` -which is used by other Boost libraries as a sentinel type in a templates to +which is used by other Boost libraries as a sentinel type in templates to indicate defaults. [endsect] diff --git a/doc/verbose_terminate_handler.qbk b/doc/verbose_terminate_handler.qbk new file mode 100644 index 0000000..35f8bff --- /dev/null +++ b/doc/verbose_terminate_handler.qbk @@ -0,0 +1,70 @@ +[/ + Copyright 2022 Peter Dimov + Distributed under the Boost Software License, Version 1.0. + https://boost.org/LICENSE_1_0.txt +] + +[section:verbose_terminate_handler verbose_terminate_handler] + +[simplesect Authors] + +* Peter Dimov + +[endsimplesect] + +[section Header ] + +The header `` defines +the function `void boost::core::verbose_terminate_handler()`. Its +purpose is to be set as a terminate handler as in +``` + std::set_terminate( boost::core::verbose_terminate_handler ); +``` + +When invoked, the function prints information about the current +uncaught exception to `stderr` and then calls `std::abort`. + +[section Synopsis] + +`` +namespace boost +{ +namespace core +{ + +[[noreturn]] void verbose_terminate_handler(); + +} // namespace core +} // namespace boost +`` + +[endsect] + +[section Example] + +``` +#include +#include +#include + +int main() +{ + std::set_terminate( boost::core::verbose_terminate_handler ); + boost::throw_with_location( std::exception() ); +} +``` + +Sample output: +``` +std::terminate called after throwing an exception: + + type: class boost::detail::with_throw_location + what(): Unknown exception + location: example.cpp:8:12 in function 'main' +``` + +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/alloc_construct.hpp b/include/boost/core/alloc_construct.hpp index e390730..075d3cb 100644 --- a/include/boost/core/alloc_construct.hpp +++ b/include/boost/core/alloc_construct.hpp @@ -8,6 +8,9 @@ Distributed under the Boost Software License, Version 1.0. #ifndef BOOST_CORE_ALLOC_CONSTRUCT_HPP #define BOOST_CORE_ALLOC_CONSTRUCT_HPP +/* +This functionality is now in . +*/ #include namespace boost { @@ -23,56 +26,9 @@ template inline void alloc_destroy_n(A& a, T* p, std::size_t n) { - while (n > 0) { - boost::allocator_destroy(a, p + --n); - } + boost::allocator_destroy_n(a, p, n); } -template -inline void -alloc_destroy(noinit_adaptor&, T* p) -{ - p->~T(); -} - -template -inline void -alloc_destroy_n(noinit_adaptor&, T* p, std::size_t n) -{ - while (n > 0) { - p[--n].~T(); - } -} - -namespace detail { - -template -class alloc_destroyer { -public: - alloc_destroyer(A& a, T* p) BOOST_NOEXCEPT - : a_(a), - p_(p), - n_(0) { } - - ~alloc_destroyer() { - boost::alloc_destroy_n(a_, p_, n_); - } - - std::size_t& size() BOOST_NOEXCEPT { - return n_; - } - -private: - alloc_destroyer(const alloc_destroyer&); - alloc_destroyer& operator=(const alloc_destroyer&); - - A& a_; - T* p_; - std::size_t n_; -}; - -} /* detail */ - template inline void alloc_construct(A& a, T* p) @@ -117,51 +73,21 @@ template inline void alloc_construct_n(A& a, T* p, std::size_t n) { - detail::alloc_destroyer hold(a, p); - for (std::size_t& i = hold.size(); i < n; ++i) { - boost::allocator_construct(a, p + i); - } - hold.size() = 0; + boost::allocator_construct_n(a, p, n); } template inline void alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m) { - detail::alloc_destroyer hold(a, p); - for (std::size_t& i = hold.size(); i < n; ++i) { - boost::allocator_construct(a, p + i, l[i % m]); - } - hold.size() = 0; + boost::allocator_construct_n(a, p, n, l, m); } template inline void alloc_construct_n(A& a, T* p, std::size_t n, I b) { - detail::alloc_destroyer hold(a, p); - for (std::size_t& i = hold.size(); i < n; void(++i), void(++b)) { - boost::allocator_construct(a, p + i, *b); - } - hold.size() = 0; -} - -template -inline void -alloc_construct(noinit_adaptor&, T* p) -{ - ::new(static_cast(p)) T; -} - -template -inline void -alloc_construct_n(noinit_adaptor& a, T* p, std::size_t n) -{ - detail::alloc_destroyer, T> hold(a, p); - for (std::size_t& i = hold.size(); i < n; ++i) { - ::new(static_cast(p + i)) T; - } - hold.size() = 0; + boost::allocator_construct_n(a, p, n, b); } } /* boost */ diff --git a/include/boost/core/allocator_access.hpp b/include/boost/core/allocator_access.hpp index 764c122..8e33ebb 100644 --- a/include/boost/core/allocator_access.hpp +++ b/include/boost/core/allocator_access.hpp @@ -1,5 +1,5 @@ /* -Copyright 2020-2021 Glen Joseph Fernandes +Copyright 2020-2022 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -9,16 +9,34 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_CORE_ALLOCATOR_ACCESS_HPP #include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #endif -#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #include #endif +#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION >= 40300) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) +#elif defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) +#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) +#elif defined(BOOST_CLANG) && !defined(__CUDACC__) +#if __has_feature(is_empty) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) +#endif +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __oracle_is_empty(T) +#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) +#elif defined(BOOST_CODEGEARC) +#define BOOST_DETAIL_ALLOC_EMPTY(T) __is_empty(T) +#endif + #if defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) _LIBCPP_SUPPRESS_DEPRECATED_PUSH #endif @@ -37,244 +55,311 @@ struct allocator_value_type { typedef typename A::value_type type; }; -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_pointer { - typedef typename A::pointer type; -}; -#else -template -struct allocator_pointer { - typedef typename A::value_type* type; -}; - namespace detail { +template +struct alloc_ptr { + typedef typename boost::allocator_value_type::type* type; +}; + template struct alloc_void { typedef void type; }; -} /* detail */ - template -struct allocator_pointer::type> { +struct alloc_ptr::type> { typedef typename A::pointer type; }; -#endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_const_pointer { - typedef typename A::const_pointer type; -}; -#else -template -struct allocator_const_pointer { - typedef typename pointer_traits::type>::template - rebind_to::type type; -}; +} /* detail */ template -struct allocator_const_pointer::type> { - typedef typename A::const_pointer type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_void_pointer { - typedef typename A::template rebind::other::pointer type; -}; -#else -template -struct allocator_void_pointer { - typedef typename pointer_traits::type>::template - rebind_to::type type; +struct allocator_pointer { + typedef typename detail::alloc_ptr::type type; }; -template -struct allocator_void_pointer::type> { - typedef typename A::void_pointer type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_const_void_pointer { - typedef typename A::template rebind::other::const_pointer type; -}; -#else -template -struct allocator_const_void_pointer { - typedef typename pointer_traits::type>::template - rebind_to::type type; -}; - -template -struct allocator_const_void_pointer::type> { - typedef typename A::const_void_pointer type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_difference_type { - typedef typename A::difference_type type; -}; -#else -template -struct allocator_difference_type { - typedef typename pointer_traits::type>::difference_type type; -}; - -template -struct allocator_difference_type::type> { - typedef typename A::difference_type type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_size_type { - typedef typename A::size_type type; -}; -#else -template -struct allocator_size_type { - typedef typename std::make_unsigned::type>::type type; -}; - -template -struct allocator_size_type::type> { - typedef typename A::size_type type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) namespace detail { -struct alloc_false { - BOOST_STATIC_CONSTEXPR bool value = false; +template +struct alloc_const_ptr { + typedef typename boost::pointer_traits::type>::template rebind_to::type>::type type; +}; + +template +struct alloc_const_ptr::type> { + typedef typename A::const_pointer type; }; } /* detail */ template -struct allocator_propagate_on_container_copy_assignment { - typedef detail::alloc_false type; -}; -#else -template -struct allocator_propagate_on_container_copy_assignment { - typedef std::false_type type; +struct allocator_const_pointer { + typedef typename detail::alloc_const_ptr::type type; }; -template -struct allocator_propagate_on_container_copy_assignment::type> { - typedef typename A::propagate_on_container_copy_assignment type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_propagate_on_container_move_assignment { - typedef detail::alloc_false type; -}; -#else -template -struct allocator_propagate_on_container_move_assignment { - typedef std::false_type type; -}; - -template -struct allocator_propagate_on_container_move_assignment::type> { - typedef typename A::propagate_on_container_move_assignment type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_propagate_on_container_swap { - typedef detail::alloc_false type; -}; -#else -template -struct allocator_propagate_on_container_swap { - typedef std::false_type type; -}; - -template -struct allocator_propagate_on_container_swap::type> { - typedef typename A::propagate_on_container_swap type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_is_always_equal { - typedef detail::alloc_false type; -}; -#else -template -struct allocator_is_always_equal { - typedef typename std::is_empty::type type; -}; - -template -struct allocator_is_always_equal::type> { - typedef typename A::is_always_equal type; -}; -#endif - -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct allocator_rebind { - typedef typename A::template rebind::other type; -}; -#else namespace detail { template struct alloc_to { }; +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template class A, class T, class U> +struct alloc_to, T> { + typedef A type; +}; + +template class A, class T, class U, class V> +struct alloc_to, T> { + typedef A type; +}; + +template class A, class T, class U, class V1, + class V2> +struct alloc_to, T> { + typedef A type; +}; +#else template class A, class T, class U, class... V> struct alloc_to, T> { typedef A type; }; - -} /* detail */ +#endif template -struct allocator_rebind { - typedef typename detail::alloc_to::type type; +struct alloc_rebind { + typedef typename alloc_to::type type; }; template -struct allocator_rebind::other>::type> { +struct alloc_rebind::other>::type> { typedef typename A::template rebind::other type; }; + +} /* detail */ + +template +struct allocator_rebind { + typedef typename detail::alloc_rebind::type type; +}; + +namespace detail { + +template +struct alloc_void_ptr { + typedef typename boost::pointer_traits::type>::template + rebind_to::type type; +}; + +template +struct alloc_void_ptr::type> { + typedef typename A::void_pointer type; +}; + +} /* detail */ + +template +struct allocator_void_pointer { + typedef typename detail::alloc_void_ptr::type type; +}; + +namespace detail { + +template +struct alloc_const_void_ptr { + typedef typename boost::pointer_traits::type>::template + rebind_to::type type; +}; + +template +struct alloc_const_void_ptr::type> { + typedef typename A::const_void_pointer type; +}; + +} /* detail */ + +template +struct allocator_const_void_pointer { + typedef typename detail::alloc_const_void_ptr::type type; +}; + +namespace detail { + +template +struct alloc_diff_type { + typedef typename boost::pointer_traits::type>::difference_type type; +}; + +template +struct alloc_diff_type::type> { + typedef typename A::difference_type type; +}; + +} /* detail */ + +template +struct allocator_difference_type { + typedef typename detail::alloc_diff_type::type type; +}; + +namespace detail { + +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_size_type { + typedef std::size_t type; +}; +#else +template +struct alloc_size_type { + typedef typename std::make_unsigned::type>::type type; +}; #endif +template +struct alloc_size_type::type> { + typedef typename A::size_type type; +}; + +} /* detail */ + +template +struct allocator_size_type { + typedef typename detail::alloc_size_type::type type; +}; + +namespace detail { + +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_bool { + typedef bool value_type; + typedef alloc_bool type; + + static const bool value = V; + + operator bool() const BOOST_NOEXCEPT { + return V; + } + + bool operator()() const BOOST_NOEXCEPT { + return V; + } +}; + +template +const bool alloc_bool::value; + +typedef alloc_bool alloc_false; +#else +typedef std::false_type alloc_false; +#endif + +template +struct alloc_pocca { + typedef alloc_false type; +}; + +template +struct alloc_pocca::type> { + typedef typename A::propagate_on_container_copy_assignment type; +}; + +} /* detail */ + +template +struct allocator_propagate_on_container_copy_assignment { + typedef typename detail::alloc_pocca::type type; +}; + +namespace detail { + +template +struct alloc_pocma { + typedef alloc_false type; +}; + +template +struct alloc_pocma::type> { + typedef typename A::propagate_on_container_move_assignment type; +}; + +} /* detail */ + +template +struct allocator_propagate_on_container_move_assignment { + typedef typename detail::alloc_pocma::type type; +}; + +namespace detail { + +template +struct alloc_pocs { + typedef alloc_false type; +}; + +template +struct alloc_pocs::type> { + typedef typename A::propagate_on_container_swap type; +}; + +} /* detail */ + +template +struct allocator_propagate_on_container_swap { + typedef typename detail::alloc_pocs::type type; +}; + +namespace detail { + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_equal { + typedef typename std::is_empty::type type; +}; +#elif defined(BOOST_DETAIL_ALLOC_EMPTY) +template +struct alloc_equal { + typedef alloc_bool type; +}; +#else +template +struct alloc_equal { + typedef alloc_false type; +}; +#endif + +template +struct alloc_equal::type> { + typedef typename A::is_always_equal type; +}; + +} /* detail */ + +template +struct allocator_is_always_equal { + typedef typename detail::alloc_equal::type type; +}; + template inline typename allocator_pointer::type allocator_allocate(A& a, typename allocator_size_type::type n) @@ -301,21 +386,24 @@ allocator_allocate(A& a, typename allocator_size_type::type n, #else namespace detail { -struct alloc_none { }; +template +struct alloc_no { + char x, y; +}; template class alloc_has_allocate { template - static auto check(int) -> decltype(std::declval().allocate( - std::declval::type>(), - std::declval::type>())); + static auto check(int) + -> alloc_no().allocate(std::declval::type>(), std::declval::type>()))>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; } /* detail */ @@ -339,9 +427,55 @@ allocator_allocate(A& a, typename allocator_size_type::type n, } #endif +namespace detail { + +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_has_construct { + BOOST_STATIC_CONSTEXPR bool value = false; +}; + +template +struct alloc_has_construct::type> { + BOOST_STATIC_CONSTEXPR bool value = true; +}; +#else +template +class alloc_has_construct { + template + static auto check(int) + -> alloc_no().construct(std::declval(), + std::declval()...))>; + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; +}; +#endif + +template +struct alloc_if { }; + +template +struct alloc_if { + typedef T type; +}; + +} /* detail */ + #if defined(BOOST_NO_CXX11_ALLOCATOR) template -inline void +inline typename detail::alloc_if::value>::type +allocator_construct(A& a, T* p) +{ + a.construct(p); +} + +template +inline typename detail::alloc_if::value>::type allocator_construct(A&, T* p) { ::new((void*)p) T(); @@ -379,25 +513,6 @@ allocator_construct(A&, T* p, V& v) } #endif #else -namespace detail { - -template -class alloc_has_construct { - template - static auto check(int) - -> decltype(std::declval().construct(std::declval(), - std::declval()...)); - - template - static alloc_none check(long); - -public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; -}; - -} /* detail */ - template inline typename std::enable_if::value>::type @@ -415,132 +530,236 @@ allocator_construct(A&, T* p, Args&&... args) } #endif -#if defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline void -allocator_destroy(A&, T* p) -{ - p->~T(); - (void)p; -} -#else namespace detail { +#if defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct alloc_has_destroy { + BOOST_STATIC_CONSTEXPR bool value = false; +}; + +template +struct alloc_has_destroy::type> { + BOOST_STATIC_CONSTEXPR bool value = true; +}; +#else template class alloc_has_destroy { template static auto check(int) - -> decltype(std::declval().destroy(std::declval())); + -> alloc_no().destroy(std::declval()))>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; +#endif } /* detail */ template -inline typename std::enable_if::value>::type +inline typename detail::alloc_if::value>::type allocator_destroy(A& a, T* p) { a.destroy(p); } template -inline typename std::enable_if::value>::type +inline typename detail::alloc_if::value>::type allocator_destroy(A&, T* p) { p->~T(); (void)p; } -#endif + +namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline typename allocator_size_type::type -allocator_max_size(const A& a) -{ - return a.max_size(); -} -#else -namespace detail { +template +struct alloc_no { + char x, y; +}; template class alloc_has_max_size { template - static auto check(int) -> decltype(std::declval().max_size()); + static alloc_no::type(O::*)(), + &O::max_size> check(int); + + template + static alloc_no::type(O::*)() const, + &O::max_size> check(int); + + template + static alloc_no::type(*)(), + &O::max_size> check(int); template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; +#else +template +class alloc_has_max_size { + template + static auto check(int) + -> alloc_no().max_size())>; + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; +}; +#endif } /* detail */ template -inline typename std::enable_if::value, +inline typename detail::alloc_if::value, typename allocator_size_type::type>::type -allocator_max_size(const A& a) +allocator_max_size(const A& a) BOOST_NOEXCEPT { return a.max_size(); } template -inline typename std::enable_if::value, +inline typename detail::alloc_if::value, typename allocator_size_type::type>::type -allocator_max_size(const A&) +allocator_max_size(const A&) BOOST_NOEXCEPT { return (std::numeric_limits::type>::max)() / sizeof(typename A::value_type); + allocator_size_type::type>::max)() / + sizeof(typename allocator_value_type::type); } -#endif + +namespace detail { #if defined(BOOST_NO_CXX11_ALLOCATOR) template -inline A -allocator_select_on_container_copy_construction(const A& a) -{ - return a; -} -#else -namespace detail { +class alloc_has_soccc { + template + static alloc_no + check(int); + template + static alloc_no + check(int); + + template + static alloc_no + check(int); + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; +}; +#else template class alloc_has_soccc { template - static auto check(int) - -> decltype(std::declval().select_on_container_copy_construction()); + static auto check(int) -> alloc_no().select_on_container_copy_construction())>; template - static alloc_none check(long); + static char check(long); public: - BOOST_STATIC_CONSTEXPR bool value = - !std::is_same(0)), alloc_none>::value; + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; }; +#endif } /* detail */ template -inline typename std::enable_if::value, A>::type +inline typename detail::alloc_if::value, A>::type allocator_select_on_container_copy_construction(const A& a) { return a.select_on_container_copy_construction(); } template -inline typename std::enable_if::value, A>::type +inline typename detail::alloc_if::value, A>::type allocator_select_on_container_copy_construction(const A& a) { return a; } -#endif + +template +inline void +allocator_destroy_n(A& a, T* p, std::size_t n) +{ + while (n > 0) { + boost::allocator_destroy(a, p + --n); + } +} + +namespace detail { + +template +class alloc_destroyer { +public: + alloc_destroyer(A& a, T* p) BOOST_NOEXCEPT + : a_(a), p_(p), n_(0) { } + + ~alloc_destroyer() { + boost::allocator_destroy_n(a_, p_, n_); + } + + std::size_t& size() BOOST_NOEXCEPT { + return n_; + } + +private: + alloc_destroyer(const alloc_destroyer&); + alloc_destroyer& operator=(const alloc_destroyer&); + + A& a_; + T* p_; + std::size_t n_; +}; + +} /* detail */ + +template +inline void +allocator_construct_n(A& a, T* p, std::size_t n) +{ + detail::alloc_destroyer d(a, p); + for (std::size_t& i = d.size(); i < n; ++i) { + boost::allocator_construct(a, p + i); + } + d.size() = 0; +} + +template +inline void +allocator_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m) +{ + detail::alloc_destroyer d(a, p); + for (std::size_t& i = d.size(); i < n; ++i) { + boost::allocator_construct(a, p + i, l[i % m]); + } + d.size() = 0; +} + +template +inline void +allocator_construct_n(A& a, T* p, std::size_t n, I b) +{ + detail::alloc_destroyer d(a, p); + for (std::size_t& i = d.size(); i < n; void(++i), void(++b)) { + boost::allocator_construct(a, p + i, *b); + } + d.size() = 0; +} #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template @@ -588,14 +807,14 @@ using allocator_rebind_t = typename allocator_rebind::type; } /* boost */ -#if defined(_LIBCPP_SUPPRESS_DEPRECATED_POP) -_LIBCPP_SUPPRESS_DEPRECATED_POP +#if defined(_MSC_VER) +#pragma warning(pop) #endif #if defined(_STL_RESTORE_DEPRECATED_WARNING) _STL_RESTORE_DEPRECATED_WARNING #endif -#if defined(_MSC_VER) -#pragma warning(pop) +#if defined(_LIBCPP_SUPPRESS_DEPRECATED_POP) +_LIBCPP_SUPPRESS_DEPRECATED_POP #endif #endif diff --git a/include/boost/core/allocator_traits.hpp b/include/boost/core/allocator_traits.hpp new file mode 100644 index 0000000..bf8749d --- /dev/null +++ b/include/boost/core/allocator_traits.hpp @@ -0,0 +1,112 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_CORE_ALLOCATOR_TRAITS_HPP +#define BOOST_CORE_ALLOCATOR_TRAITS_HPP + +#include + +namespace boost { + +template +struct allocator_traits { + typedef A allocator_type; + + typedef typename allocator_value_type::type value_type; + + typedef typename allocator_pointer::type pointer; + + typedef typename allocator_const_pointer::type const_pointer; + + typedef typename allocator_void_pointer::type void_pointer; + + typedef typename allocator_const_void_pointer::type const_void_pointer; + + typedef typename allocator_difference_type::type difference_type; + + typedef typename allocator_size_type::type size_type; + + typedef typename allocator_propagate_on_container_copy_assignment::type + propagate_on_container_copy_assignment; + + typedef typename allocator_propagate_on_container_move_assignment::type + propagate_on_container_move_assignment; + + typedef typename allocator_propagate_on_container_swap::type + propagate_on_container_swap; + + typedef typename allocator_is_always_equal::type is_always_equal; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + using rebind_traits = allocator_traits::type>; +#else + template + struct rebind_traits + : allocator_traits::type> { }; +#endif + + static pointer allocate(A& a, size_type n) { + return boost::allocator_allocate(a, n); + } + + static pointer allocate(A& a, size_type n, const_void_pointer h) { + return boost::allocator_allocate(a, n, h); + } + + static void deallocate(A& a, pointer p, size_type n) { + return boost::allocator_deallocate(a, p, n); + } + + template + static void construct(A& a, T* p) { + boost::allocator_construct(a, p); + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + static void construct(A& a, T* p, V&& v, Args&&... args) { + boost::allocator_construct(a, p, std::forward(v), + std::forward(args)...); + } +#else + template + static void construct(A& a, T* p, V&& v) { + boost::allocator_construct(a, p, std::forward(v)); + } +#endif +#else + template + static void construct(A& a, T* p, const V& v) { + boost::allocator_construct(a, p, v); + } + + template + static void construct(A& a, T* p, V& v) { + boost::allocator_construct(a, p, v); + } +#endif + + template + static void destroy(A& a, T* p) { + boost::allocator_destroy(a, p); + } + + static size_type max_size(const A& a) BOOST_NOEXCEPT { + return boost::allocator_max_size(a); + } + + static A select_on_container_copy_construction(const A& a) { + return boost::allocator_select_on_container_copy_construction(a); + } +}; + +} /* boost */ + +#endif diff --git a/include/boost/core/bit.hpp b/include/boost/core/bit.hpp index c469bc8..5d14685 100644 --- a/include/boost/core/bit.hpp +++ b/include/boost/core/bit.hpp @@ -22,13 +22,20 @@ #include #if defined(_MSC_VER) + # include # pragma intrinsic(_BitScanForward) # pragma intrinsic(_BitScanReverse) + # if defined(_M_X64) # pragma intrinsic(_BitScanForward64) # pragma intrinsic(_BitScanReverse64) # endif + +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4244) // conversion from int to T + #endif // defined(_MSC_VER) namespace boost @@ -75,9 +82,9 @@ BOOST_CONSTEXPR inline int countl_impl( unsigned long x ) BOOST_NOEXCEPT return x? __builtin_clzl( x ): std::numeric_limits::digits; } -BOOST_CONSTEXPR inline int countl_impl( unsigned long long x ) BOOST_NOEXCEPT +BOOST_CONSTEXPR inline int countl_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT { - return x? __builtin_clzll( x ): std::numeric_limits::digits; + return x? __builtin_clzll( x ): std::numeric_limits::digits; } } // namespace detail @@ -85,6 +92,8 @@ BOOST_CONSTEXPR inline int countl_impl( unsigned long long x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::detail::countl_impl( x ); } @@ -162,17 +171,19 @@ inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT template int countl_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) ); - if( sizeof(T) == sizeof(boost::uint8_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) ) { return boost::core::detail::countl_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint16_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) ) { return boost::core::detail::countl_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint32_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) ) { return boost::core::detail::countl_impl( static_cast( x ) ); } @@ -187,6 +198,8 @@ int countl_zero( T x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR int countl_one( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::countl_zero( static_cast( ~x ) ); } @@ -217,9 +230,9 @@ BOOST_CONSTEXPR inline int countr_impl( unsigned long x ) BOOST_NOEXCEPT return x? __builtin_ctzl( x ): std::numeric_limits::digits; } -BOOST_CONSTEXPR inline int countr_impl( unsigned long long x ) BOOST_NOEXCEPT +BOOST_CONSTEXPR inline int countr_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT { - return x? __builtin_ctzll( x ): std::numeric_limits::digits; + return x? __builtin_ctzll( x ): std::numeric_limits::digits; } } // namespace detail @@ -227,6 +240,8 @@ BOOST_CONSTEXPR inline int countr_impl( unsigned long long x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::detail::countr_impl( x ); } @@ -297,17 +312,19 @@ inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT template int countr_zero( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) ); - if( sizeof(T) == sizeof(boost::uint8_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) ) { return boost::core::detail::countr_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint16_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) ) { return boost::core::detail::countr_impl( static_cast( x ) ); } - else if( sizeof(T) == sizeof(boost::uint32_t) ) + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) ) { return boost::core::detail::countr_impl( static_cast( x ) ); } @@ -322,6 +339,8 @@ int countr_zero( T x ) BOOST_NOEXCEPT template BOOST_CONSTEXPR int countr_one( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::countr_zero( static_cast( ~x ) ); } @@ -358,7 +377,7 @@ BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned long x ) BOOST_ return __builtin_popcountl( x ); } -BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned long long x ) BOOST_NOEXCEPT +BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( boost::ulong_long_type x ) BOOST_NOEXCEPT { return __builtin_popcountll( x ); } @@ -370,6 +389,8 @@ BOOST_CORE_POPCOUNT_CONSTEXPR inline int popcount_impl( unsigned long long x ) B template BOOST_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return boost::core::detail::popcount_impl( x ); } @@ -401,9 +422,11 @@ BOOST_CXX14_CONSTEXPR inline int popcount_impl( boost::uint64_t x ) BOOST_NOEXCE template BOOST_CXX14_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) ); - if( sizeof(T) <= sizeof(boost::uint32_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) ) { return boost::core::detail::popcount_impl( static_cast( x ) ); } @@ -420,6 +443,8 @@ BOOST_CXX14_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT template BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + unsigned const mask = std::numeric_limits::digits - 1; return x << (s & mask) | x >> ((-s) & mask); } @@ -427,6 +452,8 @@ BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT template BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + unsigned const mask = std::numeric_limits::digits - 1; return x >> (s & mask) | x << ((-s) & mask); } @@ -436,18 +463,27 @@ BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT template BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return x != 0 && ( x & ( x - 1 ) ) == 0; } +// bit_width returns `int` now, https://cplusplus.github.io/LWG/issue3656 +// has been applied to C++20 as a DR + template -BOOST_CONSTEXPR T bit_width( T x ) BOOST_NOEXCEPT +BOOST_CONSTEXPR int bit_width( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return std::numeric_limits::digits - boost::core::countl_zero( x ); } template BOOST_CONSTEXPR T bit_floor( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + return x == 0? 0: T(1) << ( boost::core::bit_width( x ) - 1 ); } @@ -500,9 +536,11 @@ BOOST_CXX14_CONSTEXPR inline boost::uint64_t bit_ceil_impl( boost::uint64_t x ) template BOOST_CXX14_CONSTEXPR T bit_ceil( T x ) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); + BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) ); - if( sizeof(T) <= sizeof(boost::uint32_t) ) + BOOST_IF_CONSTEXPR ( sizeof(T) <= sizeof(boost::uint32_t) ) { return static_cast( boost::core::detail::bit_ceil_impl( static_cast( x ) ) ); } @@ -578,4 +616,8 @@ typedef endian::type endian_type; } // namespace core } // namespace boost +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + #endif // #ifndef BOOST_CORE_BIT_HPP_INCLUDED diff --git a/include/boost/core/default_allocator.hpp b/include/boost/core/default_allocator.hpp index 9e466ca..91d3bbc 100644 --- a/include/boost/core/default_allocator.hpp +++ b/include/boost/core/default_allocator.hpp @@ -19,21 +19,25 @@ BOOST_NORETURN void throw_exception(const std::exception&); namespace default_ { -struct true_type { +template +struct bool_constant { typedef bool value_type; - typedef true_type type; + typedef bool_constant type; - BOOST_STATIC_CONSTANT(bool, value = true); + static const bool value = V; - BOOST_CONSTEXPR operator bool() const BOOST_NOEXCEPT { - return true; + operator bool() const BOOST_NOEXCEPT { + return V; } - BOOST_CONSTEXPR bool operator()() const BOOST_NOEXCEPT { - return true; + bool operator()() const BOOST_NOEXCEPT { + return V; } }; +template +const bool bool_constant::value; + template struct add_reference { typedef T& type; @@ -58,8 +62,8 @@ struct default_allocator { typedef typename add_reference::type const_reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; - typedef true_type propagate_on_container_move_assignment; - typedef true_type is_always_equal; + typedef bool_constant propagate_on_container_move_assignment; + typedef bool_constant is_always_equal; template struct rebind { @@ -108,6 +112,12 @@ struct default_allocator { } #endif +#if defined(BOOST_NO_CXX11_ALLOCATOR) + T* allocate(std::size_t n, const void*) { + return allocate(n); + } +#endif + #if (defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000) || \ defined(BOOST_NO_CXX11_ALLOCATOR) template diff --git a/include/boost/core/detail/is_same.hpp b/include/boost/core/detail/is_same.hpp new file mode 100644 index 0000000..634d300 --- /dev/null +++ b/include/boost/core/detail/is_same.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED +#define BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED + +// is_same::value is true when T1 == T2 +// +// Copyright 2014 Peter Dimov +// +// 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 + +#include + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost +{ +namespace core +{ +namespace detail +{ + +template< class T1, class T2 > struct is_same +{ + BOOST_STATIC_CONSTANT( bool, value = false ); +}; + +template< class T > struct is_same< T, T > +{ + BOOST_STATIC_CONSTANT( bool, value = true ); +}; + +} // namespace detail +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED diff --git a/include/boost/core/detail/lwt_unattended.hpp b/include/boost/core/detail/lwt_unattended.hpp new file mode 100644 index 0000000..68cba62 --- /dev/null +++ b/include/boost/core/detail/lwt_unattended.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_CORE_DETAIL_LWT_UNATTENDED_HPP_INCLUDED +#define BOOST_CORE_DETAIL_LWT_UNATTENDED_HPP_INCLUDED + +// Copyright 2014, 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) +# include +#endif + +namespace boost +{ +namespace core +{ +namespace detail +{ + +// Setup unattended mode by disabling interactive popups on +// assertion failures + +inline void lwt_unattended() +{ +#if defined(_MSC_VER) && (_MSC_VER > 1310) + + // disable message boxes on assert(), abort() + ::_set_abort_behavior( 0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT ); + +#endif + +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) + + // disable message boxes on iterator debugging violations + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); + +#endif +} + +} // namespace detail +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_DETAIL_LWT_UNATTENDED_HPP_INCLUDED diff --git a/include/boost/core/detail/splitmix64.hpp b/include/boost/core/detail/splitmix64.hpp index a7dc532..e91ab0a 100644 --- a/include/boost/core/detail/splitmix64.hpp +++ b/include/boost/core/detail/splitmix64.hpp @@ -34,14 +34,14 @@ public: boost::uint64_t operator()() { - x_ += 0x9e3779b97f4a7c15; + x_ += ( boost::uint64_t(0x9e3779b9u) << 32 ) + 0x7f4a7c15u; boost::uint64_t z = x_; z ^= z >> 30; - z *= 0xbf58476d1ce4e5b9; + z *= ( boost::uint64_t(0xbf58476du) << 32 ) + 0x1ce4e5b9u; z ^= z >> 27; - z *= 0x94d049bb133111eb; + z *= ( boost::uint64_t(0x94d049bbu) << 32 ) + 0x133111ebu; z ^= z >> 31; return z; diff --git a/include/boost/core/detail/string_view.hpp b/include/boost/core/detail/string_view.hpp new file mode 100644 index 0000000..1d89b8b --- /dev/null +++ b/include/boost/core/detail/string_view.hpp @@ -0,0 +1,1272 @@ +#ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED +#define BOOST_CORE_STRING_VIEW_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost::core::basic_string_view +// +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif +#if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) // std::common_reference_with +# include +#endif + +namespace boost +{ + +// forward declaration of boost::basic_string_view from Utility +template class basic_string_view; + +// forward declaration of boost::hash_range from ContainerHash +template std::size_t hash_range( It, It ); + +namespace core +{ +namespace detail +{ + +template struct sv_to_uchar +{ + typedef Ch type; +}; + +template<> struct sv_to_uchar +{ + typedef unsigned char type; +}; + +#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtype-limits" +#endif + +template BOOST_CXX14_CONSTEXPR std::size_t find_first_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + + if( use_table ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + UCh ch = p_[ i ]; + if( ch >= 0 && ch < 256 && table[ ch ] ) return i; + } + } + else if( n >= 16 ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + if( std::char_traits::find( s, n, ch ) != 0 ) return i; + } + } + else + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) return i; + } + } + } + + return static_cast( -1 ); +} + +template BOOST_CXX14_CONSTEXPR std::size_t find_last_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + + std::size_t const npos = static_cast< std::size_t >( -1 ); + + std::size_t i = pos; + + if( use_table ) + { + do + { + UCh ch = p_[ i ]; + + if( ch >= 0 && ch < 256 && table[ ch ] ) return i; + + --i; + } + while( i != npos ); + } + else if( n >= 16 ) + { + do + { + Ch ch = p_[ i ]; + + if( std::char_traits::find( s, n, ch ) != 0 ) return i; + + --i; + } + while( i != npos ); + } + else + { + do + { + Ch ch = p_[ i ]; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) return i; + } + + --i; + } + while( i != npos ); + } + + return npos; +} + +template BOOST_CXX14_CONSTEXPR std::size_t find_first_not_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + + if( use_table ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + UCh ch = p_[ i ]; + if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i; + } + } + else if( n >= 16 ) + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + if( std::char_traits::find( s, n, ch ) == 0 ) return i; + } + } + else + { + for( std::size_t i = pos; i < n_; ++i ) + { + Ch ch = p_[ i ]; + + bool r = false; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) + { + r = true; + break; + } + } + + if( !r ) return i; + } + } + + return static_cast( -1 ); +} + +template BOOST_CXX14_CONSTEXPR std::size_t find_last_not_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT +{ + typedef typename sv_to_uchar::type UCh; + + unsigned char table[ 256 ] = {}; + + bool use_table = true; + + for( std::size_t j = 0; j < n; ++j ) + { + UCh ch = s[ j ]; + + if( ch >= 0 && ch < 256 ) + { + table[ ch ] = 1; + } + else + { + use_table = false; + break; + } + } + + std::size_t const npos = static_cast< std::size_t >( -1 ); + + std::size_t i = pos; + + if( use_table ) + { + do + { + UCh ch = p_[ i ]; + + if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i; + + --i; + } + while( i != npos ); + } + else if( n >= 16 ) + { + do + { + Ch ch = p_[ i ]; + + if( std::char_traits::find( s, n, ch ) == 0 ) return i; + + --i; + } + while( i != npos ); + } + else + { + do + { + Ch ch = p_[ i ]; + + bool r = false; + + for( std::size_t j = 0; j < n; ++j ) + { + if( s[ j ] == ch ) + { + r = true; + break; + } + } + + if( !r ) return i; + + --i; + } + while( i != npos ); + } + + return npos; +} + +#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406 +# pragma GCC diagnostic pop +#endif + +} // namespace detail + +template class basic_string_view +{ +private: + + Ch const* p_; + std::size_t n_; + +public: + + // types + + typedef std::char_traits traits_type; + typedef Ch value_type; + typedef Ch* pointer; + typedef Ch const* const_pointer; + typedef Ch& reference; + typedef Ch const& const_reference; + typedef Ch const* const_iterator; + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // npos + + BOOST_STATIC_CONSTEXPR size_type npos = static_cast( -1 ); + +public: + + // construction and assignment + + BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT: p_(), n_() + { + } + + BOOST_CONSTEXPR basic_string_view( Ch const* str ) BOOST_NOEXCEPT: p_( str ), n_( traits_type::length( str ) ) + { + } + + BOOST_CONSTEXPR basic_string_view( Ch const* str, size_type len ) BOOST_NOEXCEPT: p_( str ), n_( len ) + { + } + + template BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* first, End last, + typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( first ), n_( last - first ) + { + BOOST_ASSERT( last - first >= 0 ); + } + + template basic_string_view( std::basic_string, A> const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) + { + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + basic_string_view( std::basic_string_view > const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) + { + } + +#endif + + template basic_string_view( boost::basic_string_view > const& str, + typename boost::enable_if >::type* = 0 ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() ) + { + } + +#if !defined(BOOST_NO_CXX11_NULLPTR) +# if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + + basic_string_view( std::nullptr_t ) = delete; + +# else + +private: + + basic_string_view( std::nullptr_t ); + +public: + +# endif +#endif + + // BOOST_CONSTEXPR basic_string_view& operator=( basic_string_view const& ) BOOST_NOEXCEPT & = default; + + // conversions + + template operator std::basic_string, A>() const + { + return std::basic_string, A>( data(), size() ); + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + template >::type> + operator std::basic_string_view() const BOOST_NOEXCEPT + { + return std::basic_string_view( data(), size() ); + } + +#endif + + template operator boost::basic_string_view, std::char_traits >::type> () const BOOST_NOEXCEPT + { + return boost::basic_string_view< Ch, std::char_traits >( data(), size() ); + } + + // iterator support + + BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT + { + return p_; + } + + BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT + { + return p_ + n_; + } + + BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT + { + return p_; + } + + BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT + { + return p_ + n_; + } + + BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT + { + return const_reverse_iterator( end() ); + } + + BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT + { + return const_reverse_iterator( begin() ); + } + + BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT + { + return const_reverse_iterator( end() ); + } + + BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT + { + return const_reverse_iterator( begin() ); + } + + // capacity + + BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT + { + return n_; + } + + BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT + { + return n_; + } + + BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT + { + return npos / sizeof( Ch ); + } + + BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT + { + return n_ == 0; + } + + // element access + + BOOST_CXX14_CONSTEXPR const_reference operator[]( size_type pos ) const BOOST_NOEXCEPT + { + BOOST_ASSERT( pos < size() ); + return p_[ pos ]; + } + + BOOST_CXX14_CONSTEXPR const_reference at( size_type pos ) const + { + if( pos >= size() ) + { + boost::throw_exception( std::out_of_range( "basic_string_view::at" ), BOOST_CURRENT_LOCATION ); + } + + return p_[ pos ]; + } + + BOOST_CXX14_CONSTEXPR const_reference front() const BOOST_NOEXCEPT + { + BOOST_ASSERT( !empty() ); + return p_[ 0 ]; + } + + BOOST_CXX14_CONSTEXPR const_reference back() const BOOST_NOEXCEPT + { + BOOST_ASSERT( !empty() ); + return p_[ n_ - 1 ]; + } + + BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT + { + return p_; + } + + // modifiers + + BOOST_CXX14_CONSTEXPR void remove_prefix( size_type n ) BOOST_NOEXCEPT + { + BOOST_ASSERT( n <= size() ); + + p_ += n; + n_ -= n; + } + + BOOST_CXX14_CONSTEXPR void remove_suffix( size_type n ) BOOST_NOEXCEPT + { + BOOST_ASSERT( n <= size() ); + + n_ -= n; + } + + BOOST_CXX14_CONSTEXPR void swap( basic_string_view& s ) BOOST_NOEXCEPT + { + std::swap( p_, s.p_ ); + std::swap( n_, s.n_ ); + } + + // string operations + + BOOST_CXX14_CONSTEXPR size_type copy( Ch* s, size_type n, size_type pos = 0 ) const + { + if( pos > size() ) + { + boost::throw_exception( std::out_of_range( "basic_string_view::copy" ), BOOST_CURRENT_LOCATION ); + } + + std::size_t rlen = (std::min)( n, size() - pos ); + + traits_type::copy( s, data() + pos, rlen ); + + return rlen; + } + + BOOST_CXX14_CONSTEXPR basic_string_view substr( size_type pos = 0, size_type n = npos ) const + { + if( pos > size() ) + { + boost::throw_exception( std::out_of_range( "basic_string_view::substr" ), BOOST_CURRENT_LOCATION ); + } + + std::size_t rlen = (std::min)( n, size() - pos ); + + return basic_string_view( data() + pos, rlen ); + } + + // compare + + BOOST_CXX14_CONSTEXPR int compare( basic_string_view str ) const BOOST_NOEXCEPT + { + std::size_t rlen = (std::min)( size(), str.size() ); + + int cmp = traits_type::compare( data(), str.data(), rlen ); + + if( cmp != 0 ) return cmp; + + if( size() == str.size() ) return 0; + + return size() < str.size()? -1: +1; + } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str ) const + { + return substr( pos1, n1 ).compare( str ); + } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const + { + return substr( pos1, n1 ).compare( str.substr( pos2, n2 ) ); + } + + BOOST_CONSTEXPR int compare( Ch const* s ) const BOOST_NOEXCEPT + { + return compare( basic_string_view( s ) ); + } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s ) const + { + return substr( pos1, n1 ).compare( basic_string_view( s ) ); + } + + BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const + { + return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); + } + + // starts_with + + BOOST_CONSTEXPR bool starts_with( basic_string_view x ) const BOOST_NOEXCEPT + { + return size() >= x.size() && traits_type::compare( data(), x.data(), x.size() ) == 0; + } + + BOOST_CONSTEXPR bool starts_with( Ch x ) const BOOST_NOEXCEPT + { + return !empty() && front() == x; + } + + BOOST_CONSTEXPR bool starts_with( Ch const* x ) const BOOST_NOEXCEPT + { + return starts_with( basic_string_view( x ) ); + } + + // ends_with + + BOOST_CONSTEXPR bool ends_with( basic_string_view x ) const BOOST_NOEXCEPT + { + return size() >= x.size() && traits_type::compare( data() + size() - x.size(), x.data(), x.size() ) == 0; + } + + BOOST_CONSTEXPR bool ends_with( Ch x ) const BOOST_NOEXCEPT + { + return !empty() && back() == x; + } + + BOOST_CONSTEXPR bool ends_with( Ch const* x ) const BOOST_NOEXCEPT + { + return ends_with( basic_string_view( x ) ); + } + + // find + + BOOST_CONSTEXPR size_type find( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find( str.data(), pos, str.size() ); + } + + BOOST_CXX14_CONSTEXPR size_type find( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + { + if( pos >= size() ) return npos; + + Ch const* r = traits_type::find( data() + pos, size() - pos, c ); + + return r? r - data(): npos; + } + + BOOST_CXX14_CONSTEXPR size_type find( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( n == 1 ) return find( s[0], pos ); + + if( pos + n > size() ) return npos; + if( n == 0 ) return pos; + + Ch const* p = data() + pos; + Ch const* last = data() + size() - n + 1; + + for( ;; ) + { + p = traits_type::find( p, last - p, s[0] ); + + if( p == 0 ) break; + + if( traits_type::compare( p + 1, s + 1, n - 1 ) == 0 ) return p - data(); + + ++p; + } + + return npos; + } + + BOOST_CONSTEXPR size_type find( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find( s, pos, traits_type::length( s ) ); + } + + // rfind + + BOOST_CONSTEXPR size_type rfind( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + { + return rfind( str.data(), pos, str.size() ); + } + + BOOST_CXX14_CONSTEXPR size_type rfind( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + { + size_type n = size(); + + if( n == 0 ) + { + return npos; + } + + if( pos > n - 1 ) + { + pos = n - 1; + } + + do + { + if( p_[ pos ] == c ) return pos; + --pos; + } + while( pos != npos ); + + return npos; + } + + BOOST_CXX14_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( n > size() ) return npos; + + if( pos > size() - n ) + { + pos = size() - n; + } + + if( n == 0 ) return pos; + + for( ;; ) + { + size_type xpos = rfind( s[0], pos ); + + if( xpos == npos ) return npos; + + if( traits_type::compare( data() + xpos, s, n ) == 0 ) return xpos; + + if( xpos == 0 ) return npos; + + pos = xpos - 1; + } + } + + BOOST_CONSTEXPR size_type rfind( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + { + return rfind( s, pos, traits_type::length( s ) ); + } + + // find_first_of + + BOOST_CXX14_CONSTEXPR size_type find_first_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find_first_of( str.data(), pos, str.size() ); + } + + BOOST_CONSTEXPR size_type find_first_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find( c, pos ); + } + + BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( n == 0 || pos >= size() ) return npos; + if( n == 1 ) return find( s[0], pos ); + + return detail::find_first_of( data(), size(), s, pos, n ); + } + + BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find_first_of( s, pos, traits_type::length( s ) ); + } + + // find_last_of + + BOOST_CXX14_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + { + return find_last_of( str.data(), pos, str.size() ); + } + + BOOST_CONSTEXPR size_type find_last_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + { + return rfind( c, pos ); + } + + BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( n == 1 ) + { + return rfind( s[0], pos ); + } + + size_type m = size(); + + if( m == 0 ) + { + return npos; + } + + if( pos > m - 1 ) + { + pos = m - 1; + } + + return detail::find_last_of( data(), s, pos, n ); + } + + BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + { + return find_last_of( s, pos, traits_type::length( s ) ); + } + + // find_first_not_of + + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find_first_not_of( str.data(), pos, str.size() ); + } + + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT + { + for( std::size_t i = pos; i < n_; ++i ) + { + if( p_[ i ] != c ) return i; + } + + return npos; + } + + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( pos >= size() ) return npos; + if( n == 1 ) return find_first_not_of( s[0], pos ); + + return detail::find_first_not_of( data(), size(), s, pos, n ); + } + + BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT + { + return find_first_not_of( s, pos, traits_type::length( s ) ); + } + + // find_last_not_of + + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT + { + return find_last_not_of( str.data(), pos, str.size() ); + } + + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT + { + size_type m = size(); + + if( m == 0 ) + { + return npos; + } + + if( pos > m - 1 ) + { + pos = m - 1; + } + + do + { + if( p_[ pos ] != c ) return pos; + --pos; + } + while( pos != npos ); + + return npos; + } + + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT + { + if( n == 1 ) + { + return find_last_not_of( s[0], pos ); + } + + size_type m = size(); + + if( m == 0 ) + { + return npos; + } + + if( pos > m - 1 ) + { + pos = m - 1; + } + + return detail::find_last_not_of( data(), s, pos, n ); + } + + BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT + { + return find_last_not_of( s, pos, traits_type::length( s ) ); + } + + // contains + + BOOST_CONSTEXPR bool contains( basic_string_view sv ) const BOOST_NOEXCEPT + { + return find( sv ) != npos; + } + + BOOST_CXX14_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT + { + Ch const* p = data(); + size_type n = size(); + + if( n >= 16 ) + { + return traits_type::find( p, n, c ) != 0; + } + else + { + for( size_type i = 0; i < n; ++i ) + { + if( p[ i ] == c ) return true; + } + + return false; + } + } + + BOOST_CONSTEXPR bool contains( Ch const* s ) const BOOST_NOEXCEPT + { + return find( s ) != npos; + } + + // relational operators + + BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return !( sv1 == sv2 ); + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + // "sufficient number of additional overloads" + + // against std::string_view + + BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return !( sv1 == sv2 ); + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return !( sv1 == sv2 ); + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + // against Ch const* + + BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1 == basic_string_view( sv2 ); + } + + BOOST_CXX14_CONSTEXPR friend bool operator==( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return basic_string_view( sv1 ) == sv2; + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return !( sv1 == sv2 ); + } + + BOOST_CXX14_CONSTEXPR friend bool operator!=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return !( sv1 == sv2 ); + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator<=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) < 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + BOOST_CXX14_CONSTEXPR friend bool operator>=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) <= 0; + } + + // against std::string + + template BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT + { + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT + { + return !( sv1 == sv2 ); + } + + template BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return !( sv1 == sv2 ); + } + + template BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) < 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) > 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) <= 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) >= 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) > 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) < 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string, A> const& sv2 ) BOOST_NOEXCEPT + { + return sv1.compare( sv2 ) >= 0; + } + + template BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT + { + return sv2.compare( sv1 ) <= 0; + } + +#endif + + inline friend std::size_t hash_value( basic_string_view const& sv ) + { + return boost::hash_range( sv.begin(), sv.end() ); + } +}; + +// stream inserter + +template std::basic_ostream& operator<<( std::basic_ostream& os, basic_string_view str ) +{ + Ch const* p = str.data(); + std::streamsize n = str.size(); + + std::streamsize m = os.width(); + + if( n >= m ) + { + os.write( p, n ); + } + else if( ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::left ) + { + os.write( p, n ); + + os.width( m - n ); + os << ""; + } + else + { + os.width( m - n ); + os << ""; + + os.write( p, n ); + } + + os.width( 0 ); + return os; +} + +#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) +template BOOST_CONSTEXPR_OR_CONST std::size_t basic_string_view::npos; +#endif + +// typedef names + +typedef basic_string_view string_view; +typedef basic_string_view wstring_view; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) +typedef basic_string_view u16string_view; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) +typedef basic_string_view u32string_view; +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L +typedef basic_string_view u8string_view; +#endif + +} // namespace core +} // namespace boost + +// std::common_reference support +// needed for iterators that have reference=string_view and value_type=std::string + +#if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) + +template class Q1, template class Q2> +struct std::basic_common_reference< + boost::core::basic_string_view, + std::basic_string, A>, + Q1, Q2> +{ + using type = boost::core::basic_string_view; +}; + +template class Q1, template class Q2> +struct std::basic_common_reference< + std::basic_string, A>, + boost::core::basic_string_view, + Q1, Q2> +{ + using type = boost::core::basic_string_view; +}; + +#endif + +#endif // #ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED diff --git a/include/boost/core/empty_value.hpp b/include/boost/core/empty_value.hpp index 2ac2331..d8ffa30 100644 --- a/include/boost/core/empty_value.hpp +++ b/include/boost/core/empty_value.hpp @@ -25,6 +25,11 @@ Distributed under the Boost Software License, Version 1.0. #endif #endif +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4510) +#endif + namespace boost { template @@ -51,37 +56,37 @@ public: #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) empty_value() = default; #else - empty_value() { } + BOOST_CONSTEXPR empty_value() { } #endif - empty_value(boost::empty_init_t) + BOOST_CONSTEXPR empty_value(boost::empty_init_t) : value_() { } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template - empty_value(boost::empty_init_t, U&& value, Args&&... args) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value, Args&&... args) : value_(std::forward(value), std::forward(args)...) { } #else template - empty_value(boost::empty_init_t, U&& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value) : value_(std::forward(value)) { } #endif #else template - empty_value(boost::empty_init_t, const U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, const U& value) : value_(value) { } template - empty_value(boost::empty_init_t, U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U& value) : value_(value) { } #endif - const T& get() const BOOST_NOEXCEPT { + BOOST_CONSTEXPR const T& get() const BOOST_NOEXCEPT { return value_; } - T& get() BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR T& get() BOOST_NOEXCEPT { return value_; } @@ -99,37 +104,37 @@ public: #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) empty_value() = default; #else - empty_value() { } + BOOST_CONSTEXPR empty_value() { } #endif - empty_value(boost::empty_init_t) + BOOST_CONSTEXPR empty_value(boost::empty_init_t) : T() { } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template - empty_value(boost::empty_init_t, U&& value, Args&&... args) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value, Args&&... args) : T(std::forward(value), std::forward(args)...) { } #else template - empty_value(boost::empty_init_t, U&& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U&& value) : T(std::forward(value)) { } #endif #else template - empty_value(boost::empty_init_t, const U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, const U& value) : T(value) { } template - empty_value(boost::empty_init_t, U& value) + BOOST_CONSTEXPR empty_value(boost::empty_init_t, U& value) : T(value) { } #endif - const T& get() const BOOST_NOEXCEPT { + BOOST_CONSTEXPR const T& get() const BOOST_NOEXCEPT { return *this; } - T& get() BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR T& get() BOOST_NOEXCEPT { return *this; } }; @@ -143,4 +148,8 @@ BOOST_INLINE_CONSTEXPR empty_init_t empty_init = empty_init_t(); } /* boost */ +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + #endif diff --git a/include/boost/core/fclose_deleter.hpp b/include/boost/core/fclose_deleter.hpp new file mode 100644 index 0000000..8f7a7fd --- /dev/null +++ b/include/boost/core/fclose_deleter.hpp @@ -0,0 +1,46 @@ +/* + * Copyright Andrey Semashev 2022. + * 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) + */ +/*! + * \file fclose_deleter.hpp + * \author Andrey Semashev + * \date 21.09.2022 + * + * This header contains an \c fclose_deleter implementation. This is a deleter + * function object that invokes std::fclose on the passed pointer to + * a std::FILE structure. + */ + +#ifndef BOOST_CORE_FCLOSE_DELETER_HPP +#define BOOST_CORE_FCLOSE_DELETER_HPP + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +//! A function object that closes a file +struct fclose_deleter +{ + //! Function object result type + typedef void result_type; + /*! + * Closes the file handle + */ + void operator() (std::FILE* p) const BOOST_NOEXCEPT + { + if (BOOST_LIKELY(!!p)) + std::fclose(p); + } +}; + +} // namespace boost + +#endif // BOOST_CORE_FCLOSE_DELETER_HPP diff --git a/include/boost/core/is_same.hpp b/include/boost/core/is_same.hpp index f373c65..111cbd1 100644 --- a/include/boost/core/is_same.hpp +++ b/include/boost/core/is_same.hpp @@ -1,12 +1,6 @@ #ifndef BOOST_CORE_IS_SAME_HPP_INCLUDED #define BOOST_CORE_IS_SAME_HPP_INCLUDED -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - // is_same::value is true when T1 == T2 // // Copyright 2014 Peter Dimov @@ -16,6 +10,15 @@ // http://www.boost.org/LICENSE_1_0.txt #include +#include + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include + +BOOST_HEADER_DEPRECATED("") namespace boost { @@ -23,15 +26,7 @@ namespace boost namespace core { -template< class T1, class T2 > struct is_same -{ - BOOST_STATIC_CONSTANT( bool, value = false ); -}; - -template< class T > struct is_same< T, T > -{ - BOOST_STATIC_CONSTANT( bool, value = true ); -}; +using boost::core::detail::is_same; } // namespace core diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 3b5df89..c09ce87 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -22,6 +22,7 @@ // http://www.boost.org/LICENSE_1_0.txt // +#include #include #include #include @@ -32,11 +33,6 @@ #include #include #include -#include - -#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) -# include -#endif // IDE's like Visual Studio perform better if output goes to std::cout or // some other stream, so allow user to configure output stream: @@ -46,42 +42,39 @@ namespace boost { - namespace detail { -class test_result { +class test_result +{ public: - test_result() - : report_(false) - , errors_(0) { -#if defined(_MSC_VER) && (_MSC_VER > 1310) - // disable message boxes on assert(), abort() - ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); -#endif -#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) - // disable message boxes on iterator debugging violations - _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); -#endif + + test_result(): report_( false ), errors_( 0 ) + { + core::detail::lwt_unattended(); } - ~test_result() { - if (!report_) { + ~test_result() + { + if( !report_ ) + { BOOST_LIGHTWEIGHT_TEST_OSTREAM << "main() should return report_errors()" << std::endl; std::abort(); } } - int& errors() { + int& errors() + { return errors_; } - void done() { + void done() + { report_ = true; } private: + bool report_; int errors_; }; @@ -197,11 +190,6 @@ inline unsigned long test_output_impl( char16_t const& v ) { return v; } inline unsigned long test_output_impl( char32_t const& v ) { return v; } #endif -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4996) -#endif - inline std::string test_output_impl( char const& v ) { if( std::isprint( static_cast( v ) ) ) @@ -210,17 +198,17 @@ inline std::string test_output_impl( char const& v ) } else { - char buffer[ 8 ]; - std::sprintf( buffer, "\\x%02X", static_cast( v ) ); + static const char char_table[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + char buffer[ 4 ]; + buffer[ 0 ] = '\\'; + buffer[ 1 ] = 'x'; + buffer[ 2 ] = char_table[ (static_cast( v ) >> 4u) & 0x0f ]; + buffer[ 3 ] = char_table[ static_cast( v ) & 0x0f ]; - return buffer; + return std::string( buffer, 4u ); } } -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - // predicates struct lw_test_eq @@ -530,6 +518,15 @@ inline int report_errors() return errors < 256? errors: 255; } +namespace core +{ + +inline void lwt_init() +{ + boost::detail::test_results(); +} + +} // namespace core } // namespace boost #define BOOST_TEST(expr) ( ::boost::detail::test_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, (expr)? true: false) ) diff --git a/include/boost/core/lightweight_test_trait.hpp b/include/boost/core/lightweight_test_trait.hpp index bddc3ce..eea2371 100644 --- a/include/boost/core/lightweight_test_trait.hpp +++ b/include/boost/core/lightweight_test_trait.hpp @@ -11,7 +11,7 @@ // // BOOST_TEST_TRAIT_TRUE, BOOST_TEST_TRAIT_FALSE, BOOST_TEST_TRAIT_SAME // -// Copyright 2014 Peter Dimov +// Copyright 2014, 2021 Peter Dimov // // Copyright 2019 Glen Joseph Fernandes // (glenjofe@gmail.com) @@ -21,60 +21,15 @@ // http://www.boost.org/LICENSE_1_0.txt #include -#include -#include +#include +#include #include namespace boost { - namespace detail { -template struct test_print { }; - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << boost::core::demangled_name(BOOST_CORE_TYPEID(T)); -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print(); -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " const"; -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " volatile"; -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " const volatile"; -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print(); -} - -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " &"; -} - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -template inline std::ostream& operator<<(std::ostream& o, test_print) -{ - return o << test_print() << " &&"; -} -#endif - template< class T > inline void test_trait_impl( char const * trait, void (*)( T ), bool expected, char const * file, int line, char const * function ) { @@ -86,7 +41,7 @@ template< class T > inline void test_trait_impl( char const * trait, void (*)( T { BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): predicate '" << trait << "' [" - << boost::core::demangled_name( BOOST_CORE_TYPEID(T) ) << "]" + << boost::core::type_name() << "]" << " test failed in function '" << function << "' (should have been " << ( expected? "true": "false" ) << ")" << std::endl; @@ -101,7 +56,7 @@ template inline bool test_trait_same_impl_( T ) } template inline void test_trait_same_impl( char const * types, - boost::core::is_same same, char const * file, int line, char const * function ) + boost::core::detail::is_same same, char const * file, int line, char const * function ) { if( test_trait_same_impl_( same ) ) { @@ -112,8 +67,8 @@ template inline void test_trait_same_impl( char const * type BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test 'is_same<" << types << ">'" << " failed in function '" << function - << "' ('" << test_print() - << "' != '" << test_print() << "')" + << "' ('" << boost::core::type_name() + << "' != '" << boost::core::type_name() << "')" << std::endl; ++test_results().errors(); @@ -121,7 +76,6 @@ template inline void test_trait_same_impl( char const * type } } // namespace detail - } // namespace boost #define BOOST_TEST_TRAIT_TRUE(type) ( ::boost::detail::test_trait_impl(#type, (void(*)type)0, true, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) @@ -132,6 +86,6 @@ template inline void test_trait_same_impl( char const * type # pragma GCC system_header #endif -#define BOOST_TEST_TRAIT_SAME(...) ( ::boost::detail::test_trait_same_impl(#__VA_ARGS__, ::boost::core::is_same<__VA_ARGS__>(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) +#define BOOST_TEST_TRAIT_SAME(...) ( ::boost::detail::test_trait_same_impl(#__VA_ARGS__, ::boost::core::detail::is_same< __VA_ARGS__ >(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) #endif // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_TRAIT_HPP diff --git a/include/boost/core/noinit_adaptor.hpp b/include/boost/core/noinit_adaptor.hpp index 13ce4c8..623e3ea 100644 --- a/include/boost/core/noinit_adaptor.hpp +++ b/include/boost/core/noinit_adaptor.hpp @@ -15,6 +15,8 @@ namespace boost { template struct noinit_adaptor : A { + typedef void _default_construct_destroy; + template struct rebind { typedef noinit_adaptor::type> other; @@ -56,6 +58,7 @@ struct noinit_adaptor template void destroy(U* p) { p->~U(); + (void)p; } }; diff --git a/include/boost/core/noncopyable.hpp b/include/boost/core/noncopyable.hpp index 4a4f8ba..4ec2d54 100644 --- a/include/boost/core/noncopyable.hpp +++ b/include/boost/core/noncopyable.hpp @@ -27,7 +27,7 @@ namespace noncopyable_ // protection from unintended ADL // whether a type derives from noncopyable without needing the definition // of noncopyable itself. // -// The definition of base_token is macro-guarded so that Type Trais can +// The definition of base_token is macro-guarded so that Type Traits can // define it locally without including this header, to avoid a dependency // on Core. diff --git a/include/boost/core/pointer_traits.hpp b/include/boost/core/pointer_traits.hpp index e66194d..7de7a8e 100644 --- a/include/boost/core/pointer_traits.hpp +++ b/include/boost/core/pointer_traits.hpp @@ -1,5 +1,5 @@ /* -Copyright 2017-2018 Glen Joseph Fernandes +Copyright 2017-2021 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -9,43 +9,23 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_CORE_POINTER_TRAITS_HPP #include -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) -#include -#else #include #include -#endif namespace boost { - -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) -template -struct pointer_traits - : std::pointer_traits { - template - struct rebind_to { - typedef typename std::pointer_traits::template rebind type; - }; -}; - -template -struct pointer_traits - : std::pointer_traits { - template - struct rebind_to { - typedef U* type; - }; -}; -#else namespace detail { +struct ptr_none { }; + template -struct ptr_void { +struct ptr_valid { typedef void type; }; -template -struct ptr_first; +template +struct ptr_first { + typedef ptr_none type; +}; #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template class T, class U, class... Args> @@ -75,7 +55,7 @@ struct ptr_element { }; template -struct ptr_element::type> { +struct ptr_element::type> { typedef typename T::element_type type; }; @@ -86,12 +66,12 @@ struct ptr_difference { template struct ptr_difference::type> { + typename ptr_valid::type> { typedef typename T::difference_type type; }; -template -struct ptr_transform; +template +struct ptr_transform { }; #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template class T, class U, class... Args, class V> @@ -117,68 +97,139 @@ struct ptr_transform, V> { #endif template -struct ptr_rebind { - typedef typename ptr_transform::type type; -}; +struct ptr_rebind + : ptr_transform { }; #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template struct ptr_rebind >::type> { + typename ptr_valid >::type> { typedef typename T::template rebind type; }; +#else +template +struct ptr_rebind::other>::type> { + typedef typename T::template rebind::other type; +}; +#endif + +#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) +template +class ptr_to_expr { + template + struct result { + char x, y; + }; + + static E& source(); + + template + static auto check(int) -> result; + + template + static char check(long); + +public: + BOOST_STATIC_CONSTEXPR bool value = sizeof(check(0)) > 1; +}; + +template +struct ptr_to_expr { + BOOST_STATIC_CONSTEXPR bool value = true; +}; + +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = ptr_to_expr::value; +}; +#else +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = true; +}; #endif template -struct ptr_value { - typedef T type; +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = false; }; -template<> -struct ptr_value { - typedef struct { } type; +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = false; }; +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = false; +}; + +template +struct ptr_has_to { + BOOST_STATIC_CONSTEXPR bool value = false; +}; + +template::value> +struct ptr_to { }; + +template +struct ptr_to { + static T pointer_to(E& v) { + return T::pointer_to(v); + } +}; + +template +struct ptr_to { + static T* pointer_to(T& v) BOOST_NOEXCEPT { + return boost::addressof(v); + } +}; + +template +struct ptr_traits + : ptr_to { + typedef T pointer; + typedef E element_type; + typedef typename ptr_difference::type difference_type; + + template + struct rebind_to + : ptr_rebind { }; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + using rebind = typename rebind_to::type; +#endif +}; + +template +struct ptr_traits { }; + } /* detail */ template -struct pointer_traits { - typedef T pointer; - typedef typename detail::ptr_element::type element_type; - typedef typename detail::ptr_difference::type difference_type; - template - struct rebind_to { - typedef typename detail::ptr_rebind::type type; - }; -#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - template - using rebind = typename detail::ptr_rebind::type; -#endif - static pointer - pointer_to(typename detail::ptr_value::type& v) { - return pointer::pointer_to(v); - } -}; +struct pointer_traits + : detail::ptr_traits::type> { }; template -struct pointer_traits { +struct pointer_traits + : detail::ptr_to { typedef T* pointer; typedef T element_type; typedef std::ptrdiff_t difference_type; + template struct rebind_to { typedef U* type; }; + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template - using rebind = U*; + using rebind = typename rebind_to::type; #endif - static T* - pointer_to(typename detail::ptr_value::type& v) BOOST_NOEXCEPT { - return boost::addressof(v); - } }; -#endif template BOOST_CONSTEXPR inline T* diff --git a/include/boost/core/quick_exit.hpp b/include/boost/core/quick_exit.hpp index 40ead1d..ff1bda3 100644 --- a/include/boost/core/quick_exit.hpp +++ b/include/boost/core/quick_exit.hpp @@ -33,7 +33,7 @@ extern "C" _Noreturn void quick_exit(int); namespace boost { -BOOST_NORETURN void quick_exit( int code ) BOOST_NOEXCEPT +BOOST_NORETURN inline void quick_exit( int code ) BOOST_NOEXCEPT { #if defined(_MSC_VER) && _MSC_VER < 1900 diff --git a/include/boost/core/ref.hpp b/include/boost/core/ref.hpp index a416cbd..d29a4d6 100644 --- a/include/boost/core/ref.hpp +++ b/include/boost/core/ref.hpp @@ -1,17 +1,15 @@ #ifndef BOOST_CORE_REF_HPP #define BOOST_CORE_REF_HPP -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - #include #include #include #include +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + // // ref.hpp - ref/cref, useful helper functions // @@ -61,9 +59,11 @@ template< class Y, class T > struct ref_convertible enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; }; +#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) struct ref_empty { }; +#endif } // namespace detail @@ -92,11 +92,11 @@ public: @remark Does not throw. */ - BOOST_FORCEINLINE explicit reference_wrapper(T& t): t_(boost::addressof(t)) {} + BOOST_FORCEINLINE explicit reference_wrapper(T& t) BOOST_NOEXCEPT : t_(boost::addressof(t)) {} #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 ) - BOOST_FORCEINLINE explicit reference_wrapper( T & t, ref_workaround_tag ): t_( boost::addressof( t ) ) {} + BOOST_FORCEINLINE explicit reference_wrapper( T & t, ref_workaround_tag ) BOOST_NOEXCEPT : t_( boost::addressof( t ) ) {} #endif @@ -117,30 +117,37 @@ public: @remark Only enabled when `Y*` is convertible to `T*`. @remark Does not throw. */ - template reference_wrapper( reference_wrapper r, - typename enable_if_c::value, - boost::detail::ref_empty>::type = boost::detail::ref_empty() ): t_( r.t_ ) +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template::value>::type> + reference_wrapper( reference_wrapper r ) BOOST_NOEXCEPT : t_( r.t_ ) { } +#else + template reference_wrapper( reference_wrapper r, + typename enable_if_c::value, + boost::detail::ref_empty>::type = boost::detail::ref_empty() ) BOOST_NOEXCEPT : t_( r.t_ ) + { + } +#endif /** @return The stored reference. @remark Does not throw. */ - BOOST_FORCEINLINE operator T& () const { return *t_; } + BOOST_FORCEINLINE operator T& () const BOOST_NOEXCEPT { return *t_; } /** @return The stored reference. @remark Does not throw. */ - BOOST_FORCEINLINE T& get() const { return *t_; } + BOOST_FORCEINLINE T& get() const BOOST_NOEXCEPT { return *t_; } /** @return A pointer to the object referenced by the stored reference. @remark Does not throw. */ - BOOST_FORCEINLINE T* get_pointer() const { return t_; } + BOOST_FORCEINLINE T* get_pointer() const BOOST_NOEXCEPT { return t_; } private: @@ -165,7 +172,7 @@ private: @return `reference_wrapper(t)` @remark Does not throw. */ -template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref( T & t ) +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref( T & t ) BOOST_NOEXCEPT { #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 ) @@ -184,7 +191,7 @@ template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref( T @return `reference_wrapper(t)` @remark Does not throw. */ -template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST cref( T const & t ) +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST cref( T const & t ) BOOST_NOEXCEPT { return reference_wrapper(t); } @@ -315,7 +322,7 @@ template struct unwrap_reference< reference_wrapper const volatil @return `unwrap_reference::type&(t)` @remark Does not throw. */ -template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_ref( T & t ) +template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_ref( T & t ) BOOST_NOEXCEPT { return t; } @@ -325,7 +332,7 @@ template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_r /** @cond */ -template BOOST_FORCEINLINE T* get_pointer( reference_wrapper const & r ) +template BOOST_FORCEINLINE T* get_pointer( reference_wrapper const & r ) BOOST_NOEXCEPT { return r.get_pointer(); } diff --git a/include/boost/core/snprintf.hpp b/include/boost/core/snprintf.hpp new file mode 100644 index 0000000..91e252b --- /dev/null +++ b/include/boost/core/snprintf.hpp @@ -0,0 +1,173 @@ +/* + * Copyright Andrey Semashev 2022. + * 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) + */ +/*! + * \file snprintf.hpp + * \author Andrey Semashev + * \date 06.12.2022 + * + * \brief The header provides more portable definition of snprintf and vsnprintf, + * as well as \c wchar_t counterparts. + */ + +#ifndef BOOST_CORE_SNPRINTF_HPP_INCLUDED_ +#define BOOST_CORE_SNPRINTF_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__MINGW32__) + +#include +#include +#if !defined(__MINGW64_VERSION_MAJOR) +#include +#endif + +// MinGW32 and MinGW-w64 provide their own snprintf implementations that are compliant with the C standard. +#define BOOST_CORE_DETAIL_MINGW_SNPRINTF + +#elif (defined(BOOST_MSSTL_VERSION) && BOOST_MSSTL_VERSION < 140) + +#include +#include +#include + +// MSVC snprintfs are not conforming but they are good enough for typical use cases. +#define BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF + +#endif + +namespace boost { + +namespace core { + +#if defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +#if defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) + +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + return __mingw_vsnprintf(buf, size, format, args); +} + +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ +#if defined(__MINGW64_VERSION_MAJOR) + int res = __mingw_vsnwprintf(buf, size, format, args); + // __mingw_vsnwprintf returns the number of characters to be printed, but (v)swprintf is expected to return -1 on truncation + if (static_cast< unsigned int >(res) >= size) + res = -1; + return res; +#else + // Legacy MinGW32 does not provide __mingw_vsnwprintf, so use _vsnwprintf from MSVC CRT + if (BOOST_UNLIKELY(size == 0u || size > static_cast< std::size_t >(INT_MAX))) + return -1; + + int res = _vsnwprintf(buf, size, format, args); + // (v)swprintf is expected to return -1 on truncation, so we only need to ensure the output is null-terminated + if (static_cast< unsigned int >(res) >= size) + { + buf[size - 1u] = L'\0'; + res = -1; + } + + return res; +#endif +} + +#elif defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +#if defined(_MSC_VER) +#pragma warning(push) +// '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. +#pragma warning(disable: 4996) +#endif + +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + if (BOOST_UNLIKELY(size == 0u)) + return 0; + if (BOOST_UNLIKELY(size > static_cast< std::size_t >(INT_MAX))) + return -1; + + buf[size - 1u] = '\0'; + int res = _vsnprintf(buf, size, format, args); + if (static_cast< unsigned int >(res) >= size) + { + // _vsnprintf returns -1 if the output was truncated and in case of other errors. + // Detect truncation by checking whether the output buffer was written over entirely. + if (buf[size - 1u] != '\0') + { + buf[size - 1u] = '\0'; + res = static_cast< int >(size); + } + } + + return res; +} + +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ + if (BOOST_UNLIKELY(size == 0u || size > static_cast< std::size_t >(INT_MAX))) + return -1; + + int res = _vsnwprintf(buf, size, format, args); + // (v)swprintf is expected to return -1 on truncation, so we only need to ensure the output is null-terminated + if (static_cast< unsigned int >(res) >= size) + { + buf[size - 1u] = L'\0'; + res = -1; + } + + return res; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif + +inline int snprintf(char* buf, std::size_t size, const char* format, ...) +{ + std::va_list args; + va_start(args, format); + int res = vsnprintf(buf, size, format, args); + va_end(args); + return res; +} + +inline int swprintf(wchar_t* buf, std::size_t size, const wchar_t* format, ...) +{ + std::va_list args; + va_start(args, format); + int res = vswprintf(buf, size, format, args); + va_end(args); + return res; +} + +#else // defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +// Standard-conforming compilers already have the correct snprintfs +using ::snprintf; +using ::vsnprintf; + +using ::swprintf; +using ::vswprintf; + +#endif // defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +} // namespace core + +} // namespace boost + +#endif // BOOST_CORE_SNPRINTF_HPP_INCLUDED_ diff --git a/include/boost/core/span.hpp b/include/boost/core/span.hpp new file mode 100644 index 0000000..cbe8556 --- /dev/null +++ b/include/boost/core/span.hpp @@ -0,0 +1,399 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_CORE_SPAN_HPP +#define BOOST_CORE_SPAN_HPP + +#include +#include +#include +#include + +namespace boost { + +constexpr std::size_t dynamic_extent = static_cast(-1); + +template +class span; + +namespace detail { + +template +struct span_convertible { + static constexpr bool value = std::is_convertible::value; +}; + +template +struct span_capacity { + static constexpr bool value = E == boost::dynamic_extent || E == N; +}; + +template +struct span_compatible { + static constexpr bool value = span_capacity::value && + span_convertible::value; +}; + +template +struct span_uncvref { + typedef typename std::remove_cv::type>::type type; +}; + +template +struct span_is_span { + static constexpr bool value = false; +}; + +template +struct span_is_span > { + static constexpr bool value = true; +}; + +template +struct span_is_array { + static constexpr bool value = false; +}; + +template +struct span_is_array > { + static constexpr bool value = true; +}; + +template +struct span_data { }; + +template +struct span_data().data())>::value>::type> { + typedef typename std::remove_pointer().data())>::type type; +}; + +template +struct span_has_data { + static constexpr bool value = false; +}; + +template +struct span_has_data::type, T>::value>::type> { + static constexpr bool value = true; +}; + +template +struct span_has_size { + static constexpr bool value = false; +}; + +template +struct span_has_size().size()), + std::size_t>::value>::type> { + static constexpr bool value = true; +}; + +template +struct span_is_range { + static constexpr bool value = (std::is_const::value || + std::is_lvalue_reference::value) && + !span_is_span::type>::value && + !span_is_array::type>::value && + !std::is_array::type>::value && + span_has_data::value && + span_has_size::value; +}; + +template +struct span_implicit { + static constexpr bool value = E == boost::dynamic_extent || + N != boost::dynamic_extent; +}; + +template +struct span_copyable { + static constexpr bool value = (N == boost::dynamic_extent || + span_capacity::value) && span_convertible::value; +}; + +template +struct span_sub { + static constexpr std::size_t value = E == boost::dynamic_extent ? + boost::dynamic_extent : E - O; +}; + +template +struct span_store { + constexpr span_store(T* p_, std::size_t) noexcept + : p(p_) { } + static constexpr std::size_t n = E; + T* p; +}; + +template +struct span_store { + constexpr span_store(T* p_, std::size_t n_) noexcept + : p(p_) + , n(n_) { } + T* p; + std::size_t n; +}; + +template +struct span_bytes { + static constexpr std::size_t value = sizeof(T) * E; +}; + +template +struct span_bytes { + static constexpr std::size_t value = boost::dynamic_extent; +}; + +} /* detail */ + +template +class span { +public: + typedef T element_type; + typedef typename std::remove_cv::type value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T* iterator; + typedef const T* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + static constexpr std::size_t extent = E; + + template::type = 0> + constexpr span() noexcept + : s_(0, 0) { } + + template::value, int>::type = 0> + constexpr span(I* f, size_type c) + : s_(f, c) { } + + template::value, int>::type = 0> + explicit constexpr span(I* f, size_type c) + : s_(f, c) { } + + template::value, int>::type = 0> + constexpr span(I* f, L* l) + : s_(f, l - f) { } + + template::value, int>::type = 0> + explicit constexpr span(I* f, L* l) + : s_(f, l - f) { } + + template::value, + int>::type = 0> + constexpr span(typename std::enable_if::type (&a)[N]) noexcept + : s_(a, N) { } + + template::value, + int>::type = 0> + constexpr span(std::array& a) noexcept + : s_(a.data(), N) { } + + template::value, int>::type = 0> + constexpr span(const std::array& a) noexcept + : s_(a.data(), N) { } + + template::value, int>::type = 0> + constexpr span(R&& r) noexcept(noexcept(r.data()) && noexcept(r.size())) + : s_(r.data(), r.size()) { } + + template::value, int>::type = 0> + explicit constexpr span(R&& r) noexcept(noexcept(r.data()) && + noexcept(r.size())) + : s_(r.data(), r.size()) { } + + template::value && + detail::span_copyable::value, int>::type = 0> + constexpr span(const span& s) noexcept + : s_(s.data(), s.size()) { } + + template::value && + detail::span_copyable::value, int>::type = 0> + explicit constexpr span(const span& s) noexcept + : s_(s.data(), s.size()) { } + + template + constexpr span first() const { + static_assert(C <= E, "Count <= Extent"); + return span(s_.p, C); + } + + template + constexpr span last() const { + static_assert(C <= E, "Count <= Extent"); + return span(s_.p + (s_.n - C), C); + } + + template + constexpr typename std::enable_if::value> >::type subspan() const { + static_assert(O <= E, "Offset <= Extent"); + return span::value>(s_.p + O, s_.n - O); + } + + template + constexpr typename std::enable_if >::type subspan() const { + static_assert(O <= E && C <= E - O, + "Offset <= Extent && Count <= Extent - Offset"); + return span(s_.p + O, C); + } + + constexpr span first(size_type c) const { + return span(s_.p, c); + } + + constexpr span last(size_type c) const { + return span(s_.p + (s_.n - c), c); + } + + constexpr span subspan(size_type o, + size_type c = dynamic_extent) const { + return span(s_.p + o, + c == dynamic_extent ? s_.n - o : c); + } + + constexpr size_type size() const noexcept { + return s_.n; + } + + constexpr size_type size_bytes() const noexcept { + return s_.n * sizeof(T); + } + + constexpr bool empty() const noexcept { + return s_.n == 0; + } + + constexpr reference operator[](size_type i) const { + return s_.p[i]; + } + + constexpr reference front() const { + return *s_.p; + } + + constexpr reference back() const { + return s_.p[s_.n - 1]; + } + + constexpr pointer data() const noexcept { + return s_.p; + } + + constexpr iterator begin() const noexcept { + return s_.p; + } + + constexpr iterator end() const noexcept { + return s_.p + s_.n; + } + + constexpr reverse_iterator rbegin() const noexcept { + return reverse_iterator(s_.p + s_.n); + } + + constexpr reverse_iterator rend() const noexcept { + return reverse_iterator(s_.p); + } + + constexpr const_iterator cbegin() const noexcept { + return s_.p; + } + + constexpr const_iterator cend() const noexcept { + return s_.p + s_.n; + } + + constexpr const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(s_.p + s_.n); + } + + constexpr const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(s_.p); + } + +private: + detail::span_store s_; +}; + +template +constexpr std::size_t span::extent; + +#ifdef __cpp_deduction_guides +template +span(I*, L) -> span; + +template +span(T(&)[N]) -> span; + +template +span(std::array&) -> span; + +template +span(const std::array&) -> span; + +template +span(R&&) -> span::type>; + +template +span(span) -> span; +#endif + +#ifdef __cpp_lib_byte +template +inline span::value> +as_bytes(span s) noexcept +{ + return span::value>(reinterpret_cast(s.data()), + s.size_bytes()); +} + +template +inline typename std::enable_if::value, + span::value> >::type +as_writable_bytes(span s) noexcept +{ + return span::value>(reinterpret_cast(s.data()), s.size_bytes()); +} +#endif + +} /* boost */ + +#endif diff --git a/include/boost/core/swap.hpp b/include/boost/core/swap.hpp index 49e1b2d..7add2fb 100644 --- a/include/boost/core/swap.hpp +++ b/include/boost/core/swap.hpp @@ -13,10 +13,10 @@ // - swap_impl is put outside the boost namespace, to avoid infinite // recursion (causing stack overflow) when swapping objects of a primitive // type. -// - swap_impl has a using-directive, rather than a using-declaration, -// because some compilers (including MSVC 7.1, Borland 5.9.3, and -// Intel 8.1) don't do argument-dependent lookup when it has a -// using-declaration instead. +// - std::swap is imported with a using-directive, rather than +// a using-declaration, because some compilers (including MSVC 7.1, +// Borland 5.9.3, and Intel 8.1) don't do argument-dependent lookup +// when it has a using-declaration instead. // - boost::swap has two template arguments, instead of one, to // avoid ambiguity when swapping objects of a Boost type that does // not have its own boost::swap overload. @@ -30,6 +30,17 @@ #endif #include // for std::size_t +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_GCC) && (BOOST_GCC < 40700) +// gcc 4.6 ICEs on noexcept specifications below +#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) +#else +#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x) +#endif + namespace boost_swap_impl { // we can't use type_traits here @@ -37,17 +48,22 @@ namespace boost_swap_impl template struct is_const { enum _vt { value = 0 }; }; template struct is_const { enum _vt { value = 1 }; }; + // Use std::swap if argument dependent lookup fails. + // We need to have this at namespace scope to be able to use unqualified swap() call + // in noexcept specification. + using namespace std; + template BOOST_GPU_ENABLED - void swap_impl(T& left, T& right) + void swap_impl(T& left, T& right) BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(swap(left, right))) { - using namespace std;//use std::swap if argument dependent lookup fails - swap(left,right); + swap(left, right); } template BOOST_GPU_ENABLED void swap_impl(T (& left)[N], T (& right)[N]) + BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::swap_impl(left[0], right[0]))) { for (std::size_t i = 0; i < N; ++i) { @@ -62,9 +78,12 @@ namespace boost BOOST_GPU_ENABLED typename enable_if_c< !boost_swap_impl::is_const::value && !boost_swap_impl::is_const::value >::type swap(T1& left, T2& right) + BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::swap_impl(left, right))) { ::boost_swap_impl::swap_impl(left, right); } } -#endif +#undef BOOST_CORE_SWAP_NOEXCEPT_IF + +#endif // BOOST_CORE_SWAP_HPP diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 9a82dd3..81c18e6 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include @@ -30,7 +31,6 @@ namespace boost { namespace core { - namespace detail { @@ -41,86 +41,60 @@ template struct tn_identity typedef T type; }; -// tn_enable_if +// tn_remove_prefix -template struct tn_enable_if +inline bool tn_remove_prefix( std::string& str, char const* prefix ) { -}; + std::size_t n = std::strlen( prefix ); -template struct tn_enable_if -{ - typedef T type; -}; - -// tn_is_reference - -template struct tn_is_reference -{ - static const bool value = false; -}; - -template struct tn_is_reference -{ - static const bool value = true; -}; - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template struct tn_is_reference -{ - static const bool value = true; -}; - -#endif + if( str.substr( 0, n ) == prefix ) + { + str = str.substr( n ); + return true; + } + else + { + return false; + } +} #if !defined(BOOST_NO_TYPEID) // typeid_name -template std::string typeid_name() +inline std::string fix_typeid_name( char const* n ) { - std::string r = boost::core::demangle( typeid(T).name() ); + std::string r = boost::core::demangle( n ); #if defined(_MSC_VER) - if( r.substr( 0, 6 ) == "class " ) - { - r = r.substr( 6 ); - } - - if( r.substr( 0, 7 ) == "struct " ) - { - r = r.substr( 7 ); - } - - if( r.substr( 0, 5 ) == "enum " ) - { - r = r.substr( 5 ); - } + tn_remove_prefix( r, "class " ); + tn_remove_prefix( r, "struct " ); + tn_remove_prefix( r, "enum " ); #endif // libc++ inline namespace - if( r.substr( 0, 10 ) == "std::__1::" ) + if( tn_remove_prefix( r, "std::__1::" ) ) { - r = "std::" + r.substr( 10 ); + r = "std::" + r; } // libstdc++ inline namespace - if( r.substr( 0, 14 ) == "std::__cxx11::" ) + if( tn_remove_prefix( r, "std::__cxx11::" ) ) { - r = "std::" + r.substr( 14 ); + r = "std::" + r; } #if defined(BOOST_MSVC) && BOOST_MSVC == 1600 // msvc-10.0 puts TR1 things in std::tr1 - if( r.substr( 0, 10 ) == "std::tr1::" ) + if( tn_remove_prefix( r, "std::tr1::" ) ) { - r = "std::" + r.substr( 10 ); + r = "std::" + r; } #endif @@ -128,32 +102,45 @@ template std::string typeid_name() return r; } +template std::string typeid_name() +{ + return fix_typeid_name( typeid(T).name() ); +} + // template names template std::string class_template_name() { - std::string r = typeid_name(); +#if defined(BOOST_GCC) + + std::string r = typeid_name(); + +#else + + std::string r = typeid_name(); + +#endif return r.substr( 0, r.find( '<' ) ); } template std::string sequence_template_name() { - return class_template_name(); + return detail::class_template_name(); } template std::string set_template_name() { - return class_template_name(); + return detail::class_template_name(); } template std::string map_template_name() { - return class_template_name(); + return detail::class_template_name(); } template std::string array_template_name() { - return class_template_name(); + return detail::class_template_name(); } #else // #if !defined(BOOST_NO_TYPEID) @@ -197,28 +184,321 @@ template std::string array_template_name() # pragma warning( disable: 4996 ) #endif +// Use snprintf if available as some compilers (clang 14.0) issue deprecation warnings for sprintf +#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) +#else +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) +#endif + inline std::string tn_to_string( std::size_t n ) { char buffer[ 32 ]; - std::sprintf( buffer, "%lu", static_cast< unsigned long >( n ) ); + BOOST_CORE_DETAIL_SNPRINTF( buffer, "%lu", static_cast< unsigned long >( n ) ); return buffer; } +#undef BOOST_CORE_DETAIL_SNPRINTF + #if defined(BOOST_MSVC) # pragma warning( pop ) #endif -// tn_add_each +// tn_holder + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return typeid_name() + suffix; + } +}; + +// integrals + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "bool" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "signed char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "short" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned short" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "int" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned long long" + suffix; + } +}; + +#if defined(BOOST_HAS_INT128) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "__int128" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned __int128" + suffix; + } +}; + +#endif + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "wchar_t" + suffix; + } +}; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char16_t" + suffix; + } +}; + +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char32_t" + suffix; + } +}; + +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char8_t" + suffix; + } +}; + +#endif + +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::byte" + suffix; + } +}; + +#endif + +// floating point + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "float" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "double" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long double" + suffix; + } +}; + +// void + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "void" + suffix; + } +}; + +// nullptr_t + +#if !defined(BOOST_NO_CXX11_NULLPTR) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::nullptr_t" + suffix; + } +}; + +#endif + +// cv + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " const" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " volatile" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " const volatile" + suffix ); + } +}; + +// refs + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "&" + suffix ); + } +}; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "&&" + suffix ); + } +}; + +#endif + +// function types #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +// tn_add_each + template int tn_add_each_impl( std::string& st ) { if( !st.empty() ) st += ", "; - st += type_name( tn_identity() ); + st += tn_holder::type_name( "" ); return 0; -}; +} template std::string tn_add_each() { @@ -228,322 +508,538 @@ template std::string tn_add_each() (void)A{ 0, tn_add_each_impl( st )... }; return st; +} + +template std::string function_type_name( tn_identity, std::string const& trailer, std::string const& suffix ) +{ + std::string r = tn_holder::type_name( "" ); + + if( !suffix.empty() ) + { + r += '('; + + if( suffix[ 0 ] == ' ' ) + { + r += suffix.substr( 1 ); + } + else + { + r += suffix; + } + + r += ')'; + } + + r += '(' + tn_add_each() + ')'; + r += trailer; + + return r; +} + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), "", suffix ); + } +}; + +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile", suffix ); + } }; #endif -// primary +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) -template std::string type_name( tn_identity ) +template struct tn_holder { - return typeid_name(); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " &", suffix ); + } +}; -// cv - -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 - -template std::string type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + " const"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const &", suffix ); + } +}; -template std::string type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + " volatile"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile &", suffix ); + } +}; -template std::string type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + " const volatile"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile &", suffix ); + } +}; -#else - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + " const"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " &&", suffix ); + } +}; -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + " volatile"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const &&", suffix ); + } +}; -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + " const volatile"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile &&", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile &&", suffix ); + } +}; #endif -// refs +#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) -#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 - -template std::string type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + "&"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " noexcept", suffix ); + } +}; -#else - -template -typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + "&"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " && noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const && noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile && noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile && noexcept", suffix ); + } +}; #endif -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "&&"; -} - -#endif - -// function types - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + '(' + tn_add_each() + ')'; -} - -#endif +#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) // pointers -template std::string type_name( tn_identity ) +template struct tn_holder { - return type_name( tn_identity() ) + "*"; -} - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -// function pointers - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*&)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const&)(" + tn_add_each() + ')'; -} - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*&&)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const&&)(" + tn_add_each() + ')'; -} - -#endif - -#endif + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "*" + suffix ); + } +}; // arrays template std::pair array_prefix_suffix( tn_identity ) { - return std::pair( type_name( tn_identity() ), "" ); + return std::pair( tn_holder::type_name( "" ), "" ); } template std::pair array_prefix_suffix( tn_identity ) { - std::pair r = array_prefix_suffix( tn_identity() ); + std::pair r = detail::array_prefix_suffix( tn_identity() ); r.second = '[' + tn_to_string( N ) + ']' + r.second; return r; } -template std::string array_type_name( tn_identity ) +template std::string array_type_name( tn_identity, std::string const& suffix ) { - std::pair r = array_prefix_suffix( tn_identity() ); - return r.first + "[]" + r.second; + std::pair r = detail::array_prefix_suffix( tn_identity() ); + + if( suffix.empty() ) + { + return r.first + "[]" + r.second; + } + else + { + return r.first + '(' + suffix + ")[]" + r.second; + } } -template std::string type_name( tn_identity ) +template struct tn_holder { - return array_type_name( tn_identity() ); + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template std::string array_type_name( tn_identity, std::string const& suffix ) +{ + std::pair r = detail::array_prefix_suffix( tn_identity() ); + + if( suffix.empty() ) + { + return r.first + r.second; + } + else + { + return r.first + '(' + suffix + ")" + r.second; + } } -template std::string type_name( tn_identity ) +template struct tn_holder { - return array_type_name( tn_identity() ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity ) +template struct tn_holder { - return array_type_name( tn_identity() ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity ) +template struct tn_holder { - return array_type_name( tn_identity() ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string array_type_name( tn_identity ) +template struct tn_holder { - std::pair r = array_prefix_suffix( tn_identity() ); - return r.first + r.second; -} + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; -template std::string type_name( tn_identity ) +// pointers to members + +template struct tn_holder { - return array_type_name( tn_identity() ); -} + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; -template std::string type_name( tn_identity ) +#if defined(BOOST_MSVC) && BOOST_MSVC < 1900 && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template struct tn_holder { - return array_type_name( tn_identity() ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), "", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; -template std::string type_name( tn_identity ) +template struct tn_holder { - return array_type_name( tn_identity() ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; -template std::string type_name( tn_identity ) +template struct tn_holder { - return array_type_name( tn_identity() ); -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; -// nullptr_t - -#if !defined(BOOST_NO_CXX11_NULLPTR) - -inline std::string type_name( tn_identity ) +template struct tn_holder { - return "std::nullptr_t"; -} + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; #endif // strings -template class L, class Ch> std::string type_name( tn_identity< L, std::allocator > > ) +template class L, class Ch> struct tn_holder< L, std::allocator > > { - std::string tn = sequence_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = sequence_template_name< L, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::string"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::string" + suffix; + } +}; -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::wstring"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::wstring" + suffix; + } +}; #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::u16string"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u16string" + suffix; + } +}; #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::u32string"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u32string" + suffix; + } +}; #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity> ) +template<> struct tn_holder< std::basic_string > { - return "std::u8string"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u8string" + suffix; + } +}; #endif // string views (et al) -template class L, class Ch> std::string type_name( tn_identity< L > > ) +template class L, class Ch> struct tn_holder< L > > { - std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = sequence_template_name< L > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // needed for libstdc++ -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::ostream"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::ostream" + suffix; + } +}; #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::string_view"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::string_view" + suffix; + } +}; -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::wstring_view"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::wstring_view" + suffix; + } +}; #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::u16string_view"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u16string_view" + suffix; + } +}; #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity ) +template<> struct tn_holder { - return "std::u32string_view"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u32string_view" + suffix; + } +}; #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity> ) +template<> struct tn_holder< std::basic_string_view > { - return "std::u8string_view"; -} + static std::string type_name( std::string const& suffix ) + { + return "std::u8string_view" + suffix; + } +}; #endif @@ -553,87 +1049,114 @@ inline std::string type_name( tn_identity> ) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template class L, class... T> std::string type_name( tn_identity< L > ) +template class L, class... T> struct tn_holder< L > { - std::string tn = class_template_name< L >(); - std::string st = tn_add_each(); + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + std::string st = tn_add_each(); - return tn + '<' + st + '>'; -} + return tn + '<' + st + '>' + suffix; + } +}; #else -template class L, class T1> std::string type_name( tn_identity< L > ) +template class L, class T1> struct tn_holder< L > { - std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; -template class L, class T1, class T2> std::string type_name( tn_identity< L > ) +template class L, class T1, class T2> struct tn_holder< L > { - std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; #endif // sequence containers -template class L, class T> std::string type_name( tn_identity< L > > ) +template class L, class T> struct tn_holder< L > > { - std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::sequence_template_name< L > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // set -template class L, class T> std::string type_name( tn_identity< L, std::allocator > > ) +template class L, class T> struct tn_holder< L, std::allocator > > { - std::string tn = set_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::set_template_name< L, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // map -template class L, class T, class U> std::string type_name( tn_identity< L, std::allocator > > > ) +template class L, class T, class U> struct tn_holder< L, std::allocator > > > { - std::string tn = map_template_name< L, std::allocator > > >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::map_template_name< L, std::allocator > > >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) // unordered_set -template class L, class T> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > ) +template class L, class T> struct tn_holder< L, std::equal_to, std::allocator > > { - std::string tn = set_template_name< L, std::equal_to, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::set_template_name< L, std::equal_to, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; // unordered_map -template class L, class T, class U> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > > ) +template class L, class T, class U> struct tn_holder< L, std::equal_to, std::allocator > > > { - std::string tn = map_template_name< L, std::equal_to, std::allocator > > >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::map_template_name< L, std::equal_to, std::allocator > > >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; #endif // array -template class L, class T, std::size_t N> std::string type_name( tn_identity< L > ) +template class L, class T, std::size_t N> struct tn_holder< L > { - std::string tn = array_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + ", " + tn_to_string( N ) + '>'; -} + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::array_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_to_string( N ) + '>' + suffix; + } +}; } // namespace detail template std::string type_name() { - return core::detail::type_name( core::detail::tn_identity() ); + return core::detail::tn_holder::type_name( "" ); } } // namespace core diff --git a/include/boost/core/verbose_terminate_handler.hpp b/include/boost/core/verbose_terminate_handler.hpp new file mode 100644 index 0000000..b607470 --- /dev/null +++ b/include/boost/core/verbose_terminate_handler.hpp @@ -0,0 +1,88 @@ +#ifndef BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED +#define BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace core +{ + +BOOST_NORETURN inline void verbose_terminate_handler() +{ + std::set_terminate( 0 ); + +#if defined(BOOST_NO_EXCEPTIONS) + + std::fputs( "std::terminate called with exceptions disabled\n", stderr ); + +#else + + try + { + throw; + } + catch( std::exception const& x ) + { +#if defined(BOOST_NO_RTTI) + + char const * typeid_name = "unknown (RTTI is disabled)"; + +#else + + char const * typeid_name = typeid( x ).name(); + + boost::core::scoped_demangled_name typeid_demangled_name( typeid_name ); + + if( typeid_demangled_name.get() != 0 ) + { + typeid_name = typeid_demangled_name.get(); + } + +#endif + + boost::source_location loc = boost::get_throw_location( x ); + + std::fprintf( stderr, + "std::terminate called after throwing an exception:\n\n" + " type: %s\n" + " what(): %s\n" + " location: %s:%lu:%lu in function '%s'\n", + + typeid_name, + x.what(), + loc.file_name(), static_cast( loc.line() ), + static_cast( loc.column() ), loc.function_name() + ); + } + catch( ... ) + { + std::fputs( "std::terminate called after throwing an unknown exception\n", stderr ); + } + +#endif + + std::fflush( stdout ); + std::abort(); +} + +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_VERBOSE_TERMINATE_HANDLER_HPP_INCLUDED diff --git a/include/boost/iterator.hpp b/include/boost/iterator.hpp index c9c6197..4a780e8 100644 --- a/include/boost/iterator.hpp +++ b/include/boost/iterator.hpp @@ -5,7 +5,9 @@ #ifndef BOOST_ITERATOR_HPP #define BOOST_ITERATOR_HPP -// This header is obsolete and will be deprecated. +#include + +BOOST_HEADER_DEPRECATED("") #include #include // std::ptrdiff_t diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 82f1b33..88c0889 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2018, 2019 Peter Dimov +# Copyright 2018-2021 Peter Dimov # 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 @@ -6,7 +6,30 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) if(HAVE_BOOST_TEST) -boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::static_assert Boost::type_traits Boost::throw_exception) +boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::static_assert Boost::type_traits) + +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::type_traits) + +boost_test(TYPE run SOURCES eif_constructors.cpp) +boost_test(TYPE run SOURCES eif_dummy_arg_disambiguation.cpp) +boost_test(TYPE run SOURCES eif_lazy.cpp) +boost_test(TYPE run SOURCES eif_lazy_test.cpp) +boost_test(TYPE run SOURCES eif_member_templates.cpp) +boost_test(TYPE run SOURCES eif_namespace_disambiguation.cpp) +boost_test(TYPE run SOURCES eif_no_disambiguation.cpp) +boost_test(TYPE run SOURCES eif_partial_specializations.cpp) + +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::throw_exception) + +boost_test(TYPE run SOURCES no_exceptions_support_test.cpp) + +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::utility) + +boost_test(TYPE run SOURCES sv_conversion_test2.cpp) + +set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::config Boost::move Boost::smart_ptr) + +boost_test(TYPE run SOURCES fclose_deleter_test.cpp) endif() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 63f516f..e9743be 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.Core Library test Jamfile # -# Copyright (c) 2014, 2017 Peter Dimov +# Copyright (c) 2014-2021 Peter Dimov # # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at @@ -9,6 +9,19 @@ import modules ; import testing ; +project : requirements + + extra + msvc:on + clang:on + gcc:on + gcc-4.4:-Wno-sign-compare ; + +local warning-as-errors-off = + "-msvc:on" + "-gcc:on" + "-clang:on" ; + # quick test (for CI) run quick.cpp ; @@ -18,51 +31,64 @@ run addressof_test2.cpp ; run addressof_np_test.cpp ; run addressof_fn_test.cpp ; compile addressof_constexpr_test.cpp ; -compile-fail addressof_fail_rvalue.cpp ; +compile-fail addressof_fail_rvalue.cpp + : $(warning-as-errors-off) ; run checked_delete_test.cpp ; -compile-fail checked_delete_fail.cpp ; -compile-fail checked_delete_fail2.cpp ; +compile-fail checked_delete_fail.cpp + : $(warning-as-errors-off) ; +compile-fail checked_delete_fail2.cpp + : $(warning-as-errors-off) ; compile ref_ct_test.cpp ; run ref_test.cpp ; run ref_ref_test.cpp ; run ref_fn_test.cpp ; -compile-fail ref_rv_fail1.cpp ; -compile-fail ref_rv_fail2.cpp ; -compile-fail ref_rv_fail3.cpp ; -compile-fail ref_rv_fail4.cpp ; -compile-fail ref_rv_fail5.cpp ; -compile-fail ref_implicit_fail.cpp ; -compile-fail ref_implicit_fail2.cpp ; -compile-fail ref_implicit_fail3.cpp ; -compile-fail ref_implicit_fail4.cpp ; +compile-fail ref_rv_fail1.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail2.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail3.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail4.cpp + : $(warning-as-errors-off) ; +compile-fail ref_rv_fail5.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail2.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail3.cpp + : $(warning-as-errors-off) ; +compile-fail ref_implicit_fail4.cpp + : $(warning-as-errors-off) ; run ref_cv_test.cpp ; run ref_conversion_test.cpp ; -run eif_constructors.cpp ; -run eif_dummy_arg_disambiguation.cpp ; -run eif_lazy.cpp ; -run eif_lazy_test.cpp ; -run eif_member_templates.cpp ; -run eif_namespace_disambiguation.cpp ; -run eif_no_disambiguation.cpp ; -run eif_partial_specializations.cpp ; +run eif_constructors.cpp : ; +run eif_dummy_arg_disambiguation.cpp : ; +run eif_lazy.cpp : ; +run eif_lazy_test.cpp : ; +run eif_member_templates.cpp : ; +run eif_namespace_disambiguation.cpp : ; +run eif_no_disambiguation.cpp : ; +run eif_partial_specializations.cpp : ; -compile-fail noncopyable_compile_fail.cpp ; +compile-fail noncopyable_compile_fail.cpp + : $(warning-as-errors-off) ; run explicit_operator_bool.cpp ; run explicit_operator_bool_noexcept.cpp ; -compile-fail explicit_operator_bool_compile_fail_conv_int.cpp ; -compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp ; -compile-fail explicit_operator_bool_compile_fail_delete.cpp ; -compile-fail explicit_operator_bool_compile_fail_shift.cpp ; +compile-fail explicit_operator_bool_compile_fail_conv_int.cpp + : $(warning-as-errors-off) ; +compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp + : $(warning-as-errors-off) ; +compile-fail explicit_operator_bool_compile_fail_delete.cpp + : $(warning-as-errors-off) ; +compile-fail explicit_operator_bool_compile_fail_shift.cpp + : $(warning-as-errors-off) ; -compile ignore_unused_test.cpp - : extra - gcc:on - clang:on - msvc:on ; +compile ignore_unused_test.cpp ; run sp_typeinfo_test.cpp ; run sp_typeinfo_test.cpp : : : off : sp_typeinfo_test_no_rtti ; @@ -112,9 +138,9 @@ run-fail lightweight_test_fail4.cpp ; run-fail lightweight_test_fail5.cpp ; run-fail lightweight_test_fail6.cpp ; run-fail lightweight_test_fail7.cpp ; -run-fail lightweight_test_fail7.cpp : : : off : lightweight_test_fail7_no_rtti ; +run-fail lightweight_test_fail7.cpp : : : off gcc-4.4:no : lightweight_test_fail7_no_rtti ; run-fail lightweight_test_fail8.cpp ; -run-fail lightweight_test_fail8.cpp : : : off : lightweight_test_fail8_no_rtti ; +run-fail lightweight_test_fail8.cpp : : : off gcc-4.4:no : lightweight_test_fail8_no_rtti ; run-fail lightweight_test_fail9.cpp ; run-fail lightweight_test_fail10.cpp ; run-fail lightweight_test_fail11.cpp : ; @@ -122,6 +148,7 @@ run-fail lightweight_test_fail12.cpp ; run-fail lightweight_test_fail13.cpp ; run-fail lightweight_test_fail14.cpp ; run-fail lightweight_test_fail15.cpp ; +run-fail lightweight_test_fail16.cpp : ; run-fail lightweight_test_lt_fail.cpp ; run-fail lightweight_test_le_fail.cpp ; run-fail lightweight_test_gt_fail.cpp ; @@ -148,19 +175,26 @@ run demangle_test.cpp run demangled_name_test.cpp : : : always_show_run_output ; -run demangled_name_test.cpp : : : off always_show_run_output : demangled_name_test_no_rtti ; +run demangled_name_test.cpp : : : off always_show_run_output : demangled_name_test_no_rtti ; run scoped_enum.cpp ; -compile-fail scoped_enum_compile_fail_conv_from_int.cpp ; -compile-fail scoped_enum_compile_fail_conv_to_int.cpp ; +compile-fail scoped_enum_compile_fail_conv_from_int.cpp + : $(warning-as-errors-off) ; +compile-fail scoped_enum_compile_fail_conv_to_int.cpp + : $(warning-as-errors-off) ; run underlying_type.cpp ; +run fclose_deleter_test.cpp : : : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; + run pointer_traits_pointer_test.cpp ; run pointer_traits_element_type_test.cpp ; run pointer_traits_difference_type_test.cpp ; run pointer_traits_rebind_test.cpp ; run pointer_traits_pointer_to_test.cpp ; +run pointer_traits_sfinae_test.cpp ; +run pointer_traits_rebind_sfinae_test.cpp ; +run pointer_traits_pointer_to_sfinae_test.cpp ; run to_address_test.cpp ; run exchange_test.cpp ; @@ -172,6 +206,7 @@ compile first_scalar_constexpr_test.cpp ; run empty_value_test.cpp ; run empty_value_size_test.cpp ; run empty_value_final_test.cpp ; +run empty_value_constexpr_test.cpp ; run quick_exit_test.cpp ; run-fail quick_exit_fail.cpp ; @@ -183,6 +218,7 @@ run default_allocator_test.cpp msvc:on gcc:on clang:on ; +run default_allocator_allocate_hint_test.cpp ; run noinit_adaptor_test.cpp ; run alloc_construct_test.cpp ; @@ -208,6 +244,11 @@ run allocator_allocate_hint_test.cpp ; run allocator_deallocate_test.cpp ; run allocator_max_size_test.cpp ; run allocator_soccc_test.cpp ; +run allocator_construct_test.cpp ; +run allocator_destroy_test.cpp ; +run allocator_construct_n_test.cpp ; +run allocator_destroy_n_test.cpp ; +run allocator_traits_test.cpp ; lib lib_typeid : lib_typeid.cpp : shared:LIB_TYPEID_DYN_LINK=1 ; @@ -228,24 +269,88 @@ run uncaught_exceptions.cpp run uncaught_exceptions_np.cpp : : : on ; -run no_exceptions_support_test.cpp ; +run no_exceptions_support_test.cpp : ; run no_exceptions_support_test.cpp : : : off : no_exceptions_support_test_nx ; -run cmath_test.cpp ; -run cmath_test.cpp : : : BOOST_CORE_USE_GENERIC_CMATH : cmath_test_generic ; +run cmath_test.cpp + : : : $(pedantic-errors) ; +run cmath_test.cpp : : : BOOST_CORE_USE_GENERIC_CMATH msvc-8.0:no : cmath_test_generic ; -run bit_cast_test.cpp ; -run bit_rotate_test.cpp ; -run bit_countr_test.cpp ; -run bit_countl_test.cpp ; -run bit_width_test.cpp ; -run has_single_bit_test.cpp ; -run bit_floor_test.cpp ; -run bit_ceil_test.cpp ; -run bit_popcount_test.cpp ; -run bit_endian_test.cpp ; +run bit_cast_test.cpp + : : : $(pedantic-errors) ; +run bit_rotate_test.cpp + : : : $(pedantic-errors) ; +run bit_countr_test.cpp + : : : $(pedantic-errors) ; +run bit_countl_test.cpp + : : : $(pedantic-errors) ; +run bit_width_test.cpp + : : : $(pedantic-errors) ; +run has_single_bit_test.cpp + : : : $(pedantic-errors) ; +run bit_floor_test.cpp + : : : $(pedantic-errors) ; +run bit_ceil_test.cpp + : : : $(pedantic-errors) ; +run bit_popcount_test.cpp + : : : $(pedantic-errors) ; +run bit_endian_test.cpp + : : : $(pedantic-errors) ; + +compile-fail bit_width_fail.cpp + : off ; run type_name_test.cpp ; +run snprintf_test.cpp ; + +run sv_types_test.cpp ; +run sv_construct_test.cpp ; +run sv_iteration_test.cpp ; +run sv_element_access_test.cpp ; +run sv_modifiers_test.cpp ; +run sv_copy_test.cpp ; +run sv_substr_test.cpp ; +run sv_compare_test.cpp ; +run sv_starts_with_test.cpp ; +run sv_ends_with_test.cpp ; +run sv_find_test.cpp ; +run sv_rfind_test.cpp ; +run sv_find_first_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; +run sv_find_last_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; +run sv_find_first_not_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; +run sv_find_last_not_of_test.cpp + : : : gcc-4.4:-Wno-type-limits ; +run sv_contains_test.cpp ; +run sv_eq_test.cpp ; +run sv_lt_test.cpp ; +run sv_stream_insert_test.cpp ; +run sv_conversion_test.cpp ; +run sv_conversion_test2.cpp : ; +run sv_common_reference_test.cpp ; +compile sv_common_reference_test2.cpp ; +compile sv_windows_h_test.cpp ; +compile-fail sv_nullptr_fail.cpp + : $(warning-as-errors-off) ; + +run span_test.cpp ; +run span_types_test.cpp ; +run span_constructible_test.cpp ; +run span_deduction_guide_test.cpp ; +run as_bytes_test.cpp ; +run as_writable_bytes_test.cpp ; +compile span_boost_begin_test.cpp ; + +run splitmix64_test.cpp + : : : $(pedantic-errors) ; + +run-fail verbose_terminate_handler_fail.cpp : ; +run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nx ; +run-fail verbose_terminate_handler_fail.cpp : : : off : verbose_terminate_handler_fail_nr ; +run-fail verbose_terminate_handler_fail.cpp : : : off off : verbose_terminate_handler_fail_nxr ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/alloc_construct_cxx11_test.cpp b/test/alloc_construct_cxx11_test.cpp index 2075d7a..928cec8 100644 --- a/test/alloc_construct_cxx11_test.cpp +++ b/test/alloc_construct_cxx11_test.cpp @@ -10,6 +10,10 @@ Distributed under the Boost Software License, Version 1.0. #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4100) // unreferenced parameter 'ptr' +#endif + class type { public: explicit type(int x) diff --git a/test/allocator_const_pointer_test.cpp b/test/allocator_const_pointer_test.cpp index 16ae707..ef0dec1 100644 --- a/test/allocator_const_pointer_test.cpp +++ b/test/allocator_const_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -15,20 +15,16 @@ struct A1 { typedef int* const_pointer; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_const_void_pointer_test.cpp b/test/allocator_const_void_pointer_test.cpp index c07070d..c611d5f 100644 --- a/test/allocator_const_void_pointer_test.cpp +++ b/test/allocator_const_void_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -20,20 +20,16 @@ struct A1 { }; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_construct_n_test.cpp b/test/allocator_construct_n_test.cpp new file mode 100644 index 0000000..2e0b898 --- /dev/null +++ b/test/allocator_construct_n_test.cpp @@ -0,0 +1,47 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +struct A { + typedef T value_type; + A() { } +}; + +int main() +{ + { + A a; + int i[3] = { 5, 5, 5 }; + boost::allocator_construct_n(a, &i[0], 3); + BOOST_TEST_EQ(i[0], 0); + BOOST_TEST_EQ(i[1], 0); + BOOST_TEST_EQ(i[2], 0); + } + { + A a; + int i[4] = { 5, 5, 5, 5 }; + int j[2] = { 1, 2 }; + boost::allocator_construct_n(a, &i[0], 4, &j[0], 2); + BOOST_TEST_EQ(i[0], 1); + BOOST_TEST_EQ(i[1], 2); + BOOST_TEST_EQ(i[2], 1); + BOOST_TEST_EQ(i[3], 2); + } + { + A a; + int i[3] = { 5, 5, 5 }; + int j[3] = { 1, 2, 3 }; + boost::allocator_construct_n(a, &i[0], 3, &j[0]); + BOOST_TEST_EQ(i[0], 1); + BOOST_TEST_EQ(i[1], 2); + BOOST_TEST_EQ(i[2], 3); + } + return boost::report_errors(); +} diff --git a/test/allocator_construct_test.cpp b/test/allocator_construct_test.cpp index ded2278..2bd1db2 100644 --- a/test/allocator_construct_test.cpp +++ b/test/allocator_construct_test.cpp @@ -36,7 +36,7 @@ int main() } #if !defined(BOOST_NO_CXX11_ALLOCATOR) { - A1 a; + A2 a; int i = 0; boost::allocator_construct(a, &i, 5); BOOST_TEST_EQ(i, 6); diff --git a/test/allocator_destroy_n_test.cpp b/test/allocator_destroy_n_test.cpp new file mode 100644 index 0000000..381cd68 --- /dev/null +++ b/test/allocator_destroy_n_test.cpp @@ -0,0 +1,66 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +struct S { + static int count; + S() { + ++count; + } + S(const S&) { + ++count; + } + ~S() { + --count; + } +}; + +int S::count = 0; + +template +struct A1 { + typedef T value_type; + A1() { } +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct A2 { + typedef T value_type; + A2() { } + template + void destroy(U* p) { + *p = U(); + } +}; +#endif + +int main() +{ + { + A1 a; + S s[3]; + boost::allocator_destroy_n(a, &s[0], 3); + BOOST_TEST_EQ(S::count, 0); + ::new((void*)&s[0]) S(); + ::new((void*)&s[1]) S(); + ::new((void*)&s[2]) S(); + } +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + { + A2 a; + int i[3] = { 5, 5, 5 }; + boost::allocator_destroy_n(a, &i[0], 3); + BOOST_TEST_EQ(i[0], 0); + BOOST_TEST_EQ(i[1], 0); + BOOST_TEST_EQ(i[2], 0); + } +#endif + return boost::report_errors(); +} diff --git a/test/allocator_destroy_test.cpp b/test/allocator_destroy_test.cpp index 9f2e0c0..0b5b64e 100644 --- a/test/allocator_destroy_test.cpp +++ b/test/allocator_destroy_test.cpp @@ -52,7 +52,7 @@ int main() } #if !defined(BOOST_NO_CXX11_ALLOCATOR) { - A1 a; + A2 a; int i = 5; boost::allocator_destroy(a, &i); BOOST_TEST_EQ(i, 0); diff --git a/test/allocator_difference_type_test.cpp b/test/allocator_difference_type_test.cpp index 24c373d..610f592 100644 --- a/test/allocator_difference_type_test.cpp +++ b/test/allocator_difference_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -15,20 +15,16 @@ struct A1 { typedef short difference_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_is_always_equal_test.cpp b/test/allocator_is_always_equal_test.cpp index c0d8bf2..378eb19 100644 --- a/test/allocator_is_always_equal_test.cpp +++ b/test/allocator_is_always_equal_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template @@ -15,7 +14,6 @@ struct A1 { int value; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; @@ -24,24 +22,25 @@ struct A2 { template struct A3 { typedef T value_type; - typedef std::false_type is_always_equal; + struct is_always_equal { + static const bool value = false; + }; }; template struct A4 { typedef T value_type; - typedef std::true_type is_always_equal; + struct is_always_equal { + static const bool value = true; + }; int value; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost::allocator_is_always_equal >::type)); - #if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost::allocator_is_always_equal >::type)); BOOST_TEST_TRAIT_FALSE((boost::allocator_is_always_equal >::type)); BOOST_TEST_TRAIT_TRUE((boost::allocator_is_always_equal >::type)); - #endif return boost::report_errors(); } diff --git a/test/allocator_max_size_test.cpp b/test/allocator_max_size_test.cpp index 7da57d6..b2837f1 100644 --- a/test/allocator_max_size_test.cpp +++ b/test/allocator_max_size_test.cpp @@ -19,21 +19,17 @@ struct A1 { } }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; typedef short size_type; A2() { } }; -#endif int main() { BOOST_TEST_EQ(boost::allocator_max_size(A1()), 1); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_LE(boost::allocator_max_size(A2()), (std::numeric_limits::max)()); -#endif return boost::report_errors(); } diff --git a/test/allocator_pocca_test.cpp b/test/allocator_pocca_test.cpp index 2318652..40a7aa1 100644 --- a/test/allocator_pocca_test.cpp +++ b/test/allocator_pocca_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template @@ -14,21 +13,19 @@ struct A1 { typedef T value_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; - typedef std::true_type propagate_on_container_copy_assignment; + struct propagate_on_container_copy_assignment { + static const bool value = true; + }; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost:: allocator_propagate_on_container_copy_assignment >::type)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost:: allocator_propagate_on_container_copy_assignment >::type)); -#endif return boost::report_errors(); } diff --git a/test/allocator_pocma_test.cpp b/test/allocator_pocma_test.cpp index a971c02..7738054 100644 --- a/test/allocator_pocma_test.cpp +++ b/test/allocator_pocma_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template @@ -14,21 +13,19 @@ struct A1 { typedef T value_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; - typedef std::true_type propagate_on_container_move_assignment; + struct propagate_on_container_move_assignment { + static const bool value = true; + }; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost:: allocator_propagate_on_container_move_assignment >::type)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost:: allocator_propagate_on_container_move_assignment >::type)); -#endif return boost::report_errors(); } diff --git a/test/allocator_pocs_test.cpp b/test/allocator_pocs_test.cpp index 1a8e6e2..bf62738 100644 --- a/test/allocator_pocs_test.cpp +++ b/test/allocator_pocs_test.cpp @@ -6,7 +6,6 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include template @@ -14,21 +13,19 @@ struct A1 { typedef T value_type; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; - typedef std::true_type propagate_on_container_swap; + struct propagate_on_container_swap { + static const bool value = true; + }; }; -#endif int main() { BOOST_TEST_TRAIT_FALSE((boost:: allocator_propagate_on_container_swap >::type)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_TRAIT_TRUE((boost:: allocator_propagate_on_container_swap >::type)); -#endif return boost::report_errors(); } diff --git a/test/allocator_pointer_test.cpp b/test/allocator_pointer_test.cpp index 6359492..a88fc7e 100644 --- a/test/allocator_pointer_test.cpp +++ b/test/allocator_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -15,20 +15,16 @@ struct A1 { typedef int* pointer; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_rebind_test.cpp b/test/allocator_rebind_test.cpp index 4e35da4..5f1577a 100644 --- a/test/allocator_rebind_test.cpp +++ b/test/allocator_rebind_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -18,20 +18,16 @@ struct A1 { }; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::allocator_rebind, bool>::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::allocator_rebind, int>::type>)); -#endif return boost::report_errors(); } diff --git a/test/allocator_size_type_test.cpp b/test/allocator_size_type_test.cpp index cb84965..50301ca 100644 --- a/test/allocator_size_type_test.cpp +++ b/test/allocator_size_type_test.cpp @@ -6,8 +6,11 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#endif template struct A1 { @@ -24,11 +27,11 @@ struct A2 { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); #if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same< - std::make_unsigned::type, + BOOST_TEST_TRAIT_TRUE((boost::is_same< + boost::make_unsigned::type, boost::allocator_size_type >::type>)); #endif return boost::report_errors(); diff --git a/test/allocator_soccc_test.cpp b/test/allocator_soccc_test.cpp index 2d25fbd..7f65233 100644 --- a/test/allocator_soccc_test.cpp +++ b/test/allocator_soccc_test.cpp @@ -16,7 +16,6 @@ struct A1 { int value; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; @@ -27,15 +26,12 @@ struct A2 { } int value; }; -#endif int main() { BOOST_TEST_EQ(1, boost:: allocator_select_on_container_copy_construction(A1(1)).value); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) BOOST_TEST_EQ(2, boost:: allocator_select_on_container_copy_construction(A2(1)).value); -#endif return boost::report_errors(); } diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp new file mode 100644 index 0000000..f8f0939 --- /dev/null +++ b/test/allocator_traits_test.cpp @@ -0,0 +1,114 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +class creator { +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + template + struct rebind { + typedef creator other; + }; + + explicit creator(int value) BOOST_NOEXCEPT + : state_(value) { } + + template + creator(const creator& other) BOOST_NOEXCEPT + : state_(other.state) { } + + std::size_t max_size() const BOOST_NOEXCEPT { + return static_cast(-1) / sizeof(T); + } + + T* allocate(std::size_t n, const void* = 0) { + return static_cast(::operator new(sizeof(T) * n)); + } + + void deallocate(T* p, std::size_t) { + ::operator delete(p); + } + + int state() const { + return state_; + } + +private: + int state_; +}; + +template +inline bool operator==(const creator& lhs, + const creator& rhs) BOOST_NOEXCEPT +{ + return lhs.state() == rhs.state(); +} + +template +inline bool operator!=(const creator& lhs, + const creator& rhs) BOOST_NOEXCEPT +{ + return !(lhs == rhs); +} + +int main() +{ + BOOST_TEST_TRAIT_SAME(creator, + boost::allocator_traits >::allocator_type); + BOOST_TEST_TRAIT_SAME(int, + boost::allocator_traits >::value_type); + BOOST_TEST_TRAIT_SAME(int*, + boost::allocator_traits >::pointer); + BOOST_TEST_TRAIT_SAME(const int*, + boost::allocator_traits >::const_pointer); + BOOST_TEST_TRAIT_SAME(void*, + boost::allocator_traits >::void_pointer); + BOOST_TEST_TRAIT_SAME(const void*, + boost::allocator_traits >::const_void_pointer); + BOOST_TEST_TRAIT_SAME(std::ptrdiff_t, + boost::allocator_traits >::difference_type); + BOOST_TEST_TRAIT_SAME(std::size_t, + boost::allocator_traits >::size_type); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + propagate_on_container_copy_assignment)); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + propagate_on_container_move_assignment)); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + propagate_on_container_swap)); + BOOST_TEST_TRAIT_FALSE((boost::allocator_traits >:: + is_always_equal)); + BOOST_TEST_TRAIT_SAME(creator, + boost::allocator_traits >:: + rebind_traits::allocator_type); + creator a(1); + int* p1 = boost::allocator_traits >::allocate(a, 1); + if (BOOST_TEST(p1)) { + boost::allocator_traits >::construct(a, p1, 5); + BOOST_TEST_EQ(*p1, 5); + boost::allocator_traits >::destroy(a, p1); + boost::allocator_traits >::deallocate(a, p1, 1); + } + int* p2 = boost::allocator_traits >::allocate(a, 1, 0); + if (BOOST_TEST(p2)) { + boost::allocator_traits >::deallocate(a, p2, 1); + } + BOOST_TEST_EQ(boost::allocator_traits >::max_size(a), + static_cast(-1) / sizeof(int)); + BOOST_TEST(boost::allocator_traits >:: + select_on_container_copy_construction(a) == a); + return boost::report_errors(); +} diff --git a/test/allocator_value_type_test.cpp b/test/allocator_value_type_test.cpp index 575222c..eb9c92a 100644 --- a/test/allocator_value_type_test.cpp +++ b/test/allocator_value_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A { @@ -16,7 +16,7 @@ struct A { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); return boost::report_errors(); } diff --git a/test/allocator_void_pointer_test.cpp b/test/allocator_void_pointer_test.cpp index c5c08c1..1569673 100644 --- a/test/allocator_void_pointer_test.cpp +++ b/test/allocator_void_pointer_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct A1 { @@ -20,20 +20,16 @@ struct A1 { }; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct A2 { typedef T value_type; }; -#endif int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::type>)); -#endif return boost::report_errors(); } diff --git a/test/as_bytes_test.cpp b/test/as_bytes_test.cpp new file mode 100644 index 0000000..2c714aa --- /dev/null +++ b/test/as_bytes_test.cpp @@ -0,0 +1,42 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#ifdef __cpp_lib_byte +#include +#include + +void test_dynamic() +{ + int a[4]; + boost::span s = + boost::as_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +void test_static() +{ + int a[4]; + boost::span s = + boost::as_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +int main() +{ + test_dynamic(); + test_static(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/as_writable_bytes_test.cpp b/test/as_writable_bytes_test.cpp new file mode 100644 index 0000000..8ef59be --- /dev/null +++ b/test/as_writable_bytes_test.cpp @@ -0,0 +1,42 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#ifdef __cpp_lib_byte +#include +#include + +void test_dynamic() +{ + int a[4]; + boost::span s = + boost::as_writable_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +void test_static() +{ + int a[4]; + boost::span s = + boost::as_writable_bytes(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), reinterpret_cast(&a[0])); + BOOST_TEST_EQ(s.size(), sizeof(int) * 4); +} + +int main() +{ + test_dynamic(); + test_static(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/bit_ceil_test.cpp b/test/bit_ceil_test.cpp index 1509d55..2cde75b 100644 --- a/test/bit_ceil_test.cpp +++ b/test/bit_ceil_test.cpp @@ -38,14 +38,14 @@ int main() test_bit_ceil( static_cast( 0 ) ); test_bit_ceil( static_cast( 0 ) ); test_bit_ceil( static_cast( 0 ) ); - test_bit_ceil( static_cast( 0 ) ); + test_bit_ceil( static_cast( 0 ) ); } { test_bit_ceil( static_cast( 0x80 ) ); test_bit_ceil( static_cast( 0x8000 ) ); test_bit_ceil( static_cast( 0x80000000 ) ); - test_bit_ceil( static_cast( 0x8000000000000000 ) ); + test_bit_ceil( boost::uint64_t( 1 ) << 63 ); } boost::detail::splitmix64 rng; @@ -58,7 +58,7 @@ int main() test_bit_ceil( static_cast( x ) ); test_bit_ceil( static_cast( x ) ); test_bit_ceil( static_cast( x ) ); - test_bit_ceil( static_cast( x ) ); + test_bit_ceil( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_countl_test.cpp b/test/bit_countl_test.cpp index e9473c8..c25423e 100644 --- a/test/bit_countl_test.cpp +++ b/test/bit_countl_test.cpp @@ -27,7 +27,7 @@ int main() test_countl( static_cast( 0 ) ); test_countl( static_cast( 0 ) ); test_countl( static_cast( 0 ) ); - test_countl( static_cast( 0 ) ); + test_countl( static_cast( 0 ) ); boost::detail::splitmix64 rng; @@ -39,7 +39,7 @@ int main() test_countl( static_cast( x ) ); test_countl( static_cast( x ) ); test_countl( static_cast( x ) ); - test_countl( static_cast( x ) ); + test_countl( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_countr_test.cpp b/test/bit_countr_test.cpp index dedcf9e..a3b0c96 100644 --- a/test/bit_countr_test.cpp +++ b/test/bit_countr_test.cpp @@ -27,7 +27,7 @@ int main() test_countr( static_cast( 0 ) ); test_countr( static_cast( 0 ) ); test_countr( static_cast( 0 ) ); - test_countr( static_cast( 0 ) ); + test_countr( static_cast( 0 ) ); boost::detail::splitmix64 rng; @@ -39,7 +39,7 @@ int main() test_countr( static_cast( x ) ); test_countr( static_cast( x ) ); test_countr( static_cast( x ) ); - test_countr( static_cast( x ) ); + test_countr( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_endian_test.cpp b/test/bit_endian_test.cpp index 361df16..06f415e 100644 --- a/test/bit_endian_test.cpp +++ b/test/bit_endian_test.cpp @@ -9,9 +9,13 @@ #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + int main() { - boost::uint64_t v = static_cast( 0x0102030405060708ull ); + boost::uint64_t v = ( static_cast( 0x01020304u ) << 32 ) + 0x05060708u; if( boost::core::endian::native == boost::core::endian::little ) { diff --git a/test/bit_floor_test.cpp b/test/bit_floor_test.cpp index 6afa11e..04dc720 100644 --- a/test/bit_floor_test.cpp +++ b/test/bit_floor_test.cpp @@ -33,7 +33,7 @@ int main() test_bit_floor( static_cast( 0 ) ); test_bit_floor( static_cast( 0 ) ); test_bit_floor( static_cast( 0 ) ); - test_bit_floor( static_cast( 0 ) ); + test_bit_floor( static_cast( 0 ) ); } boost::detail::splitmix64 rng; @@ -46,7 +46,7 @@ int main() test_bit_floor( static_cast( x ) ); test_bit_floor( static_cast( x ) ); test_bit_floor( static_cast( x ) ); - test_bit_floor( static_cast( x ) ); + test_bit_floor( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_popcount_test.cpp b/test/bit_popcount_test.cpp index d5cc678..30d4777 100644 --- a/test/bit_popcount_test.cpp +++ b/test/bit_popcount_test.cpp @@ -26,7 +26,7 @@ int main() test_popcount( static_cast( 0 ) ); test_popcount( static_cast( 0 ) ); test_popcount( static_cast( 0 ) ); - test_popcount( static_cast( 0 ) ); + test_popcount( static_cast( 0 ) ); } boost::detail::splitmix64 rng; @@ -39,7 +39,7 @@ int main() test_popcount( static_cast( x ) ); test_popcount( static_cast( x ) ); test_popcount( static_cast( x ) ); - test_popcount( static_cast( x ) ); + test_popcount( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_rotate_test.cpp b/test/bit_rotate_test.cpp index c99f29c..d37569e 100644 --- a/test/bit_rotate_test.cpp +++ b/test/bit_rotate_test.cpp @@ -103,26 +103,28 @@ int main() BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x44444444 ); } +#define CONST64(x) ((boost::uint64_t(x) << 32) + (x)) + { - boost::uint64_t x = 0x1111111111111111; + boost::uint64_t x = CONST64(0x11111111); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x2222222222222222 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x8888888888888888 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x22222222) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x88888888) ); - x = 0x2222222222222222; + x = CONST64(0x22222222); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x4444444444444444 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x1111111111111111 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x44444444) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x11111111) ); - x = 0x4444444444444444; + x = CONST64(0x44444444); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x8888888888888888 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x2222222222222222 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x88888888) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x22222222) ); - x = 0x8888888888888888; + x = CONST64(0x88888888); - BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x1111111111111111 ); - BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x4444444444444444 ); + BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), CONST64(0x11111111) ); + BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), CONST64(0x44444444) ); } for( int i = -M; i <= M; ++i ) @@ -152,7 +154,7 @@ int main() } { - unsigned long long x = 0; + boost::ulong_long_type x = 0; BOOST_TEST_EQ( boost::core::rotl( x, i ), x ); BOOST_TEST_EQ( boost::core::rotr( x, i ), x ); } @@ -168,7 +170,7 @@ int main() test_rotate( static_cast( x ) ); test_rotate( static_cast( x ) ); test_rotate( static_cast( x ) ); - test_rotate( static_cast( x ) ); + test_rotate( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/bit_width_fail.cpp b/test/bit_width_fail.cpp new file mode 100644 index 0000000..9e76000 --- /dev/null +++ b/test/bit_width_fail.cpp @@ -0,0 +1,13 @@ +// Negative test for boost/core/bit.hpp (bit_width) +// +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +int main() +{ + // should fail, because 0 is a signed integral type + return boost::core::bit_width( 0 ); +} diff --git a/test/bit_width_test.cpp b/test/bit_width_test.cpp index 1447b90..15ac76d 100644 --- a/test/bit_width_test.cpp +++ b/test/bit_width_test.cpp @@ -87,7 +87,7 @@ int main() test_width( static_cast( x ) ); test_width( static_cast( x ) ); test_width( static_cast( x ) ); - test_width( static_cast( x ) ); + test_width( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt index 8fee7b3..c8eac57 100644 --- a/test/cmake_subdir_test/CMakeLists.txt +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2018, 2019 Peter Dimov +# Copyright 2018, 2019, 2021 Peter Dimov # 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 @@ -9,6 +9,8 @@ project(cmake_subdir_test LANGUAGES CXX) add_subdirectory(../.. boostorg/core) add_subdirectory(../../../assert boostorg/assert) add_subdirectory(../../../config boostorg/config) +add_subdirectory(../../../static_assert boostorg/static_assert) +add_subdirectory(../../../throw_exception boostorg/throw_exception) add_executable(quick ../quick.cpp) target_link_libraries(quick Boost::core) diff --git a/test/default_allocator_allocate_hint_test.cpp b/test/default_allocator_allocate_hint_test.cpp new file mode 100644 index 0000000..fed2c90 --- /dev/null +++ b/test/default_allocator_allocate_hint_test.cpp @@ -0,0 +1,19 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +int main() +{ + boost::default_allocator a; + int* p = boost::allocator_allocate(a, 1, 0); + BOOST_TEST(p != 0); + a.deallocate(p, 1); + return boost::report_errors(); +} diff --git a/test/detail_iterator_test.cpp b/test/detail_iterator_test.cpp index 13eef58..0865ec4 100644 --- a/test/detail_iterator_test.cpp +++ b/test/detail_iterator_test.cpp @@ -10,8 +10,8 @@ #define BOOST_ALLOW_DEPRECATED_HEADERS #include -#include #include +#include #include #include @@ -62,7 +62,7 @@ struct iterator int main() { - using boost::core::is_same; + using boost::is_same; /* template struct iterator_traits { diff --git a/test/eif_constructors.cpp b/test/eif_constructors.cpp index 6314c85..0cd3a97 100644 --- a/test/eif_constructors.cpp +++ b/test/eif_constructors.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using boost::enable_if; using boost::disable_if; @@ -39,7 +40,7 @@ struct xstring disable_if >::type* = 0) : data(end-begin) {} - int data; + std::ptrdiff_t data; }; @@ -58,4 +59,3 @@ int main() return boost::report_errors(); } - diff --git a/test/eif_dummy_arg_disambiguation.cpp b/test/eif_dummy_arg_disambiguation.cpp index ab65f4f..78346c0 100644 --- a/test/eif_dummy_arg_disambiguation.cpp +++ b/test/eif_dummy_arg_disambiguation.cpp @@ -24,11 +24,11 @@ template struct dummy { template typename enable_if, bool>::type -arithmetic_object(T t, dummy<0> = 0) { return true; } +arithmetic_object(T /*t*/, dummy<0> = 0) { return true; } template typename disable_if, bool>::type -arithmetic_object(T t, dummy<1> = 0) { return false; } +arithmetic_object(T /*t*/, dummy<1> = 0) { return false; } int main() @@ -42,4 +42,3 @@ int main() return boost::report_errors(); } - diff --git a/test/eif_lazy_test.cpp b/test/eif_lazy_test.cpp index 905d0a9..3eb1ae7 100644 --- a/test/eif_lazy_test.cpp +++ b/test/eif_lazy_test.cpp @@ -12,7 +12,7 @@ // Testing all variations of lazy_enable_if. -#include +#include #include #include @@ -26,7 +26,7 @@ using boost::lazy_disable_if_c; template struct is_int_or_double { BOOST_STATIC_CONSTANT(bool, - value = (boost::is_same::value || + value = (boost::is_same::value || boost::is_same::value)); }; @@ -60,21 +60,21 @@ namespace A { template typename lazy_enable_if, some_traits >::type - foo(T t) { return true; } + foo(T /*t*/) { return true; } template typename lazy_enable_if_c::value, some_traits >::type - foo2(T t) { return true; } + foo2(T /*t*/) { return true; } } namespace B { template typename lazy_disable_if, make_bool >::type - foo(T t) { return false; } + foo(T /*t*/) { return false; } template typename lazy_disable_if_c::value, make_bool >::type - foo2(T t) { return false; } + foo2(T /*t*/) { return false; } } int main() @@ -84,15 +84,14 @@ int main() BOOST_TEST(foo(1)); BOOST_TEST(foo(1.0)); - BOOST_TEST(!foo("1")); - BOOST_TEST(!foo(static_cast(0))); + BOOST_TEST(!foo("1")); + BOOST_TEST(!foo(static_cast(0))); BOOST_TEST(foo2(1)); BOOST_TEST(foo2(1.0)); - BOOST_TEST(!foo2("1")); - BOOST_TEST(!foo2(static_cast(0))); + BOOST_TEST(!foo2("1")); + BOOST_TEST(!foo2(static_cast(0))); return boost::report_errors(); } - diff --git a/test/eif_namespace_disambiguation.cpp b/test/eif_namespace_disambiguation.cpp index d5589ae..fd24a4b 100644 --- a/test/eif_namespace_disambiguation.cpp +++ b/test/eif_namespace_disambiguation.cpp @@ -26,13 +26,13 @@ template struct not_ namespace A { template typename enable_if, bool>::type - arithmetic_object(T t) { return true; } + arithmetic_object(T /*t*/) { return true; } } namespace B { template typename enable_if >, bool>::type - arithmetic_object(T t) { return false; } + arithmetic_object(T /*t*/) { return false; } } int main() @@ -47,4 +47,3 @@ int main() return boost::report_errors(); } - diff --git a/test/eif_no_disambiguation.cpp b/test/eif_no_disambiguation.cpp index 3853cbf..37afb43 100644 --- a/test/eif_no_disambiguation.cpp +++ b/test/eif_no_disambiguation.cpp @@ -25,11 +25,11 @@ template struct not_ template typename enable_if, bool>::type -arithmetic_object(T t) { return true; } +arithmetic_object(T /*t*/) { return true; } template typename enable_if >, bool>::type -arithmetic_object(T t) { return false; } +arithmetic_object(T /*t*/) { return false; } int main() @@ -43,4 +43,3 @@ int main() return boost::report_errors(); } - diff --git a/test/empty_value_constexpr_test.cpp b/test/empty_value_constexpr_test.cpp new file mode 100644 index 0000000..f05e314 --- /dev/null +++ b/test/empty_value_constexpr_test.cpp @@ -0,0 +1,65 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) +#include +#include + +struct empty { + constexpr int value() const { + return 1; + } +}; + +class type { +public: + explicit constexpr type(int count) + : value_(count) { } + + constexpr int value() const { + return value_; + } + +private: + int value_; +}; + +void test_int() +{ + constexpr boost::empty_value v(boost::empty_init_t(), 4); + constexpr int c = v.get(); + BOOST_TEST_EQ(c, 4); +} + +void test_empty() +{ + constexpr boost::empty_value v = boost::empty_init_t(); + constexpr int c = v.get().value(); + BOOST_TEST_EQ(c, 1); +} + +void test_type() +{ + constexpr boost::empty_value v(boost::empty_init_t(), 2); + constexpr int c = v.get().value(); + BOOST_TEST_EQ(c, 2); +} + +int main() +{ + test_int(); + test_empty(); + test_type(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/explicit_operator_bool_noexcept.cpp b/test/explicit_operator_bool_noexcept.cpp index d4b69eb..e913043 100644 --- a/test/explicit_operator_bool_noexcept.cpp +++ b/test/explicit_operator_bool_noexcept.cpp @@ -76,6 +76,11 @@ int main(int, char*[]) BOOST_TEST(noexcept(static_cast< bool >(noexcept_val1))); BOOST_TEST(noexcept(static_cast< bool >(noexcept_val2))); + (void)val1; + (void)val2; + (void)noexcept_val1; + (void)noexcept_val2; + return boost::report_errors(); } diff --git a/test/fclose_deleter_test.cpp b/test/fclose_deleter_test.cpp new file mode 100644 index 0000000..4363335 --- /dev/null +++ b/test/fclose_deleter_test.cpp @@ -0,0 +1,73 @@ +/* + * Copyright Andrey Semashev 2022. + * 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) + */ +/*! + * \file fclose_deleter_test.cpp + * \author Andrey Semashev + * \date 21.09.2022 + * + * This file contains tests for \c boost::fclose_deleter. + */ + +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#endif + +boost::movelib::unique_ptr< std::FILE, boost::fclose_deleter > make_boost_unique_file(const char* filename) +{ + return boost::movelib::unique_ptr< std::FILE, boost::fclose_deleter >(std::fopen(filename, "w")); +} + +boost::shared_ptr< std::FILE > make_boost_shared_file(const char* filename) +{ + return boost::shared_ptr< std::FILE >(std::fopen(filename, "w"), boost::fclose_deleter()); +} + +#if !defined(BOOST_NO_CXX11_SMART_PTR) +std::unique_ptr< std::FILE, boost::fclose_deleter > make_std_unique_file(const char* filename) +{ + return std::unique_ptr< std::FILE, boost::fclose_deleter >(std::fopen(filename, "w")); +} + +std::shared_ptr< std::FILE > make_std_shared_file(const char* filename) +{ + return std::shared_ptr< std::FILE >(std::fopen(filename, "w"), boost::fclose_deleter()); +} +#endif + +int main() +{ + const char* const filename = "fcd_test.txt"; + + std::FILE* file = std::fopen(filename, "w"); + if (file) + { + boost::fclose_deleter()(file); + file = NULL; + } + + make_boost_unique_file(filename); + make_boost_shared_file(filename); + +#if !defined(BOOST_NO_CXX11_SMART_PTR) + make_std_unique_file(filename); + make_std_shared_file(filename); +#endif + + // Test if the deleter can be called on a NULL pointer + boost::shared_ptr< std::FILE >(static_cast< std::FILE* >(NULL), boost::fclose_deleter()); +#if !defined(BOOST_NO_CXX11_SMART_PTR) + std::shared_ptr< std::FILE >(static_cast< std::FILE* >(NULL), boost::fclose_deleter()); +#endif + + std::remove(filename); +} diff --git a/test/get_pointer_test.cpp b/test/get_pointer_test.cpp index 1ddf3be..4bccccb 100644 --- a/test/get_pointer_test.cpp +++ b/test/get_pointer_test.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // std::auto_ptr +#endif + #include #include #include diff --git a/test/has_single_bit_test.cpp b/test/has_single_bit_test.cpp index 0be8fcd..1e0fe39 100644 --- a/test/has_single_bit_test.cpp +++ b/test/has_single_bit_test.cpp @@ -103,7 +103,7 @@ int main() test_single_bit( static_cast( x ) ); test_single_bit( static_cast( x ) ); test_single_bit( static_cast( x ) ); - test_single_bit( static_cast( x ) ); + test_single_bit( static_cast( x ) ); } return boost::report_errors(); diff --git a/test/is_same_test.cpp b/test/is_same_test.cpp index 838db22..23a927c 100644 --- a/test/is_same_test.cpp +++ b/test/is_same_test.cpp @@ -1,5 +1,5 @@ // -// Test for core::is_same +// Test for core::detail::is_same // // Copyright 2014 Peter Dimov // @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #include struct X @@ -21,18 +21,18 @@ struct Y int main() { - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); - BOOST_TEST_TRAIT_TRUE(( boost::core::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_TRUE(( boost::core::detail::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); - BOOST_TEST_TRAIT_FALSE(( boost::core::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); + BOOST_TEST_TRAIT_FALSE(( boost::core::detail::is_same )); return boost::report_errors(); } diff --git a/test/iterator_test.cpp b/test/iterator_test.cpp index 3eb2902..5d8c52a 100644 --- a/test/iterator_test.cpp +++ b/test/iterator_test.cpp @@ -8,9 +8,18 @@ // http://www.boost.org/LICENSE_1_0.txt // +#define BOOST_ALLOW_DEPRECATED_HEADERS +#define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING + +#include + +// std::iterator template is deprecated in C++17. Some standard libraries emit warnings +// that cannot be easily suppressed, so disable the tests in C++17 onwards. +#if BOOST_CXX_VERSION < 201703 + #include -#include #include +#include /* @@ -51,7 +60,7 @@ struct R int main() { - using boost::core::is_same; + using boost::is_same; BOOST_TEST_TRAIT_TRUE((is_same::iterator_category,C>)); BOOST_TEST_TRAIT_TRUE((is_same::value_type,T>)); @@ -67,3 +76,11 @@ int main() return boost::report_errors(); } + +#else // BOOST_CXX_VERSION < 201703 + +int main() +{ +} + +#endif // BOOST_CXX_VERSION < 201703 diff --git a/test/lightweight_test_fail10.cpp b/test/lightweight_test_fail10.cpp index 388c47e..80cd49d 100644 --- a/test/lightweight_test_fail10.cpp +++ b/test/lightweight_test_fail10.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wstring-plus-int" +#endif + #include int main() diff --git a/test/lightweight_test_fail16.cpp b/test/lightweight_test_fail16.cpp new file mode 100644 index 0000000..dbeb3c0 --- /dev/null +++ b/test/lightweight_test_fail16.cpp @@ -0,0 +1,12 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +// Should fail, because boost::report_errors() hasn't been called + +int main() +{ + boost::core::lwt_init(); +} diff --git a/test/lightweight_test_fail6.cpp b/test/lightweight_test_fail6.cpp index f73a6df..4296f5c 100644 --- a/test/lightweight_test_fail6.cpp +++ b/test/lightweight_test_fail6.cpp @@ -8,6 +8,10 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif + #include struct X diff --git a/test/no_exceptions_support_test.cpp b/test/no_exceptions_support_test.cpp index 64533fa..6cce8ae 100644 --- a/test/no_exceptions_support_test.cpp +++ b/test/no_exceptions_support_test.cpp @@ -8,6 +8,12 @@ // http://www.boost.org/LICENSE_1_0.txt // +#if defined(_MSC_VER) +# pragma warning(disable: 4530) // C++ exception handler used +# pragma warning(disable: 4577) // noexcept used without /EHsc +# pragma warning(disable: 4702) // unreachable code +#endif + #include #include #include diff --git a/test/pointer_traits_difference_type_test.cpp b/test/pointer_traits_difference_type_test.cpp index e9d0b09..52ad709 100644 --- a/test/pointer_traits_difference_type_test.cpp +++ b/test/pointer_traits_difference_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P { }; @@ -19,23 +19,23 @@ struct E { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::difference_type>)); return boost::report_errors(); } diff --git a/test/pointer_traits_element_type_test.cpp b/test/pointer_traits_element_type_test.cpp index a20733e..2b1bf12 100644 --- a/test/pointer_traits_element_type_test.cpp +++ b/test/pointer_traits_element_type_test.cpp @@ -6,8 +6,8 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P1 { }; @@ -45,39 +45,39 @@ struct E { int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same >::element_type>)); return boost::report_errors(); } diff --git a/test/pointer_traits_pointer_test.cpp b/test/pointer_traits_pointer_test.cpp index a98eb4d..c8070f2 100644 --- a/test/pointer_traits_pointer_test.cpp +++ b/test/pointer_traits_pointer_test.cpp @@ -6,25 +6,25 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P { }; int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::pointer>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::pointer>)); return boost::report_errors(); } diff --git a/test/pointer_traits_pointer_to_sfinae_test.cpp b/test/pointer_traits_pointer_to_sfinae_test.cpp new file mode 100644 index 0000000..479bfce --- /dev/null +++ b/test/pointer_traits_pointer_to_sfinae_test.cpp @@ -0,0 +1,72 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276) +#include +#include + +template +class has_pointer_to { + template + struct result { + char x, y; + }; + + template + static auto check(int) -> result; + + template + static char check(long); + +public: + static const bool value = sizeof(check(0)) > 1; +}; + +struct P1 { }; + +struct P2 { + typedef int element_type; + + static int* pointer_to(int& value) { + return &value; + } +}; + +struct P3 { + typedef void element_type; +}; + +struct P4 { + typedef int element_type; +}; + +struct P5 { + typedef int element_type; + + static int* pointer_to() { + return 0; + } +}; + +int main() +{ + BOOST_TEST((!has_pointer_to >::value)); + BOOST_TEST(has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); + BOOST_TEST(has_pointer_to >::value); + BOOST_TEST(!has_pointer_to >::value); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/pointer_traits_rebind_sfinae_test.cpp b/test/pointer_traits_rebind_sfinae_test.cpp new file mode 100644 index 0000000..8c7a1eb --- /dev/null +++ b/test/pointer_traits_rebind_sfinae_test.cpp @@ -0,0 +1,83 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \ + (!defined(BOOST_GCC) || (BOOST_GCC >= 40800)) && \ + (!defined(BOOST_MSVC) || (BOOST_MSVC >= 1900)) +#include +#include + +template +struct valid { + typedef void type; +}; + +#if !defined(BOOST_GCC) || (BOOST_GCC >= 50000) +template +struct has_rebind { + static const bool value = false; +}; + +template +struct has_rebind >::type> { + static const bool value = true; +}; +#else +template class T, class U> +using defer = T; + +template +using rebind = defer; + +template class = rebind, class = void> +struct has_rebind { + static const bool value = false; +}; + +template class R> +struct has_rebind >::type> { + static const bool value = true; +}; +#endif + +struct P1 { }; + +struct P2 { + typedef int element_type; +}; + +struct P3 { + typedef int element_type; + + template + using rebind = P3; +}; + +template +struct S { + typedef T element_type; +}; + +typedef S P4; + +int main() +{ + BOOST_TEST((!has_rebind, char>::value)); + BOOST_TEST((!has_rebind, char>::value)); + BOOST_TEST((has_rebind, char>::value)); + BOOST_TEST((has_rebind, char>::value)); + BOOST_TEST((has_rebind, char>::value)); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/pointer_traits_rebind_test.cpp b/test/pointer_traits_rebind_test.cpp index 999d195..42c510e 100644 --- a/test/pointer_traits_rebind_test.cpp +++ b/test/pointer_traits_rebind_test.cpp @@ -1,13 +1,13 @@ /* -Copyright 2017 Glen Joseph Fernandes +Copyright 2017-2022 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #include -#include #include +#include template struct P1 { }; @@ -55,53 +55,95 @@ struct R { }; int main() { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); #endif - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); - BOOST_TEST_TRAIT_TRUE((boost::core::is_same, + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, boost::pointer_traits >::rebind_to::type>)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); + BOOST_TEST_TRAIT_TRUE((boost::core::detail::is_same, + boost::pointer_traits >::rebind >)); #endif return boost::report_errors(); } diff --git a/test/pointer_traits_sfinae_test.cpp b/test/pointer_traits_sfinae_test.cpp new file mode 100644 index 0000000..45c00d8 --- /dev/null +++ b/test/pointer_traits_sfinae_test.cpp @@ -0,0 +1,108 @@ +/* +Copyright 2021 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +template +struct valid { + typedef void type; +}; + +template +struct has_pointer { + static const bool value = false; +}; + +template +struct has_pointer::type> { + static const bool value = true; +}; + +template +struct has_element_type { + static const bool value = false; +}; + +template +struct has_element_type::type> { + static const bool value = true; +}; + +template +struct has_difference_type { + static const bool value = false; +}; + +template +struct has_difference_type::type> { + static const bool value = true; +}; + +template +struct has_rebind_to_type { + static const bool value = false; +}; + +template +struct has_rebind_to_type::type>::type> { + static const bool value = true; +}; + +struct P1 { }; + +struct P2 { + typedef int element_type; +}; + +struct P3 { + typedef int element_type; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + using rebind = P3; +#else + template + struct rebind { + typedef P3 other; + }; +#endif +}; + +template +struct S { + typedef T element_type; +}; + +typedef S P4; + +int main() +{ + BOOST_TEST(!has_pointer >::value); + BOOST_TEST(!has_element_type >::value); + BOOST_TEST(!has_difference_type >::value); + BOOST_TEST((!has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((!has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((has_rebind_to_type, char>::value)); + BOOST_TEST(has_pointer >::value); + BOOST_TEST(has_element_type >::value); + BOOST_TEST(has_difference_type >::value); + BOOST_TEST((has_rebind_to_type, char>::value)); + return boost::report_errors(); +} diff --git a/test/quick.cpp b/test/quick.cpp index f82d77b..4b381db 100644 --- a/test/quick.cpp +++ b/test/quick.cpp @@ -16,12 +16,12 @@ #include #include #include -#include #include #include #include +#include #include -#include +#include #include #include #include diff --git a/test/quick_exit_fail.cpp b/test/quick_exit_fail.cpp index b1d394e..e32c298 100644 --- a/test/quick_exit_fail.cpp +++ b/test/quick_exit_fail.cpp @@ -1,4 +1,3 @@ - // Test for quick_exit.hpp // // Copyright 2018 Peter Dimov @@ -7,6 +6,9 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif #include diff --git a/test/quick_exit_test.cpp b/test/quick_exit_test.cpp index e5f7795..9b25ac5 100644 --- a/test/quick_exit_test.cpp +++ b/test/quick_exit_test.cpp @@ -1,4 +1,3 @@ - // Test for quick_exit.hpp // // Copyright 2018 Peter Dimov @@ -7,6 +6,9 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif #include diff --git a/test/ref_conversion_test.cpp b/test/ref_conversion_test.cpp index 6c336ca..2eed2ba 100644 --- a/test/ref_conversion_test.cpp +++ b/test/ref_conversion_test.cpp @@ -6,7 +6,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include #include struct X diff --git a/test/ref_ct_test.cpp b/test/ref_ct_test.cpp index 7e97957..624e007 100644 --- a/test/ref_ct_test.cpp +++ b/test/ref_ct_test.cpp @@ -3,13 +3,13 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// compile-time test for "boost/ref.hpp" header content +// compile-time test for "boost/core/ref.hpp" header content // see 'ref_test.cpp' for run-time part -#include -#include +#include #include #include +#include namespace { @@ -17,14 +17,20 @@ template< typename T, typename U > void ref_test(boost::reference_wrapper) { typedef typename boost::reference_wrapper::type type; - BOOST_STATIC_ASSERT((boost::core::is_same::value)); - BOOST_STATIC_ASSERT((boost::core::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); +} + +template< typename T > +void assignable_test_(T x1, T x2) +{ + x1 = x2; } template< typename T > void assignable_test(T x) { - x = x; + assignable_test_( x, x ); } template< bool R, typename T > @@ -36,14 +42,14 @@ void is_reference_wrapper_test(T) template< typename R, typename Ref > void cxx_reference_test(Ref) { - BOOST_STATIC_ASSERT((boost::core::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); } template< typename R, typename Ref > void unwrap_reference_test(Ref) { typedef typename boost::unwrap_reference::type type; - BOOST_STATIC_ASSERT((boost::core::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); } } // namespace diff --git a/test/ref_cv_test.cpp b/test/ref_cv_test.cpp index 734d9b3..bfba505 100644 --- a/test/ref_cv_test.cpp +++ b/test/ref_cv_test.cpp @@ -6,7 +6,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include #include #define BOOST_TEST_REF( x ) BOOST_TEST( &boost::ref( x ).get() == &x ) diff --git a/test/ref_fn_test.cpp b/test/ref_fn_test.cpp index be13824..83fdbd8 100644 --- a/test/ref_fn_test.cpp +++ b/test/ref_fn_test.cpp @@ -15,7 +15,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#include +#include #include diff --git a/test/ref_implicit_fail.cpp b/test/ref_implicit_fail.cpp index a012f52..4f384f6 100644 --- a/test/ref_implicit_fail.cpp +++ b/test/ref_implicit_fail.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include void f( boost::reference_wrapper< int > ) { diff --git a/test/ref_implicit_fail2.cpp b/test/ref_implicit_fail2.cpp index ff67630..e33c6fc 100644 --- a/test/ref_implicit_fail2.cpp +++ b/test/ref_implicit_fail2.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include void f( boost::reference_wrapper< int const > ) { diff --git a/test/ref_implicit_fail3.cpp b/test/ref_implicit_fail3.cpp index 726feb4..5a45976 100644 --- a/test/ref_implicit_fail3.cpp +++ b/test/ref_implicit_fail3.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include struct X { diff --git a/test/ref_implicit_fail4.cpp b/test/ref_implicit_fail4.cpp index 5f5e0c9..6fda3ce 100644 --- a/test/ref_implicit_fail4.cpp +++ b/test/ref_implicit_fail4.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include void f( boost::reference_wrapper< int const > ) { diff --git a/test/ref_ref_test.cpp b/test/ref_ref_test.cpp index 46be561..064b3d2 100644 --- a/test/ref_ref_test.cpp +++ b/test/ref_ref_test.cpp @@ -11,7 +11,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #include template void test( T const & t ) diff --git a/test/ref_rv_fail1.cpp b/test/ref_rv_fail1.cpp index 1c0a2e6..95bba18 100644 --- a/test/ref_rv_fail1.cpp +++ b/test/ref_rv_fail1.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_rv_fail2.cpp b/test/ref_rv_fail2.cpp index 8ce2680..20657bf 100644 --- a/test/ref_rv_fail2.cpp +++ b/test/ref_rv_fail2.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include int main() { diff --git a/test/ref_rv_fail3.cpp b/test/ref_rv_fail3.cpp index 14b39b8..dd3b5b6 100644 --- a/test/ref_rv_fail3.cpp +++ b/test/ref_rv_fail3.cpp @@ -8,7 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_rv_fail4.cpp b/test/ref_rv_fail4.cpp index 899de7b..9a8bc50 100644 --- a/test/ref_rv_fail4.cpp +++ b/test/ref_rv_fail4.cpp @@ -9,7 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_rv_fail5.cpp b/test/ref_rv_fail5.cpp index ed18edf..5ddbc5f 100644 --- a/test/ref_rv_fail5.cpp +++ b/test/ref_rv_fail5.cpp @@ -9,7 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt // -#include +#include #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/test/ref_test.cpp b/test/ref_test.cpp index 6251b74..2efbcde 100644 --- a/test/ref_test.cpp +++ b/test/ref_test.cpp @@ -3,10 +3,10 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// run-time test for "boost/ref.hpp" header content +// run-time test for "boost/core/ref.hpp" header content // see 'ref_ct_test.cpp' for compile-time part -#include +#include #include namespace { diff --git a/test/scoped_enum.cpp b/test/scoped_enum.cpp index 2a83749..3befebe 100644 --- a/test/scoped_enum.cpp +++ b/test/scoped_enum.cpp @@ -15,6 +15,10 @@ #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4244) // conversion from enum_type to underlying_type +#endif + BOOST_SCOPED_ENUM_DECLARE_BEGIN(namespace_enum1) { value0, @@ -142,6 +146,7 @@ void check_underlying_type() // The real check for the type is in the underlying_type trait test. namespace_enum2 enum1 = namespace_enum2::value1; BOOST_TEST(sizeof(enum1) == sizeof(unsigned char)); + (void)enum1; } int main(int, char*[]) diff --git a/test/snprintf_test.cpp b/test/snprintf_test.cpp new file mode 100644 index 0000000..48483ba --- /dev/null +++ b/test/snprintf_test.cpp @@ -0,0 +1,86 @@ +/* + * Copyright Andrey Semashev 2022. + * 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) + */ +/*! + * \file snprintf_test.cpp + * \author Andrey Semashev + * \date 06.12.2022 + * + * This file contains tests for \c boost::core::snprintf. + */ + +#include +#include +#include +#include + +void test_snprintf() +{ + char buf[11]; + std::memset(buf, 0xFF, sizeof(buf)); + + std::size_t buf_size = sizeof(buf) - 1u; + + int res = boost::core::snprintf(buf, buf_size, "%s", "0123"); + BOOST_TEST_EQ(res, 4); + int cmp_res = std::memcmp(buf, "0123", sizeof("0123")); + BOOST_TEST_EQ(cmp_res, 0); + + std::memset(buf, 0xFF, sizeof(buf)); + + // Suppress compiler checks for buffer overflow + const char* volatile str = "0123456789"; + + res = boost::core::snprintf(buf, buf_size, "%s", str); + BOOST_TEST_GE(res, 10); + cmp_res = std::memcmp(buf, "012345678", sizeof("012345678")); + BOOST_TEST_EQ(cmp_res, 0); + BOOST_TEST_EQ(buf[10], static_cast< char >(~static_cast< char >(0))); + + std::memset(buf, 0xFF, sizeof(buf)); + + res = boost::core::snprintf(buf, 0, "%s", str); + BOOST_TEST_GE(res, 0); + BOOST_TEST_EQ(buf[0], static_cast< char >(~static_cast< char >(0))); +} + +void test_swprintf() +{ + wchar_t buf[11]; + std::memset(buf, 0xFF, sizeof(buf)); + + std::size_t buf_size = sizeof(buf) / sizeof(*buf) - 1u; + + int res = boost::core::swprintf(buf, buf_size, L"%ls", L"0123"); + BOOST_TEST_EQ(res, 4); + int cmp_res = std::memcmp(buf, L"0123", sizeof(L"0123")); + BOOST_TEST_EQ(cmp_res, 0); + + std::memset(buf, 0xFF, sizeof(buf)); + + // Suppress compiler checks for buffer overflow + const wchar_t* volatile str = L"0123456789"; + + res = boost::core::swprintf(buf, buf_size, L"%ls", str); + BOOST_TEST_LT(res, 0); + // swprintf may or may not write to the buffer in case of overflow. + // E.g. glibc 2.35 doesn't and libc on MacOS 11 does. + BOOST_TEST_EQ(buf[10], static_cast< wchar_t >(~static_cast< wchar_t >(0))); + + std::memset(buf, 0xFF, sizeof(buf)); + + res = boost::core::swprintf(buf, 0, L"%ls", str); + BOOST_TEST_LT(res, 0); + BOOST_TEST_EQ(buf[0], static_cast< wchar_t >(~static_cast< wchar_t >(0))); +} + +int main() +{ + test_snprintf(); + test_swprintf(); + + return boost::report_errors(); +} diff --git a/test/span_boost_begin_test.cpp b/test/span_boost_begin_test.cpp new file mode 100644 index 0000000..b7dc1e6 --- /dev/null +++ b/test/span_boost_begin_test.cpp @@ -0,0 +1,32 @@ +/* +Copyright 2022 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) +#include +#include + +namespace boost { +namespace begin_ { + +template +void begin(T&) { } + +} // begin_ + +using namespace begin_; + +} // boost + +template class boost::span; + +void function() +{ + std::vector y; + boost::begin(y); +} +#endif diff --git a/test/span_constructible_test.cpp b/test/span_constructible_test.cpp new file mode 100644 index 0000000..01e4542 --- /dev/null +++ b/test/span_constructible_test.cpp @@ -0,0 +1,200 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) +#include +#include + +template +struct range { + T* data() { + return 0; + } + + const T* data() const { + return 0; + } + + std::size_t size() const { + return 0; + } +}; + +struct base { }; + +struct derived + : base { }; + +void test_default() +{ + BOOST_TEST_TRAIT_TRUE((std::is_default_constructible< + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_default_constructible< + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_default_constructible< + boost::span >)); +} + +void test_data_size() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, std::size_t>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, std::size_t>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int, std::size_t>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const int*, std::size_t>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + derived*, std::size_t>)); +} + +void test_first_last() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, int*>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, const int*>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int*, int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int, int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const int*, int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + derived*, derived*>)); +} + +void test_array() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int(&)[4]>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + int(&)[4]>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int(&)[4]>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int(&)[2]>)); +} + +void test_std_array() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + std::array&>)); +} + +void test_const_std_array() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + const std::array >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const std::array >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, const std::array >)); +} + +void test_range() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + range&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + range&>)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + range >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + int*>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + range >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + const range&>)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + range&>)); +} + +void test_span() +{ + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_constructible, boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); + BOOST_TEST_TRAIT_FALSE((std::is_constructible, + boost::span >)); +} + +void test_copy() +{ + BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible< + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible< + boost::span >)); +} + +void test_assign() +{ + BOOST_TEST_TRAIT_TRUE((std::is_copy_assignable< + boost::span >)); + BOOST_TEST_TRAIT_TRUE((std::is_copy_assignable< + boost::span >)); +} + +int main() +{ + test_default(); + test_data_size(); + test_first_last(); + test_array(); + test_std_array(); + test_const_std_array(); + test_range(); + test_span(); + test_copy(); + test_assign(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/span_deduction_guide_test.cpp b/test/span_deduction_guide_test.cpp new file mode 100644 index 0000000..519c881 --- /dev/null +++ b/test/span_deduction_guide_test.cpp @@ -0,0 +1,116 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifdef __cpp_deduction_guides +#include +#include + +template +class range { +public: + T* data() { + return &v_[0]; + } + + std::size_t size() const { + return 4; + } + +private: + T v_[4]; +}; + +void test_data_size() +{ + int a[4]; + boost::span s(&a[0], 4); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_first_last() +{ + int a[4]; + boost::span s(&a[0], &a[4]); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_array() +{ + int a[4]; + boost::span s(a); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_std_array() +{ + std::array a; + boost::span s(a); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_const_std_array() +{ + const std::array a = std::array(); + boost::span s(a); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_range() +{ + range c; + boost::span s(c); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), c.data()); + BOOST_TEST_EQ(s.size(), c.size()); +} + +void test_span_dynamic() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.extent, boost::dynamic_extent); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_span_static() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.extent, 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +int main() +{ + test_data_size(); + test_first_last(); + test_array(); + test_std_array(); + test_const_std_array(); + test_range(); + test_span_dynamic(); + test_span_static(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/span_test.cpp b/test/span_test.cpp new file mode 100644 index 0000000..fb05778 --- /dev/null +++ b/test/span_test.cpp @@ -0,0 +1,419 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) +#include +#include + +template +class range { +public: + T* data() { + return &v_[0]; + } + + std::size_t size() const { + return 4; + } + +private: + T v_[4]; +}; + +void test_extent() +{ + BOOST_TEST_EQ(boost::span::extent, + boost::dynamic_extent); + BOOST_TEST_EQ((boost::span::extent), 2); +} + +void test_default_construct_dynamic() +{ + boost::span s; + BOOST_TEST_EQ(s.data(), static_cast(0)); + BOOST_TEST_EQ(s.size(), 0); +} + +void test_default_construct_static() +{ + boost::span s; + BOOST_TEST_EQ(s.data(), static_cast(0)); + BOOST_TEST_EQ(s.size(), 0); +} + +void test_construct_data_size() +{ + int a[4]; + boost::span s(&a[0], 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_first_last() +{ + int a[4]; + boost::span s(&a[0], &a[4]); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_array_dynamic() +{ + int a[4]; + boost::span s(a); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_array_static() +{ + int a[4]; + boost::span s(a); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_std_array_dynamic() +{ + std::array a; + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_std_array_static() +{ + std::array a; + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_const_std_array_dynamic() +{ + const std::array a = std::array(); + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_const_std_array_static() +{ + const std::array a = std::array(); + boost::span s(a); + BOOST_TEST_EQ(s.data(), a.data()); + BOOST_TEST_EQ(s.size(), a.size()); +} + +void test_construct_range() +{ + range c; + boost::span s(c); + BOOST_TEST_EQ(s.data(), c.data()); + BOOST_TEST_EQ(s.size(), c.size()); +} + +void test_construct_span_dynamic() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_span_dynamic_static() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_span_static() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_construct_span_static_dynamic() +{ + int a[4]; + boost::span s(boost::span(&a[0], 4)); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_copy_dynamic() +{ + int a[4]; + boost::span s1(&a[0], 4); + boost::span s2(s1); + BOOST_TEST_EQ(s2.data(), &a[0]); + BOOST_TEST_EQ(s2.size(), 4); +} + +void test_copy_static() +{ + int a[4]; + boost::span s1(&a[0], 4); + boost::span s2(s1); + BOOST_TEST_EQ(s2.data(), &a[0]); + BOOST_TEST_EQ(s2.size(), 4); +} + +void test_assign_dynamic() +{ + boost::span s; + int a[4]; + s = boost::span(&a[0], 4); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_assign_static() +{ + int a1[4]; + boost::span s(&a1[0], 4); + int a2[4]; + s = boost::span(&a2[0], 4); + BOOST_TEST_EQ(s.data(), &a2[0]); + BOOST_TEST_EQ(s.size(), 4); +} + +void test_first() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).first<2>(); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_last() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).last<2>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_dynamic() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).subspan<2>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_static() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).subspan<2>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).subspan<2, 1>(); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 1); +} + +void test_first_size() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).first(2); + BOOST_TEST_EQ(s.data(), &a[0]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_last_size() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).last(2); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_range() +{ + int a[4]; + boost::span s = boost::span(&a[0], 4).subspan(2); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan_range_count() +{ + int a[4]; + boost::span s = boost::span(&a[0], + 4).subspan(2, 1); + BOOST_TEST_EQ(s.data(), &a[2]); + BOOST_TEST_EQ(s.size(), 1); +} + +void test_size() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).size()), 4); +} + +void test_size_bytes() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).size_bytes()), + 4 * sizeof(int)); +} + +void test_empty_dynamic() +{ + int a[4]; + BOOST_TEST(boost::span().empty()); + BOOST_TEST_NOT((boost::span(&a[0], 4).empty())); +} + +void test_empty_static() +{ + int a[4]; + BOOST_TEST((boost::span().empty())); + BOOST_TEST_NOT((boost::span(&a[0], 4).empty())); +} + +void test_index() +{ + int a[4] = { 1, 2, 3, 4 }; + BOOST_TEST_EQ((boost::span(&a[0], 4)[2]), 3); +} + +void test_front() +{ + int a[4] = { 1, 2, 3, 4 }; + BOOST_TEST_EQ((boost::span(&a[0], 4).front()), 1); +} + +void test_back() +{ + int a[4] = { 1, 2, 3, 4 }; + BOOST_TEST_EQ((boost::span(&a[0], 4).back()), 4); +} + +void test_data() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).data()), &a[0]); +} + +void test_begin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).begin()), &a[0]); +} + +void test_end() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).end()), &a[4]); +} + +void test_rbegin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).rbegin().base()), &a[4]); +} + +void test_rend() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).rend().base()), &a[0]); +} + +void test_cbegin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).cbegin()), &a[0]); +} + +void test_cend() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).cend()), &a[4]); +} + +void test_crbegin() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).crbegin().base()), &a[4]); +} + +void test_crend() +{ + int a[4]; + BOOST_TEST_EQ((boost::span(&a[0], 4).crend().base()), &a[0]); +} + +int main() +{ + test_extent(); + test_default_construct_dynamic(); + test_default_construct_static(); + test_construct_data_size(); + test_construct_first_last(); + test_construct_array_dynamic(); + test_construct_array_static(); + test_construct_std_array_dynamic(); + test_construct_std_array_static(); + test_construct_const_std_array_dynamic(); + test_construct_const_std_array_static(); + test_construct_range(); + test_construct_span_dynamic(); + test_construct_span_dynamic_static(); + test_construct_span_static(); + test_construct_span_static_dynamic(); + test_copy_dynamic(); + test_copy_static(); + test_assign_dynamic(); + test_assign_static(); + test_first(); + test_last(); + test_subspan_dynamic(); + test_subspan_static(); + test_subspan(); + test_first_size(); + test_last_size(); + test_subspan_range(); + test_subspan_range_count(); + test_size(); + test_size_bytes(); + test_empty_dynamic(); + test_empty_static(); + test_index(); + test_front(); + test_back(); + test_data(); + test_begin(); + test_end(); + test_rbegin(); + test_rend(); + test_cbegin(); + test_cend(); + test_crbegin(); + test_crend(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/span_types_test.cpp b/test/span_types_test.cpp new file mode 100644 index 0000000..49f7346 --- /dev/null +++ b/test/span_types_test.cpp @@ -0,0 +1,136 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DECLTYPE) +#include +#include + +void test_element_type() +{ + BOOST_TEST_TRAIT_SAME(int, + boost::span::element_type); + BOOST_TEST_TRAIT_SAME(char, + boost::span::element_type); +} + +void test_value_type() +{ + BOOST_TEST_TRAIT_SAME(char, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); + BOOST_TEST_TRAIT_SAME(int, + boost::span::value_type); +} + +void test_size_type() +{ + BOOST_TEST_TRAIT_SAME(std::size_t, + boost::span::size_type); + BOOST_TEST_TRAIT_SAME(std::size_t, + boost::span::size_type); +} + +void test_difference_type() +{ + BOOST_TEST_TRAIT_SAME(std::ptrdiff_t, + boost::span::difference_type); + BOOST_TEST_TRAIT_SAME(std::ptrdiff_t, + boost::span::difference_type); +} + +void test_pointer() +{ + BOOST_TEST_TRAIT_SAME(char*, + boost::span::pointer); + BOOST_TEST_TRAIT_SAME(int*, + boost::span::pointer); +} + +void test_const_pointer() +{ + BOOST_TEST_TRAIT_SAME(const char*, + boost::span::const_pointer); + BOOST_TEST_TRAIT_SAME(const int*, + boost::span::const_pointer); +} + +void test_reference() +{ + BOOST_TEST_TRAIT_SAME(char&, + boost::span::reference); + BOOST_TEST_TRAIT_SAME(int&, + boost::span::reference); +} + +void test_const_reference() +{ + BOOST_TEST_TRAIT_SAME(const char&, + boost::span::const_reference); + BOOST_TEST_TRAIT_SAME(const int&, + boost::span::const_reference); +} + +void test_iterator() +{ + BOOST_TEST_TRAIT_SAME(char*, + boost::span::iterator); + BOOST_TEST_TRAIT_SAME(int*, + boost::span::iterator); +} + +void test_const_iterator() +{ + BOOST_TEST_TRAIT_SAME(const char*, + boost::span::const_iterator); + BOOST_TEST_TRAIT_SAME(const int*, + boost::span::const_iterator); +} + +void test_reverse_iterator() +{ + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::reverse_iterator); + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::reverse_iterator); +} + +void test_const_reverse_iterator() +{ + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::const_reverse_iterator); + BOOST_TEST_TRAIT_SAME(std::reverse_iterator, + boost::span::const_reverse_iterator); +} + +int main() +{ + test_element_type(); + test_value_type(); + test_size_type(); + test_difference_type(); + test_pointer(); + test_const_pointer(); + test_reference(); + test_const_reference(); + test_iterator(); + test_const_iterator(); + test_reverse_iterator(); + test_const_reverse_iterator(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/splitmix64_test.cpp b/test/splitmix64_test.cpp new file mode 100644 index 0000000..7120d7a --- /dev/null +++ b/test/splitmix64_test.cpp @@ -0,0 +1,38 @@ +// Test for boost/core/detail/splitmix64.hpp +// +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + boost::detail::splitmix64 rng; + + boost::uint64_t r1 = rng(), x1 = ( boost::uint64_t(0xe220a839u) << 32 ) + 0x7b1dcdafu; + BOOST_TEST_EQ( r1, x1 ); + + for( int i = 0; i < 1000; ++i ) rng(); + + boost::uint64_t r2 = rng(), x2 = ( boost::uint64_t(0xdcad513cu) << 32 ) + 0x211f942du; + BOOST_TEST_EQ( r2, x2 ); + } + + { + boost::detail::splitmix64 rng( 12345 ); + + boost::uint64_t r1 = rng(), x1 = ( boost::uint64_t(0x22118258u) << 32 ) + 0xa9d111a0u; + BOOST_TEST_EQ( r1, x1 ); + + for( int i = 0; i < 1000; ++i ) rng(); + + boost::uint64_t r2 = rng(), x2 = ( boost::uint64_t(0xaaefb4b6u) << 32 ) + 0x5c15e958u; + BOOST_TEST_EQ( r2, x2 ); + } + + return boost::report_errors(); +} diff --git a/test/sv_common_reference_test.cpp b/test/sv_common_reference_test.cpp new file mode 100644 index 0000000..3a0b444 --- /dev/null +++ b/test/sv_common_reference_test.cpp @@ -0,0 +1,34 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX20_HDR_CONCEPTS) + +BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_NO_CXX20_HDR_CONCEPTS is defined" ) +int main() {} + +#else + +#include +#include + +using T = std::common_reference_t< boost::core::string_view&&, std::string& >; + +static_assert( std::common_reference_with< boost::core::string_view&&, std::string& > ); +static_assert( std::common_reference_with< boost::core::wstring_view&&, std::wstring const& > ); + +int main() +{ + BOOST_TEST_TRAIT_SAME( std::common_reference_t< boost::core::string_view&&, std::string& >, boost::core::string_view ); + BOOST_TEST_TRAIT_SAME( std::common_reference_t< boost::core::wstring_view&&, std::wstring const& >, boost::core::wstring_view ); + + return boost::report_errors(); +} + +#endif diff --git a/test/sv_common_reference_test2.cpp b/test/sv_common_reference_test2.cpp new file mode 100644 index 0000000..91e61e0 --- /dev/null +++ b/test/sv_common_reference_test2.cpp @@ -0,0 +1,24 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +#if !defined(__cpp_lib_ranges) + +BOOST_PRAGMA_MESSAGE( "Skipping test because __cpp_lib_ranges is not defined" ) + +#else + +struct Iterator +{ + using value_type = std::string; + boost::core::string_view operator*() const noexcept; +}; + +static_assert( std::indirectly_readable ); + +#endif diff --git a/test/sv_compare_test.cpp b/test/sv_compare_test.cpp new file mode 100644 index 0000000..eef12d6 --- /dev/null +++ b/test/sv_compare_test.cpp @@ -0,0 +1,145 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv1( "" ); + boost::core::string_view sv2( "" ); + + BOOST_TEST_EQ( sv1.compare( sv2 ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, sv2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 1, sv2 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, sv2 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, sv2 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, npos, sv2 ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, sv2, 0, 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 1, sv2, 0, 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, sv2, 0, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, sv2, 0, 1 ), std::out_of_range ); + + BOOST_TEST_THROWS( sv1.compare( 0, 0, sv2, 1, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 0, 1, sv2, 1, 1 ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( "" ), 0 ); + BOOST_TEST_LT( sv1.compare( "1" ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, "" ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 0, "1" ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 1, "" ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 1, "1" ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, "" ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, "1" ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, "", 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 0, "1", 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 0, "1", 1 ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 0, 1, "", 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 1, "1", 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 1, "1", 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 1, 0, "", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, "1", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 1, 1, "1", 1 ), std::out_of_range ); + } + + { + boost::core::string_view sv1( "123412345" ); + boost::core::string_view sv2( "1234" ); + + BOOST_TEST_GT( sv1.compare( sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 0, 3, sv2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 4, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 0, 5, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 0, npos, sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 1, 0, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 1, 1, sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 4, 3, sv2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 4, 4, sv2 ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 5, sv2 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 9, 0, sv2 ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, 1, sv2 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, 0, sv2 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, 1, sv2 ), std::out_of_range ); + + BOOST_TEST_GT( sv1.compare( 0, 3, sv2, 0, 2 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 3, sv2, 0, 3 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 3, sv2, 0, 4 ), 0 ); + BOOST_TEST_LT( sv1.compare( 0, 3, sv2, 0, 5 ), 0 ); + + BOOST_TEST_GT( sv1.compare( 0, 4, sv2, 0, 3 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 4, sv2, 0, 4 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 0, 4, sv2, 0, 5 ), 0 ); + + BOOST_TEST_LT( sv1.compare( 5, 2, sv2, 1, npos ), 0 ); + BOOST_TEST_EQ( sv1.compare( 5, 3, sv2, 1, npos ), 0 ); + BOOST_TEST_GT( sv1.compare( 5, 4, sv2, 1, npos ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 9, 0, sv2, 0, 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, 1, sv2, 0, 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, 0, sv2, 0, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, 1, sv2, 0, 1 ), std::out_of_range ); + + BOOST_TEST_EQ( sv1.compare( 0, 0, sv2, 4, 0 ), 0 ); + BOOST_TEST_GT( sv1.compare( 0, 1, sv2, 4, 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 0, 0, sv2, 5, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 0, 1, sv2, 5, 1 ), std::out_of_range ); + + BOOST_TEST_GT( sv1.compare( "" ), 0 ); + BOOST_TEST_GT( sv1.compare( "12341234" ), 0 ); + BOOST_TEST_GT( sv1.compare( "123412344" ), 0 ); + BOOST_TEST_EQ( sv1.compare( "123412345" ), 0 ); + BOOST_TEST_LT( sv1.compare( "123412346" ), 0 ); + BOOST_TEST_LT( sv1.compare( "1234123456" ), 0 ); + + BOOST_TEST_GT( sv1.compare( 4, 3, "" ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 3, "1" ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 3, "12" ), 0 ); + BOOST_TEST_GT( sv1.compare( 4, 3, "122" ), 0 ); + BOOST_TEST_EQ( sv1.compare( 4, 3, "123" ), 0 ); + BOOST_TEST_LT( sv1.compare( 4, 3, "124" ), 0 ); + BOOST_TEST_LT( sv1.compare( 4, 3, "1234" ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 9, 0, "" ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, 1, "1" ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, 0, "" ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, 1, "1" ), std::out_of_range ); + + BOOST_TEST_GT( sv1.compare( 4, npos, "123456", 4 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 4, npos, "123456", 5 ), 0 ); + BOOST_TEST_LT( sv1.compare( 4, npos, "123456", 6 ), 0 ); + + BOOST_TEST_EQ( sv1.compare( 9, npos, "", 0 ), 0 ); + BOOST_TEST_EQ( sv1.compare( 9, npos, "1", 0 ), 0 ); + BOOST_TEST_LT( sv1.compare( 9, npos, "1", 1 ), 0 ); + + BOOST_TEST_THROWS( sv1.compare( 10, npos, "", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, npos, "1", 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv1.compare( 10, npos, "1", 1 ), std::out_of_range ); + } + + return boost::report_errors(); +} diff --git a/test/sv_construct_test.cpp b/test/sv_construct_test.cpp new file mode 100644 index 0000000..3a33fbd --- /dev/null +++ b/test/sv_construct_test.cpp @@ -0,0 +1,346 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif + +template std::reverse_iterator make_reverse_iterator( It it ) +{ + return std::reverse_iterator( it ); +} + +int main() +{ + { + boost::core::string_view sv; + + BOOST_TEST_EQ( sv.data(), static_cast(0) ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + } + + { + char const* s = ""; + + boost::core::string_view sv( s ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 3 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, 0 ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, 2 ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 2 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, s ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 0 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + char const* s = "123"; + + boost::core::string_view sv( s, s + 2 ); + + BOOST_TEST_EQ( sv.data(), s ); + BOOST_TEST_EQ( sv.size(), 2 ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + + { + std::string str = "123"; + + boost::core::string_view sv( str ); + + BOOST_TEST_EQ( sv.data(), str.data() ); + BOOST_TEST_EQ( sv.size(), str.size() ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + { + std::string_view str = "123"; + + boost::core::string_view sv( str ); + + BOOST_TEST_EQ( sv.data(), str.data() ); + BOOST_TEST_EQ( sv.size(), str.size() ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + { + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + pmr_string str = "123"; + + boost::core::string_view sv( str ); + + BOOST_TEST_EQ( sv.data(), str.data() ); + BOOST_TEST_EQ( sv.size(), str.size() ); + + BOOST_TEST_EQ( sv.begin(), sv.data() ); + BOOST_TEST_EQ( sv.end(), sv.data() + sv.size() ); + + BOOST_TEST_EQ( sv.cbegin(), sv.data() ); + BOOST_TEST_EQ( sv.cend(), sv.data() + sv.size() ); + + BOOST_TEST( sv.rbegin() == ::make_reverse_iterator( sv.end() ) ); + BOOST_TEST( sv.rend() == ::make_reverse_iterator( sv.begin() ) ); + + BOOST_TEST( sv.crbegin() == ::make_reverse_iterator( sv.cend() ) ); + BOOST_TEST( sv.crend() == ::make_reverse_iterator( sv.cbegin() ) ); + + BOOST_TEST_EQ( sv.length(), sv.size() ); + BOOST_TEST_EQ( sv.empty(), sv.size() == 0 ); + + BOOST_TEST_EQ( sv.max_size(), boost::core::string_view::npos ); + + if( !sv.empty() ) + { + BOOST_TEST_EQ( &sv.front(), sv.data() ); + BOOST_TEST_EQ( &sv.back(), sv.data() + sv.size() - 1 ); + } + } + +#endif + + return boost::report_errors(); +} diff --git a/test/sv_contains_test.cpp b/test/sv_contains_test.cpp new file mode 100644 index 0000000..f42f1e4 --- /dev/null +++ b/test/sv_contains_test.cpp @@ -0,0 +1,71 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "" ); + + BOOST_TEST( sv.contains( boost::core::string_view() ) ); + + BOOST_TEST( sv.contains( boost::core::string_view( "" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "1" ) ) ); + + BOOST_TEST( !sv.contains( '1' ) ); + + BOOST_TEST( sv.contains( "" ) ); + BOOST_TEST( !sv.contains( "1" ) ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST( sv.contains( boost::core::string_view() ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "" ) ) ); + + BOOST_TEST( sv.contains( boost::core::string_view( "1" ) ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "2" ) ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "3" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "4" ) ) ); + + BOOST_TEST( sv.contains( boost::core::string_view( "12" ) ) ); + BOOST_TEST( sv.contains( boost::core::string_view( "23" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "34" ) ) ); + BOOST_TEST( !sv.contains( boost::core::string_view( "21" ) ) ); + + BOOST_TEST( sv.contains( '1' ) ); + BOOST_TEST( sv.contains( '2' ) ); + BOOST_TEST( sv.contains( '3' ) ); + BOOST_TEST( !sv.contains( '4' ) ); + + BOOST_TEST( sv.contains( "" ) ); + + BOOST_TEST( sv.contains( "1" ) ); + BOOST_TEST( sv.contains( "2" ) ); + BOOST_TEST( sv.contains( "3" ) ); + BOOST_TEST( !sv.contains( "4" ) ); + + BOOST_TEST( sv.contains( "12" ) ); + BOOST_TEST( sv.contains( "23" ) ); + BOOST_TEST( !sv.contains( "34" ) ); + BOOST_TEST( !sv.contains( "21" ) ); + + BOOST_TEST( sv.contains( "123" ) ); + BOOST_TEST( !sv.contains( "234" ) ); + BOOST_TEST( sv.contains( "231" ) ); + BOOST_TEST( !sv.contains( "321" ) ); + + BOOST_TEST( !sv.contains( "1234" ) ); + BOOST_TEST( sv.contains( "1231" ) ); + + BOOST_TEST( sv.contains( "123123" ) ); + BOOST_TEST( !sv.contains( "1231231" ) ); + } + + return boost::report_errors(); +} diff --git a/test/sv_conversion_test.cpp b/test/sv_conversion_test.cpp new file mode 100644 index 0000000..64a7105 --- /dev/null +++ b/test/sv_conversion_test.cpp @@ -0,0 +1,54 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif + +boost::core::string_view f( boost::core::string_view const& str ) +{ + return str; +} + +int main() +{ + { + std::string s1( "123" ); + std::string s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + { + std::string_view s1( "123" ); + std::string_view s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + { + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + pmr_string s1( "123" ); + pmr_string s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/sv_conversion_test2.cpp b/test/sv_conversion_test2.cpp new file mode 100644 index 0000000..ee0e196 --- /dev/null +++ b/test/sv_conversion_test2.cpp @@ -0,0 +1,32 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +boost::core::string_view f( boost::core::string_view const& str ) +{ + return str; +} + +int main() +{ + { + std::string s1( "123" ); + std::string s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + + { + boost::string_view s1( "123" ); + boost::string_view s2 = f( s1 ); + + BOOST_TEST_EQ( s1, s2 ); + } + + return boost::report_errors(); +} diff --git a/test/sv_copy_test.cpp b/test/sv_copy_test.cpp new file mode 100644 index 0000000..75abe88 --- /dev/null +++ b/test/sv_copy_test.cpp @@ -0,0 +1,52 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#define _SCL_SECURE_NO_WARNINGS + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv; + + BOOST_TEST_EQ( sv.copy( 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.copy( 0, 0, 0 ), 0 ); + BOOST_TEST_THROWS( sv.copy( 0, 0, 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.copy( 0, 0, boost::core::string_view::npos ), std::out_of_range ); + } + + { + boost::core::string_view sv( "12345" ); + char buffer[ 8 ] = {}; + + BOOST_TEST_EQ( sv.copy( buffer, 0 ), 0 ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 0, 0 ), 0 ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 0, 1 ), 0 ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_THROWS( sv.copy( buffer, 0, boost::core::string_view::npos ), std::out_of_range ); + BOOST_TEST_EQ( buffer[0], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 1 ), 1 ); + BOOST_TEST_EQ( buffer[0], '1' ); + BOOST_TEST_EQ( buffer[1], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 1, 1 ), 1 ); + BOOST_TEST_EQ( buffer[0], '2' ); + BOOST_TEST_EQ( buffer[1], 0 ); + + BOOST_TEST_EQ( sv.copy( buffer, 8 ), 5 ); + BOOST_TEST_CSTR_EQ( buffer, "12345" ); + } + + return boost::report_errors(); +} diff --git a/test/sv_element_access_test.cpp b/test/sv_element_access_test.cpp new file mode 100644 index 0000000..e4a94f7 --- /dev/null +++ b/test/sv_element_access_test.cpp @@ -0,0 +1,41 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "12345" ); + + for( std::size_t i = 0; i < 5; ++i ) + { + BOOST_TEST_EQ( &sv[ i ], sv.data() + i ); + BOOST_TEST_EQ( &sv.at( i ), sv.data() + i ); + } + + BOOST_TEST_THROWS( sv.at( 5 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( boost::core::string_view::npos ), std::out_of_range ); + } + + { + boost::core::string_view sv; + + BOOST_TEST_THROWS( sv.at( 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( boost::core::string_view::npos ), std::out_of_range ); + } + + { + boost::core::string_view sv( "12345", 0 ); + + BOOST_TEST_THROWS( sv.at( 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.at( boost::core::string_view::npos ), std::out_of_range ); + } + + return boost::report_errors(); +} diff --git a/test/sv_ends_with_test.cpp b/test/sv_ends_with_test.cpp new file mode 100644 index 0000000..86de3da --- /dev/null +++ b/test/sv_ends_with_test.cpp @@ -0,0 +1,50 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "" ); + + BOOST_TEST( sv.ends_with( boost::core::string_view() ) ); + BOOST_TEST( sv.ends_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.ends_with( "" ) ); + + BOOST_TEST( !sv.ends_with( boost::core::string_view( "1" ) ) ); + BOOST_TEST( !sv.ends_with( '1' ) ); + BOOST_TEST( !sv.ends_with( "1" ) ); + } + + { + boost::core::string_view sv( "123" ); + + BOOST_TEST( sv.ends_with( boost::core::string_view() ) ); + BOOST_TEST( sv.ends_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.ends_with( "" ) ); + + BOOST_TEST( sv.ends_with( boost::core::string_view( "3" ) ) ); + BOOST_TEST( sv.ends_with( '3' ) ); + BOOST_TEST( sv.ends_with( "3" ) ); + + BOOST_TEST( sv.ends_with( boost::core::string_view( "23" ) ) ); + BOOST_TEST( sv.ends_with( "23" ) ); + + BOOST_TEST( sv.ends_with( boost::core::string_view( "123" ) ) ); + BOOST_TEST( sv.ends_with( "123" ) ); + + BOOST_TEST( !sv.ends_with( boost::core::string_view( "1234" ) ) ); + BOOST_TEST( !sv.ends_with( "1234" ) ); + + BOOST_TEST( !sv.ends_with( boost::core::string_view( "2" ) ) ); + BOOST_TEST( !sv.ends_with( '2' ) ); + BOOST_TEST( !sv.ends_with( "2" ) ); + } + + return boost::report_errors(); +} diff --git a/test/sv_eq_test.cpp b/test/sv_eq_test.cpp new file mode 100644 index 0000000..46e6ef7 --- /dev/null +++ b/test/sv_eq_test.cpp @@ -0,0 +1,113 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif + +#define TEST_EQ(x, y) \ + BOOST_TEST_EQ(x, y); \ + BOOST_TEST_NOT((x) != (y)); \ + BOOST_TEST_LE(x, y); \ + BOOST_TEST_GE(x, y); \ + BOOST_TEST_NOT((x) < (y)); \ + BOOST_TEST_NOT((x) > (y)) + +#define TEST_NE(x, y) \ + BOOST_TEST_NE(x, y); \ + BOOST_TEST_NOT((x) == (y)); \ + BOOST_TEST((x) < (y) || (x) > (y)); + +int main() +{ + { + boost::core::string_view sv1( "" ); + boost::core::string_view sv2( "" ); + boost::core::string_view sv3( "123" ); + boost::core::string_view sv4( "123" ); + boost::core::string_view sv5( "12345" ); + boost::core::string_view sv6( "12345" ); + + TEST_EQ( sv1, sv1 ); + TEST_EQ( sv1, sv2 ); + TEST_NE( sv1, sv3 ); + TEST_NE( sv1, sv5 ); + + TEST_EQ( sv3, sv3 ); + TEST_EQ( sv3, sv4 ); + TEST_NE( sv3, sv1 ); + TEST_NE( sv3, sv5 ); + + TEST_EQ( sv5, sv5 ); + TEST_EQ( sv5, sv6 ); + TEST_NE( sv5, sv1 ); + TEST_NE( sv5, sv3 ); + + BOOST_TEST_EQ( sv1, std::string( "" ) ); + BOOST_TEST_EQ( std::string( "" ), sv1 ); + + BOOST_TEST_NE( sv1, std::string( "1" ) ); + BOOST_TEST_NE( std::string( "1" ), sv1 ); + + BOOST_TEST_EQ( sv3, std::string( "123" ) ); + BOOST_TEST_EQ( std::string( "123" ), sv3 ); + + BOOST_TEST_NE( sv3, std::string( "122" ) ); + BOOST_TEST_NE( std::string( "122" ), sv3 ); + + BOOST_TEST_EQ( sv1, "" ); + BOOST_TEST_EQ( "", sv1 ); + + BOOST_TEST_NE( sv1, "1" ); + BOOST_TEST_NE( "1", sv1 ); + + BOOST_TEST_EQ( sv3, "123" ); + BOOST_TEST_EQ( "123", sv3 ); + + BOOST_TEST_NE( sv3, "122" ); + BOOST_TEST_NE( "122", sv3 ); + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + BOOST_TEST_EQ( sv1, std::string_view( "" ) ); + BOOST_TEST_EQ( std::string_view( "" ), sv1 ); + + BOOST_TEST_NE( sv1, std::string_view( "1" ) ); + BOOST_TEST_NE( std::string_view( "1" ), sv1 ); + + BOOST_TEST_EQ( sv3, std::string_view( "123" ) ); + BOOST_TEST_EQ( std::string_view( "123" ), sv3 ); + + BOOST_TEST_NE( sv3, std::string_view( "122" ) ); + BOOST_TEST_NE( std::string_view( "122" ), sv3 ); + +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + BOOST_TEST_EQ( sv1, pmr_string( "" ) ); + BOOST_TEST_EQ( pmr_string( "" ), sv1 ); + + BOOST_TEST_NE( sv1, pmr_string( "1" ) ); + BOOST_TEST_NE( pmr_string( "1" ), sv1 ); + + BOOST_TEST_EQ( sv3, pmr_string( "123" ) ); + BOOST_TEST_EQ( pmr_string( "123" ), sv3 ); + + BOOST_TEST_NE( sv3, pmr_string( "122" ) ); + BOOST_TEST_NE( pmr_string( "122" ), sv3 ); + +#endif + } + + return boost::report_errors(); +} diff --git a/test/sv_find_first_not_of_test.cpp b/test/sv_find_first_not_of_test.cpp new file mode 100644 index 0000000..92b12ed --- /dev/null +++ b/test/sv_find_first_not_of_test.cpp @@ -0,0 +1,648 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "12", 1, 2 ), npos ); + } + + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::string_view( "23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '1' ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '3' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( '9' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( '9', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "1" ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "23" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( "123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( "123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view() ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( boost::core::wstring_view( L"23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'1' ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'3' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L'9' ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L'9', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"1" ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"23" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( L"\x101\x102\x103", 7, 3 ), npos ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "0123456789", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"0123456789", 12 ), npos ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_first_not_of( sv ), npos ); + + std::string str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), 255 - i ); + } + } + + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_first_not_of( sv ), npos ); + + std::wstring str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), 255 - i ); + } + } + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"1" ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 0 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"23" ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"123", 7 ), npos ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"0123456789", 12 ), npos ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/sv_find_first_of_test.cpp b/test/sv_find_first_of_test.cpp new file mode 100644 index 0000000..e17ed6d --- /dev/null +++ b/test/sv_find_first_of_test.cpp @@ -0,0 +1,553 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "12", 1, 2 ), npos ); + } + + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::string_view( "23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '1' ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( '1', 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '3' ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 4 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( '3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( '3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( '9' ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "1" ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "1", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "23" ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( "23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( "123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( "123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ) ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ) ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"4" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ) ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( boost::core::wstring_view( L"23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'1' ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'3' ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 1 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 4 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L'3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L'9' ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"1" ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"23" ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 2 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 2 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( L"\x101\x102\x103", 7, 3 ), npos ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_of( "0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "0123456789", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_of( L"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"0123456789", 12 ), npos ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), 255 - i ); + } + } + + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), 255 - i ); + } + } + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_first_of( u8"" ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( u8"1" ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 4 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 5 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( u8"23" ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 3 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find_first_of( u8"123", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 6 ), npos ); + BOOST_TEST_EQ( sv.find_first_of( u8"123", 7 ), npos ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"0123456789", 12 ), npos ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_first_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), npos ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/sv_find_last_not_of_test.cpp b/test/sv_find_last_not_of_test.cpp new file mode 100644 index 0000000..0e7e974 --- /dev/null +++ b/test/sv_find_last_not_of_test.cpp @@ -0,0 +1,648 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "12", 1, 2 ), npos ); + } + + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view(), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view() ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "1" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "4" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::string_view( "23" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( '1', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '1' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( '3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 5 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 6 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3', 7 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '3' ), 4 ); + + BOOST_TEST_EQ( sv.find_last_not_of( '9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( '9' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "1", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "1" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "23" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 0 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 1 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 2 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( "123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view(), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view() ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"1" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"4" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( boost::core::wstring_view( L"23" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'1' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 5 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 6 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3', 7 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'3' ), 4 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L'9' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"1" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"23" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 0 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 1 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 2 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"123", 7, 3 ), npos ); + } + + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 0 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 0 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 0 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 0 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 0 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 1 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 1 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 1 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 1 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 2 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 2 ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 0, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 1, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 2, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 3, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 5, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"\x101\x102\x103", 7, 3 ), npos ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "0123456789" ), 11 ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"0123456789" ), 11 ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_last_not_of( sv ), npos ); + + std::string str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_last_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_last_not_of( str3 ), 255 - i ); + } + } + + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + BOOST_TEST_EQ( sv.find_first_not_of( sv ), npos ); + + std::wstring str2( sv.data(), sv.size() ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring str3( str2 ); + + str3[ i ] = ~str3[ i ]; + + BOOST_TEST_EQ( sv.find_first_not_of( str3 ), 255 - i ); + } + } + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"1" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"23" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 3 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 4 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 5 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"123", 7 ), npos ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"0123456789" ), 11 ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_not_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/sv_find_last_of_test.cpp b/test/sv_find_last_of_test.cpp new file mode 100644 index 0000000..f058197 --- /dev/null +++ b/test/sv_find_last_of_test.cpp @@ -0,0 +1,575 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( '1' ), npos ); + BOOST_TEST_EQ( sv.find_last_of( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "1" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "12", 1, 2 ), npos ); + } + + { + boost::core::wstring_view sv( L"" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view() ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L'1' ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"1" ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"12", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"12", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"12", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"12", 1, 1 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"12", 0, 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"12", 1, 2 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view(), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view() ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "1" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "4" ) ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::string_view( "23" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( '1', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1', 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( '1' ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( '3', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( '3', 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 4 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( '3', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( '3' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( '9' ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "", 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "" ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "1", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "1" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( "23", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "23", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "23" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 1 ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 2 ), 4 ); + + BOOST_TEST_EQ( sv.find_last_of( "123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 6, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( "123", 7, 3 ), 5 ); + } + + { + boost::core::wstring_view sv( L"123123" ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view(), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view() ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ) ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"1" ) ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ), 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"4" ) ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ), 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( boost::core::wstring_view( L"23" ) ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( L'1', 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1', 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L'1' ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L'3', 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 4 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L'3', 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L'3' ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( L'9' ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"", 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"" ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"1", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"1" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L"23", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"23", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"23" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 1 ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 2 ), 4 ); + + BOOST_TEST_EQ( sv.find_last_of( L"123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 6, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"123", 7, 3 ), 5 ); + } + + { + boost::core::wstring_view sv( L"\x101\x102\x103\x101\x102\x103" ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 1 ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 2 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 2 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 2 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 2 ), 4 ); + + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 1, 3 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 2, 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 4, 3 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 5, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 6, 3 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( L"\x101\x102\x103", 7, 3 ), 5 ); + } + + { + boost::core::string_view sv( "abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "0123456789" ), 11 ); + } + + { + boost::core::wstring_view sv( L"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"0123456789" ), 11 ); + } + + { + boost::core::string_view sv( "123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + boost::core::wstring_view sv( L"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + + { + char str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< unsigned char >( i ); + } + + boost::core::string_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_last_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::string needle( 12, static_cast< unsigned char >( i ) ); + BOOST_TEST_EQ( sv.find_last_of( needle ), 255 - i ); + } + } + + { + wchar_t str[ 256 ]; + + for( int i = 0; i < 256; ++i ) + { + str[ i ] = static_cast< wchar_t >( 0x100 + i ); + } + + boost::core::wstring_view sv( str, 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), i ); + } + + std::reverse( str, str + 256 ); + + for( int i = 0; i < 256; ++i ) + { + std::wstring needle( 12, static_cast< wchar_t >( 0x100 + i ) ); + BOOST_TEST_EQ( sv.find_first_of( needle ), 255 - i ); + } + } + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + + { + boost::core::u8string_view sv( u8"123123" ); + + BOOST_TEST_EQ( sv.find_last_of( u8"", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"", 6 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"", 7 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"" ), npos ); + + BOOST_TEST_EQ( sv.find_last_of( u8"1", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 1 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 2 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1", 7 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"1" ), 3 ); + + BOOST_TEST_EQ( sv.find_last_of( u8"23", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 3 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"23" ), 5 ); + + BOOST_TEST_EQ( sv.find_last_of( u8"123", 0 ), 0 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 1 ), 1 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 2 ), 2 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 4 ), 4 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 5 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 6 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123", 7 ), 5 ); + BOOST_TEST_EQ( sv.find_last_of( u8"123" ), 5 ); + } + + { + boost::core::u8string_view sv( u8"abc1abc2abc3" ); + + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"0123456789" ), 11 ); + } + + { + boost::core::u8string_view sv( u8"123a123B123c" ); + + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 0 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 1 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 2 ), npos ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 3 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 4 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 5 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 6 ), 3 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 7 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 8 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 10 ), 7 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 11 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 12 ), 11 ); + BOOST_TEST_EQ( sv.find_last_of( u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ), 11 ); + } + +#endif + + return boost::report_errors(); +} diff --git a/test/sv_find_test.cpp b/test/sv_find_test.cpp new file mode 100644 index 0000000..cdf97ac --- /dev/null +++ b/test/sv_find_test.cpp @@ -0,0 +1,130 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 1 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 1 ), npos ); + + BOOST_TEST_EQ( sv.find( '1' ), npos ); + BOOST_TEST_EQ( sv.find( '1', 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "" ), 0 ); + BOOST_TEST_EQ( sv.find( "", 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "1" ), npos ); + BOOST_TEST_EQ( sv.find( "1", 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "1", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find( "1", 1, 0 ), npos ); + + BOOST_TEST_EQ( sv.find( "1", 0, 1 ), npos ); + BOOST_TEST_EQ( sv.find( "1", 1, 1 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 6 ), 6 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view(), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 6 ), 6 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ) ), 0 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 1 ), 3 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 4 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "1" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ) ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 2 ), 4 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 5 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 6 ), npos ); + BOOST_TEST_EQ( sv.find( boost::core::string_view( "23" ), 7 ), npos ); + + BOOST_TEST_EQ( sv.find( '1' ), 0 ); + BOOST_TEST_EQ( sv.find( '1', 1 ), 3 ); + BOOST_TEST_EQ( sv.find( '1', 2 ), 3 ); + BOOST_TEST_EQ( sv.find( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.find( '1', 4 ), npos ); + BOOST_TEST_EQ( sv.find( '1', 5 ), npos ); + BOOST_TEST_EQ( sv.find( '1', 6 ), npos ); + BOOST_TEST_EQ( sv.find( '1', 7 ), npos ); + + BOOST_TEST_EQ( sv.find( '3' ), 2 ); + BOOST_TEST_EQ( sv.find( '3', 1 ), 2 ); + BOOST_TEST_EQ( sv.find( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.find( '3', 3 ), 5 ); + BOOST_TEST_EQ( sv.find( '3', 4 ), 5 ); + BOOST_TEST_EQ( sv.find( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.find( '3', 6 ), npos ); + BOOST_TEST_EQ( sv.find( '3', 7 ), npos ); + + BOOST_TEST_EQ( sv.find( '9' ), npos ); + + BOOST_TEST_EQ( sv.find( "" ), 0 ); + BOOST_TEST_EQ( sv.find( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.find( "", 6 ), 6 ); + BOOST_TEST_EQ( sv.find( "", 7 ), npos ); + + BOOST_TEST_EQ( sv.find( "1" ), 0 ); + BOOST_TEST_EQ( sv.find( "1", 1 ), 3 ); + BOOST_TEST_EQ( sv.find( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.find( "1", 4 ), npos ); + BOOST_TEST_EQ( sv.find( "1", 6 ), npos ); + BOOST_TEST_EQ( sv.find( "1", 7 ), npos ); + + BOOST_TEST_EQ( sv.find( "23" ), 1 ); + BOOST_TEST_EQ( sv.find( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.find( "23", 2 ), 4 ); + BOOST_TEST_EQ( sv.find( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.find( "23", 5 ), npos ); + BOOST_TEST_EQ( sv.find( "23", 6 ), npos ); + BOOST_TEST_EQ( sv.find( "23", 7 ), npos ); + + BOOST_TEST_EQ( sv.find( "123", 0, 0 ), 0 ); + BOOST_TEST_EQ( sv.find( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.find( "123", 6, 0 ), 6 ); + BOOST_TEST_EQ( sv.find( "123", 7, 0 ), npos ); + + BOOST_TEST_EQ( sv.find( "123", 0, 1 ), 0 ); + BOOST_TEST_EQ( sv.find( "123", 1, 1 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 4, 1 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 6, 1 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 7, 1 ), npos ); + + BOOST_TEST_EQ( sv.find( "123", 0, 3 ), 0 ); + BOOST_TEST_EQ( sv.find( "123", 1, 3 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.find( "123", 4, 3 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 6, 3 ), npos ); + BOOST_TEST_EQ( sv.find( "123", 7, 3 ), npos ); + } + + return boost::report_errors(); +} diff --git a/test/sv_iteration_test.cpp b/test/sv_iteration_test.cpp new file mode 100644 index 0000000..57078d6 --- /dev/null +++ b/test/sv_iteration_test.cpp @@ -0,0 +1,61 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv; + + { + std::string s( sv.begin(), sv.end() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + + { + std::string s( sv.cbegin(), sv.cend() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + + { + std::string s( sv.rbegin(), sv.rend() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + + { + std::string s( sv.crbegin(), sv.crend() ); + BOOST_TEST_EQ( s, std::string( "" ) ); + } + } + + { + boost::core::string_view sv( "123" ); + + { + std::string s( sv.begin(), sv.end() ); + BOOST_TEST_EQ( s, std::string( "123" ) ); + } + + { + std::string s( sv.cbegin(), sv.cend() ); + BOOST_TEST_EQ( s, std::string( "123" ) ); + } + + { + std::string s( sv.rbegin(), sv.rend() ); + BOOST_TEST_EQ( s, std::string( "321" ) ); + } + + { + std::string s( sv.crbegin(), sv.crend() ); + BOOST_TEST_EQ( s, std::string( "321" ) ); + } + } + + return boost::report_errors(); +} diff --git a/test/sv_lt_test.cpp b/test/sv_lt_test.cpp new file mode 100644 index 0000000..dfa4227 --- /dev/null +++ b/test/sv_lt_test.cpp @@ -0,0 +1,109 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) +# include +#endif + +#define TEST_LT(x, y) \ + BOOST_TEST_LT(x, y); \ + BOOST_TEST_LE(x, y); \ + BOOST_TEST_NE(x, y); \ + BOOST_TEST_NOT((x) == (y)); \ + BOOST_TEST_NOT((x) >= (y)); \ + BOOST_TEST_NOT((x) > (y)); \ + BOOST_TEST_GT(y, x); \ + BOOST_TEST_GE(y, x); \ + BOOST_TEST_NOT((y) < (x)); \ + BOOST_TEST_NOT((y) <= (x)); + +int main() +{ + { + boost::core::string_view sv0( "" ); + boost::core::string_view sv1( "12" ); + boost::core::string_view sv2( "122" ); + boost::core::string_view sv3( "123" ); + boost::core::string_view sv4( "124" ); + boost::core::string_view sv5( "1234" ); + + TEST_LT( sv0, sv1 ); + TEST_LT( sv1, sv2 ); + TEST_LT( sv2, sv3 ); + TEST_LT( sv3, sv4 ); + TEST_LT( sv3, sv5 ); + TEST_LT( sv5, sv4 ); + + TEST_LT( sv0, std::string( "12" ) ); + TEST_LT( sv1, std::string( "122" ) ); + TEST_LT( sv2, std::string( "123" ) ); + TEST_LT( sv3, std::string( "124" ) ); + TEST_LT( sv3, std::string( "1234" ) ); + TEST_LT( sv5, std::string( "124" ) ); + + TEST_LT( sv0, "12" ); + TEST_LT( sv1, "122" ); + TEST_LT( sv2, "123" ); + TEST_LT( sv3, "124" ); + TEST_LT( sv3, "1234" ); + TEST_LT( sv5, "124" ); + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + TEST_LT( sv0, std::string_view( "12" ) ); + TEST_LT( sv1, std::string_view( "122" ) ); + TEST_LT( sv2, std::string_view( "123" ) ); + TEST_LT( sv3, std::string_view( "124" ) ); + TEST_LT( sv3, std::string_view( "1234" ) ); + TEST_LT( sv5, std::string_view( "124" ) ); + +#endif + + TEST_LT( std::string( "" ), sv1 ); + TEST_LT( std::string( "12" ), sv2 ); + TEST_LT( std::string( "122" ), sv3 ); + TEST_LT( std::string( "123" ), sv4 ); + TEST_LT( std::string( "123" ), sv5 ); + TEST_LT( std::string( "1234" ), sv4 ); + + TEST_LT( "", sv1 ); + TEST_LT( "12", sv2 ); + TEST_LT( "122", sv3 ); + TEST_LT( "123", sv4 ); + TEST_LT( "123", sv5 ); + TEST_LT( "1234", sv4 ); + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + TEST_LT( std::string_view( "" ), sv1 ); + TEST_LT( std::string_view( "12" ), sv2 ); + TEST_LT( std::string_view( "122" ), sv3 ); + TEST_LT( std::string_view( "123" ), sv4 ); + TEST_LT( std::string_view( "123" ), sv5 ); + TEST_LT( std::string_view( "1234" ), sv4 ); + +#endif + +#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) + + using pmr_string = std::basic_string, std::pmr::polymorphic_allocator>; + + TEST_LT( pmr_string( "" ), sv1 ); + TEST_LT( pmr_string( "12" ), sv2 ); + TEST_LT( pmr_string( "122" ), sv3 ); + TEST_LT( pmr_string( "123" ), sv4 ); + TEST_LT( pmr_string( "123" ), sv5 ); + TEST_LT( pmr_string( "1234" ), sv4 ); + +#endif + } + + return boost::report_errors(); +} diff --git a/test/sv_modifiers_test.cpp b/test/sv_modifiers_test.cpp new file mode 100644 index 0000000..1a4d2b0 --- /dev/null +++ b/test/sv_modifiers_test.cpp @@ -0,0 +1,127 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + { + char const* s1 = "12345"; + char const* s2 = ""; + + boost::core::string_view sv1( s1 ); + boost::core::string_view sv2( s2 ); + + sv1.swap( sv2 ); + + BOOST_TEST_EQ( sv1.data(), s2 ); + BOOST_TEST_EQ( sv1.size(), 0 ); + + BOOST_TEST_EQ( sv2.data(), s1 ); + BOOST_TEST_EQ( sv2.size(), 5); + } + + { + boost::core::string_view sv; + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + + sv.remove_suffix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + } + + { + boost::core::string_view sv( "" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + + sv.remove_suffix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + + sv.remove_suffix( 0 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 2 ); + + BOOST_TEST_EQ( sv.data(), data + 2 ); + BOOST_TEST_EQ( sv.size(), size - 2 ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_prefix( 5 ); + + BOOST_TEST_EQ( sv.data(), data + 5 ); + BOOST_TEST_EQ( sv.size(), size - 5 ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_suffix( 2 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size - 2 ); + } + + { + boost::core::string_view sv( "12345" ); + + char const* data = sv.data(); + std::size_t size = sv.size(); + + sv.remove_suffix( 5 ); + + BOOST_TEST_EQ( sv.data(), data ); + BOOST_TEST_EQ( sv.size(), size - 5 ); + } + + return boost::report_errors(); +} diff --git a/test/sv_nullptr_fail.cpp b/test/sv_nullptr_fail.cpp new file mode 100644 index 0000000..d862038 --- /dev/null +++ b/test/sv_nullptr_fail.cpp @@ -0,0 +1,19 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +#if defined(BOOST_NO_CXX11_NULLPTR) + +#error BOOST_NO_CXX11_NULLPTR is defined, test will be skipped. + +#else + +int main() +{ + return boost::core::string_view( nullptr ).size() == 0; +} + +#endif diff --git a/test/sv_rfind_test.cpp b/test/sv_rfind_test.cpp new file mode 100644 index 0000000..12ab0cc --- /dev/null +++ b/test/sv_rfind_test.cpp @@ -0,0 +1,169 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +int main() +{ + std::size_t const npos = boost::core::string_view::npos; + + { + boost::core::string_view sv( "" ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view() ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ) ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ) ), npos ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( '1' ), npos ); + BOOST_TEST_EQ( sv.rfind( '1', 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( '1', 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "" ), 0 ); + BOOST_TEST_EQ( sv.rfind( "", 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "", 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "1" ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "1", npos, 0 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 1, 0 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 0, 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "1", npos, 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 1, 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( "1", 0, 1 ), npos ); + } + + { + boost::core::string_view sv( "123123" ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view() ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 7 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 6 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view(), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ) ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 7 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 6 ), 6 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "" ), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ) ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 7 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 6 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 5 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 4 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 2 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "1" ), 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ) ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 7 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 6 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 5 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 4 ), 4 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 3 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 2 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( boost::core::string_view( "23" ), 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( '1' ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 7 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 6 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 5 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 4 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( '1', 2 ), 0 ); + BOOST_TEST_EQ( sv.rfind( '1', 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( '1', 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( '3' ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 7 ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 6 ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( '3', 4 ), 2 ); + BOOST_TEST_EQ( sv.rfind( '3', 3 ), 2 ); + BOOST_TEST_EQ( sv.rfind( '3', 2 ), 2 ); + BOOST_TEST_EQ( sv.rfind( '3', 1 ), npos ); + BOOST_TEST_EQ( sv.rfind( '3', 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( '9' ), npos ); + BOOST_TEST_EQ( sv.rfind( '9', 7 ), npos ); + BOOST_TEST_EQ( sv.rfind( '9', 6 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "" ), 6 ); + BOOST_TEST_EQ( sv.rfind( "", 7 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "", 6 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "", 5 ), 5 ); + BOOST_TEST_EQ( sv.rfind( "", 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "", 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "1" ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 7 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 6 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 5 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 4 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "1", 2 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1", 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "23" ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 7 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 6 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 5 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 4 ), 4 ); + BOOST_TEST_EQ( sv.rfind( "23", 3 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "23", 2 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "23", 1 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "23", 0 ), npos ); + + BOOST_TEST_EQ( sv.rfind( "123", npos, 0 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "123", 7, 0 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "123", 6, 0 ), 6 ); + BOOST_TEST_EQ( sv.rfind( "123", 5, 0 ), 5 ); + BOOST_TEST_EQ( sv.rfind( "123", 1, 0 ), 1 ); + BOOST_TEST_EQ( sv.rfind( "123", 0, 0 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "123", npos, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 7, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 6, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 5, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 4, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 3, 1 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 2, 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 1, 1 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 0, 1 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "123", npos, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 7, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 6, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 5, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 4, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 3, 3 ), 3 ); + BOOST_TEST_EQ( sv.rfind( "123", 2, 3 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 1, 3 ), 0 ); + BOOST_TEST_EQ( sv.rfind( "123", 0, 3 ), 0 ); + + BOOST_TEST_EQ( sv.rfind( "123123" ), 0 ); + BOOST_TEST_EQ( sv.rfind( "1231231" ), npos ); + } + + return boost::report_errors(); +} diff --git a/test/sv_starts_with_test.cpp b/test/sv_starts_with_test.cpp new file mode 100644 index 0000000..8fa8869 --- /dev/null +++ b/test/sv_starts_with_test.cpp @@ -0,0 +1,50 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv( "" ); + + BOOST_TEST( sv.starts_with( boost::core::string_view() ) ); + BOOST_TEST( sv.starts_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.starts_with( "" ) ); + + BOOST_TEST( !sv.starts_with( boost::core::string_view( "1" ) ) ); + BOOST_TEST( !sv.starts_with( '1' ) ); + BOOST_TEST( !sv.starts_with( "1" ) ); + } + + { + boost::core::string_view sv( "123" ); + + BOOST_TEST( sv.starts_with( boost::core::string_view() ) ); + BOOST_TEST( sv.starts_with( boost::core::string_view( "" ) ) ); + BOOST_TEST( sv.starts_with( "" ) ); + + BOOST_TEST( sv.starts_with( boost::core::string_view( "1" ) ) ); + BOOST_TEST( sv.starts_with( '1' ) ); + BOOST_TEST( sv.starts_with( "1" ) ); + + BOOST_TEST( sv.starts_with( boost::core::string_view( "12" ) ) ); + BOOST_TEST( sv.starts_with( "12" ) ); + + BOOST_TEST( sv.starts_with( boost::core::string_view( "123" ) ) ); + BOOST_TEST( sv.starts_with( "123" ) ); + + BOOST_TEST( !sv.starts_with( boost::core::string_view( "1234" ) ) ); + BOOST_TEST( !sv.starts_with( "1234" ) ); + + BOOST_TEST( !sv.starts_with( boost::core::string_view( "2" ) ) ); + BOOST_TEST( !sv.starts_with( '2' ) ); + BOOST_TEST( !sv.starts_with( "2" ) ); + } + + return boost::report_errors(); +} diff --git a/test/sv_stream_insert_test.cpp b/test/sv_stream_insert_test.cpp new file mode 100644 index 0000000..864c2bd --- /dev/null +++ b/test/sv_stream_insert_test.cpp @@ -0,0 +1,111 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + using boost::core::string_view; + + { + std::ostringstream os; + + os << string_view( "" ); + + BOOST_TEST_EQ( os.str(), std::string( "" ) ); + } + + { + std::ostringstream os; + + os << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "123" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "" ); + + BOOST_TEST_EQ( os.str(), std::string( " " ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::setw( 5 ) << string_view( "" ); + + BOOST_TEST_EQ( os.str(), std::string( "-----" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( " 123" ) ); + } + + { + std::ostringstream os; + + os << std::left << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "123 " ) ); + } + + { + std::ostringstream os; + + os << std::right << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( " 123" ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "--123" ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::left << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "123--" ) ); + } + + { + std::ostringstream os; + + os << std::setfill( '-' ) << std::right << std::setw( 5 ) << string_view( "123" ); + + BOOST_TEST_EQ( os.str(), std::string( "--123" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "12345" ); + + BOOST_TEST_EQ( os.str(), std::string( "12345" ) ); + } + + { + std::ostringstream os; + + os << std::setw( 5 ) << string_view( "1234567" ); + + BOOST_TEST_EQ( os.str(), std::string( "1234567" ) ); + } + + return boost::report_errors(); +} diff --git a/test/sv_substr_test.cpp b/test/sv_substr_test.cpp new file mode 100644 index 0000000..51cde0a --- /dev/null +++ b/test/sv_substr_test.cpp @@ -0,0 +1,203 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + { + boost::core::string_view sv; + + { + boost::core::string_view sv2 = sv.substr(); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + BOOST_TEST_THROWS( sv.substr( 1 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 1 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 0, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + BOOST_TEST_THROWS( sv.substr( 1, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 0 ), std::out_of_range ); + } + + { + boost::core::string_view sv( "12345" ); + + { + boost::core::string_view sv2 = sv.substr(); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), sv.size() ); + } + + { + boost::core::string_view sv2 = sv.substr( 2 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), sv.size() - 2 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), sv.size() - 5 ); + } + + BOOST_TEST_THROWS( sv.substr( 6 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 0 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 0 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 0 ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 4, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 4 ); + BOOST_TEST_EQ( sv2.size(), 1 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 3 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 3 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 3 ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 5 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 4, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 4 ); + BOOST_TEST_EQ( sv2.size(), 1 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 5 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 5 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 5 ), std::out_of_range ); + + { + boost::core::string_view sv2 = sv.substr( 0, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() ); + BOOST_TEST_EQ( sv2.size(), 5 ); + } + + { + boost::core::string_view sv2 = sv.substr( 2, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 2 ); + BOOST_TEST_EQ( sv2.size(), 3 ); + } + + { + boost::core::string_view sv2 = sv.substr( 4, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 4 ); + BOOST_TEST_EQ( sv2.size(), 1 ); + } + + { + boost::core::string_view sv2 = sv.substr( 5, 8 ); + + BOOST_TEST_EQ( sv2.data(), sv.data() + 5 ); + BOOST_TEST_EQ( sv2.size(), 0 ); + } + + BOOST_TEST_THROWS( sv.substr( 6, 8 ), std::out_of_range ); + BOOST_TEST_THROWS( sv.substr( boost::core::string_view::npos, 8 ), std::out_of_range ); + } + + return boost::report_errors(); +} diff --git a/test/sv_types_test.cpp b/test/sv_types_test.cpp new file mode 100644 index 0000000..9afe05b --- /dev/null +++ b/test/sv_types_test.cpp @@ -0,0 +1,46 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +struct Ch +{ +}; + +int main() +{ + typedef boost::core::basic_string_view ch_string_view; + + BOOST_TEST_TRAIT_SAME(ch_string_view::traits_type, std::char_traits); + BOOST_TEST_TRAIT_SAME(ch_string_view::value_type, Ch); + BOOST_TEST_TRAIT_SAME(ch_string_view::pointer, Ch*); + BOOST_TEST_TRAIT_SAME(ch_string_view::const_pointer, Ch const*); + BOOST_TEST_TRAIT_SAME(ch_string_view::reference, Ch&); + BOOST_TEST_TRAIT_SAME(ch_string_view::const_reference, Ch const&); + BOOST_TEST_TRAIT_SAME(ch_string_view::iterator, ch_string_view::const_iterator); + BOOST_TEST_TRAIT_SAME(std::iterator_traits::iterator_category, std::random_access_iterator_tag); + BOOST_TEST_TRAIT_SAME(ch_string_view::reverse_iterator, ch_string_view::const_reverse_iterator); + BOOST_TEST_TRAIT_SAME(ch_string_view::reverse_iterator, std::reverse_iterator); + BOOST_TEST_TRAIT_SAME(ch_string_view::size_type, std::size_t); + BOOST_TEST_TRAIT_SAME(ch_string_view::difference_type, std::ptrdiff_t); + + BOOST_TEST_EQ(ch_string_view::npos, static_cast(-1)); + + BOOST_TEST_TRAIT_SAME(boost::core::string_view, boost::core::basic_string_view); + BOOST_TEST_TRAIT_SAME(boost::core::wstring_view, boost::core::basic_string_view); +#if !defined(BOOST_NO_CXX11_CHAR16_T) + BOOST_TEST_TRAIT_SAME(boost::core::u16string_view, boost::core::basic_string_view); +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) + BOOST_TEST_TRAIT_SAME(boost::core::u32string_view, boost::core::basic_string_view); +#endif +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + BOOST_TEST_TRAIT_SAME(boost::core::u8string_view, boost::core::basic_string_view); +#endif + + return boost::report_errors(); +} diff --git a/test/sv_windows_h_test.cpp b/test/sv_windows_h_test.cpp new file mode 100644 index 0000000..d22c7fd --- /dev/null +++ b/test/sv_windows_h_test.cpp @@ -0,0 +1,15 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if !defined(_WIN32) && !defined(__CYGWIN__) + +#include +BOOST_PRAGMA_MESSAGE( "Skipping test because _WIN32 and __CYGWIN__ are not defined" ) + +#else + +#include +#include + +#endif diff --git a/test/swap/Jamfile.v2 b/test/swap/Jamfile.v2 index 2b43737..d7f705e 100644 --- a/test/swap/Jamfile.v2 +++ b/test/swap/Jamfile.v2 @@ -13,6 +13,7 @@ compile swap_lib_header_1.cpp ; compile swap_lib_header_2.cpp ; compile swap_mixed_headers_1.cpp ; compile swap_mixed_headers_2.cpp ; +compile swap_noexcept.cpp ; compile-fail swap_const_wrapper_fail.cpp ; diff --git a/test/swap/swap_array_of_array_of_class.cpp b/test/swap/swap_array_of_array_of_class.cpp index 67541d3..1ea78da 100644 --- a/test/swap/swap_array_of_array_of_class.cpp +++ b/test/swap/swap_array_of_array_of_class.cpp @@ -17,6 +17,10 @@ #include //for std::copy and std::equal #include //for std::size_t +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#endif + //Provide swap function in both the namespace of swap_test_class //(which is the global namespace), and the std namespace. //It's common to provide a swap function for a class in both diff --git a/test/swap/swap_array_of_class.cpp b/test/swap/swap_array_of_class.cpp index ef7327e..b8b496a 100644 --- a/test/swap/swap_array_of_class.cpp +++ b/test/swap/swap_array_of_class.cpp @@ -17,6 +17,10 @@ #include //for std::copy and std::equal #include //for std::size_t +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#endif + //Provide swap function in both the namespace of swap_test_class //(which is the global namespace), and the std namespace. //It's common to provide a swap function for a class in both @@ -42,13 +46,13 @@ int main() const std::size_t array_size = 2; const swap_test_class initial_array1[array_size] = { swap_test_class(1), swap_test_class(2) }; const swap_test_class initial_array2[array_size] = { swap_test_class(3), swap_test_class(4) }; - + swap_test_class array1[array_size]; swap_test_class array2[array_size]; std::copy(initial_array1, initial_array1 + array_size, array1); std::copy(initial_array2, initial_array2 + array_size, array2); - + swap_test_class::reset(); boost::swap(array1, array2); diff --git a/test/swap/swap_array_of_int.cpp b/test/swap/swap_array_of_int.cpp index e8285e0..1978d90 100644 --- a/test/swap/swap_array_of_int.cpp +++ b/test/swap/swap_array_of_int.cpp @@ -20,13 +20,13 @@ int main() const std::size_t array_size = 3; const int initial_array1[array_size] = { 1, 2, 3 }; const int initial_array2[array_size] = { 4, 5, 6 }; - + int array1[array_size]; int array2[array_size]; std::copy(initial_array1, initial_array1 + array_size, array1); std::copy(initial_array2, initial_array2 + array_size, array2); - + boost::swap(array1, array2); BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2)); diff --git a/test/swap/swap_array_of_template.cpp b/test/swap/swap_array_of_template.cpp index c0e76e3..652d418 100644 --- a/test/swap/swap_array_of_template.cpp +++ b/test/swap/swap_array_of_template.cpp @@ -50,15 +50,15 @@ void swap(swap_test_template& left, swap_test_template& right) int main() { const std::size_t array_size = 2; - const swap_test_template initial_array1[array_size] = { swap_test_class(1), swap_test_class(2) }; - const swap_test_template initial_array2[array_size] = { swap_test_class(3), swap_test_class(4) }; - + const swap_test_template initial_array1[array_size] = { { swap_test_class(1) }, { swap_test_class(2) } }; + const swap_test_template initial_array2[array_size] = { { swap_test_class(3) }, { swap_test_class(4) } }; + swap_test_template array1[array_size]; swap_test_template array2[array_size]; std::copy(initial_array1, initial_array1 + array_size, array1); std::copy(initial_array2, initial_array2 + array_size, array2); - + swap_test_class::reset(); boost::swap(array1, array2); diff --git a/test/swap/swap_const_wrapper_fail.cpp b/test/swap/swap_const_wrapper_fail.cpp index da2e4c6..ea44a4d 100644 --- a/test/swap/swap_const_wrapper_fail.cpp +++ b/test/swap/swap_const_wrapper_fail.cpp @@ -6,7 +6,7 @@ namespace boost { - + template struct Wrapper { T value; @@ -16,9 +16,9 @@ template inline void swap( Wrapper & w, Wrapper & v ) { boost::swap( w, v ); } - + } // namespace boost - + int main() { boost::Wrapper const w = { 2 }; diff --git a/test/swap/swap_noexcept.cpp b/test/swap/swap_noexcept.cpp new file mode 100644 index 0000000..cafbde1 --- /dev/null +++ b/test/swap/swap_noexcept.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2023 Andrey Semashev +// +// 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) + +// Tests that boost::swap propagates noexcept specification correctly + +#include +#include + +#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_STATIC_ASSERT) && \ + !(defined(BOOST_GCC) && (BOOST_GCC < 40700)) + +namespace test_ns { + +struct class_with_noexcept_swap +{ + static class_with_noexcept_swap& instance() noexcept; + + friend void swap(class_with_noexcept_swap&, class_with_noexcept_swap&) noexcept + { + } +}; + +struct class_with_except_swap +{ + static class_with_except_swap& instance() noexcept; + + friend void swap(class_with_except_swap&, class_with_except_swap&) + { + } +}; + +} // namespace test_ns + +static_assert(noexcept(boost::swap(test_ns::class_with_noexcept_swap::instance(), test_ns::class_with_noexcept_swap::instance())), + "boost::swap for class_with_noexcept_swap should have noexcept specification"); +static_assert(!noexcept(boost::swap(test_ns::class_with_except_swap::instance(), test_ns::class_with_except_swap::instance())), + "boost::swap for class_with_except_swap should not have noexcept specification"); + +#endif // !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_STATIC_ASSERT) ... diff --git a/test/swap/swap_specialized_in_boost.cpp b/test/swap/swap_specialized_in_boost.cpp index dcb015d..ab74b5e 100644 --- a/test/swap/swap_specialized_in_boost.cpp +++ b/test/swap/swap_specialized_in_boost.cpp @@ -31,7 +31,7 @@ int main() boost::swap_test_class object1 = initial_value1; boost::swap_test_class object2 = initial_value2; - + boost::swap_test_class::reset(); boost::swap(object1,object2); diff --git a/test/swap/swap_specialized_in_boost_and_other.cpp b/test/swap/swap_specialized_in_boost_and_other.cpp index d596775..3f874bc 100644 --- a/test/swap/swap_specialized_in_boost_and_other.cpp +++ b/test/swap/swap_specialized_in_boost_and_other.cpp @@ -10,7 +10,7 @@ // in an other namespace to have a custom swap function in boost, because the // boost::swap utility should find the swap function in the other namespace, by // argument dependent lookup (ADL). Unfortunately ADL isn't fully implemented -// by some specific compiler versions, including Intel C++ 8.1, MSVC 7.1, and +// by some specific compiler versions, including Intel C++ 8.1, MSVC 7.1, and // Borland 5.9.3. Users of those compilers might consider adding a swap overload // to the boost namespace. @@ -50,13 +50,13 @@ int main() other::swap_test_class object1 = initial_value1; other::swap_test_class object2 = initial_value2; - + other::swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(other::swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(other::swap_test_class::copy_count(),0); diff --git a/test/swap/swap_specialized_in_global.cpp b/test/swap/swap_specialized_in_global.cpp index 8b0f10a..72eb15c 100644 --- a/test/swap/swap_specialized_in_global.cpp +++ b/test/swap/swap_specialized_in_global.cpp @@ -25,13 +25,13 @@ int main() swap_test_class object1 = initial_value1; swap_test_class object2 = initial_value2; - + swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(swap_test_class::copy_count(),0); diff --git a/test/swap/swap_specialized_in_other.cpp b/test/swap/swap_specialized_in_other.cpp index 016cc8a..74240fc 100644 --- a/test/swap/swap_specialized_in_other.cpp +++ b/test/swap/swap_specialized_in_other.cpp @@ -31,13 +31,13 @@ int main() other::swap_test_class object1 = initial_value1; other::swap_test_class object2 = initial_value2; - + other::swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(other::swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(other::swap_test_class::copy_count(),0); diff --git a/test/swap/swap_specialized_in_std.cpp b/test/swap/swap_specialized_in_std.cpp index 62d4ee4..6be5e77 100644 --- a/test/swap/swap_specialized_in_std.cpp +++ b/test/swap/swap_specialized_in_std.cpp @@ -30,13 +30,13 @@ int main() swap_test_class object1 = initial_value1; swap_test_class object2 = initial_value2; - + swap_test_class::reset(); boost::swap(object1,object2); BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(swap_test_class::swap_count(),1); BOOST_CHECK_EQUAL(swap_test_class::copy_count(),0); diff --git a/test/swap/swap_std_typeinfo_ptr.cpp b/test/swap/swap_std_typeinfo_ptr.cpp index 10fd6e5..dfd35a5 100644 --- a/test/swap/swap_std_typeinfo_ptr.cpp +++ b/test/swap/swap_std_typeinfo_ptr.cpp @@ -19,7 +19,7 @@ int main() { const std::type_info * const initial_value1 = 0; const std::type_info * const initial_value2 = &typeid(double); - + const std::type_info * ptr1 = initial_value1; const std::type_info * ptr2 = initial_value2; diff --git a/test/swap/swap_std_vector_of_boost.cpp b/test/swap/swap_std_vector_of_boost.cpp index 93d5d61..e2badc5 100644 --- a/test/swap/swap_std_vector_of_boost.cpp +++ b/test/swap/swap_std_vector_of_boost.cpp @@ -5,7 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // Tests swapping std::vector objects by means of boost::swap, -// having boost::swap_test_class as vector element type. +// having boost::swap_test_class as vector element type. #include #include @@ -39,12 +39,12 @@ int main() const vector_type initial_value1(initial_size1, swap_test_class_type(1)); const vector_type initial_value2(initial_size2, swap_test_class_type(2)); - + vector_type object1 = initial_value1; vector_type object2 = initial_value2; swap_test_class_type::reset(); - + boost::swap(object1,object2); BOOST_CHECK_EQUAL(object1.size(),initial_size2); @@ -52,7 +52,7 @@ int main() BOOST_CHECK(object1 == initial_value2); BOOST_CHECK(object2 == initial_value1); - + BOOST_CHECK_EQUAL(swap_test_class_type::swap_count(),0); BOOST_CHECK_EQUAL(swap_test_class_type::copy_count(),0); diff --git a/test/swap/swap_std_vector_of_global.cpp b/test/swap/swap_std_vector_of_global.cpp index 08d6974..11fe9b3 100644 --- a/test/swap/swap_std_vector_of_global.cpp +++ b/test/swap/swap_std_vector_of_global.cpp @@ -5,7 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // Tests swapping std::vector objects by means of boost::swap, -// having ::swap_test_class as vector element type. +// having ::swap_test_class as vector element type. #include #include @@ -17,7 +17,7 @@ //Put test class in the global namespace #include "./swap_test_class.hpp" -//Provide swap function in the global namespace +//Provide swap function in the global namespace void swap(swap_test_class& left, swap_test_class& right) { left.swap(right); @@ -32,12 +32,12 @@ int main() const vector_type initial_value1(initial_size1, swap_test_class(1)); const vector_type initial_value2(initial_size2, swap_test_class(2)); - + vector_type object1 = initial_value1; vector_type object2 = initial_value2; swap_test_class::reset(); - + boost::swap(object1,object2); BOOST_CHECK_EQUAL(object1.size(),initial_size2); diff --git a/test/swap/swap_std_vector_of_other.cpp b/test/swap/swap_std_vector_of_other.cpp index 77a3525..a713767 100644 --- a/test/swap/swap_std_vector_of_other.cpp +++ b/test/swap/swap_std_vector_of_other.cpp @@ -5,7 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // Tests swapping std::vector objects by means of boost::swap, -// having other::swap_test_class as vector element type. +// having other::swap_test_class as vector element type. #include #include @@ -39,12 +39,12 @@ int main() const vector_type initial_value1(initial_size1, swap_test_class_type(1)); const vector_type initial_value2(initial_size2, swap_test_class_type(2)); - + vector_type object1 = initial_value1; vector_type object2 = initial_value2; swap_test_class_type::reset(); - + boost::swap(object1,object2); BOOST_CHECK_EQUAL(object1.size(),initial_size2); diff --git a/test/swap/swap_test_class.hpp b/test/swap/swap_test_class.hpp index a25dbbd..a36bd41 100644 --- a/test/swap/swap_test_class.hpp +++ b/test/swap/swap_test_class.hpp @@ -59,7 +59,7 @@ public: { m_data = arg; } - + static unsigned int swap_count(){ return swapCount(); } static unsigned int copy_count(){ return copyCount(); } static unsigned int construct_count(){ return constructCount(); } @@ -68,7 +68,7 @@ public: static void reset() { swapCount() = 0; - copyCount() = 0; + copyCount() = 0; constructCount() = 0; destructCount() = 0; } @@ -80,19 +80,19 @@ private: return value; } - static unsigned int& copyCount() + static unsigned int& copyCount() { static unsigned int value = 0; return value; } - static unsigned int& constructCount() + static unsigned int& constructCount() { static unsigned int value = 0; return value; } - static unsigned int& destructCount() + static unsigned int& destructCount() { static unsigned int value = 0; return value; diff --git a/test/to_address_test.cpp b/test/to_address_test.cpp index e1b55c4..4662e32 100644 --- a/test/to_address_test.cpp +++ b/test/to_address_test.cpp @@ -13,9 +13,11 @@ class P1 { public: explicit P1(T* p) : p_(p) { } + T* operator->() const BOOST_NOEXCEPT { return p_; } + private: T* p_; }; @@ -25,9 +27,11 @@ class P2 { public: explicit P2(T* p) : p_(p) { } + P1 operator->() const BOOST_NOEXCEPT { return p_; } + private: P1 p_; }; @@ -38,20 +42,24 @@ class P3 { public: explicit P3(T* p) : p_(p) { } + T* get() const BOOST_NOEXCEPT { return p_; } + private: T* p_; }; namespace boost { + template struct pointer_traits > { static T* to_address(const P3& p) BOOST_NOEXCEPT { return p.get(); } }; + } /* boost */ template @@ -59,77 +67,29 @@ class P4 { public: explicit P4(T* p) : p_(p) { } + T* operator->() const BOOST_NOEXCEPT { return 0; } + T* get() const BOOST_NOEXCEPT { return p_; } + private: int* p_; }; namespace boost { + template struct pointer_traits > { static T* to_address(const P4& p) BOOST_NOEXCEPT { return p.get(); } }; + } /* boost */ - -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) -template -class P5 { -public: - explicit P5(T* p) - : p_(p) { } - T* get() const BOOST_NOEXCEPT { - return p_; - } -private: - T* p_; -}; - -namespace std { -template -struct pointer_traits > { - static T* to_address(const P5& p) BOOST_NOEXCEPT { - return p.get(); - } -}; -} /* std */ - -template -class P6 { -public: - explicit P6(T* p) - : p_(p) { } - T* get() const BOOST_NOEXCEPT { - return p_; - } -private: - T* p_; -}; - -namespace boost { -template -struct pointer_traits > { - static T* to_address(const P6& p) BOOST_NOEXCEPT { - return p.get(); - } -}; -} /* boost */ - -namespace std { -template -struct pointer_traits > { - static T* to_address(const P6& p) BOOST_NOEXCEPT { - return 0; - } -}; -} /* std */ -#endif #endif int main() @@ -147,12 +107,6 @@ int main() BOOST_TEST(boost::to_address(p3) == &i); P4 p4(&i); BOOST_TEST(boost::to_address(p4) == &i); -#if !defined(BOOST_NO_CXX11_POINTER_TRAITS) - P5 p5(&i); - BOOST_TEST(boost::to_address(p5) == &i); - P6 p6(&i); - BOOST_TEST(boost::to_address(p6) == &i); -#endif #endif return boost::report_errors(); } diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index 6ab08f5..bac8ccd 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -27,6 +27,10 @@ # include #endif +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) +# include +#endif + #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif @@ -67,7 +71,47 @@ struct Ch int main() { + TEST(signed char); + TEST(unsigned char); + TEST(short); + TEST(unsigned short); TEST(int); + TEST(unsigned); + TEST(long); + TEST(unsigned long); + TEST(long long); + TEST(unsigned long long); + +#if defined(BOOST_HAS_INT128) + TEST(__int128); + TEST(unsigned __int128); +#endif + + TEST(char); + TEST(wchar_t); +#if !defined(BOOST_NO_CXX11_CHAR16_T) + TEST(char16_t); +#endif +#if !defined(BOOST_NO_CXX11_CHAR16_T) + TEST(char32_t); +#endif +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + TEST(char8_t); +#endif +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L + TEST(std::byte); +#endif + + TEST(bool); + + TEST(float); + TEST(double); + TEST(long double); + + TEST(void); + TEST(void const); + TEST(void volatile); + TEST(void const volatile); TEST(A); TEST(B); @@ -94,33 +138,133 @@ int main() #endif - TEST(void); - TEST(void const); - TEST(void volatile); - TEST(void const volatile); - TEST(A*); TEST(B const* volatile*); TEST(void*); TEST(void const* volatile*); +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + TEST(void()); + TEST(int(float, A, B*)); + + TEST(void(*)()); + TEST(void(**)()); + TEST(void(***)()); + + TEST(void(* const* const*)()); + TEST(void(* const* const&)()); + + TEST(void(&)()); + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + TEST(void(&&)()); + +#endif + +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 + + TEST(void() const); + TEST(void() volatile); + TEST(void() const volatile); + +#endif + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + + TEST(void() &); + TEST(void() const &); + TEST(void() volatile &); + TEST(void() const volatile &); + + TEST(void() &&); + TEST(void() const &&); + TEST(void() volatile &&); + TEST(void() const volatile &&); + +#endif + +#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) + + TEST(void() noexcept); + TEST(void() const noexcept); + TEST(void() volatile noexcept); + TEST(void() const volatile noexcept); + + TEST(void() & noexcept); + TEST(void() const & noexcept); + TEST(void() volatile & noexcept); + TEST(void() const volatile & noexcept); + + TEST(void() && noexcept); + TEST(void() const && noexcept); + TEST(void() volatile && noexcept); + TEST(void() const volatile && noexcept); + +#endif + +#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + TEST(A[]); TEST(A const[]); TEST(A volatile[]); TEST(A const volatile[]); +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1700 + TEST(A(&)[]); +#endif + TEST(A const(***)[]); + TEST(B[1]); TEST(B const[1]); TEST(B volatile[1]); TEST(B const volatile[1]); + TEST(B(&)[1]); + TEST(B const(***)[1]); + TEST(A[][2][3]); TEST(A const[][2][3]); +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1700 + TEST(A(&)[][2][3]); +#endif + TEST(A const(***)[][2][3]); + TEST(B[1][2][3]); TEST(B const volatile[1][2][3]); + TEST(B(&)[1][2][3]); + TEST(B const volatile(***)[1][2][3]); + + TEST(int A::*); + TEST(int const B::*); + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + TEST(void(A::*)()); + TEST(void(A::*)() const); + TEST(void(A::*)() volatile); + TEST(void(A::*)() const volatile); + +#endif + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + + TEST(void(A::*)() &); + TEST(void(A::*)() const &&); + +#endif + +#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) + + TEST(void(A::*)() volatile & noexcept); + TEST(void(A::*)() const volatile && noexcept); + +#endif + #if !defined(BOOST_NO_CXX11_NULLPTR) TEST(std::nullptr_t); @@ -130,6 +274,9 @@ int main() TEST(std::pair); TEST(std::pair volatile&); + TEST(std::pair); + TEST(std::pair, void>); + TEST(std::basic_string); TEST(std::string); @@ -151,6 +298,8 @@ int main() TEST(X); TEST(X volatile&); + TEST(X, void>); + TEST(std::vector); TEST(std::vector); TEST(std::vector); @@ -191,6 +340,23 @@ int main() TEST(std::array); TEST(std::array const&); +#endif + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && ( !defined(BOOST_MSVC) || BOOST_MSVC >= 1700 ) + + TEST(std::tuple<>); + TEST(std::tuple); + TEST(std::tuple); + TEST(std::tuple); + + TEST(std::tuple); + TEST(std::tuple); + TEST(std::tuple); + + TEST(std::tuple, void>); + + TEST(X, void>); + #endif TEST(std::ostream); diff --git a/test/uncaught_exceptions.cpp b/test/uncaught_exceptions.cpp index d8b1fc6..c5d7958 100644 --- a/test/uncaught_exceptions.cpp +++ b/test/uncaught_exceptions.cpp @@ -18,6 +18,10 @@ #include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + struct my_exception {}; class exception_watcher diff --git a/test/uncaught_exceptions_np.cpp b/test/uncaught_exceptions_np.cpp index 7498ccf..f60aef1 100644 --- a/test/uncaught_exceptions_np.cpp +++ b/test/uncaught_exceptions_np.cpp @@ -20,6 +20,10 @@ #include +#if defined(_MSC_VER) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + struct my_exception1 {}; struct my_exception2 {}; diff --git a/test/underlying_type.cpp b/test/underlying_type.cpp index 0823f58..27bc4f9 100644 --- a/test/underlying_type.cpp +++ b/test/underlying_type.cpp @@ -15,9 +15,13 @@ #include #include #include -#include +#include #include +#if defined(_MSC_VER) +# pragma warning(disable: 4244) // conversion from enum_type to underlying_type +#endif + BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(emulated_enum, unsigned char) { value0, @@ -59,9 +63,9 @@ struct underlying_type< native_enum > int main(int, char*[]) { - BOOST_TEST_TRAIT_TRUE((boost::core::is_same< boost::underlying_type< emulated_enum >::type, unsigned char >)); + BOOST_TEST_TRAIT_TRUE((boost::is_same< boost::underlying_type< emulated_enum >::type, unsigned char >)); #if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) - BOOST_TEST_TRAIT_TRUE((boost::core::is_same< boost::underlying_type< native_enum >::type, unsigned short >)); + BOOST_TEST_TRAIT_TRUE((boost::is_same< boost::underlying_type< native_enum >::type, unsigned short >)); #endif return boost::report_errors(); diff --git a/test/use_default_test.cpp b/test/use_default_test.cpp index adf1da6..69e6e68 100644 --- a/test/use_default_test.cpp +++ b/test/use_default_test.cpp @@ -11,5 +11,5 @@ Distributed under the Boost Software License, Version 1.0. template struct type { }; -template class type; -template class type; +template struct type; +template struct type; diff --git a/test/verbose_terminate_handler_fail.cpp b/test/verbose_terminate_handler_fail.cpp new file mode 100644 index 0000000..31c6bc4 --- /dev/null +++ b/test/verbose_terminate_handler_fail.cpp @@ -0,0 +1,50 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +# pragma warning(disable: 4530) // C++ exception handler used +# pragma warning(disable: 4577) // 'noexcept' used +#endif + +#include +#include +#include +#include +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) +# include +#endif + +int main() +{ +#if defined(_MSC_VER) && (_MSC_VER > 1310) + // disable message boxes on assert(), abort() + ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); +#endif +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG) + // disable message boxes on iterator debugging violations + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); +#endif + + std::set_terminate( boost::core::verbose_terminate_handler ); + + boost::throw_with_location( std::exception() ); +} + +#if defined(BOOST_NO_EXCEPTIONS) + +void boost::throw_exception( std::exception const& x ) +{ + std::fprintf( stderr, "throw_exception: %s\n\n", x.what() ); + std::terminate(); +} + +void boost::throw_exception( std::exception const& x, boost::source_location const& ) +{ + std::fprintf( stderr, "throw_exception: %s\n\n", x.what() ); + std::terminate(); +} + +#endif diff --git a/test/visit_each_test.cpp b/test/visit_each_test.cpp index 726188e..d1fcc3c 100644 --- a/test/visit_each_test.cpp +++ b/test/visit_each_test.cpp @@ -34,7 +34,7 @@ struct V { } - template< class T > void operator()( T const & t ) + template< class T > void operator()( T const & /*t*/ ) { } @@ -45,7 +45,7 @@ struct V void operator()( std::string const & w ) { - s_ = s_ * 10 + w.size(); + s_ = s_ * 10 + static_cast( w.size() ); } };