From 10237b8761d9c9c0ce54bdb68895e95c73cea817 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 7 May 2024 22:19:48 +0200 Subject: [PATCH] Update vendored vtzero dependency to v1.1.0 (#6871) --- scripts/update_dependencies.sh | 4 +- third_party/vtzero/.clang-tidy | 16 +- third_party/vtzero/.travis.yml | 176 +- third_party/vtzero/CHANGELOG.md | 47 +- third_party/vtzero/CMakeLists.txt | 8 +- third_party/vtzero/README.md | 2 +- third_party/vtzero/appveyor.yml | 5 - third_party/vtzero/build-appveyor.bat | 11 +- third_party/vtzero/doc/Doxyfile.in | 4 +- third_party/vtzero/doc/advanced.md | 4 +- third_party/vtzero/doc/reading.md | 4 +- third_party/vtzero/doc/writing.md | 28 +- third_party/vtzero/examples/vtzero-create.cpp | 164 +- .../vtzero/examples/vtzero-encode-geom.cpp | 2 + third_party/vtzero/examples/vtzero-filter.cpp | 137 +- third_party/vtzero/examples/vtzero-show.cpp | 4 +- third_party/vtzero/examples/vtzero-stats.cpp | 26 +- .../vtzero/examples/vtzero-streets.cpp | 8 +- third_party/vtzero/include/vtzero/builder.hpp | 151 +- .../vtzero/include/vtzero/builder_impl.hpp | 91 +- third_party/vtzero/include/vtzero/feature.hpp | 13 + .../include/vtzero/feature_builder_impl.hpp | 8 + .../vtzero/include/vtzero/geometry.hpp | 6 +- third_party/vtzero/include/vtzero/layer.hpp | 30 +- third_party/vtzero/include/vtzero/types.hpp | 17 +- third_party/vtzero/include/vtzero/version.hpp | 6 +- third_party/vtzero/test/catch/catch.hpp | 24446 ++++++++++------ third_party/vtzero/test/fixture_tests.cpp | 86 +- third_party/vtzero/test/include/test.hpp | 3 + third_party/vtzero/test/mvt-fixtures | 1 + third_party/vtzero/test/t/test_builder.cpp | 235 +- .../vtzero/test/t/test_builder_linestring.cpp | 12 +- .../vtzero/test/t/test_builder_point.cpp | 18 +- .../vtzero/test/t/test_builder_polygon.cpp | 22 +- third_party/vtzero/test/t/test_geometry.cpp | 20 +- .../test/t/test_geometry_linestring.cpp | 14 +- .../vtzero/test/t/test_geometry_point.cpp | 12 +- .../vtzero/test/t/test_geometry_polygon.cpp | 14 +- third_party/vtzero/test/t/test_index.cpp | 8 +- third_party/vtzero/test/t/test_layer.cpp | 18 +- .../vtzero/test/t/test_property_value.cpp | 16 +- third_party/vtzero/test/t/test_types.cpp | 2 +- third_party/vtzero/test/test_main.cpp | 4 +- 43 files changed, 16229 insertions(+), 9674 deletions(-) create mode 160000 third_party/vtzero/test/mvt-fixtures diff --git a/scripts/update_dependencies.sh b/scripts/update_dependencies.sh index 3a8afe370..2baedbaea 100755 --- a/scripts/update_dependencies.sh +++ b/scripts/update_dependencies.sh @@ -28,10 +28,10 @@ PROTOZERO_PATH="mapbox/protozero" PROTOZERO_TAG=v1.6.2 VTZERO_PATH="mapbox/vtzero" -VTZERO_TAG=v1.0.1 +VTZERO_TAG=v1.1.0 FMT_PATH="fmtlib/fmt" -FMT_TAG=v9.1.0 +FMT_TAG=v10.2.1 function update_subtree () { name=${1^^} diff --git a/third_party/vtzero/.clang-tidy b/third_party/vtzero/.clang-tidy index f75b2822c..9b1d2e3d2 100644 --- a/third_party/vtzero/.clang-tidy +++ b/third_party/vtzero/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: '*,-cert-dcl21-cpp,-cert-err60-cpp,-clang-analyzer-core.CallAndMessage,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-fuchsia-*,-google-runtime-references,-hicpp-no-array-decay,-readability-avoid-const-params-in-decls,-readability-implicit-bool-cast,-readability-implicit-bool-conversion' +Checks: '*,-cert-dcl21-cpp,-cert-err60-cpp,-clang-analyzer-core.CallAndMessage,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-non-private-member-variables-in-classes,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-fuchsia-*,-google-runtime-references,-hicpp-no-array-decay,-hicpp-vararg,-misc-non-private-member-variables-in-classes,-modernize-use-trailing-return-type,-readability-avoid-const-params-in-decls,-readability-implicit-bool-cast,-readability-implicit-bool-conversion,-readability-magic-numbers' # # Disabled checks: # @@ -12,6 +12,14 @@ Checks: '*,-cert-dcl21-cpp,-cert-err60-cpp,-clang-analyzer-core.CallAndMessage,- # clang-analyzer-core.CallAndMessage # Produces false positives # +# cppcoreguidelines-avoid-magic-numbers +# readability-magic-numbers +# Not wrong, but many tests just have those +# +# cppcoreguidelines-non-private-member-variables-in-classes +# misc-non-private-member-variables-in-classes +# Can be useful, we use it for some mock classes in tests for instance +# # cppcoreguidelines-owning-memory # Don't want to add dependency on gsl library. # @@ -31,6 +39,12 @@ Checks: '*,-cert-dcl21-cpp,-cert-err60-cpp,-clang-analyzer-core.CallAndMessage,- # hicpp-no-array-decay # Limited use and many false positives including for all asserts. # +# hicpp-vararg +# False positives from Catch2 +# +# modernize-use-trailing-return-type +# We are not that modern. +# # readability-avoid-const-params-in-decls # Inconsistently complaines about some cases but not others. It is nice # to have const in parameters if we don't change them just like with any diff --git a/third_party/vtzero/.travis.yml b/third_party/vtzero/.travis.yml index 8da323b3f..6be32fc6d 100644 --- a/third_party/vtzero/.travis.yml +++ b/third_party/vtzero/.travis.yml @@ -8,8 +8,6 @@ language: generic sudo: false -dist: trusty - #----------------------------------------------------------------------------- # Save common build configurations as shortcuts, so we can reference them later. @@ -33,11 +31,20 @@ addons_shortcuts: addons_clang50: &clang50 apt: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0' ] - packages: [ 'libboost1.55-dev', 'clang-5.0', 'clang-tidy-5.0' ] + packages: [ 'libboost1.55-dev', 'clang-5.0' ] addons_clang60: &clang60 apt: sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0' ] - packages: [ 'libboost1.55-dev', 'clang-6.0', 'clang-tidy-6.0' ] + packages: [ 'libboost1.55-dev', 'clang-6.0' ] + addons_clang7: &clang7 + apt: + packages: [ 'libboost-dev', 'clang-7' ] + addons_clang8: &clang8 + apt: + packages: [ 'libboost-dev', 'clang-8' ] + addons_clang9: &clang9 + apt: + packages: [ 'libboost-dev', 'clang-9', 'clang-tidy-9' ] addons_gcc48: &gcc48 apt: sources: [ 'ubuntu-toolchain-r-test' ] @@ -54,99 +61,192 @@ addons_shortcuts: apt: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'libboost1.55-dev', 'g++-6', 'gcc-6' ] + addons_gcc7: &gcc7 + apt: + packages: [ 'libboost-dev' ] + addons_gcc8: &gcc8 + apt: + packages: [ 'libboost-dev', 'g++-8', 'gcc-8' ] + #----------------------------------------------------------------------------- -matrix: +jobs: include: - os: linux + dist: trusty compiler: "clang-3.5" env: BUILD='Debug' CC=clang-3.5 CXX=clang++-3.5 addons: *clang35 - os: linux + dist: trusty compiler: "clang-3.8" env: BUILD='Debug' CC=clang-3.8 CXX=clang++-3.8 addons: *clang38 - os: linux + dist: trusty compiler: "clang-3.9" env: BUILD='Debug' CC=clang-3.9 CXX=clang++-3.9 addons: *clang39 - os: linux + dist: trusty compiler: "clang-4.0" env: BUILD='Debug' CC=clang-4.0 CXX=clang++-4.0 addons: *clang40 - os: linux + dist: trusty compiler: "clang-5.0" env: BUILD='Debug' CC=clang-5.0 CXX=clang++-5.0 - CLANG_TIDY=clang-tidy-5.0 - addons: *clang50 - - os: linux - compiler: "clang-5.0" - env: BUILD='Release' CC=clang-5.0 CXX=clang++-5.0 - addons: *clang50 - - os: linux - compiler: "clang-5.0" - env: BUILD='Debug' CC=clang-5.0 CXX=clang++-5.0 - CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer" - LDFLAGS="-fsanitize=address,undefined,integer" - # LSAN doesn't work on container-based system - sudo: required addons: *clang50 - os: linux + dist: trusty compiler: "clang-6.0" env: BUILD='Debug' CC=clang-6.0 CXX=clang++-6.0 addons: *clang60 - os: linux + dist: bionic + compiler: "clang-7" + env: BUILD='Debug' CC=clang-7 CXX=clang++-7 + addons: *clang7 + - os: linux + dist: bionic + compiler: "clang-8" + env: BUILD='Debug' CC=clang-8 CXX=clang++-8 + addons: *clang8 + - os: linux + dist: bionic + compiler: "clang-9" + env: BUILD='Debug' CC=clang-9 CXX=clang++-9 + CLANG_TIDY=clang-tidy-9 + addons: *clang9 + - os: linux + dist: bionic + compiler: "clang-9" + env: BUILD='Release' CC=clang-9 CXX=clang++-9 + addons: *clang9 + - os: linux + dist: bionic + compiler: "clang-9" + env: BUILD='Debug' CC=clang-9 CXX=clang++-9 + CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer" + LDFLAGS="-fsanitize=address,undefined,integer" + # LSAN doesn't work on container-based system + sudo: required + addons: *clang9 + + - os: linux + arch: arm64 + dist: bionic + compiler: "clang-9" + env: BUILD='Debug' CC=clang-9 CXX=clang++-9 + CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer" + LDFLAGS="-fsanitize=address,undefined,integer" + # LSAN doesn't work on container-based system + sudo: required + addons: *clang9 + - os: linux + arch: ppc64le + dist: bionic + compiler: "clang-9" + env: BUILD='Debug' CC=clang-9 CXX=clang++-9 + CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer" + LDFLAGS="-fsanitize=address,undefined,integer" + # LSAN doesn't work on container-based system + sudo: required + addons: *clang9 + - os: linux + arch: s390x + dist: bionic + compiler: "clang-9" + env: BUILD='Debug' CC=clang-9 CXX=clang++-9 + CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer" + LDFLAGS="-fsanitize=address,undefined,integer" + # LSAN doesn't work on container-based system + sudo: required + addons: *clang9 + + - os: linux + dist: trusty compiler: "gcc-4.8" env: BUILD='Debug' CC=gcc-4.8 CXX=g++-4.8 addons: *gcc48 - os: linux - compiler: "gcc-4.9" - env: BUILD='Debug' CC=gcc-4.9 CXX=g++-4.9 - COVERAGE=gcov-4.9 - CXXFLAGS="--coverage" LDFLAGS="--coverage" - addons: *gcc49 - - os: linux + dist: trusty compiler: "gcc-5" env: BUILD='Debug' CC=gcc-5 CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" addons: *gcc5 - os: linux + dist: trusty compiler: "gcc-5" env: BUILD='Debug' CC=gcc-5 CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=1" addons: *gcc5 - os: linux + dist: trusty compiler: "gcc-6" env: BUILD='Debug' CC=gcc-6 CXX=g++-6 addons: *gcc6 - os: linux - compiler: "gcc-6" - env: BUILD='Debug' CC=gcc-6 CXX=g++-6 + dist: bionic + compiler: "gcc-7" + env: BUILD='Debug' CC=gcc-7 CXX=g++-7 + addons: *gcc7 + - os: linux + dist: bionic + compiler: "gcc-8" + env: BUILD='Debug' CC=gcc-8 CXX=g++-8 + COVERAGE=gcov-8 + CXXFLAGS="--coverage" LDFLAGS="--coverage" + addons: *gcc8 + - os: linux + dist: bionic + compiler: "gcc-8" + env: BUILD='Debug' CC=gcc-8 CXX=g++-8 PROTOZERO_DATA_VIEW=std::experimental::string_view - addons: *gcc6 + addons: *gcc8 - os: linux - compiler: "gcc-6" - env: BUILD='Release' CC=gcc-6 CXX=g++-6 - addons: *gcc6 + dist: bionic + compiler: "gcc-8" + env: BUILD='Release' CC=gcc-8 CXX=g++-8 + addons: *gcc8 + + - os: linux + arch: arm64 + dist: bionic + compiler: "gcc-8" + env: BUILD='Debug' CC=gcc-8 CXX=g++-8 + addons: *gcc8 + + - os: linux + arch: ppc64le + dist: bionic + compiler: "gcc-8" + env: BUILD='Debug' CC=gcc-8 CXX=g++-8 + addons: *gcc8 + +# Fails with out of memory error +# - os: linux +# arch: s390x +# dist: bionic +# compiler: "gcc-8" +# env: BUILD='Debug' CC=gcc-8 CXX=g++-8 +# addons: *gcc8 + - os: osx - osx_image: xcode6.4 + osx_image: xcode9.4 compiler: clang env: BUILD='Debug' - os: osx - osx_image: xcode7.3 + osx_image: xcode10.3 compiler: clang env: BUILD='Debug' - os: osx - osx_image: xcode8.3 + osx_image: xcode11.4 compiler: clang env: BUILD='Debug' - os: osx - osx_image: xcode9.1 - compiler: clang - env: BUILD='Debug' - - os: osx - osx_image: xcode9.1 + osx_image: xcode11.4 compiler: clang env: BUILD='Release' diff --git a/third_party/vtzero/CHANGELOG.md b/third_party/vtzero/CHANGELOG.md index 7c4cae19c..94a122fc9 100644 --- a/third_party/vtzero/CHANGELOG.md +++ b/third_party/vtzero/CHANGELOG.md @@ -14,6 +14,47 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Fixed +## [1.1.0] - 2020-06-11 + +### Changed + +* Now needs protozero 1.7.0 or above. +* Use `protozero::basic_pbf_builder` to make buffer type configurable. This + allows you to create the final vector tile in any type of buffer, not just + `std::string`. See documentation for details. +* Switch to catch2 for testing. + +### Fixed + +* Examples `vtzero-create` and `vtzero-streets` now commit features written. +* Various fixes and small cleanups, mostly based on clang-tidy reports. + + +## [1.0.3] - 2018-07-17 + +### Added + +* New `copy_id()` helper function on feature builder copies ID (if it exists) + from an existing feature. +* New `copy_properties()` helper funtion on feature builder copies all + properties from an existing feature, optionally using a `property_mapper`. +* New `feature::for_each_property_indexes()` member function. + +### Fixed + +* The example program `vtzero-stats` now catches exceptions and exists with + an error message. +* Fix an assert where a wrong iterator was checked. + + +## [1.0.2] - 2018-06-26 + +### Fixed + +* `layer_builder::add_feature()` did not work, because it didn't commit + the features it added. + + ## [1.0.1] - 2018-04-12 ### Added @@ -37,8 +78,12 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [1.0.0] - 2018-03-09 -First release +First release [unreleased]: https://github.com/osmcode/libosmium/compare/v1.1.0...HEAD +[1.1.0]: https://github.com/osmcode/libosmium/compare/v1.0.3...v1.1.0 +[1.0.3]: https://github.com/osmcode/libosmium/compare/v1.0.2...v1.0.3 +[1.0.2]: https://github.com/osmcode/libosmium/compare/v1.0.1...v1.0.2 +[1.0.1]: https://github.com/osmcode/libosmium/compare/v1.0.0...v1.0.1 diff --git a/third_party/vtzero/CMakeLists.txt b/third_party/vtzero/CMakeLists.txt index 5e6609295..57cbed529 100644 --- a/third_party/vtzero/CMakeLists.txt +++ b/third_party/vtzero/CMakeLists.txt @@ -15,8 +15,8 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") project(vtzero) set(VTZERO_VERSION_MAJOR 1) -set(VTZERO_VERSION_MINOR 0) -set(VTZERO_VERSION_PATCH 1) +set(VTZERO_VERSION_MINOR 1) +set(VTZERO_VERSION_PATCH 0) set(VTZERO_VERSION "${VTZERO_VERSION_MAJOR}.${VTZERO_VERSION_MINOR}.${VTZERO_VERSION_PATCH}") @@ -62,7 +62,7 @@ endif() # #----------------------------------------------------------------------------- -find_package(Protozero 1.6.0 REQUIRED) +find_package(Protozero 1.7.0 REQUIRED) include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR}) @@ -75,7 +75,7 @@ find_package(Boost) # #----------------------------------------------------------------------------- message(STATUS "Looking for clang-tidy") -find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-6.0 clang-tidy-5.0) +find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-10 clang-tidy-9 clang-tidy-8 clang-tidy-7 clang-tidy-6.0 clang-tidy-5.0) if(CLANG_TIDY) message(STATUS "Looking for clang-tidy - found ${CLANG_TIDY}") diff --git a/third_party/vtzero/README.md b/third_party/vtzero/README.md index ef62c5a09..52500e460 100644 --- a/third_party/vtzero/README.md +++ b/third_party/vtzero/README.md @@ -13,7 +13,7 @@ Implements the [Mapbox Vector Tile Specification 2.x](https://www.mapbox.com/vec * C++11 compiler (GCC 4.8 or higher, clang 3.5 or higher, ...) * CMake -* [Protozero](https://github.com/mapbox/protozero) version >= 1.6.0 +* [Protozero](https://github.com/mapbox/protozero) version >= 1.7.0 ## Build diff --git a/third_party/vtzero/appveyor.yml b/third_party/vtzero/appveyor.yml index 24b560798..6b469d4cb 100644 --- a/third_party/vtzero/appveyor.yml +++ b/third_party/vtzero/appveyor.yml @@ -52,10 +52,5 @@ build_script: build-appveyor.bat ) -# remove garbage VS messages -# https://help.appveyor.com/discussions/problems/4569-the-target-_convertpdbfiles-listed-in-a-beforetargets-attribute-at-c-does-not-exist-in-the-project-and-will-be-ignored -before_build: - - del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" - #----------------------------------------------------------------------------- diff --git a/third_party/vtzero/build-appveyor.bat b/third_party/vtzero/build-appveyor.bat index 7a572e89b..39e59cae1 100644 --- a/third_party/vtzero/build-appveyor.bat +++ b/third_party/vtzero/build-appveyor.bat @@ -9,7 +9,7 @@ SET ECHO cmake on AppVeyor cmake -version -ECHO activating VS cmd prompt && CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 +ECHO activating VS cmd prompt && CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" IF %ERRORLEVEL% NEQ 0 GOTO ERROR IF EXIST build ECHO deleting build dir... && RD /Q /S build @@ -21,11 +21,8 @@ IF %ERRORLEVEL% NEQ 0 GOTO ERROR CD build ECHO config^: %config% -::This will produce lots of LNK4099 warnings which can be ignored. -::Unfortunately they can't be disabled, see -::https://stackoverflow.com/questions/661606/visual-c-how-to-disable-specific-linker-warnings SET CMAKE_CMD=cmake .. ^ --LA -G "Visual Studio 14 Win64" +-LA -G "Visual Studio 15 2017 Win64" ECHO calling^: %CMAKE_CMD% %CMAKE_CMD% @@ -36,9 +33,7 @@ IF /I "%APPVEYOR%"=="True" SET avlogger=/logger:"C:\Program Files\AppVeyor\Build msbuild vtzero.sln ^ /p:Configuration=%config% ^ -/toolsversion:14.0 ^ -/p:Platform=x64 ^ -/p:PlatformToolset=v140 %avlogger% +%avlogger% IF %ERRORLEVEL% NEQ 0 GOTO ERROR ctest --output-on-failure ^ diff --git a/third_party/vtzero/doc/Doxyfile.in b/third_party/vtzero/doc/Doxyfile.in index 374c717f8..b90edcbb3 100644 --- a/third_party/vtzero/doc/Doxyfile.in +++ b/third_party/vtzero/doc/Doxyfile.in @@ -2044,7 +2044,7 @@ EXTERNAL_PAGES = YES # interpreter (i.e. the result of 'which perl'). # The default file (with absolute path) is: /usr/bin/perl. -PERL_PATH = /usr/bin/perl +#PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool @@ -2066,7 +2066,7 @@ CLASS_DIAGRAMS = YES # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. -MSCGEN_PATH = +#MSCGEN_PATH = # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The diff --git a/third_party/vtzero/doc/advanced.md b/third_party/vtzero/doc/advanced.md index 47126020f..8f0b5013e 100644 --- a/third_party/vtzero/doc/advanced.md +++ b/third_party/vtzero/doc/advanced.md @@ -65,9 +65,7 @@ while (auto feature = layer.next_feature()) { if (keep_feature(feature)) { // instantiate a feature builder as usual and copy id and geometry vtzero::geometry_feature_builder feature_builder{layer_builder}; - if (feature.has_id()) { - feature_builder.set_id(feature.id()); - } + feature_builder.copy_id(feature); feature_builder.set_geometry(feature.geometry()); // now iterate over all properties... diff --git a/third_party/vtzero/doc/reading.md b/third_party/vtzero/doc/reading.md index 4006024e9..e4336b07e 100644 --- a/third_party/vtzero/doc/reading.md +++ b/third_party/vtzero/doc/reading.md @@ -210,8 +210,8 @@ converted into whatever type the value really has. ```cpp auto property = ...; -std::string pkey = property.key(); // returns a vtzero::data_view which can - // be converted to std::string +auto pkey = std::string(property.key()); // returns a vtzero::data_view which can + // be converted to std::string property_value pvalue = property.value(); ``` diff --git a/third_party/vtzero/doc/writing.md b/third_party/vtzero/doc/writing.md index 72200c7c2..39fb09b5a 100644 --- a/third_party/vtzero/doc/writing.md +++ b/third_party/vtzero/doc/writing.md @@ -140,7 +140,7 @@ you can create your own overload of this function. See the ### Adding a multipoint geometry -Call `add_points()` with the number of points in the geometry as only argument. +Call `add_points()` with the number of points in the geometry as the only argument. After that call `set_point()` for each of those points. `set_point()` has multiple overloads just like the `add_point()` method described above. @@ -537,3 +537,29 @@ own functions (for instance when you need to convert from your own types to vtzero types like with the `mylocation` and `stars` types above) or just use the functions in the base classes. +## Using a custom buffer type + +Usually `std::string` is used as a buffer type: + +```cpp +std::string buffer; +tbuilder.serialize(buffer); +``` + +But you can also use other buffer types supported by Protozero, like +`std::vector`: + +```cpp +#include + +std::vector buffer; +tbuilder.serialize(buffer); +``` + +Or you can use your own buffer types and write special adaptors for it. +See the Protozero documentation for details. + +Note that while in theory this allows you to also use fixed-sized buffers +through the `protozero::fixed_sized_buffer_adaptor` class, vtzero will still +use `std::string` for additional buffers internally. + diff --git a/third_party/vtzero/examples/vtzero-create.cpp b/third_party/vtzero/examples/vtzero-create.cpp index 6507ff6fb..c0a81244d 100644 --- a/third_party/vtzero/examples/vtzero-create.cpp +++ b/third_party/vtzero/examples/vtzero-create.cpp @@ -17,85 +17,97 @@ #include int main() { - vtzero::tile_builder tile; - vtzero::layer_builder layer_points{tile, "points"}; - vtzero::layer_builder layer_lines{tile, "lines"}; - vtzero::layer_builder layer_polygons{tile, "polygons"}; + try { + vtzero::tile_builder tile; + vtzero::layer_builder layer_points{tile, "points"}; + vtzero::layer_builder layer_lines{tile, "lines"}; + vtzero::layer_builder layer_polygons{tile, "polygons"}; - vtzero::key_index idx{layer_points}; + vtzero::key_index idx{layer_points}; - { - vtzero::point_feature_builder feature{layer_points}; - feature.set_id(1); - feature.add_points(1); - feature.set_point(10, 10); - feature.add_property("foo", "bar"); - feature.add_property("x", "y"); - feature.rollback(); + { + vtzero::point_feature_builder feature{layer_points}; + feature.set_id(1); + feature.add_points(1); + feature.set_point(10, 10); + feature.add_property("foo", "bar"); + feature.add_property("x", "y"); + feature.rollback(); + } + + const auto some = idx("some"); + + { + vtzero::point_feature_builder feature{layer_points}; + feature.set_id(2); + feature.add_point(20, 20); + feature.add_property(some, "attr"); + feature.commit(); + } + { + vtzero::point_feature_builder feature{layer_points}; + feature.set_id(3); + feature.add_point(20, 20); + feature.add_property(idx("some"), "attr"); + feature.commit(); + } + + { + vtzero::point_feature_builder feature{layer_points}; + feature.set_id(4); + feature.add_point(20, 20); + feature.add_property(idx("some"), "otherattr"); + feature.commit(); + } + + + vtzero::point_feature_builder feature1{layer_points}; + feature1.set_id(5); + feature1.add_point(vtzero::point{20, 20}); + feature1.add_property("otherkey", "attr"); + feature1.commit(); + + vtzero::value_index maxspeed_index{layer_lines}; + { + vtzero::linestring_feature_builder feature{layer_lines}; + feature.set_id(6); + feature.add_linestring(3); + feature.set_point(10, 10); + feature.set_point(10, 20); + feature.set_point(vtzero::point{20, 20}); + std::vector points = {{11, 11}, {12, 13}}; + feature.add_linestring_from_container(points); + feature.add_property("highway", "primary"); + feature.add_property(std::string{"maxspeed"}, maxspeed_index(50)); + feature.commit(); + } + + { + vtzero::polygon_feature_builder feature{layer_polygons}; + feature.set_id(7); + feature.add_ring(5); + feature.set_point(0, 0); + feature.set_point(10, 0); + feature.set_point(10, 10); + feature.set_point(0, 10); + feature.set_point(0, 0); + feature.add_ring(4); + feature.set_point(3, 3); + feature.set_point(3, 5); + feature.set_point(5, 5); + feature.close_ring(); + feature.add_property("natural", "wood"); + feature.add_property("number_of_trees", vtzero::sint_value_type{23402752}); + feature.commit(); + } + + const auto data = tile.serialize(); + write_data_to_file(data, "test.mvt"); + } catch (const std::exception& e) { + std::cerr << "Fatal error: " << e.what() << '\n'; + return 1; } - const auto some = idx("some"); - - { - vtzero::point_feature_builder feature{layer_points}; - feature.set_id(2); - feature.add_point(20, 20); - feature.add_property(some, "attr"); - } - { - vtzero::point_feature_builder feature{layer_points}; - feature.set_id(3); - feature.add_point(20, 20); - feature.add_property(idx("some"), "attr"); - } - - { - vtzero::point_feature_builder feature{layer_points}; - feature.set_id(4); - feature.add_point(20, 20); - feature.add_property(idx("some"), "otherattr"); - } - - - vtzero::point_feature_builder feature1{layer_points}; - feature1.set_id(5); - feature1.add_point(vtzero::point{20, 20}); - feature1.add_property("otherkey", "attr"); - feature1.commit(); - - vtzero::value_index maxspeed_index{layer_lines}; - { - vtzero::linestring_feature_builder feature{layer_lines}; - feature.set_id(6); - feature.add_linestring(3); - feature.set_point(10, 10); - feature.set_point(10, 20); - feature.set_point(vtzero::point{20, 20}); - std::vector points = {{11, 11}, {12, 13}}; - feature.add_linestring_from_container(points); - feature.add_property("highway", "primary"); - feature.add_property(std::string{"maxspeed"}, maxspeed_index(50)); - } - - { - vtzero::polygon_feature_builder feature{layer_polygons}; - feature.set_id(7); - feature.add_ring(5); - feature.set_point(0, 0); - feature.set_point(10, 0); - feature.set_point(10, 10); - feature.set_point(0, 10); - feature.set_point(0, 0); - feature.add_ring(4); - feature.set_point(3, 3); - feature.set_point(3, 5); - feature.set_point(5, 5); - feature.close_ring(); - feature.add_property("natural", "wood"); - feature.add_property("number_of_trees", vtzero::sint_value_type{23402752}); - } - - const auto data = tile.serialize(); - write_data_to_file(data, "test.mvt"); + return 0; } diff --git a/third_party/vtzero/examples/vtzero-encode-geom.cpp b/third_party/vtzero/examples/vtzero-encode-geom.cpp index fa7d7840b..60200ce9e 100644 --- a/third_party/vtzero/examples/vtzero-encode-geom.cpp +++ b/third_party/vtzero/examples/vtzero-encode-geom.cpp @@ -138,5 +138,7 @@ int main(int argc, char* argv[]) { out.back() = ' '; std::cout << '\n' << out << "]\n"; + + return 0; } diff --git a/third_party/vtzero/examples/vtzero-filter.cpp b/third_party/vtzero/examples/vtzero-filter.cpp index b0ec6c24b..e09f8d53c 100644 --- a/third_party/vtzero/examples/vtzero-filter.cpp +++ b/third_party/vtzero/examples/vtzero-filter.cpp @@ -21,81 +21,88 @@ #include int main(int argc, char* argv[]) { - std::string filename; - std::string layer_num_or_name; - std::string idstr; - std::string output_file{"filtered.mvt"}; + try { + std::string filename; + std::string layer_num_or_name; + std::string idstr; + std::string output_file{"filtered.mvt"}; - bool help = false; + bool help = false; - const auto cli - = clara::Opt(output_file, "FILE") - ["-o"]["--output"] - ("write output to FILE") - | clara::Help(help) - | clara::Arg(filename, "FILENAME").required() - ("vector tile") - | clara::Arg(layer_num_or_name, "LAYER-NUM|LAYER-NAME").required() - ("layer") - | clara::Arg(idstr, "ID") - ("feature_id"); + const auto cli + = clara::Opt(output_file, "FILE") + ["-o"]["--output"] + ("write output to FILE") + | clara::Help(help) + | clara::Arg(filename, "FILENAME").required() + ("vector tile") + | clara::Arg(layer_num_or_name, "LAYER-NUM|LAYER-NAME").required() + ("layer") + | clara::Arg(idstr, "ID") + ("feature_id"); - const auto result = cli.parse(clara::Args(argc, argv)); - if (!result) { - std::cerr << "Error in command line: " << result.errorMessage() << '\n'; - return 1; - } - - if (help) { - std::cout << cli - << "\nFilter contents of vector tile.\n"; - return 0; - } - - if (filename.empty()) { - std::cerr << "Error in command line: Missing file name of vector tile to read\n"; - return 1; - } - - if (layer_num_or_name.empty()) { - std::cerr << "Error in command line: Missing layer number or name\n"; - return 1; - } - - const auto data = read_file(filename); - vtzero::vector_tile tile{data}; - - auto layer = get_layer(tile, layer_num_or_name); - std::cerr << "Found layer: " << std::string(layer.name()) << "\n"; - - vtzero::tile_builder tb; - - if (idstr.empty()) { - tb.add_existing_layer(layer); - } else { - char* str_end = nullptr; - const int64_t id = std::strtoll(idstr.c_str(), &str_end, 10); - if (str_end != idstr.c_str() + idstr.size()) { - std::cerr << "Feature ID must be numeric.\n"; - return 1; - } - if (id < 0) { - std::cerr << "Feature ID must be >= 0.\n"; + const auto result = cli.parse(clara::Args(argc, argv)); + if (!result) { + std::cerr << "Error in command line: " << result.errorMessage() << '\n'; return 1; } - const auto feature = layer.get_feature_by_id(static_cast(id)); - if (!feature.valid()) { - std::cerr << "No feature with that id: " << id << '\n'; + if (help) { + std::cout << cli + << "\nFilter contents of vector tile.\n"; + return 0; + } + + if (filename.empty()) { + std::cerr << "Error in command line: Missing file name of vector tile to read\n"; return 1; } - vtzero::layer_builder layer_builder{tb, layer}; - layer_builder.add_feature(feature); + if (layer_num_or_name.empty()) { + std::cerr << "Error in command line: Missing layer number or name\n"; + return 1; + } + + const auto data = read_file(filename); + vtzero::vector_tile tile{data}; + + auto layer = get_layer(tile, layer_num_or_name); + std::cerr << "Found layer: " << std::string(layer.name()) << "\n"; + + vtzero::tile_builder tb; + + if (idstr.empty()) { + tb.add_existing_layer(layer); + } else { + char* str_end = nullptr; + const int64_t id = std::strtoll(idstr.c_str(), &str_end, 10); + if (str_end != idstr.c_str() + idstr.size()) { + std::cerr << "Feature ID must be numeric.\n"; + return 1; + } + if (id < 0) { + std::cerr << "Feature ID must be >= 0.\n"; + return 1; + } + + const auto feature = layer.get_feature_by_id(static_cast(id)); + if (!feature.valid()) { + std::cerr << "No feature with that id: " << id << '\n'; + return 1; + } + + vtzero::layer_builder layer_builder{tb, layer}; + layer_builder.add_feature(feature); + } + + std::string output = tb.serialize(); + + write_data_to_file(output, output_file); + } catch (const std::exception& e) { + std::cerr << "Fatal error: " << e.what() << '\n'; + return 1; } - std::string output = tb.serialize(); - - write_data_to_file(output, output_file); + return 0; } diff --git a/third_party/vtzero/examples/vtzero-show.cpp b/third_party/vtzero/examples/vtzero-show.cpp index 030fe0f8c..a752a23d6 100644 --- a/third_party/vtzero/examples/vtzero-show.cpp +++ b/third_party/vtzero/examples/vtzero-show.cpp @@ -26,7 +26,7 @@ public: void points_begin(const uint32_t /*count*/) const noexcept { } - void points_point(const vtzero::point point) const { + static void points_point(const vtzero::point point) { std::cout << " POINT(" << point.x << ',' << point.y << ")\n"; } @@ -111,7 +111,7 @@ struct print_value { }; // struct print_value -static void print_layer(vtzero::layer& layer, bool print_tables, bool print_value_types, int& layer_num, int& feature_num) { +static void print_layer(vtzero::layer& layer, bool print_tables, bool print_value_types, int layer_num, int& feature_num) { std::cout << "=============================================================\n" << "layer: " << layer_num << '\n' << " name: " << std::string(layer.name()) << '\n' diff --git a/third_party/vtzero/examples/vtzero-stats.cpp b/third_party/vtzero/examples/vtzero-stats.cpp index bef3173f5..e35fd0964 100644 --- a/third_party/vtzero/examples/vtzero-stats.cpp +++ b/third_party/vtzero/examples/vtzero-stats.cpp @@ -20,17 +20,23 @@ int main(int argc, char* argv[]) { return 1; } - std::string input_file{argv[1]}; - const auto data = read_file(input_file); + try { + std::string input_file{argv[1]}; + const auto data = read_file(input_file); - vtzero::vector_tile tile{data}; + vtzero::vector_tile tile{data}; - while (const auto layer = tile.next_layer()) { - std::cout.write(layer.name().data(), static_cast(layer.name().size())); - std::cout << ' ' - << layer.num_features() << ' ' - << layer.key_table().size() << ' ' - << layer.value_table().size() << '\n'; + while (const auto layer = tile.next_layer()) { + std::cout.write(layer.name().data(), static_cast(layer.name().size())); + std::cout << ' ' + << layer.num_features() << ' ' + << layer.key_table().size() << ' ' + << layer.value_table().size() << '\n'; + } + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << '\n'; + return 1; } -} + return 0; +} diff --git a/third_party/vtzero/examples/vtzero-streets.cpp b/third_party/vtzero/examples/vtzero-streets.cpp index 0406f1d44..2d1dbbef1 100644 --- a/third_party/vtzero/examples/vtzero-streets.cpp +++ b/third_party/vtzero/examples/vtzero-streets.cpp @@ -58,14 +58,14 @@ int main(int argc, char* argv[]) { while (auto feature = layer.next_feature()) { if (keep_feature(feature)) { vtzero::geometry_feature_builder feature_builder{layer_builder}; - if (feature.has_id()) { - feature_builder.set_id(feature.id()); - } + feature_builder.copy_id(feature); feature_builder.set_geometry(feature.geometry()); while (auto idxs = feature.next_property_indexes()) { feature_builder.add_property(mapper(idxs)); } + + feature_builder.commit(); } } @@ -75,5 +75,7 @@ int main(int argc, char* argv[]) { std::cerr << "Error: " << e.what() << '\n'; return 1; } + + return 0; } diff --git a/third_party/vtzero/include/vtzero/builder.hpp b/third_party/vtzero/include/vtzero/builder.hpp index 666d3cb33..9919287ae 100644 --- a/third_party/vtzero/include/vtzero/builder.hpp +++ b/third_party/vtzero/include/vtzero/builder.hpp @@ -22,11 +22,12 @@ documentation. #include "types.hpp" #include "vector_tile.hpp" -#include +#include #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ namespace vtzero { friend class layer_builder; - std::vector> m_layers; + std::vector> m_layers; /** * Add a new layer to the vector tile based on an existing layer. The @@ -63,7 +64,7 @@ namespace vtzero { * existing layer. */ detail::layer_builder_impl* add_layer(const layer& layer) { - const auto ptr = new detail::layer_builder_impl{layer.name(), layer.version(), layer.extent()}; + auto* ptr = new detail::layer_builder_impl{layer.name(), layer.version(), layer.extent()}; m_layers.emplace_back(ptr); return ptr; } @@ -82,7 +83,7 @@ namespace vtzero { */ template detail::layer_builder_impl* add_layer(TString&& name, uint32_t version, uint32_t extent) { - const auto ptr = new detail::layer_builder_impl{std::forward(name), version, extent}; + auto* ptr = new detail::layer_builder_impl{std::forward(name), version, extent}; m_layers.emplace_back(ptr); return ptr; } @@ -116,7 +117,7 @@ namespace vtzero { * layer. */ void add_existing_layer(data_view&& data) { - m_layers.emplace_back(new detail::layer_builder_existing{std::forward(data)}); + m_layers.emplace_back(new detail::layer_builder_impl{std::forward(data)}); } /** @@ -135,17 +136,18 @@ namespace vtzero { * The data will be appended to the specified buffer. The buffer * doesn't have to be empty. * + * @tparam TBuffer Type of buffer. Must be std:string or other buffer + * type supported by protozero. * @param buffer Buffer to append the encoded vector tile to. */ - void serialize(std::string& buffer) const { - std::size_t estimated_size = 0; - for (const auto& layer : m_layers) { - estimated_size += layer->estimated_size(); - } + template + void serialize(TBuffer& buffer) const { + const std::size_t estimated_size = std::accumulate(m_layers.cbegin(), m_layers.cend(), 0ULL, [](std::size_t sum, const std::unique_ptr& layer) { + return sum + layer->estimated_size(); + }); - buffer.reserve(buffer.size() + estimated_size); - - protozero::pbf_builder pbf_tile_builder{buffer}; + protozero::basic_pbf_builder pbf_tile_builder{buffer}; + pbf_tile_builder.reserve(estimated_size); for (const auto& layer : m_layers) { layer->build(pbf_tile_builder); } @@ -156,7 +158,7 @@ namespace vtzero { * and return it. * * If you want to use an existing buffer instead, use the serialize() - * method taking a std::string& as parameter. + * member function taking a TBuffer& as parameter. * * @returns std::string Buffer with encoded vector_tile data. */ @@ -373,7 +375,7 @@ namespace vtzero { /// Helper function to check size isn't too large template uint32_t check_num_points(T size) { - if (size >= (1ul << 29u)) { + if (size >= (1UL << 29U)) { throw geometry_exception{"Maximum of 2^29 - 1 points allowed in geometry"}; } return static_cast(size); @@ -420,7 +422,7 @@ namespace vtzero { * Set the ID of this feature. * * You can only call this method once and it must be before calling - * any other method manipulating the geometry. + * any method manipulating the geometry. * * @param id The ID. */ @@ -430,7 +432,27 @@ namespace vtzero { vtzero_assert(!m_pbf_geometry.valid() && !m_pbf_tags.valid() && "Call set_id() before setting the geometry or adding properties"); - m_feature_writer.add_uint64(detail::pbf_feature::id, id); + set_id_impl(id); + } + + /** + * Copy the ID of an existing feature to this feature. If the + * feature doesn't have an ID, no ID is set. + * + * You can only call this method once and it must be before calling + * any method manipulating the geometry. + * + * @param feature The feature to copy the ID from. + */ + void copy_id(const feature& feature) { + vtzero_assert(m_feature_writer.valid() && + "Can not call copy_id() after commit() or rollback()"); + vtzero_assert(!m_pbf_geometry.valid() && + !m_pbf_tags.valid() && + "Call copy_id() before setting the geometry or adding properties"); + if (feature.has_id()) { + set_id_impl(feature.id()); + } } /** @@ -448,6 +470,41 @@ namespace vtzero { add_property_impl(std::forward(prop)); } + /** + * Copy all properties of an existing feature to the one being built. + * + * @param feature The feature to copy the properties from. + */ + void copy_properties(const feature& feature) { + vtzero_assert(m_feature_writer.valid() && + "Can not call copy_properties() after commit() or rollback()"); + prepare_to_add_property(); + feature.for_each_property([this](const property& prop) { + add_property_impl(prop); + return true; + }); + } + + /** + * Copy all properties of an existing feature to the one being built + * using a property_mapper. + * + * @tparam TMapper Must be the property_mapper class or something + * equivalent. + * @param feature The feature to copy the properties from. + * @param mapper Instance of the property_mapper class. + */ + template + void copy_properties(const feature& feature, TMapper& mapper) { + vtzero_assert(m_feature_writer.valid() && + "Can not call copy_properties() after commit() or rollback()"); + prepare_to_add_property(); + feature.for_each_property_indexes([this, &mapper](const index_value_pair& idxs) { + add_property_impl(mapper(idxs)); + return true; + }); + } + /** * Add a property to this feature. Can only be called after all the * methods manipulating the geometry. @@ -607,7 +664,7 @@ namespace vtzero { "can not call add_points() twice or mix with add_point()"); vtzero_assert(!m_pbf_tags.valid() && "add_points() has to be called before properties are added"); - vtzero_assert(count > 0 && count < (1ul << 29u) && "add_points() must be called with 0 < count < 2^29"); + vtzero_assert(count > 0 && count < (1UL << 29U) && "add_points() must be called with 0 < count < 2^29"); m_num_points.set(count); m_pbf_geometry = {m_feature_writer, detail::pbf_feature::geometry}; m_pbf_geometry.add_element(detail::command_move_to(count)); @@ -750,7 +807,7 @@ namespace vtzero { "Can not add geometry after commit() or rollback()"); vtzero_assert(!m_pbf_tags.valid() && "add_linestring() has to be called before properties are added"); - vtzero_assert(count > 1 && count < (1ul << 29u) && "add_linestring() must be called with 1 < count < 2^29"); + vtzero_assert(count > 1 && count < (1UL << 29U) && "add_linestring() must be called with 1 < count < 2^29"); m_num_points.assert_is_zero(); if (!m_pbf_geometry.valid()) { m_pbf_geometry = {m_feature_writer, detail::pbf_feature::geometry}; @@ -924,7 +981,7 @@ namespace vtzero { "Can not add geometry after commit() or rollback()"); vtzero_assert(!m_pbf_tags.valid() && "add_ring() has to be called before properties are added"); - vtzero_assert(count > 3 && count < (1ul << 29u) && "add_ring() must be called with 3 < count < 2^29"); + vtzero_assert(count > 3 && count < (1UL << 29U) && "add_ring() must be called with 3 < count < 2^29"); m_num_points.assert_is_zero(); if (!m_pbf_geometry.valid()) { m_pbf_geometry = {m_feature_writer, detail::pbf_feature::geometry}; @@ -1152,7 +1209,25 @@ namespace vtzero { vtzero_assert(m_feature_writer.valid() && "Can not call set_id() after commit() or rollback()"); vtzero_assert(!m_pbf_tags.valid()); - m_feature_writer.add_uint64(detail::pbf_feature::id, id); + set_id_impl(id); + } + + /** + * Copy the ID of an existing feature to this feature. If the + * feature doesn't have an ID, no ID is set. + * + * You can only call this function once and it must be before calling + * set_geometry(). + * + * @param feature The feature to copy the ID from. + */ + void copy_id(const feature& feature) { + vtzero_assert(m_feature_writer.valid() && + "Can not call copy_id() after commit() or rollback()"); + vtzero_assert(!m_pbf_tags.valid()); + if (feature.has_id()) { + set_id_impl(feature.id()); + } } /** @@ -1204,6 +1279,39 @@ namespace vtzero { add_property_impl(std::forward(key), std::forward(value)); } + /** + * Copy all properties of an existing feature to the one being built. + * + * @param feature The feature to copy the properties from. + */ + void copy_properties(const feature& feature) { + vtzero_assert(m_feature_writer.valid() && + "Can not call copy_properties() after commit() or rollback()"); + feature.for_each_property([this](const property& prop) { + add_property_impl(prop); + return true; + }); + } + + /** + * Copy all properties of an existing feature to the one being built + * using a property_mapper. + * + * @tparam TMapper Must be the property_mapper class or something + * equivalent. + * @param feature The feature to copy the properties from. + * @param mapper Instance of the property_mapper class. + */ + template + void copy_properties(const feature& feature, TMapper& mapper) { + vtzero_assert(m_feature_writer.valid() && + "Can not call copy_properties() after commit() or rollback()"); + feature.for_each_property_indexes([this, &mapper](const index_value_pair& idxs) { + add_property_impl(mapper(idxs)); + return true; + }); + } + /** * Commit this feature. Call this after all the details of this * feature have been added. If this is not called, the feature @@ -1249,6 +1357,7 @@ namespace vtzero { feature_builder.add_property(p); return true; }); + feature_builder.commit(); } } // namespace vtzero diff --git a/third_party/vtzero/include/vtzero/builder_impl.hpp b/third_party/vtzero/include/vtzero/builder_impl.hpp index 95db484d2..1b348df2d 100644 --- a/third_party/vtzero/include/vtzero/builder_impl.hpp +++ b/third_party/vtzero/include/vtzero/builder_impl.hpp @@ -20,7 +20,7 @@ documentation. #include "property_value.hpp" #include "types.hpp" -#include +#include #include #include @@ -32,27 +32,12 @@ namespace vtzero { namespace detail { - class layer_builder_base { + class layer_builder_impl { - public: - - layer_builder_base() noexcept = default; - - virtual ~layer_builder_base() noexcept = default; - - layer_builder_base(const layer_builder_base&) noexcept = default; - layer_builder_base& operator=(const layer_builder_base&) noexcept = default; - - layer_builder_base(layer_builder_base&&) noexcept = default; - layer_builder_base& operator=(layer_builder_base&&) noexcept = default; - - virtual std::size_t estimated_size() const = 0; - - virtual void build(protozero::pbf_builder& pbf_tile_builder) const = 0; - - }; // class layer_builder_base - - class layer_builder_impl : public layer_builder_base { + // If this layer is copied from an existing layer, this points + // to the data of the original layer. For newly built layers, + // this is empty. + data_view m_data_view{}; // Buffer containing the encoded layer metadata and features std::string m_data; @@ -63,13 +48,16 @@ namespace vtzero { // Buffer containing the encoded values table std::string m_values_data; - protozero::pbf_builder m_pbf_message_layer; - protozero::pbf_builder m_pbf_message_keys; - protozero::pbf_builder m_pbf_message_values; + protozero::pbf_builder m_pbf_message_layer{}; + protozero::pbf_builder m_pbf_message_keys{}; + protozero::pbf_builder m_pbf_message_values{}; // The number of features in the layer std::size_t m_num_features = 0; + // Vector tile spec version + uint32_t m_version = 0; + // The number of keys in the keys table uint32_t m_num_keys = 0; @@ -160,17 +148,24 @@ namespace vtzero { public: + // This layer should be a copy of an existing layer + explicit layer_builder_impl(const data_view data) : + m_data_view(data) { + } + + // This layer is being created from scratch template layer_builder_impl(TString&& name, uint32_t version, uint32_t extent) : m_pbf_message_layer(m_data), m_pbf_message_keys(m_keys_data), - m_pbf_message_values(m_values_data) { + m_pbf_message_values(m_values_data), + m_version(version) { m_pbf_message_layer.add_uint32(detail::pbf_layer::version, version); m_pbf_message_layer.add_string(detail::pbf_layer::name, std::forward(name)); m_pbf_message_layer.add_uint32(detail::pbf_layer::extent, extent); } - ~layer_builder_impl() noexcept override = default; + ~layer_builder_impl() noexcept = default; layer_builder_impl(const layer_builder_impl&) = delete; layer_builder_impl& operator=(const layer_builder_impl&) = delete; @@ -178,6 +173,10 @@ namespace vtzero { layer_builder_impl(layer_builder_impl&&) = default; layer_builder_impl& operator=(layer_builder_impl&&) = default; + uint32_t version() const noexcept { + return m_version; + } + index_value add_key_without_dup_check(const data_view text) { m_pbf_message_keys.add_string(detail::pbf_layer::keys, text); return m_num_keys++; @@ -227,7 +226,14 @@ namespace vtzero { ++m_num_features; } - std::size_t estimated_size() const override { + std::size_t estimated_size() const { + if (m_data_view.data()) { + // This is a layer created as copy from an existing layer + constexpr const std::size_t estimated_overhead_for_pbf_encoding = 8; + return m_data_view.size() + estimated_overhead_for_pbf_encoding; + } + + // This is a layer created from scratch constexpr const std::size_t estimated_overhead_for_pbf_encoding = 8; return data().size() + keys_data().size() + @@ -235,7 +241,15 @@ namespace vtzero { estimated_overhead_for_pbf_encoding; } - void build(protozero::pbf_builder& pbf_tile_builder) const override { + template + void build(protozero::basic_pbf_builder& pbf_tile_builder) const { + if (m_data_view.data()) { + // This is a layer created as copy from an existing layer + pbf_tile_builder.add_bytes(detail::pbf_tile::layers, m_data_view); + return; + } + + // This is a layer created from scratch if (m_num_features > 0) { pbf_tile_builder.add_bytes_vectored(detail::pbf_tile::layers, data(), @@ -246,27 +260,6 @@ namespace vtzero { }; // class layer_builder_impl - class layer_builder_existing : public layer_builder_base { - - data_view m_data; - - public: - - explicit layer_builder_existing(const data_view data) : - m_data(data) { - } - - std::size_t estimated_size() const override { - constexpr const std::size_t estimated_overhead_for_pbf_encoding = 8; - return m_data.size() + estimated_overhead_for_pbf_encoding; - } - - void build(protozero::pbf_builder& pbf_tile_builder) const override { - pbf_tile_builder.add_bytes(detail::pbf_tile::layers, m_data); - } - - }; // class layer_builder_existing - } // namespace detail } // namespace vtzero diff --git a/third_party/vtzero/include/vtzero/feature.hpp b/third_party/vtzero/include/vtzero/feature.hpp index 504f155f7..745d49a1a 100644 --- a/third_party/vtzero/include/vtzero/feature.hpp +++ b/third_party/vtzero/include/vtzero/feature.hpp @@ -259,6 +259,19 @@ namespace vtzero { template bool for_each_property(TFunc&& func) const; + /** + * Call a function for each key/value index of this feature. + * + * @tparam TFunc The type of the function. It must take a single + * argument of type index_value_pair&& and return a bool. + * If the function returns false, the iteration will be stopped. + * @param func The function to call. + * @returns true if the iteration was completed and false otherwise. + * @pre @code valid() @endcode + */ + template + bool for_each_property_indexes(TFunc&& func) const; + }; // class feature /** diff --git a/third_party/vtzero/include/vtzero/feature_builder_impl.hpp b/third_party/vtzero/include/vtzero/feature_builder_impl.hpp index 761a79579..30674186c 100644 --- a/third_party/vtzero/include/vtzero/feature_builder_impl.hpp +++ b/third_party/vtzero/include/vtzero/feature_builder_impl.hpp @@ -78,6 +78,14 @@ namespace vtzero { feature_builder_base& operator=(feature_builder_base&&) noexcept = default; + uint32_t version() const noexcept { + return m_layer->version(); + } + + void set_id_impl(uint64_t id) { + m_feature_writer.add_uint64(detail::pbf_feature::id, id); + } + void add_property_impl(const property& property) { add_key_internal(property.key()); add_value_internal(property.value()); diff --git a/third_party/vtzero/include/vtzero/geometry.hpp b/third_party/vtzero/include/vtzero/geometry.hpp index c505feb3e..62ee140a2 100644 --- a/third_party/vtzero/include/vtzero/geometry.hpp +++ b/third_party/vtzero/include/vtzero/geometry.hpp @@ -89,7 +89,7 @@ namespace vtzero { }; inline constexpr uint32_t command_integer(CommandId id, const uint32_t count) noexcept { - return (static_cast(id) & 0x7u) | (count << 3u); + return (static_cast(id) & 0x7U) | (count << 3U); } inline constexpr uint32_t command_move_to(const uint32_t count) noexcept { @@ -105,11 +105,11 @@ namespace vtzero { } inline constexpr uint32_t get_command_id(const uint32_t command_integer) noexcept { - return command_integer & 0x7u; + return command_integer & 0x7U; } inline constexpr uint32_t get_command_count(const uint32_t command_integer) noexcept { - return command_integer >> 3u; + return command_integer >> 3U; } // The maximum value for the command count according to the spec. diff --git a/third_party/vtzero/include/vtzero/layer.hpp b/third_party/vtzero/include/vtzero/layer.hpp index f5ca7f941..8556851fb 100644 --- a/third_party/vtzero/include/vtzero/layer.hpp +++ b/third_party/vtzero/include/vtzero/layer.hpp @@ -48,6 +48,10 @@ namespace vtzero { * @code * layer.get_feature_by_id(7); * @endcode + * + * Note that the layer class uses mutable members inside to cache the + * key and value tables. It can not be used safely in several threads + * at once! */ class layer { @@ -465,7 +469,7 @@ namespace vtzero { throw out_of_range_exception{ki}; } - assert(m_property_iterator != m_properties.end()); + assert(it != m_properties.end()); const uint32_t vi = *it++; if (!index_value{vi}.valid()) { throw out_of_range_exception{vi}; @@ -479,6 +483,30 @@ namespace vtzero { return true; } + template + bool feature::for_each_property_indexes(TFunc&& func) const { + vtzero_assert(valid()); + + for (auto it = m_properties.begin(); it != m_properties.end();) { + const uint32_t ki = *it++; + if (!index_value{ki}.valid()) { + throw out_of_range_exception{ki}; + } + + assert(it != m_properties.end()); + const uint32_t vi = *it++; + if (!index_value{vi}.valid()) { + throw out_of_range_exception{vi}; + } + + if (!std::forward(func)(index_value_pair{ki, vi})) { + return false; + } + } + + return true; + } + } // namespace vtzero #endif // VTZERO_LAYER_HPP diff --git a/third_party/vtzero/include/vtzero/types.hpp b/third_party/vtzero/include/vtzero/types.hpp index 3fffb3db5..c3d24465b 100644 --- a/third_party/vtzero/include/vtzero/types.hpp +++ b/third_party/vtzero/include/vtzero/types.hpp @@ -12,14 +12,17 @@ documentation. #include +#include #include // @cond internal // Wrappers for assert() used for testing #ifndef vtzero_assert +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) # define vtzero_assert(x) assert(x) #endif #ifndef vtzero_assert_in_noexcept_function +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) # define vtzero_assert_in_noexcept_function(x) assert(x) #endif // @endcond @@ -56,10 +59,10 @@ namespace vtzero { * Return the name of a GeomType (for debug output etc.) */ inline const char* geom_type_name(GeomType type) noexcept { - static const char* names[] = { - "unknown", "point", "linestring", "polygon" + static const std::array names = { + {"unknown", "point", "linestring", "polygon"} }; - return names[static_cast(type)]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) + return names[static_cast(type)]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) } /// The property value type as specified in the vector tile spec @@ -77,10 +80,10 @@ namespace vtzero { * Return the name of a property value type (for debug output etc.) */ inline const char* property_value_type_name(property_value_type type) noexcept { - static const char* names[] = { - "", "string", "float", "double", "int", "uint", "sint", "bool" + static const std::array names = { + {"", "string", "float", "double", "int", "uint", "sint", "bool"} }; - return names[static_cast(type)]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) + return names[static_cast(type)]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index) } namespace detail { @@ -145,7 +148,7 @@ namespace vtzero { /// @endcond /// value - float value = 0.0f; + float value = 0.0F; /// Construct float_value_type with value 0.0 constexpr float_value_type() noexcept = default; diff --git a/third_party/vtzero/include/vtzero/version.hpp b/third_party/vtzero/include/vtzero/version.hpp index 2cf9df887..d01cf34d6 100644 --- a/third_party/vtzero/include/vtzero/version.hpp +++ b/third_party/vtzero/include/vtzero/version.hpp @@ -20,10 +20,10 @@ documentation. #define VTZERO_VERSION_MAJOR 1 /// The minor version number -#define VTZERO_VERSION_MINOR 0 +#define VTZERO_VERSION_MINOR 1 /// The patch number -#define VTZERO_VERSION_PATCH 1 +#define VTZERO_VERSION_PATCH 0 /// The complete version number #define VTZERO_VERSION_CODE \ @@ -31,6 +31,6 @@ documentation. VTZERO_VERSION_PATCH) /// Version number as string -#define VTZERO_VERSION_STRING "1.0.1" +#define VTZERO_VERSION_STRING "1.1.0" #endif // VTZERO_VERSION_HPP diff --git a/third_party/vtzero/test/catch/catch.hpp b/third_party/vtzero/test/catch/catch.hpp index 6b5129d60..6beb0eadb 100644 --- a/third_party/vtzero/test/catch/catch.hpp +++ b/third_party/vtzero/test/catch/catch.hpp @@ -1,17 +1,21 @@ /* - * Catch v1.12.0 - * Generated: 2018-01-11 21:56:34.893972 + * Catch v2.12.1 + * Generated: 2020-04-21 19:29:20.964532 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp -#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 12 +#define CATCH_VERSION_PATCH 1 #ifdef __clang__ # pragma clang system_header @@ -19,36 +23,66 @@ # pragma GCC system_header #endif -// #included from: internal/catch_suppress_warnings.h +// start catch_suppress_warnings.h #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro # pragma warning(push) # pragma warning(disable: 161 1682) # else // __ICC -# pragma clang diagnostic ignored "-Wglobal-constructors" -# pragma clang diagnostic ignored "-Wvariadic-macros" -# pragma clang diagnostic ignored "-Wc99-extensions" -# pragma clang diagnostic ignored "-Wunused-variable" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ -# pragma GCC diagnostic ignored "-Wvariadic-macros" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wparentheses" + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details # pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wpadded" #endif +// end catch_suppress_warnings.h #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS #endif +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_OSX == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + #ifdef CATCH_IMPL # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED @@ -56,93 +90,110 @@ # endif #endif -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED +// start catch_user_interfaces.h -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED +namespace Catch { + unsigned int rngSeed(); +} -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler // The following features are defined: // -// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? -// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported -// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? -// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? -// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) -// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? -// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? - -// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? // **************** // Note to maintainers: if new toggles are added please document them // in configuration.md, too // **************** // In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. -// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 - #ifdef __cplusplus -# if __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER # endif -# if __cplusplus >= 201402L -# define CATCH_CPP14_OR_GREATER +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER # endif #endif -#ifdef __clang__ +#if defined(__cpp_lib_uncaught_exceptions) +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +// We have to avoid both ICC and Clang, because they try to mask themselves +// as gcc, and we want only GCC in this block +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg) */ # endif -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# if defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) -# endif +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) #endif // __clang__ +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# endif - +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS #endif #ifdef __OS400__ @@ -150,6 +201,25 @@ # define CATCH_CONFIG_COLOUR_NONE #endif +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + //////////////////////////////////////////////////////////////////////////////// // Cygwin #ifdef __CYGWIN__ @@ -157,219 +227,248 @@ // Required for some versions of Cygwin to declare gettimeofday // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin # define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif #endif // __CYGWIN__ -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - //////////////////////////////////////////////////////////////////////////////// // Visual C++ -#ifdef _MSC_VER +#if defined(_MSC_VER) -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -#endif +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ #endif // _MSC_VER +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + //////////////////////////////////////////////////////////////////////////////// - -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS - +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED #endif -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ - ( defined __clang__ && __clang_major__ >= 3 ) +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ -// Use of __COUNTER__ is suppressed during code analysis in CLion/AppCode 2017.2.x and former, -// because __COUNTER__ is not properly handled by it. -// This does not affect compilation -#if ( !defined __JETBRAINS_IDE__ || __JETBRAINS_IDE__ >= 20170300L ) +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) #define CATCH_INTERNAL_CONFIG_COUNTER #endif -#endif - //////////////////////////////////////////////////////////////////////////////// -// C++ language feature support -// catch all support for C++11 -#if defined(CATCH_CPP11_OR_GREATER) - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# endif - -# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) -# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) -# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) -# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) -# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -# endif - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NULLPTR +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_IS_ENUM -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TUPLE -#endif -#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -# define CATCH_CONFIG_VARIADIC_MACROS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_LONG_LONG -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_UNIQUE_PTR + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER #endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) # define CATCH_CONFIG_COUNTER #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_SHUFFLE -#endif -# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TYPE_TRAITS -# endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) # define CATCH_CONFIG_POSIX_SIGNALS #endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS #endif -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) #else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) #endif -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL -#endif - -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override -#else -# define CATCH_OVERRIDE -#endif - -// unique_ptr support -#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR -# define CATCH_AUTO_PTR( T ) std::unique_ptr -#else -# define CATCH_AUTO_PTR( T ) std::auto_ptr +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #endif +// end catch_compiler_capabilities.h #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #ifdef CATCH_CONFIG_COUNTER @@ -378,95 +477,48 @@ # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) +#include +#include +#include -#include -#include +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); namespace Catch { - struct IConfig; - struct CaseSensitive { enum Choice { Yes, No }; }; class NonCopyable { -#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete; -#else - NonCopyable( NonCopyable const& info ); - NonCopyable& operator = ( NonCopyable const& ); -#endif protected: - NonCopyable() {} + NonCopyable(); virtual ~NonCopyable(); }; - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; - } - template - void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; - } - - bool startsWith( std::string const& s, std::string const& prefix ); - bool startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - struct SourceLineInfo { - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SourceLineInfo(SourceLineInfo const& other) = default; - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; -# endif - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - bool operator < ( SourceLineInfo const& other ) const; + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; char const* file; std::size_t line; @@ -474,24 +526,17 @@ namespace Catch { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - inline bool alwaysTrue() { return true; } - inline bool alwaysFalse() { return false; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - void seedRng( IConfig const& config ); - unsigned int rngSeed(); + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as // >> stuff +StreamEndStop struct StreamEndStop { - std::string operator+() { - return std::string(); - } + std::string operator+() const; }; template T const& operator + ( T const& value, StreamEndStop ) { @@ -499,180 +544,28 @@ namespace Catch { } } -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +// end catch_common.h namespace Catch { - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - - virtual ~NotImplementedException() CATCH_NOEXCEPT {} - - virtual const char* what() const CATCH_NOEXCEPT; - - private: - std::string m_what; - SourceLineInfo m_lineInfo; + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); }; } // end namespace Catch -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { - public: - Ptr() : m_p( CATCH_NULL ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( Ptr const& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - void reset() { - if( m_p ) - m_p->release(); - m_p = CATCH_NULL; - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( Ptr const& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() const{ return m_p; } - T& operator*() const { return *m_p; } - T* operator->() const { return m_p; } - bool operator !() const { return m_p == CATCH_NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; - - template - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef() const { - ++m_rc; - } - virtual void release() const { - if( --m_rc == 0 ) - delete this; - } - - mutable unsigned int m_rc; - }; - -} // end namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual Ptr getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( std::string const& streamName ); - -} - -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED - -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED +// start catch_interfaces_testcase.h #include @@ -680,10 +573,9 @@ namespace Catch { class TestSpec; - struct ITestCase : IShared { + struct ITestInvoker { virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); + virtual ~ITestInvoker(); }; class TestCase; @@ -695,167 +587,769 @@ namespace Catch { virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); } +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } + + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template