From 3b431403137fe4e5dc74c030af9e89ea4e0baa2e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 7 May 2024 21:01:26 +0200 Subject: [PATCH] Squashed 'third_party/vtzero/' changes from 2b43c8f5c..cf89d56ac cf89d56ac Release 1.1.0 6defc33ea Update changelog 8480ce447 Use basic_pbf_builder to make buffer type configurable 25fbe0caf Travis: Disable test that fails with out of memory error f6741c19a Travis: Test on different architectures 598031339 Explicitly return 0 or 1 in example code, don't use std::exit dd8d315ea Remove virtual inheritance in builder f8511cc9e Fix another unused variable 4002414f0 Switch to catch2 for testing 9bb27a31f Avoid unused variable warning b04163da6 Use std::array instead of C array 4701b6a57 Make string non-const so the return doesn't copy 454f7d711 Fix clang-tidy config 6105d7a62 "Modernize" travis config 7fefbf932 Use try/catch in main() b3a62df21 Various fixes based on clang-tidy reports 83f784641 Use uppercase letters for numeric literals 23fd5f5c9 CMake config: Also look for newer clang-tidy versions 25ba7a7f6 Remove unnecessary ref qualifier f1cc1728a Doxygen: Remove config settings not available in newer versions 0a0afc97d Fix doc. 630dc80bc fix docs e022ba387 Call commit on finished features. 5d3f6eaf9 Remember version in layer_builder_impl. Add accessor functions. bc9d5f977 Remove comment that doesn't apply (any more). e1618d063 Update appveyor config to use more recent visual studio version. e6f9e3e62 Remove unnecessary workaround in Appveyor config. e1df3894c Remove xcode6.4 build soon to be removed from travis. 808a7b6a1 Release 1.0.3 d4faa2fb0 catch exceptions in vtzero-stats 291572505 Add overload of copy_properties function using a property_manager. 189caf4b8 Use new copy_id() function in advanced documentation. 184bb33e1 Add feature::for_each_property_indexes() member function. 3e296a36f Bugfix: Wrong iterator was checked in assert. 1115c0910 Update submodule to use newest mvt-fixtures. f32e73893 Explicitly initialize member (needed by older GCCs). 8d37928ca More tests. bf68443be Add copy_properties() helper function to feature builders. 96ed8cbd7 Add copy_id() helper function to builders. b166fcc3a Document that layer class uses mutable. 8609cdf96 Add missing word 3484299f2 Release 1.0.2 6d3dd8940 Bugfix: layer_builder::add_feature() now commits features it adds. 8da72723f Update links in change log. git-subtree-dir: third_party/vtzero git-subtree-split: cf89d56ac22eee0a252aab8d2e87344e4ce73d70 --- .clang-tidy | 16 +- .travis.yml | 176 +- CHANGELOG.md | 47 +- CMakeLists.txt | 8 +- README.md | 2 +- appveyor.yml | 5 - build-appveyor.bat | 11 +- doc/Doxyfile.in | 4 +- doc/advanced.md | 4 +- doc/reading.md | 4 +- doc/writing.md | 28 +- examples/vtzero-create.cpp | 164 +- examples/vtzero-encode-geom.cpp | 2 + examples/vtzero-filter.cpp | 137 +- examples/vtzero-show.cpp | 4 +- examples/vtzero-stats.cpp | 26 +- examples/vtzero-streets.cpp | 8 +- include/vtzero/builder.hpp | 151 +- include/vtzero/builder_impl.hpp | 91 +- include/vtzero/feature.hpp | 13 + include/vtzero/feature_builder_impl.hpp | 8 + include/vtzero/geometry.hpp | 6 +- include/vtzero/layer.hpp | 30 +- include/vtzero/types.hpp | 17 +- include/vtzero/version.hpp | 6 +- test/catch/catch.hpp | 24446 ++++++++++++++-------- test/fixture_tests.cpp | 86 +- test/include/test.hpp | 3 + test/mvt-fixtures | 2 +- test/t/test_builder.cpp | 235 +- test/t/test_builder_linestring.cpp | 12 +- test/t/test_builder_point.cpp | 18 +- test/t/test_builder_polygon.cpp | 22 +- test/t/test_geometry.cpp | 20 +- test/t/test_geometry_linestring.cpp | 14 +- test/t/test_geometry_point.cpp | 12 +- test/t/test_geometry_polygon.cpp | 14 +- test/t/test_index.cpp | 8 +- test/t/test_layer.cpp | 18 +- test/t/test_property_value.cpp | 16 +- test/t/test_types.cpp | 2 +- test/test_main.cpp | 4 +- 42 files changed, 16227 insertions(+), 9673 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index f75b2822c..9b1d2e3d2 100644 --- a/.clang-tidy +++ b/.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/.travis.yml b/.travis.yml index 8da323b3f..6be32fc6d 100644 --- a/.travis.yml +++ b/.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/CHANGELOG.md b/CHANGELOG.md index 7c4cae19c..94a122fc9 100644 --- a/CHANGELOG.md +++ b/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/CMakeLists.txt b/CMakeLists.txt index 5e6609295..57cbed529 100644 --- a/CMakeLists.txt +++ b/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/README.md b/README.md index ef62c5a09..52500e460 100644 --- a/README.md +++ b/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/appveyor.yml b/appveyor.yml index 24b560798..6b469d4cb 100644 --- a/appveyor.yml +++ b/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/build-appveyor.bat b/build-appveyor.bat index 7a572e89b..39e59cae1 100644 --- a/build-appveyor.bat +++ b/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/doc/Doxyfile.in b/doc/Doxyfile.in index 374c717f8..b90edcbb3 100644 --- a/doc/Doxyfile.in +++ b/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/doc/advanced.md b/doc/advanced.md index 47126020f..8f0b5013e 100644 --- a/doc/advanced.md +++ b/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/doc/reading.md b/doc/reading.md index 4006024e9..e4336b07e 100644 --- a/doc/reading.md +++ b/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/doc/writing.md b/doc/writing.md index 72200c7c2..39fb09b5a 100644 --- a/doc/writing.md +++ b/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/examples/vtzero-create.cpp b/examples/vtzero-create.cpp index 6507ff6fb..c0a81244d 100644 --- a/examples/vtzero-create.cpp +++ b/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/examples/vtzero-encode-geom.cpp b/examples/vtzero-encode-geom.cpp index fa7d7840b..60200ce9e 100644 --- a/examples/vtzero-encode-geom.cpp +++ b/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/examples/vtzero-filter.cpp b/examples/vtzero-filter.cpp index b0ec6c24b..e09f8d53c 100644 --- a/examples/vtzero-filter.cpp +++ b/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/examples/vtzero-show.cpp b/examples/vtzero-show.cpp index 030fe0f8c..a752a23d6 100644 --- a/examples/vtzero-show.cpp +++ b/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/examples/vtzero-stats.cpp b/examples/vtzero-stats.cpp index bef3173f5..e35fd0964 100644 --- a/examples/vtzero-stats.cpp +++ b/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/examples/vtzero-streets.cpp b/examples/vtzero-streets.cpp index 0406f1d44..2d1dbbef1 100644 --- a/examples/vtzero-streets.cpp +++ b/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/include/vtzero/builder.hpp b/include/vtzero/builder.hpp index 666d3cb33..9919287ae 100644 --- a/include/vtzero/builder.hpp +++ b/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/include/vtzero/builder_impl.hpp b/include/vtzero/builder_impl.hpp index 95db484d2..1b348df2d 100644 --- a/include/vtzero/builder_impl.hpp +++ b/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/include/vtzero/feature.hpp b/include/vtzero/feature.hpp index 504f155f7..745d49a1a 100644 --- a/include/vtzero/feature.hpp +++ b/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/include/vtzero/feature_builder_impl.hpp b/include/vtzero/feature_builder_impl.hpp index 761a79579..30674186c 100644 --- a/include/vtzero/feature_builder_impl.hpp +++ b/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/include/vtzero/geometry.hpp b/include/vtzero/geometry.hpp index c505feb3e..62ee140a2 100644 --- a/include/vtzero/geometry.hpp +++ b/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/include/vtzero/layer.hpp b/include/vtzero/layer.hpp index f5ca7f941..8556851fb 100644 --- a/include/vtzero/layer.hpp +++ b/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/include/vtzero/types.hpp b/include/vtzero/types.hpp index 3fffb3db5..c3d24465b 100644 --- a/include/vtzero/types.hpp +++ b/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/include/vtzero/version.hpp b/include/vtzero/version.hpp index 2cf9df887..d01cf34d6 100644 --- a/include/vtzero/version.hpp +++ b/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/test/catch/catch.hpp b/test/catch/catch.hpp index 6b5129d60..6beb0eadb 100644 --- a/test/catch/catch.hpp +++ b/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