From 3345255f16548ca248ac897b0a69fd97026afe11 Mon Sep 17 00:00:00 2001 From: Johan Vromans Date: Thu, 12 Jan 2023 20:53:26 +0100 Subject: [PATCH 01/89] Fix comma tests. --- extras/tests/JsonDeserializer/object.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extras/tests/JsonDeserializer/object.cpp b/extras/tests/JsonDeserializer/object.cpp index e5d5de7f4..79b29757a 100644 --- a/extras/tests/JsonDeserializer/object.cpp +++ b/extras/tests/JsonDeserializer/object.cpp @@ -100,7 +100,7 @@ TEST_CASE("deserialize JSON object") { REQUIRE(obj["key"] == "value"); } - SECTION("Before the colon") { + SECTION("Before the comma") { DeserializationError err = deserializeJson(doc, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); JsonObject obj = doc.as(); @@ -112,9 +112,9 @@ TEST_CASE("deserialize JSON object") { REQUIRE(obj["key2"] == "value2"); } - SECTION("After the colon") { + SECTION("After the comma") { DeserializationError err = - deserializeJson(doc, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); + deserializeJson(doc, "{\"key1\":\"value1\", \"key2\":\"value2\"}"); JsonObject obj = doc.as(); REQUIRE(err == DeserializationError::Ok); From 1909ffe0f9df5bf2bc0ba4140ef10c531b9da0a4 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 13 Jan 2023 08:52:33 +0100 Subject: [PATCH 02/89] Remove link to Discord server --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 1e843d80b..73d4d6c78 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,6 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). * Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories) * [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson) * [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed) - * [Discord server](https://discord.gg/DzN6hHHD4h) ## Quickstart From 7885155634ef8b58d3a1b07eb0456a50968acbdd Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 12 Jan 2023 09:52:03 +0100 Subject: [PATCH 03/89] Add to IDF Component Registry (closes #1844) --- .github/workflows/release.yml | 14 +++++++++++++- .gitignore | 3 +++ LICENSE.md => LICENSE.txt | 20 ++++++++++---------- README.md | 9 +++++---- extras/scripts/publish.sh | 3 +++ idf_component.yml | 12 ++++++++++++ logo.svg | 1 - 7 files changed, 46 insertions(+), 16 deletions(-) rename LICENSE.md => LICENSE.txt (99%) create mode 100644 idf_component.yml delete mode 100644 logo.svg diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2335b056e..4a7ee0b45 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Write release body id: body run: | @@ -49,3 +49,15 @@ jobs: name: ArduinoJson ${{ steps.init.outputs.version }} artifacts: ${{ steps.amalgamate_h.outputs.filename }},${{ steps.amalgamate_hpp.outputs.filename }},${{ steps.arduino.outputs.filename }} token: ${{ secrets.GITHUB_TOKEN }} + + idf: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Upload component to the component registry + uses: espressif/upload-components-ci-action@v1 + with: + name: ArduinoJson + namespace: bblanchon + api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/.gitignore b/.gitignore index 2a5bc3001..b2b9c95c0 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ # Used by CI for Particle /src/*.ino /project.properties + +# Used by IDF +/dist/ diff --git a/LICENSE.md b/LICENSE.txt similarity index 99% rename from LICENSE.md rename to LICENSE.txt index dee0b5ba4..e59620d1d 100644 --- a/LICENSE.md +++ b/LICENSE.txt @@ -1,10 +1,10 @@ -The MIT License (MIT) ---------------------- - -Copyright © 2014-2022, Benoit BLANCHON - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The MIT License (MIT) +--------------------- + +Copyright © 2014-2022, Benoit BLANCHON + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 73d4d6c78..dc37db836 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,18 @@

- ArduinoJson + ArduinoJson

--- -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bblanchon/ArduinoJson/ci.yml?branch=6.x)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bblanchon/ArduinoJson/ci.yml?branch=6.x&logo=github)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x) [![Continuous Integration](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) [![Coveralls branch](https://img.shields.io/coveralls/github/bblanchon/ArduinoJson/6.x?logo=coveralls)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) [![Arduino Library Manager](https://img.shields.io/static/v1?label=Arduino&message=v6.20.0&logo=arduino&logoColor=white&color=blue)](https://www.ardu-badge.com/ArduinoJson/6.20.0) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/bblanchon/library/ArduinoJson.svg?version=6.20.0)](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.20.0) -[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat&logo=github)](https://github.com/bblanchon/ArduinoJson/stargazers) -[![GitHub Sponsors](https://img.shields.io/github/sponsors/bblanchon?logo=github)](https://github.com/sponsors/bblanchon) +[![ESP IDF](https://img.shields.io/static/v1?label=ESP+IDF&message=v6.20.0&logo=cpu&logoColor=white&color=blue)](https://components.espressif.com/components/bblanchon/arduinojson) +[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat&logo=github&color=orange)](https://github.com/bblanchon/ArduinoJson/stargazers) +[![GitHub Sponsors](https://img.shields.io/github/sponsors/bblanchon?logo=github&color=orange)](https://github.com/sponsors/bblanchon) ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). diff --git a/extras/scripts/publish.sh b/extras/scripts/publish.sh index c5a4eefd3..d3459d046 100755 --- a/extras/scripts/publish.sh +++ b/extras/scripts/publish.sh @@ -38,6 +38,9 @@ update_version_in_source () { sed -i~ -bE "s/version: .*$/version: $VERSION.{build}/" appveyor.yml rm appveyor.yml~ + sed -i~ -bE "s/^version: .*$/version: \"$VERSION\"/" idf_component.yml + rm idf_component.yml~ + sed -i~ -bE \ -e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \ -e "s/ARDUINOJSON_VERSION_MAJOR .*$/ARDUINOJSON_VERSION_MAJOR $MAJOR/" \ diff --git a/idf_component.yml b/idf_component.yml new file mode 100644 index 000000000..b88706f89 --- /dev/null +++ b/idf_component.yml @@ -0,0 +1,12 @@ +version: "6.20.0" +description: >- + A simple and efficient JSON library for embedded C++. + ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, ✔ filtering, and more. + It is the most popular Arduino library on GitHub ❤❤❤❤❤. + Check out arduinojson.org for a comprehensive documentation. +url: https://arduinojson.org/ +files: + exclude: + - "**/.vs/**/*" + - "examples/**/*" + - "extras/**/*" diff --git a/logo.svg b/logo.svg deleted file mode 100644 index 5afb6ac74..000000000 --- a/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 175e5b3062642b33b8bdc6127e6a460fdfeca2c8 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Tue, 17 Jan 2023 08:59:45 +0100 Subject: [PATCH 04/89] Add missing semicolon (fixes #1857) --- extras/tests/JsonArray/copyArray.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/tests/JsonArray/copyArray.cpp b/extras/tests/JsonArray/copyArray.cpp index 599821df8..a28c5ac5c 100644 --- a/extras/tests/JsonArray/copyArray.cpp +++ b/extras/tests/JsonArray/copyArray.cpp @@ -165,7 +165,7 @@ TEST_CASE("copyArray()") { char json[32] = ""; int source[][3] = {{1, 2, 3}, {4, 5, 6}}; - CAPTURE(SIZE) + CAPTURE(SIZE); bool ok = copyArray(source, array); CAPTURE(doc.memoryUsage()); From dd0f7019ef6e710551e2c50db99b437ec8d9c499 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Tue, 17 Jan 2023 09:09:47 +0100 Subject: [PATCH 05/89] CI: Update runner to get GCC 11.3 (resolves #1859) --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 75aa3f5f5..3293a78b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: gcc: name: GCC needs: lint - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: @@ -52,9 +52,11 @@ jobs: steps: - name: Install run: | + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial main universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic main universe' + sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ focal main universe' sudo apt-get update sudo apt-get install -y gcc-${{ matrix.gcc }} g++-${{ matrix.gcc }} - name: Checkout From bf93779b4f3d2c4c01263a856a4d35c7e37f24a5 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Tue, 17 Jan 2023 09:33:19 +0100 Subject: [PATCH 06/89] Update catch.hpp (fixes #1856) See also catchorg/Catch2#2627 --- extras/tests/catch/catch.hpp | 427 +++++++++++++++++++++++------------ 1 file changed, 282 insertions(+), 145 deletions(-) diff --git a/extras/tests/catch/catch.hpp b/extras/tests/catch/catch.hpp index fdb046fe4..fe13018da 100644 --- a/extras/tests/catch/catch.hpp +++ b/extras/tests/catch/catch.hpp @@ -1,6 +1,6 @@ /* * Catch v1.12.2 - * Generated: 2018-05-14 15:10:01.112442 + * Generated: 2023-01-17 08:45:40.979381 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -214,7 +214,7 @@ //////////////////////////////////////////////////////////////////////////////// // Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ +#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 ) @@ -2129,6 +2129,9 @@ namespace Catch{ #define CATCH_TRAP() \ __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ : : : "memory","r0","r3","r4" ) /* NOLINT */ + #elif defined(__aarch64__) + // Backport of https://github.com/catchorg/Catch2/commit/a25c1a24af8bffd35727a888a307ff0280cf9387 + #define CATCH_TRAP() __asm__(".inst 0xd4200000") #else #define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ ) #endif @@ -6392,18 +6395,21 @@ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS // #included from: catch_fatal_condition.hpp #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED +#include +#include + namespace Catch { - // Report the error condition - inline void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); - } +//! Signals fatal error message to the run context +inline void reportFatal(std::string const &message) { + IContext &context = Catch::getCurrentContext(); + IResultCapture *resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition(message); +} } // namespace Catch -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// +#if defined(CATCH_PLATFORM_WINDOWS) ///////////////////////////////////////// // #included from: catch_windows_h_proxy.h #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED @@ -6429,176 +6435,307 @@ namespace Catch { #endif -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) +#if !defined(CATCH_CONFIG_WINDOWS_SEH) namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} +class FatalConditionHandler { + bool m_started; + + // Install/disengage implementation for specific platform. + // Should be if-defed to work on current platform, can assume + // engage-disengage 1:1 pairing. + void engage_platform() {} + void disengage_platform() {} + +public: + // Should also have platform-specific implementations as needed + FatalConditionHandler() : m_started(false) {} + ~FatalConditionHandler() {} + + void engage() { + assert(!m_started && "Handler cannot be installed twice."); + m_started = true; + engage_platform(); + } + + void disengage() { + assert(m_started && + "Handler cannot be uninstalled without being installed first"); + m_started = false; + disengage_platform(); + } +}; +} // namespace Catch -# else // CATCH_CONFIG_WINDOWS_SEH is defined +#else // CATCH_CONFIG_WINDOWS_SEH is defined namespace Catch { - struct SignalDefs { DWORD id; const char* name; }; - extern SignalDefs signalDefs[]; - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { - { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, - { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, - { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, - }; +struct SignalDefs { + DWORD id; + const char *name; +}; +extern SignalDefs signalDefs[]; +// There is no 1-1 mapping between signals and windows exceptions. +// Windows can easily distinguish between SO and SigSegV, +// but SigInt, SigTerm, etc are handled differently. +SignalDefs signalDefs[] = { + {EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal"}, + {EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow"}, + {EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal"}, + {EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error"}, +}; - struct FatalConditionHandler { +static LONG CALLBACK +handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + } + } + // If its not an exception we care about, pass it along. + // This stops us from eating debugger breaks etc. + return EXCEPTION_CONTINUE_SEARCH; +} - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; - } +// Since we do not support multiple instantiations, we put these +// into global variables and rely on cleaning them up in outlined +// constructors/destructors +static PVOID exceptionHandlerHandle = CATCH_NULL; - FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = CATCH_NULL; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } +class FatalConditionHandler { + bool m_started; - static void reset() { - if (isSet) { - // Unregister handler and restore the old guarantee - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = CATCH_NULL; - isSet = false; - } - } + // Install/disengage implementation for specific platform. + // Should be if-defed to work on current platform, can assume + // engage-disengage 1:1 pairing. - ~FatalConditionHandler() { - reset(); - } - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; + void engage_platform() { + // Register as first handler in current chain + exceptionHandlerHandle = + AddVectoredExceptionHandler(1, handleVectoredException); + if (!exceptionHandlerHandle) { + throw std::runtime_error("Could not register vectored exception handler"); + } + } + + void disengage_platform() { + if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { + throw std::runtime_error( + "Could not unregister vectored exception handler"); + } + exceptionHandlerHandle = CATCH_NULL; + } - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; +public: + FatalConditionHandler() : m_started(false) { + ULONG guaranteeSize = static_cast(32 * 1024); + if (!SetThreadStackGuarantee(&guaranteeSize)) { + // We do not want to fully error out, because needing + // the stack reserve should be rare enough anyway. + Catch::cerr() << "Failed to reserve piece of stack." + << " Stack overflows will not be reported successfully."; + } + } + + // We do not attempt to unset the stack guarantee, because + // Windows does not support lowering the stack size guarantee. + ~FatalConditionHandler() {} + + void engage() { + assert(!m_started && "Handler cannot be installed twice."); + m_started = true; + engage_platform(); + } + + void disengage() { + assert(m_started && + "Handler cannot be uninstalled without being installed first"); + m_started = false; + disengage_platform(); + } +}; } // namespace Catch -# endif // CATCH_CONFIG_WINDOWS_SEH +#endif // CATCH_CONFIG_WINDOWS_SEH #else // Not Windows - assumed to be POSIX compatible ////////////////////////// -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) +#if !defined(CATCH_CONFIG_POSIX_SIGNALS) namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} +class FatalConditionHandler { + bool m_started; -# else // CATCH_CONFIG_POSIX_SIGNALS is defined + // Install/disengage implementation for specific platform. + // Should be if-defed to work on current platform, can assume + // engage-disengage 1:1 pairing. + void engage_platform() {} + void disengage_platform() {} + +public: + // Should also have platform-specific implementations as needed + FatalConditionHandler() : m_started(false) {} + ~FatalConditionHandler() {} + + void engage() { + assert(!m_started && "Handler cannot be installed twice."); + m_started = true; + engage_platform(); + } + + void disengage() { + assert(m_started && + "Handler cannot be uninstalled without being installed first"); + m_started = false; + disengage_platform(); + } +}; +} // namespace Catch + +#else // CATCH_CONFIG_POSIX_SIGNALS is defined #include namespace Catch { - struct SignalDefs { - int id; - const char* name; - }; - extern SignalDefs signalDefs[]; - SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; - static stack_t oldSigStack; - static char altStackMem[SIGSTKSZ]; - - static void handleSignal( int sig ) { - std::string name = ""; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - SignalDefs &def = signalDefs[i]; - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise( sig ); - } +struct SignalDefs { + int id; + const char *name; +}; +extern SignalDefs signalDefs[]; +SignalDefs signalDefs[] = { + {SIGINT, "SIGINT - Terminal interrupt signal"}, + {SIGILL, "SIGILL - Illegal instruction signal"}, + {SIGFPE, "SIGFPE - Floating point error signal"}, + {SIGSEGV, "SIGSEGV - Segmentation violation signal"}, + {SIGTERM, "SIGTERM - Termination request signal"}, + {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}}; + +// Older GCCs trigger -Wmissing-field-initializers for T foo = {} +// which is zero initialization, but not explicit. We want to avoid +// that. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +static char *altStackMem = CATCH_NULL; +static std::size_t altStackSize = 0; +static stack_t oldSigStack; +static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]; + +static void restorePreviousSignalHandlers() { + // We set signal handlers back to the previous ones. Hopefully + // nobody overwrote them in the meantime, and doesn't expect + // their signal handlers to live past ours given that they + // installed them after ours.. + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); + } + // Return the old stack + sigaltstack(&oldSigStack, CATCH_NULL); +} - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = SIGSTKSZ; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = { 0 }; +static void handleSignal(int sig) { + char const *name = ""; + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + SignalDefs &def = signalDefs[i]; + if (sig == def.id) { + name = def.name; + break; + } + } + // We need to restore previous signal handlers and let them do + // their thing, so that the users can have the debugger break + // when a signal is raised, and so on. + restorePreviousSignalHandlers(); + reportFatal(name); + raise(sig); +} - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } +class FatalConditionHandler { + bool m_started; - ~FatalConditionHandler() { - reset(); - } - static void reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); - } - // Return the old stack - sigaltstack(&oldSigStack, CATCH_NULL); - isSet = false; - } - } - }; + // Install/disengage implementation for specific platform. + // Should be if-defed to work on current platform, can assume + // engage-disengage 1:1 pairing. + + void engage_platform() { + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = SIGSTKSZ; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = {0}; + + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + void disengage_platform() { restorePreviousSignalHandlers(); } - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; +public: + FatalConditionHandler() : m_started(false) { + assert(!altStackMem && + "Cannot initialize POSIX signal handler when one already exists"); + if (altStackSize == 0) { + altStackSize = SIGSTKSZ; + } + altStackMem = new char[altStackSize](); + } + + ~FatalConditionHandler() { + delete[] altStackMem; + // We signal that another instance can be constructed by zeroing + // out the pointer. + altStackMem = CATCH_NULL; + } + + void engage() { + assert(!m_started && "Handler cannot be installed twice."); + m_started = true; + engage_platform(); + } + + void disengage() { + assert(m_started && + "Handler cannot be uninstalled without being installed first"); + m_started = false; + disengage_platform(); + } +}; + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif } // namespace Catch -# endif // CATCH_CONFIG_POSIX_SIGNALS +#endif // CATCH_CONFIG_POSIX_SIGNALS #endif // not Windows +namespace Catch { + +//! Simple RAII guard for (dis)engaging the FatalConditionHandler +class FatalConditionHandlerGuard { + FatalConditionHandler *m_handler; + +public: + FatalConditionHandlerGuard(FatalConditionHandler *handler) + : m_handler(handler) { + m_handler->engage(); + } + ~FatalConditionHandlerGuard() { m_handler->disengage(); } +}; + +} // end namespace Catch + #include #include #include @@ -6938,9 +7075,8 @@ namespace Catch { } void invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals + FatalConditionHandlerGuard _(&m_fatalConditionhandler); m_activeTestCase->invoke(); - fatalConditionHandler.reset(); } private: @@ -6978,6 +7114,7 @@ namespace Catch { std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; + FatalConditionHandler m_fatalConditionhandler; size_t m_prevPassed; bool m_shouldReportUnexpected; }; From b350a9664370f37654a406d75f99b1e5b3a2d637 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 18 Jan 2023 22:08:42 +0100 Subject: [PATCH 07/89] Remove explicit exclusion of `as()` and `as()` (#1860) If you try to call them, you'll now get the same error message as any unsupported type. You could also add a custom converter for `char*` and `char`. --- CHANGELOG.md | 7 +++++++ src/ArduinoJson/Variant/VariantRefBase.hpp | 8 +++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0125a958..408828fce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ ArduinoJson: change log ======================= +HEAD +---- + +* Remove explicit exclusion of `as()` and `as()` (issue #1860) + If you try to call them, you'll now get the same error message as any unsupported type. + You could also add a custom converter for `char*` and `char`. + v6.20.0 (2022-12-26) ------- diff --git a/src/ArduinoJson/Variant/VariantRefBase.hpp b/src/ArduinoJson/Variant/VariantRefBase.hpp index ddfcf0d60..c2df2dc62 100644 --- a/src/ArduinoJson/Variant/VariantRefBase.hpp +++ b/src/ArduinoJson/Variant/VariantRefBase.hpp @@ -46,11 +46,9 @@ class VariantRefBase : public VariantTag { // Casts the value to the specified type. // https://arduinojson.org/v6/api/jsonvariant/as/ template - FORCE_INLINE typename enable_if::value && - !is_same::value && - !ConverterNeedsWriteableRef::value, - T>::type - as() const { + FORCE_INLINE + typename enable_if::value, T>::type + as() const { return Converter::fromJson(getVariantConst()); } From 1ec16ca94fdd2acf82f1bd4582b733f3697c3f30 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 26 Jan 2023 14:28:35 +0100 Subject: [PATCH 08/89] Use `pgm_read()` instead of `ARDUINOJSON_READ_STATIC_ARRAY` --- extras/tests/Helpers/Arduino.h | 1 - extras/tests/Misc/StringAdapters.cpp | 1 + .../MixedConfiguration/enable_progmem_1.cpp | 2 + .../enable_string_deduplication_0.cpp | 2 + .../enable_string_deduplication_1.cpp | 2 + extras/tests/MixedConfiguration/issue1707.cpp | 2 + .../Deserialization/DeserializationError.hpp | 19 ++--- src/ArduinoJson/Numbers/FloatTraits.hpp | 83 +++++++++---------- .../Polyfills/pgmspace_generic.hpp | 27 +++++- src/ArduinoJson/Polyfills/static_array.hpp | 30 ------- 10 files changed, 83 insertions(+), 86 deletions(-) delete mode 100644 src/ArduinoJson/Polyfills/static_array.hpp diff --git a/extras/tests/Helpers/Arduino.h b/extras/tests/Helpers/Arduino.h index 4f24b263e..bacc1a887 100644 --- a/extras/tests/Helpers/Arduino.h +++ b/extras/tests/Helpers/Arduino.h @@ -7,6 +7,5 @@ #include "api/Print.h" #include "api/Stream.h" #include "api/String.h" -#include "progmem_emulation.hpp" #define ARDUINO_H_INCLUDED 1 diff --git a/extras/tests/Misc/StringAdapters.cpp b/extras/tests/Misc/StringAdapters.cpp index 022823345..03c4196d1 100644 --- a/extras/tests/Misc/StringAdapters.cpp +++ b/extras/tests/Misc/StringAdapters.cpp @@ -6,6 +6,7 @@ #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 #include "custom_string.hpp" +#include "progmem_emulation.hpp" #include "weird_strcmp.hpp" #include diff --git a/extras/tests/MixedConfiguration/enable_progmem_1.cpp b/extras/tests/MixedConfiguration/enable_progmem_1.cpp index 9ddf7f263..61e6c2817 100644 --- a/extras/tests/MixedConfiguration/enable_progmem_1.cpp +++ b/extras/tests/MixedConfiguration/enable_progmem_1.cpp @@ -2,6 +2,8 @@ // Copyright © 2014-2022, Benoit BLANCHON // MIT License +#include "progmem_emulation.hpp" + #define ARDUINOJSON_ENABLE_PROGMEM 1 #include diff --git a/extras/tests/MixedConfiguration/enable_string_deduplication_0.cpp b/extras/tests/MixedConfiguration/enable_string_deduplication_0.cpp index d9ca166e2..4adb5ca37 100644 --- a/extras/tests/MixedConfiguration/enable_string_deduplication_0.cpp +++ b/extras/tests/MixedConfiguration/enable_string_deduplication_0.cpp @@ -2,6 +2,8 @@ // Copyright © 2014-2022, Benoit BLANCHON // MIT License +#include "progmem_emulation.hpp" + #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 #define ARDUINOJSON_ENABLE_PROGMEM 1 #define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 0 diff --git a/extras/tests/MixedConfiguration/enable_string_deduplication_1.cpp b/extras/tests/MixedConfiguration/enable_string_deduplication_1.cpp index 27fc18d68..0059777c1 100644 --- a/extras/tests/MixedConfiguration/enable_string_deduplication_1.cpp +++ b/extras/tests/MixedConfiguration/enable_string_deduplication_1.cpp @@ -2,6 +2,8 @@ // Copyright © 2014-2022, Benoit BLANCHON // MIT License +#include "progmem_emulation.hpp" + #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 #define ARDUINOJSON_ENABLE_PROGMEM 1 #define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1 diff --git a/extras/tests/MixedConfiguration/issue1707.cpp b/extras/tests/MixedConfiguration/issue1707.cpp index befdee536..fce024c26 100644 --- a/extras/tests/MixedConfiguration/issue1707.cpp +++ b/extras/tests/MixedConfiguration/issue1707.cpp @@ -5,6 +5,8 @@ #define ARDUINO #define memcpy_P(dest, src, n) memcpy((dest), (src), (n)) +#include "progmem_emulation.hpp" + #include #include diff --git a/src/ArduinoJson/Deserialization/DeserializationError.hpp b/src/ArduinoJson/Deserialization/DeserializationError.hpp index 96b3a178b..9720096fd 100644 --- a/src/ArduinoJson/Deserialization/DeserializationError.hpp +++ b/src/ArduinoJson/Deserialization/DeserializationError.hpp @@ -6,8 +6,8 @@ #include #include +#include #include -#include #if ARDUINOJSON_ENABLE_STD_STREAM # include @@ -74,16 +74,15 @@ class DeserializationError : public SafeBoolIdom { #if ARDUINOJSON_ENABLE_PROGMEM const __FlashStringHelper* f_str() const { - ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok"); - ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput"); - ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput"); - ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput"); - ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory"); - ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "TooDeep"); - ARDUINOJSON_DEFINE_STATIC_ARRAY( + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s0, "Ok"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s1, "EmptyInput"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s2, "IncompleteInput"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s3, "InvalidInput"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s4, "NoMemory"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s5, "TooDeep"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY( const char*, messages, ARDUINOJSON_EXPAND6({s0, s1, s2, s3, s4, s5})); - return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages, - _code); + return pgm_read(messages + _code); } #endif diff --git a/src/ArduinoJson/Numbers/FloatTraits.hpp b/src/ArduinoJson/Numbers/FloatTraits.hpp index 4d5782b7a..be15108dd 100644 --- a/src/ArduinoJson/Numbers/FloatTraits.hpp +++ b/src/ArduinoJson/Numbers/FloatTraits.hpp @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include namespace ARDUINOJSON_NAMESPACE { @@ -49,7 +49,7 @@ struct FloatTraits { } static T positiveBinaryPowerOfTen(int index) { - ARDUINOJSON_DEFINE_STATIC_ARRAY( // + ARDUINOJSON_DEFINE_PROGMEM_ARRAY( // uint32_t, factors, ARDUINOJSON_EXPAND18({ 0x40240000, 0x00000000, // 1e1 @@ -62,13 +62,12 @@ struct FloatTraits { 0x5A827748, 0xF9301D32, // 1e128 0x75154FDD, 0x7F73BF3C // 1e256 })); - return forge( - ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), - ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); + return forge(pgm_read(factors + 2 * index), + pgm_read(factors + 2 * index + 1)); } static T negativeBinaryPowerOfTen(int index) { - ARDUINOJSON_DEFINE_STATIC_ARRAY( // + ARDUINOJSON_DEFINE_PROGMEM_ARRAY( // uint32_t, factors, ARDUINOJSON_EXPAND18({ 0x3FB99999, 0x9999999A, // 1e-1 @@ -81,13 +80,12 @@ struct FloatTraits { 0x255BBA08, 0xCF8C979D, // 1e-128 0x0AC80628, 0x64AC6F43 // 1e-256 })); - return forge( - ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), - ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); + return forge(pgm_read(factors + 2 * index), + pgm_read(factors + 2 * index + 1)); } static T negativeBinaryPowerOfTenPlusOne(int index) { - ARDUINOJSON_DEFINE_STATIC_ARRAY( // + ARDUINOJSON_DEFINE_PROGMEM_ARRAY( // uint32_t, factors, ARDUINOJSON_EXPAND18({ 0x3FF00000, 0x00000000, // 1e0 @@ -100,9 +98,8 @@ struct FloatTraits { 0x25915445, 0x81B7DEC2, // 1e-127 0x0AFE07B2, 0x7DD78B14 // 1e-255 })); - return forge( - ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), - ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); + return forge(pgm_read(factors + 2 * index), + pgm_read(factors + 2 * index + 1)); } static T nan() { @@ -175,42 +172,42 @@ struct FloatTraits { } static T positiveBinaryPowerOfTen(int index) { - ARDUINOJSON_DEFINE_STATIC_ARRAY(uint32_t, factors, - ARDUINOJSON_EXPAND6({ - 0x41200000, // 1e1f - 0x42c80000, // 1e2f - 0x461c4000, // 1e4f - 0x4cbebc20, // 1e8f - 0x5a0e1bca, // 1e16f - 0x749dc5ae // 1e32f - })); - return forge(ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, index)); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors, + ARDUINOJSON_EXPAND6({ + 0x41200000, // 1e1f + 0x42c80000, // 1e2f + 0x461c4000, // 1e4f + 0x4cbebc20, // 1e8f + 0x5a0e1bca, // 1e16f + 0x749dc5ae // 1e32f + })); + return forge(pgm_read(factors + index)); } static T negativeBinaryPowerOfTen(int index) { - ARDUINOJSON_DEFINE_STATIC_ARRAY(uint32_t, factors, - ARDUINOJSON_EXPAND6({ - 0x3dcccccd, // 1e-1f - 0x3c23d70a, // 1e-2f - 0x38d1b717, // 1e-4f - 0x322bcc77, // 1e-8f - 0x24e69595, // 1e-16f - 0x0a4fb11f // 1e-32f - })); - return forge(ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, index)); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors, + ARDUINOJSON_EXPAND6({ + 0x3dcccccd, // 1e-1f + 0x3c23d70a, // 1e-2f + 0x38d1b717, // 1e-4f + 0x322bcc77, // 1e-8f + 0x24e69595, // 1e-16f + 0x0a4fb11f // 1e-32f + })); + return forge(pgm_read(factors + index)); } static T negativeBinaryPowerOfTenPlusOne(int index) { - ARDUINOJSON_DEFINE_STATIC_ARRAY(uint32_t, factors, - ARDUINOJSON_EXPAND6({ - 0x3f800000, // 1e0f - 0x3dcccccd, // 1e-1f - 0x3a83126f, // 1e-3f - 0x33d6bf95, // 1e-7f - 0x26901d7d, // 1e-15f - 0x0c01ceb3 // 1e-31f - })); - return forge(ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, index)); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors, + ARDUINOJSON_EXPAND6({ + 0x3f800000, // 1e0f + 0x3dcccccd, // 1e-1f + 0x3a83126f, // 1e-3f + 0x33d6bf95, // 1e-7f + 0x26901d7d, // 1e-15f + 0x0c01ceb3 // 1e-31f + })); + return forge(pgm_read(factors + index)); } static T forge(uint32_t bits) { diff --git a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp index d9e964b85..826827fb9 100644 --- a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp +++ b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp @@ -5,11 +5,21 @@ #pragma once #include -#include -#include + +#if ARDUINOJSON_ENABLE_PROGMEM +# include +# include +#endif namespace ARDUINOJSON_NAMESPACE { +#if ARDUINOJSON_ENABLE_PROGMEM + +# ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY +# define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, value) \ + static type const name[] PROGMEM = value; +# endif + template typename enable_if::value, T>::type pgm_read(const void* p) { return reinterpret_cast(pgm_read_ptr(p)); @@ -20,5 +30,18 @@ typename enable_if::value, T>::type pgm_read( const void* p) { return pgm_read_dword(p); } +#else + +# ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY +# define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, value) \ + static type const name[] = value; +# endif + +template +inline T pgm_read(const void* p) { + return *reinterpret_cast(p); +} + +#endif } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Polyfills/static_array.hpp b/src/ArduinoJson/Polyfills/static_array.hpp deleted file mode 100644 index b2ebbf6b2..000000000 --- a/src/ArduinoJson/Polyfills/static_array.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// ArduinoJson - https://arduinojson.org -// Copyright © 2014-2022, Benoit BLANCHON -// MIT License - -#pragma once - -#include - -#if ARDUINOJSON_ENABLE_PROGMEM - -# include - -# ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY -# define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, value) \ - static type const name[] PROGMEM = value; -# endif - -# define ARDUINOJSON_DEFINE_STATIC_ARRAY ARDUINOJSON_DEFINE_PROGMEM_ARRAY - -# define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \ - pgm_read(name + index) - -#else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0 - -# define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ - static type const name[] = value; - -# define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index] - -#endif From 34b38e07c7836273e3730a9338bc4848ca9894a4 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 26 Jan 2023 18:10:41 +0100 Subject: [PATCH 09/89] Deduce template argument of `pgm_read()` --- .../Deserialization/DeserializationError.hpp | 3 ++- src/ArduinoJson/Numbers/FloatTraits.hpp | 18 +++++++++--------- src/ArduinoJson/Polyfills/pgmspace_generic.hpp | 12 +++++------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/ArduinoJson/Deserialization/DeserializationError.hpp b/src/ArduinoJson/Deserialization/DeserializationError.hpp index 9720096fd..16c52ffd2 100644 --- a/src/ArduinoJson/Deserialization/DeserializationError.hpp +++ b/src/ArduinoJson/Deserialization/DeserializationError.hpp @@ -82,7 +82,8 @@ class DeserializationError : public SafeBoolIdom { ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s5, "TooDeep"); ARDUINOJSON_DEFINE_PROGMEM_ARRAY( const char*, messages, ARDUINOJSON_EXPAND6({s0, s1, s2, s3, s4, s5})); - return pgm_read(messages + _code); + return reinterpret_cast( + pgm_read(messages + _code)); } #endif diff --git a/src/ArduinoJson/Numbers/FloatTraits.hpp b/src/ArduinoJson/Numbers/FloatTraits.hpp index be15108dd..08aa3d66a 100644 --- a/src/ArduinoJson/Numbers/FloatTraits.hpp +++ b/src/ArduinoJson/Numbers/FloatTraits.hpp @@ -62,8 +62,8 @@ struct FloatTraits { 0x5A827748, 0xF9301D32, // 1e128 0x75154FDD, 0x7F73BF3C // 1e256 })); - return forge(pgm_read(factors + 2 * index), - pgm_read(factors + 2 * index + 1)); + return forge(pgm_read(factors + 2 * index), + pgm_read(factors + 2 * index + 1)); } static T negativeBinaryPowerOfTen(int index) { @@ -80,8 +80,8 @@ struct FloatTraits { 0x255BBA08, 0xCF8C979D, // 1e-128 0x0AC80628, 0x64AC6F43 // 1e-256 })); - return forge(pgm_read(factors + 2 * index), - pgm_read(factors + 2 * index + 1)); + return forge(pgm_read(factors + 2 * index), + pgm_read(factors + 2 * index + 1)); } static T negativeBinaryPowerOfTenPlusOne(int index) { @@ -98,8 +98,8 @@ struct FloatTraits { 0x25915445, 0x81B7DEC2, // 1e-127 0x0AFE07B2, 0x7DD78B14 // 1e-255 })); - return forge(pgm_read(factors + 2 * index), - pgm_read(factors + 2 * index + 1)); + return forge(pgm_read(factors + 2 * index), + pgm_read(factors + 2 * index + 1)); } static T nan() { @@ -181,7 +181,7 @@ struct FloatTraits { 0x5a0e1bca, // 1e16f 0x749dc5ae // 1e32f })); - return forge(pgm_read(factors + index)); + return forge(pgm_read(factors + index)); } static T negativeBinaryPowerOfTen(int index) { @@ -194,7 +194,7 @@ struct FloatTraits { 0x24e69595, // 1e-16f 0x0a4fb11f // 1e-32f })); - return forge(pgm_read(factors + index)); + return forge(pgm_read(factors + index)); } static T negativeBinaryPowerOfTenPlusOne(int index) { @@ -207,7 +207,7 @@ struct FloatTraits { 0x26901d7d, // 1e-15f 0x0c01ceb3 // 1e-31f })); - return forge(pgm_read(factors + index)); + return forge(pgm_read(factors + index)); } static T forge(uint32_t bits) { diff --git a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp index 826827fb9..106e01451 100644 --- a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp +++ b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp @@ -21,13 +21,11 @@ namespace ARDUINOJSON_NAMESPACE { # endif template -typename enable_if::value, T>::type pgm_read(const void* p) { - return reinterpret_cast(pgm_read_ptr(p)); +inline const T* pgm_read(const T* const* p) { + return reinterpret_cast(pgm_read_ptr(p)); } -template -typename enable_if::value, T>::type pgm_read( - const void* p) { +inline uint32_t pgm_read(const uint32_t* p) { return pgm_read_dword(p); } #else @@ -38,8 +36,8 @@ typename enable_if::value, T>::type pgm_read( # endif template -inline T pgm_read(const void* p) { - return *reinterpret_cast(p); +inline T pgm_read(const T* p) { + return *p; } #endif From 6013a1a56ff5765d4a2d1c68a40794801a1d172e Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 8 Feb 2023 16:33:09 +0100 Subject: [PATCH 10/89] Fix the name of the license file --- extras/scripts/build-arduino-package.sh | 2 +- extras/scripts/publish-particle-library.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/scripts/build-arduino-package.sh b/extras/scripts/build-arduino-package.sh index 339db2f62..09f6efb30 100755 --- a/extras/scripts/build-arduino-package.sh +++ b/extras/scripts/build-arduino-package.sh @@ -18,6 +18,6 @@ rm -f "$OUTPUT" src \ keywords.txt \ library.properties \ - LICENSE.md \ + LICENSE.txt \ README.md \ ArduinoJson.h diff --git a/extras/scripts/publish-particle-library.sh b/extras/scripts/publish-particle-library.sh index 62c3140f5..d410c470a 100755 --- a/extras/scripts/publish-particle-library.sh +++ b/extras/scripts/publish-particle-library.sh @@ -9,7 +9,7 @@ trap 'rm -rf "$WORK_DIR"' EXIT cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md" cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md" cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties" -cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt" +cp "$SOURCE_DIR/LICENSE.txt" "$WORK_DIR/LICENSE.txt" cp -r "$SOURCE_DIR/src" "$WORK_DIR/" cp -r "$SOURCE_DIR/examples" "$WORK_DIR/" From d4bb839ce9e2d8f4470b7d81a9432d7a4c5bcbc3 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 8 Feb 2023 16:25:44 +0100 Subject: [PATCH 11/89] CI: remove the draft flag on the GitHub Release --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a7ee0b45..c2efcafe0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,7 +45,6 @@ jobs: uses: ncipollo/release-action@v1 with: bodyFile: ${{ steps.body.outputs.filename }} - draft: true name: ArduinoJson ${{ steps.init.outputs.version }} artifacts: ${{ steps.amalgamate_h.outputs.filename }},${{ steps.amalgamate_hpp.outputs.filename }},${{ steps.arduino.outputs.filename }} token: ${{ secrets.GITHUB_TOKEN }} From 06b22633291dca40a7c69dceb65f6aa45150f02e Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 8 Feb 2023 16:29:29 +0100 Subject: [PATCH 12/89] README: reduce the size of the logo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dc37db836..34a76e5f5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- ArduinoJson + ArduinoJson

--- From d2cd13bf2e158a86b6fb9d5c43ca4e0b7e1f60f1 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 8 Feb 2023 16:32:57 +0100 Subject: [PATCH 13/89] CI: automatically publish Particle library --- .github/workflows/release.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c2efcafe0..aa608f45c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -60,3 +60,15 @@ jobs: name: ArduinoJson namespace: bblanchon api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} + + particle: + runs-on: ubuntu-latest + steps: + - name: Install + run: npm install -g particle-cli + - name: Checkout + uses: actions/checkout@v3 + - name: Login + run: particle login --token ${{ secrets.PARTICLE_TOKEN }} + - name: Publish + run: extras/scripts/publish-particle-library.sh From b33966c7551ea7585010a901a1d54118294dbaac Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 8 Feb 2023 16:42:04 +0100 Subject: [PATCH 14/89] Set version to 6.20.1 --- CHANGELOG.md | 4 ++-- CMakeLists.txt | 2 +- README.md | 6 +++--- appveyor.yml | 2 +- library.json | 2 +- library.properties | 2 +- src/ArduinoJson/version.hpp | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 408828fce..dd4945bce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ ArduinoJson: change log ======================= -HEAD ----- +v6.20.1 (2023-02-08) +------- * Remove explicit exclusion of `as()` and `as()` (issue #1860) If you try to call them, you'll now get the same error message as any unsupported type. diff --git a/CMakeLists.txt b/CMakeLists.txt index 7841c0ece..f31fffefd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(ESP_PLATFORM) return() endif() -project(ArduinoJson VERSION 6.20.0) +project(ArduinoJson VERSION 6.20.1) if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(CTest) diff --git a/README.md b/README.md index 34a76e5f5..b0f539dd3 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ [![Continuous Integration](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) [![Coveralls branch](https://img.shields.io/coveralls/github/bblanchon/ArduinoJson/6.x?logo=coveralls)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) -[![Arduino Library Manager](https://img.shields.io/static/v1?label=Arduino&message=v6.20.0&logo=arduino&logoColor=white&color=blue)](https://www.ardu-badge.com/ArduinoJson/6.20.0) -[![PlatformIO Registry](https://badges.registry.platformio.org/packages/bblanchon/library/ArduinoJson.svg?version=6.20.0)](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.20.0) -[![ESP IDF](https://img.shields.io/static/v1?label=ESP+IDF&message=v6.20.0&logo=cpu&logoColor=white&color=blue)](https://components.espressif.com/components/bblanchon/arduinojson) +[![Arduino Library Manager](https://img.shields.io/static/v1?label=Arduino&message=v6.20.1&logo=arduino&logoColor=white&color=blue)](https://www.ardu-badge.com/ArduinoJson/6.20.1) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/bblanchon/library/ArduinoJson.svg?version=6.20.1)](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.20.1) +[![ESP IDF](https://img.shields.io/static/v1?label=ESP+IDF&message=v6.20.1&logo=cpu&logoColor=white&color=blue)](https://components.espressif.com/components/bblanchon/arduinojson) [![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat&logo=github&color=orange)](https://github.com/bblanchon/ArduinoJson/stargazers) [![GitHub Sponsors](https://img.shields.io/github/sponsors/bblanchon?logo=github&color=orange)](https://github.com/sponsors/bblanchon) diff --git a/appveyor.yml b/appveyor.yml index 0276d5d15..06681d4a4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 6.20.0.{build} +version: 6.20.1.{build} environment: matrix: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 diff --git a/library.json b/library.json index 01596a965..a368d7ba5 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/bblanchon/ArduinoJson.git" }, - "version": "6.20.0", + "version": "6.20.1", "authors": { "name": "Benoit Blanchon", "url": "https://blog.benoitblanchon.fr" diff --git a/library.properties b/library.properties index 72a5334ea..15d5000af 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoJson -version=6.20.0 +version=6.20.1 author=Benoit Blanchon maintainer=Benoit Blanchon sentence=A simple and efficient JSON library for embedded C++. diff --git a/src/ArduinoJson/version.hpp b/src/ArduinoJson/version.hpp index 7f4aff88f..30f688cc1 100644 --- a/src/ArduinoJson/version.hpp +++ b/src/ArduinoJson/version.hpp @@ -4,7 +4,7 @@ #pragma once -#define ARDUINOJSON_VERSION "6.20.0" +#define ARDUINOJSON_VERSION "6.20.1" #define ARDUINOJSON_VERSION_MAJOR 6 #define ARDUINOJSON_VERSION_MINOR 20 -#define ARDUINOJSON_VERSION_REVISION 0 +#define ARDUINOJSON_VERSION_REVISION 1 From ae0499fd5761c90eb7a56ea6a7f2efce1d3edd2d Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 8 Feb 2023 16:46:15 +0100 Subject: [PATCH 15/89] Update `idf_component.yml` --- extras/scripts/publish.sh | 2 +- idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/scripts/publish.sh b/extras/scripts/publish.sh index d3459d046..a562a24cb 100755 --- a/extras/scripts/publish.sh +++ b/extras/scripts/publish.sh @@ -51,7 +51,7 @@ update_version_in_source () { } commit_new_version () { - git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties appveyor.yml CMakeLists.txt + git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties appveyor.yml CMakeLists.txt idf_component.yml git commit -m "Set version to $VERSION" } diff --git a/idf_component.yml b/idf_component.yml index b88706f89..f3f70b973 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -1,4 +1,4 @@ -version: "6.20.0" +version: "6.20.1" description: >- A simple and efficient JSON library for embedded C++. ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, ✔ filtering, and more. From de7afc201544fa4f48904712879cdccc8ca0dd36 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 8 Feb 2023 16:51:47 +0100 Subject: [PATCH 16/89] Minor improvements in the release workflow --- .github/workflows/release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aa608f45c..6a6c7d60d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,6 +50,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} idf: + name: IDF Component Registry runs-on: ubuntu-latest steps: - name: Checkout @@ -62,6 +63,7 @@ jobs: api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} particle: + name: Particle runs-on: ubuntu-latest steps: - name: Install @@ -71,4 +73,4 @@ jobs: - name: Login run: particle login --token ${{ secrets.PARTICLE_TOKEN }} - name: Publish - run: extras/scripts/publish-particle-library.sh + run: bash -eux extras/scripts/publish-particle-library.sh From 3d8287265c82b6db7d696b3b549c83a582bbf63f Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 9 Feb 2023 19:06:10 +0100 Subject: [PATCH 17/89] Remove unused `NOEXCEPT` macro --- src/ArduinoJson/Polyfills/attributes.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ArduinoJson/Polyfills/attributes.hpp b/src/ArduinoJson/Polyfills/attributes.hpp index 9e37c82ae..4af0903df 100644 --- a/src/ArduinoJson/Polyfills/attributes.hpp +++ b/src/ArduinoJson/Polyfills/attributes.hpp @@ -21,12 +21,6 @@ #endif -#if __cplusplus >= 201103L -# define NOEXCEPT noexcept -#else -# define NOEXCEPT throw() -#endif - #if defined(__has_attribute) # if __has_attribute(no_sanitize) # define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check))) From e054cba610b741c5908b110926b10f5d1fca9801 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 9 Feb 2023 19:04:23 +0100 Subject: [PATCH 18/89] Set minimum Visual Studio version to 2017 (#1820) --- README.md | 2 +- appveyor.yml | 5 ----- extras/CompileOptions.cmake | 7 +------ src/ArduinoJson/Numbers/arithmeticCompare.hpp | 5 +---- 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index b0f539dd3..1b2bb38b5 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). * Well tested * [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) * Continuously tested on - * [Visual Studio 2010, 2012, 2013, 2015, 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) + * [Visual Studio 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) * [GCC 4.4, 4.6, 4.7, 4.8, 4.9, 5, 6, 7, 8, 9, 10, 11](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) * [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) diff --git a/appveyor.yml b/appveyor.yml index 06681d4a4..90fba8933 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,11 +7,6 @@ environment: CMAKE_GENERATOR: Visual Studio 16 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 CMAKE_GENERATOR: Visual Studio 15 2017 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - CMAKE_GENERATOR: Visual Studio 14 2015 - - CMAKE_GENERATOR: Visual Studio 12 2013 - - CMAKE_GENERATOR: Visual Studio 11 2012 - - CMAKE_GENERATOR: Visual Studio 10 2010 - CMAKE_GENERATOR: Ninja MINGW: MinGW # MinGW 32-bit 5.3.0 - CMAKE_GENERATOR: Ninja diff --git a/extras/CompileOptions.cmake b/extras/CompileOptions.cmake index 82a750a12..9eadfa6ad 100644 --- a/extras/CompileOptions.cmake +++ b/extras/CompileOptions.cmake @@ -85,13 +85,8 @@ if(MSVC) add_compile_options( /W4 # Set warning level /WX # Treats all compiler warnings as errors. + /Zc:__cplusplus # Enable updated __cplusplus macro ) - - if (NOT MSVC_VERSION LESS 1910) # >= Visual Studio 2017 - add_compile_options( - /Zc:__cplusplus # Enable updated __cplusplus macro - ) - endif() endif() if(MINGW) diff --git a/src/ArduinoJson/Numbers/arithmeticCompare.hpp b/src/ArduinoJson/Numbers/arithmeticCompare.hpp index 515bc4e62..fb0c9975f 100644 --- a/src/ArduinoJson/Numbers/arithmeticCompare.hpp +++ b/src/ArduinoJson/Numbers/arithmeticCompare.hpp @@ -33,10 +33,7 @@ template CompareResult arithmeticCompare( const T1& lhs, const T2& rhs, typename enable_if::value && is_integral::value && - sizeof(T1) < sizeof(T2), - int // Using int instead of void to avoid C2572 on - // Visual Studio 2012, 2013, and 2015 - >::type* = 0) { + sizeof(T1) < sizeof(T2)>::type* = 0) { return arithmeticCompare(static_cast(lhs), rhs); } From 669ee4dfe38797698b58ec8d4f73e12c007dcb33 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 10 Feb 2023 17:02:33 +0100 Subject: [PATCH 19/89] Set minimum GCC version to 6 (#1820) --- .github/workflows/ci.yml | 8 -------- README.md | 2 +- appveyor.yml | 4 ---- src/ArduinoJson/Numbers/convertNumber.hpp | 8 ++------ 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3293a78b7..f782d5cc0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,12 +33,6 @@ jobs: fail-fast: false matrix: include: - - gcc: "4.4" - - gcc: "4.6" - - gcc: "4.7" - - gcc: "4.8" - - gcc: "4.9" - - gcc: "5" - gcc: "6" - gcc: "7" cxxflags: -fsanitize=leak -fno-sanitize-recover=all @@ -53,8 +47,6 @@ jobs: - name: Install run: | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 - sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' - sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial main universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic main universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ focal main universe' sudo apt-get update diff --git a/README.md b/README.md index 1b2bb38b5..8636cbf28 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). * [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x) * Continuously tested on * [Visual Studio 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) - * [GCC 4.4, 4.6, 4.7, 4.8, 4.9, 5, 6, 7, 8, 9, 10, 11](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) + * [GCC 6, 7, 8, 9, 10, 11](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) * [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) * Passes all default checks of [clang-tidy](https://releases.llvm.org/10.0.0/tools/clang/tools/extra/docs/clang-tidy/) diff --git a/appveyor.yml b/appveyor.yml index 90fba8933..45c88e317 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,10 +7,6 @@ environment: CMAKE_GENERATOR: Visual Studio 16 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 CMAKE_GENERATOR: Visual Studio 15 2017 - - CMAKE_GENERATOR: Ninja - MINGW: MinGW # MinGW 32-bit 5.3.0 - - CMAKE_GENERATOR: Ninja - MINGW32: i686-5.3.0-posix-dwarf-rt_v4-rev0 # MinGW-w64 5.3.0 - CMAKE_GENERATOR: Ninja MINGW32: i686-6.3.0-posix-dwarf-rt_v5-rev1 # MinGW-w64 6.3.0 i686 - CMAKE_GENERATOR: Ninja diff --git a/src/ArduinoJson/Numbers/convertNumber.hpp b/src/ArduinoJson/Numbers/convertNumber.hpp index 9a78bdd57..0fa3ee3e6 100644 --- a/src/ArduinoJson/Numbers/convertNumber.hpp +++ b/src/ArduinoJson/Numbers/convertNumber.hpp @@ -8,9 +8,7 @@ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wconversion" #elif defined(__GNUC__) -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -# pragma GCC diagnostic push -# endif +# pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" #endif @@ -133,7 +131,5 @@ TOut convertNumber(TIn value) { #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -# pragma GCC diagnostic pop -# endif +# pragma GCC diagnostic pop #endif From c2de812cbde151f95257df98d691c1dc1c39feb2 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 9 Feb 2023 18:56:34 +0100 Subject: [PATCH 20/89] Set minimum Clang version to 3.8 (#1820) --- .github/workflows/ci.yml | 8 -------- README.md | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f782d5cc0..30b27b34d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,12 +78,6 @@ jobs: fail-fast: false matrix: include: - - clang: "3.5" - cxxflags: "-stdlib=libc++" - - clang: "3.6" - cxxflags: "-stdlib=libc++" - - clang: "3.7" - cxxflags: "-stdlib=libc++" - clang: "3.8" cxxflags: "-stdlib=libc++" - clang: "3.9" @@ -102,8 +96,6 @@ jobs: steps: - name: Install run: | - sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty main' - sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial main' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic main' diff --git a/README.md b/README.md index 8636cbf28..03c52f87b 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). * Continuously tested on * [Visual Studio 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) * [GCC 6, 7, 8, 9, 10, 11](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) - * [Clang 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) + * [Clang 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) * Passes all default checks of [clang-tidy](https://releases.llvm.org/10.0.0/tools/clang/tools/extra/docs/clang-tidy/) * Well documented From 94b2b3f9ce761a92eb5c3791b56c953a92adf4ae Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 9 Feb 2023 18:57:34 +0100 Subject: [PATCH 21/89] Run all tests with C++11 enabled (#1820) --- README.md | 3 +- extras/tests/CMakeLists.txt | 3 +- extras/tests/Cpp11/CMakeLists.txt | 36 ------------------- extras/tests/FailingBuilds/CMakeLists.txt | 2 -- extras/tests/FailingBuilds/read_long_long.cpp | 4 --- extras/tests/JsonDocument/CMakeLists.txt | 1 + .../{Cpp11 => JsonDocument}/issue1120.cpp | 0 extras/tests/JsonVariant/CMakeLists.txt | 2 ++ .../tests/{Cpp11 => JsonVariant}/nullptr.cpp | 0 .../{Cpp11 => JsonVariant}/stl_containers.cpp | 0 .../tests/MixedConfiguration/CMakeLists.txt | 2 ++ .../use_long_long_0.cpp | 0 .../use_long_long_1.cpp | 0 extras/tests/Numbers/CMakeLists.txt | 3 -- 14 files changed, 8 insertions(+), 48 deletions(-) delete mode 100644 extras/tests/Cpp11/CMakeLists.txt rename extras/tests/{Cpp11 => JsonDocument}/issue1120.cpp (100%) rename extras/tests/{Cpp11 => JsonVariant}/nullptr.cpp (100%) rename extras/tests/{Cpp11 => JsonVariant}/stl_containers.cpp (100%) rename extras/tests/{Cpp11 => MixedConfiguration}/use_long_long_0.cpp (100%) rename extras/tests/{Cpp11 => MixedConfiguration}/use_long_long_1.cpp (100%) diff --git a/README.md b/README.md index 03c52f87b..3e6461315 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,8 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). * Supports [custom converters](https://arduinojson.org/news/2021/05/04/version-6-18-0/) * Portable * Usable on any C++ project (not limited to Arduino) - * Compatible with C++98, C++11, C++14 and C++17 + * Compatible with C++11, C++14 and C++17 + * Support for C++98/C++03 available on [ArduinoJson 6.20.x](https://github.com/bblanchon/ArduinoJson/tree/6.20.x) * Zero warnings with `-Wall -Wextra -pedantic` and `/W4` * [Header-only library](https://en.wikipedia.org/wiki/Header-only) * Works with virtually any board diff --git a/extras/tests/CMakeLists.txt b/extras/tests/CMakeLists.txt index faf4cd9a6..d3b285edb 100644 --- a/extras/tests/CMakeLists.txt +++ b/extras/tests/CMakeLists.txt @@ -2,7 +2,7 @@ # Copyright © 2014-2022, Benoit BLANCHON # MIT License -set(CMAKE_CXX_STANDARD 98) +set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_subdirectory(catch) @@ -10,7 +10,6 @@ add_subdirectory(catch) link_libraries(ArduinoJson catch) include_directories(Helpers) -add_subdirectory(Cpp11) add_subdirectory(Cpp17) add_subdirectory(Cpp20) add_subdirectory(FailingBuilds) diff --git a/extras/tests/Cpp11/CMakeLists.txt b/extras/tests/Cpp11/CMakeLists.txt deleted file mode 100644 index 0b84a14c7..000000000 --- a/extras/tests/Cpp11/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# ArduinoJson - https://arduinojson.org -# Copyright © 2014-2022, Benoit BLANCHON -# MIT License - -if("cxx_nullptr" IN_LIST CMAKE_CXX_COMPILE_FEATURES) - list(APPEND SOURCES nullptr.cpp) - add_definitions(-DARDUINOJSON_HAS_NULLPTR=1) -endif() - -if("cxx_auto_type" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND "cxx_constexpr" IN_LIST CMAKE_CXX_COMPILE_FEATURES) - list(APPEND SOURCES issue1120.cpp) -endif() - -if("cxx_long_long_type" IN_LIST CMAKE_CXX_COMPILE_FEATURES) - list(APPEND SOURCES use_long_long_0.cpp use_long_long_1.cpp) -endif() - -if("cxx_range_for" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND "cxx_generalized_initializers" IN_LIST CMAKE_CXX_COMPILE_FEATURES) - list(APPEND SOURCES stl_containers.cpp) -endif() - -if(NOT SOURCES) - return() -endif() - -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -add_executable(Cpp11Tests ${SOURCES}) - -add_test(Cpp11 Cpp11Tests) - -set_tests_properties(Cpp11 - PROPERTIES - LABELS "Catch" -) diff --git a/extras/tests/FailingBuilds/CMakeLists.txt b/extras/tests/FailingBuilds/CMakeLists.txt index dc76c9108..1ddab769c 100644 --- a/extras/tests/FailingBuilds/CMakeLists.txt +++ b/extras/tests/FailingBuilds/CMakeLists.txt @@ -31,11 +31,9 @@ add_executable(Issue1189 Issue1189.cpp) build_should_fail(Issue1189) add_executable(read_long_long read_long_long.cpp) -set_property(TARGET read_long_long PROPERTY CXX_STANDARD 11) build_should_fail(read_long_long) add_executable(write_long_long write_long_long.cpp) -set_property(TARGET write_long_long PROPERTY CXX_STANDARD 11) build_should_fail(write_long_long) add_executable(delete_jsondocument delete_jsondocument.cpp) diff --git a/extras/tests/FailingBuilds/read_long_long.cpp b/extras/tests/FailingBuilds/read_long_long.cpp index d900a7f34..da4516f17 100644 --- a/extras/tests/FailingBuilds/read_long_long.cpp +++ b/extras/tests/FailingBuilds/read_long_long.cpp @@ -9,10 +9,6 @@ # error This test requires sizeof(long) < 8 #endif -#if !ARDUINOJSON_HAS_LONG_LONG -# error This test requires C++11 -#endif - ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(long long) int main() { DynamicJsonDocument doc(1024); diff --git a/extras/tests/JsonDocument/CMakeLists.txt b/extras/tests/JsonDocument/CMakeLists.txt index 535678033..781d128f7 100644 --- a/extras/tests/JsonDocument/CMakeLists.txt +++ b/extras/tests/JsonDocument/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable(JsonDocumentTests DynamicJsonDocument.cpp ElementProxy.cpp isNull.cpp + issue1120.cpp MemberProxy.cpp nesting.cpp overflowed.cpp diff --git a/extras/tests/Cpp11/issue1120.cpp b/extras/tests/JsonDocument/issue1120.cpp similarity index 100% rename from extras/tests/Cpp11/issue1120.cpp rename to extras/tests/JsonDocument/issue1120.cpp diff --git a/extras/tests/JsonVariant/CMakeLists.txt b/extras/tests/JsonVariant/CMakeLists.txt index 1a0d14a93..3f37a11bf 100644 --- a/extras/tests/JsonVariant/CMakeLists.txt +++ b/extras/tests/JsonVariant/CMakeLists.txt @@ -16,12 +16,14 @@ add_executable(JsonVariantTests memoryUsage.cpp misc.cpp nesting.cpp + nullptr.cpp or.cpp overflow.cpp remove.cpp set.cpp shallowCopy.cpp size.cpp + stl_containers.cpp subscript.cpp types.cpp unbound.cpp diff --git a/extras/tests/Cpp11/nullptr.cpp b/extras/tests/JsonVariant/nullptr.cpp similarity index 100% rename from extras/tests/Cpp11/nullptr.cpp rename to extras/tests/JsonVariant/nullptr.cpp diff --git a/extras/tests/Cpp11/stl_containers.cpp b/extras/tests/JsonVariant/stl_containers.cpp similarity index 100% rename from extras/tests/Cpp11/stl_containers.cpp rename to extras/tests/JsonVariant/stl_containers.cpp diff --git a/extras/tests/MixedConfiguration/CMakeLists.txt b/extras/tests/MixedConfiguration/CMakeLists.txt index 01d1216e3..791a7a624 100644 --- a/extras/tests/MixedConfiguration/CMakeLists.txt +++ b/extras/tests/MixedConfiguration/CMakeLists.txt @@ -19,6 +19,8 @@ add_executable(MixedConfigurationTests issue1707.cpp use_double_0.cpp use_double_1.cpp + use_long_long_0.cpp + use_long_long_1.cpp ) set_target_properties(MixedConfigurationTests PROPERTIES UNITY_BUILD OFF) diff --git a/extras/tests/Cpp11/use_long_long_0.cpp b/extras/tests/MixedConfiguration/use_long_long_0.cpp similarity index 100% rename from extras/tests/Cpp11/use_long_long_0.cpp rename to extras/tests/MixedConfiguration/use_long_long_0.cpp diff --git a/extras/tests/Cpp11/use_long_long_1.cpp b/extras/tests/MixedConfiguration/use_long_long_1.cpp similarity index 100% rename from extras/tests/Cpp11/use_long_long_1.cpp rename to extras/tests/MixedConfiguration/use_long_long_1.cpp diff --git a/extras/tests/Numbers/CMakeLists.txt b/extras/tests/Numbers/CMakeLists.txt index 05e1e8949..f7cf66169 100644 --- a/extras/tests/Numbers/CMakeLists.txt +++ b/extras/tests/Numbers/CMakeLists.txt @@ -2,9 +2,6 @@ # Copyright © 2014-2022, Benoit BLANCHON # MIT License -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED OFF) - add_executable(NumbersTests convertNumber.cpp parseFloat.cpp From 007b4f3362b1b272901ed67419e468e3ef145594 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Thu, 9 Feb 2023 18:56:14 +0100 Subject: [PATCH 22/89] Update Catch library to 2.13.10 (#1820) --- extras/tests/Cpp17/string_view.cpp | 2 +- .../JsonDeserializer/DeserializationError.cpp | 2 + .../tests/JsonDeserializer/nestingLimit.cpp | 2 + extras/tests/JsonVariant/nullptr.cpp | 8 +- extras/tests/Misc/Readers.cpp | 2 + extras/tests/Misc/TypeTraits.cpp | 61 +- extras/tests/Misc/arithmeticCompare.cpp | 100 +- extras/tests/MsgPackDeserializer/filter.cpp | 2 + extras/tests/MsgPackDeserializer/misc.cpp | 2 + .../MsgPackDeserializer/nestingLimit.cpp | 2 + extras/tests/Numbers/convertNumber.cpp | 137 +- extras/tests/catch/CMakeLists.txt | 8 +- extras/tests/catch/catch.hpp | 24456 ++++++++++------ 13 files changed, 15469 insertions(+), 9315 deletions(-) diff --git a/extras/tests/Cpp17/string_view.cpp b/extras/tests/Cpp17/string_view.cpp index 729c59ae9..a0b4b61d9 100644 --- a/extras/tests/Cpp17/string_view.cpp +++ b/extras/tests/Cpp17/string_view.cpp @@ -1,6 +1,6 @@ #include - #include + #include #if !ARDUINOJSON_ENABLE_STRING_VIEW diff --git a/extras/tests/JsonDeserializer/DeserializationError.cpp b/extras/tests/JsonDeserializer/DeserializationError.cpp index 01ddaf69e..0ff27dbef 100644 --- a/extras/tests/JsonDeserializer/DeserializationError.cpp +++ b/extras/tests/JsonDeserializer/DeserializationError.cpp @@ -5,6 +5,8 @@ #include #include +#include + void testStringification(DeserializationError error, std::string expected) { REQUIRE(error.c_str() == expected); } diff --git a/extras/tests/JsonDeserializer/nestingLimit.cpp b/extras/tests/JsonDeserializer/nestingLimit.cpp index 0cdcb3e54..1977be33c 100644 --- a/extras/tests/JsonDeserializer/nestingLimit.cpp +++ b/extras/tests/JsonDeserializer/nestingLimit.cpp @@ -5,6 +5,8 @@ #include #include +#include + #define SHOULD_WORK(expression) REQUIRE(DeserializationError::Ok == expression); #define SHOULD_FAIL(expression) \ REQUIRE(DeserializationError::TooDeep == expression); diff --git a/extras/tests/JsonVariant/nullptr.cpp b/extras/tests/JsonVariant/nullptr.cpp index 813b9cc2a..02fa1a4c7 100644 --- a/extras/tests/JsonVariant/nullptr.cpp +++ b/extras/tests/JsonVariant/nullptr.cpp @@ -11,15 +11,15 @@ TEST_CASE("nullptr") { JsonVariant variant = doc.to(); SECTION("JsonVariant == nullptr") { - REQUIRE((variant == nullptr)); - REQUIRE_FALSE((variant != nullptr)); + REQUIRE(variant == nullptr); + REQUIRE_FALSE(variant != nullptr); } SECTION("JsonVariant != nullptr") { variant.set(42); - REQUIRE_FALSE((variant == nullptr)); - REQUIRE((variant != nullptr)); + REQUIRE_FALSE(variant == nullptr); + REQUIRE(variant != nullptr); } SECTION("JsonVariant.set(nullptr)") { diff --git a/extras/tests/Misc/Readers.cpp b/extras/tests/Misc/Readers.cpp index e46ad1e72..b4fa2b9bd 100644 --- a/extras/tests/Misc/Readers.cpp +++ b/extras/tests/Misc/Readers.cpp @@ -6,6 +6,8 @@ #include #include +#include + using namespace ARDUINOJSON_NAMESPACE; TEST_CASE("Reader") { diff --git a/extras/tests/Misc/TypeTraits.cpp b/extras/tests/Misc/TypeTraits.cpp index 76ec48617..891a09037 100644 --- a/extras/tests/Misc/TypeTraits.cpp +++ b/extras/tests/Misc/TypeTraits.cpp @@ -5,6 +5,8 @@ #include #include +#include + using namespace ARDUINOJSON_NAMESPACE; class EmptyClass {}; @@ -19,9 +21,9 @@ TEST_CASE("Polyfills/type_traits") { } SECTION("is_array") { - REQUIRE_FALSE((is_array::value)); - REQUIRE((is_array::value)); - REQUIRE((is_array::value)); + REQUIRE_FALSE(is_array::value); + REQUIRE(is_array::value); + REQUIRE(is_array::value); } SECTION("is_const") { @@ -172,36 +174,35 @@ TEST_CASE("Polyfills/type_traits") { } SECTION("is_convertible") { - CHECK((is_convertible::value == true)); - CHECK((is_convertible::value == true)); - CHECK((is_convertible::value == true)); - CHECK((is_convertible::value == false)); - CHECK((is_convertible::value == false)); - - CHECK((is_convertible::value == - false)); - CHECK((is_convertible::value == false)); - CHECK((is_convertible::value == true)); - CHECK((is_convertible::value == true)); - CHECK((is_convertible::value == true)); - CHECK((is_convertible, JsonVariantConst>::value == - true)); - CHECK((is_convertible::value == true)); - CHECK((is_convertible::value == true)); - CHECK((is_convertible, - JsonVariantConst>::value == true)); - CHECK((is_convertible::value == true)); - CHECK( - (is_convertible::value == true)); - CHECK((is_convertible, JsonVariantConst>::value == - true)); + CHECK(is_convertible::value == true); + CHECK(is_convertible::value == true); + CHECK(is_convertible::value == true); + CHECK(is_convertible::value == false); + CHECK(is_convertible::value == false); + + CHECK(is_convertible::value == + false); + CHECK(is_convertible::value == false); + CHECK(is_convertible::value == true); + CHECK(is_convertible::value == true); + CHECK(is_convertible::value == true); + CHECK(is_convertible, JsonVariantConst>::value == + true); + CHECK(is_convertible::value == true); + CHECK(is_convertible::value == true); + CHECK(is_convertible, + JsonVariantConst>::value == true); + CHECK(is_convertible::value == true); + CHECK(is_convertible::value == true); + CHECK(is_convertible, JsonVariantConst>::value == + true); } SECTION("is_class") { - CHECK((is_class::value == false)); - CHECK((is_class::value == false)); - CHECK((is_class::value == false)); - CHECK((is_class::value == true)); + CHECK(is_class::value == false); + CHECK(is_class::value == false); + CHECK(is_class::value == false); + CHECK(is_class::value == true); } SECTION("is_enum") { diff --git a/extras/tests/Misc/arithmeticCompare.cpp b/extras/tests/Misc/arithmeticCompare.cpp index a67943e8a..c9900b95d 100644 --- a/extras/tests/Misc/arithmeticCompare.cpp +++ b/extras/tests/Misc/arithmeticCompare.cpp @@ -9,95 +9,89 @@ using namespace ARDUINOJSON_NAMESPACE; TEST_CASE("arithmeticCompare()") { SECTION("int vs uint8_t") { - CHECK((arithmeticCompare(256, 1) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(41, 42) == COMPARE_RESULT_LESS)); - CHECK((arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(43, 42) == COMPARE_RESULT_GREATER)); + CHECK(arithmeticCompare(256, 1) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(41, 42) == COMPARE_RESULT_LESS); + CHECK(arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(43, 42) == COMPARE_RESULT_GREATER); } SECTION("unsigned vs int") { - CHECK((arithmeticCompare(0, -1) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(42, 41) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(42, 43) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompare(0, -1) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(42, 41) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(42, 43) == COMPARE_RESULT_LESS); } SECTION("float vs int") { - CHECK((arithmeticCompare(42, 41) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(42, 43) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompare(42, 41) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(42, 43) == COMPARE_RESULT_LESS); } SECTION("int vs unsigned") { - CHECK((arithmeticCompare(-1, 0) == COMPARE_RESULT_LESS)); - CHECK((arithmeticCompare(0, 0) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(1, 0) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(42, 41) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(42, 43) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompare(-1, 0) == COMPARE_RESULT_LESS); + CHECK(arithmeticCompare(0, 0) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(1, 0) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(42, 41) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(42, 42) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(42, 43) == COMPARE_RESULT_LESS); } SECTION("unsigned vs unsigned") { - CHECK((arithmeticCompare(42, 41) == - COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(42, 42) == - COMPARE_RESULT_EQUAL)); - CHECK( - (arithmeticCompare(42, 43) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompare(42, 41) == + COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(42, 42) == + COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(42, 43) == COMPARE_RESULT_LESS); } SECTION("bool vs bool") { - CHECK( - (arithmeticCompare(false, false) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(true, true) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(false, true) == COMPARE_RESULT_LESS)); - CHECK( - (arithmeticCompare(true, false) == COMPARE_RESULT_GREATER)); + CHECK(arithmeticCompare(false, false) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(true, true) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(false, true) == COMPARE_RESULT_LESS); + CHECK(arithmeticCompare(true, false) == COMPARE_RESULT_GREATER); } SECTION("bool vs int") { - CHECK((arithmeticCompare(false, -1) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(false, 0) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(false, 1) == COMPARE_RESULT_LESS)); - CHECK((arithmeticCompare(true, 0) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(true, 1) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(true, 2) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompare(false, -1) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(false, 0) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(false, 1) == COMPARE_RESULT_LESS); + CHECK(arithmeticCompare(true, 0) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(true, 1) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(true, 2) == COMPARE_RESULT_LESS); } SECTION("bool vs int") { - CHECK((arithmeticCompare(0, false) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(1, true) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompare(1, false) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompare(0, true) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompare(0, false) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(1, true) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompare(1, false) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompare(0, true) == COMPARE_RESULT_LESS); } } TEST_CASE("arithmeticCompareNegateLeft()") { SECTION("unsigned vs int") { - CHECK((arithmeticCompareNegateLeft(0, 1) == COMPARE_RESULT_LESS)); - CHECK((arithmeticCompareNegateLeft(42, -41) == COMPARE_RESULT_LESS)); - CHECK((arithmeticCompareNegateLeft(42, -42) == COMPARE_RESULT_EQUAL)); - CHECK( - (arithmeticCompareNegateLeft(42, -43) == COMPARE_RESULT_GREATER)); + CHECK(arithmeticCompareNegateLeft(0, 1) == COMPARE_RESULT_LESS); + CHECK(arithmeticCompareNegateLeft(42, -41) == COMPARE_RESULT_LESS); + CHECK(arithmeticCompareNegateLeft(42, -42) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompareNegateLeft(42, -43) == COMPARE_RESULT_GREATER); } SECTION("unsigned vs unsigned") { - CHECK( - (arithmeticCompareNegateLeft(42, 42) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompareNegateLeft(42, 42) == COMPARE_RESULT_LESS); } } TEST_CASE("arithmeticCompareNegateRight()") { SECTION("int vs unsigned") { - CHECK((arithmeticCompareNegateRight(1, 0) == COMPARE_RESULT_GREATER)); - CHECK( - (arithmeticCompareNegateRight(-41, 42) == COMPARE_RESULT_GREATER)); - CHECK((arithmeticCompareNegateRight(-42, 42) == COMPARE_RESULT_EQUAL)); - CHECK((arithmeticCompareNegateRight(-43, 42) == COMPARE_RESULT_LESS)); + CHECK(arithmeticCompareNegateRight(1, 0) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompareNegateRight(-41, 42) == COMPARE_RESULT_GREATER); + CHECK(arithmeticCompareNegateRight(-42, 42) == COMPARE_RESULT_EQUAL); + CHECK(arithmeticCompareNegateRight(-43, 42) == COMPARE_RESULT_LESS); } SECTION("unsigned vs unsigned") { - CHECK((arithmeticCompareNegateRight(42, 42) == - COMPARE_RESULT_GREATER)); + CHECK(arithmeticCompareNegateRight(42, 42) == + COMPARE_RESULT_GREATER); } } diff --git a/extras/tests/MsgPackDeserializer/filter.cpp b/extras/tests/MsgPackDeserializer/filter.cpp index 57dd7bea9..8de3aec71 100644 --- a/extras/tests/MsgPackDeserializer/filter.cpp +++ b/extras/tests/MsgPackDeserializer/filter.cpp @@ -5,6 +5,8 @@ #include #include +#include + using namespace ARDUINOJSON_NAMESPACE; TEST_CASE("deserializeMsgPack() filter") { diff --git a/extras/tests/MsgPackDeserializer/misc.cpp b/extras/tests/MsgPackDeserializer/misc.cpp index 071717164..7f880fe56 100644 --- a/extras/tests/MsgPackDeserializer/misc.cpp +++ b/extras/tests/MsgPackDeserializer/misc.cpp @@ -5,6 +5,8 @@ #include #include +#include + TEST_CASE("deserializeMsgPack() returns EmptyInput") { StaticJsonDocument<100> doc; diff --git a/extras/tests/MsgPackDeserializer/nestingLimit.cpp b/extras/tests/MsgPackDeserializer/nestingLimit.cpp index 6005f55bb..568b8c449 100644 --- a/extras/tests/MsgPackDeserializer/nestingLimit.cpp +++ b/extras/tests/MsgPackDeserializer/nestingLimit.cpp @@ -5,6 +5,8 @@ #include #include +#include + #define SHOULD_WORK(expression) REQUIRE(DeserializationError::Ok == expression); #define SHOULD_FAIL(expression) \ REQUIRE(DeserializationError::TooDeep == expression); diff --git a/extras/tests/Numbers/convertNumber.cpp b/extras/tests/Numbers/convertNumber.cpp index 8c193dc30..3cf795dce 100644 --- a/extras/tests/Numbers/convertNumber.cpp +++ b/extras/tests/Numbers/convertNumber.cpp @@ -10,126 +10,123 @@ using namespace ARDUINOJSON_NAMESPACE; TEST_CASE("canConvertNumber()") { SECTION("int8_t -> int8_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(-128)) == true); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(-128) == true); } SECTION("int8_t -> int16_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(-128)) == true); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(-128) == true); } SECTION("int8_t -> uint8_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(-128)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(-128) == false); } SECTION("int8_t -> uint16_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(-128)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(-128) == false); } SECTION("int16_t -> int8_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(128)) == false); - CHECK((canConvertNumber(-128)) == true); - CHECK((canConvertNumber(-129)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(128) == false); + CHECK(canConvertNumber(-128) == true); + CHECK(canConvertNumber(-129) == false); } SECTION("int16_t -> uint8_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(255)) == true); - CHECK((canConvertNumber(256)) == false); - CHECK((canConvertNumber(-1)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(255) == true); + CHECK(canConvertNumber(256) == false); + CHECK(canConvertNumber(-1) == false); } SECTION("uint8_t -> int8_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(128)) == false); - CHECK((canConvertNumber(255)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(128) == false); + CHECK(canConvertNumber(255) == false); } SECTION("uint8_t -> int16_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(128)) == true); - CHECK((canConvertNumber(255)) == true); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(128) == true); + CHECK(canConvertNumber(255) == true); } SECTION("uint8_t -> uint8_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(128)) == true); - CHECK((canConvertNumber(255)) == true); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(128) == true); + CHECK(canConvertNumber(255) == true); } SECTION("uint8_t -> uint16_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(127)) == true); - CHECK((canConvertNumber(128)) == true); - CHECK((canConvertNumber(255)) == true); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(127) == true); + CHECK(canConvertNumber(128) == true); + CHECK(canConvertNumber(255) == true); } SECTION("float -> int32_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(-2.147483904e9f)) == false); - CHECK((canConvertNumber(-2.147483648e+9f)) == true); - CHECK((canConvertNumber(2.14748352e+9f)) == true); - CHECK((canConvertNumber(2.14748365e+9f)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(-2.147483904e9f) == false); + CHECK(canConvertNumber(-2.147483648e+9f) == true); + CHECK(canConvertNumber(2.14748352e+9f) == true); + CHECK(canConvertNumber(2.14748365e+9f) == false); } SECTION("double -> int32_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(-2.147483649e+9)) == false); - CHECK((canConvertNumber(-2.147483648e+9)) == true); - CHECK((canConvertNumber(2.147483647e+9)) == true); - CHECK((canConvertNumber(2.147483648e+9)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(-2.147483649e+9) == false); + CHECK(canConvertNumber(-2.147483648e+9) == true); + CHECK(canConvertNumber(2.147483647e+9) == true); + CHECK(canConvertNumber(2.147483648e+9) == false); } SECTION("float -> uint32_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(-1.401298e-45f)) == false); - CHECK((canConvertNumber(4.29496704e+9f)) == true); - CHECK((canConvertNumber(4.294967296e+9f)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(-1.401298e-45f) == false); + CHECK(canConvertNumber(4.29496704e+9f) == true); + CHECK(canConvertNumber(4.294967296e+9f) == false); } #if ARDUINOJSON_HAS_LONG_LONG SECTION("float -> int64_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(-9.22337204e+18f)) == true); - CHECK((canConvertNumber(9.22337149e+18f)) == true); - CHECK((canConvertNumber(9.22337204e+18f)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(-9.22337204e+18f) == true); + CHECK(canConvertNumber(9.22337149e+18f) == true); + CHECK(canConvertNumber(9.22337204e+18f) == false); } SECTION("double -> int64_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(-9.2233720368547758e+18)) == true); - CHECK((canConvertNumber(9.2233720368547748e+18)) == true); - CHECK((canConvertNumber(9.2233720368547758e+18)) == false); + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(-9.2233720368547758e+18) == true); + CHECK(canConvertNumber(9.2233720368547748e+18) == true); + CHECK(canConvertNumber(9.2233720368547758e+18) == false); } SECTION("float -> uint64_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(-1.401298e-45f)) == false); - CHECK((canConvertNumber(1.844674297419792384e+19f)) == - true); - CHECK((canConvertNumber(1.8446744073709551616e+19f)) == + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(-1.401298e-45f) == false); + CHECK(canConvertNumber(1.84467429741979238e+19f) == true); + CHECK(canConvertNumber(1.844674407370955161e+19f) == false); } SECTION("double -> uint64_t") { - CHECK((canConvertNumber(0)) == true); - CHECK((canConvertNumber(-4.94065645841247e-324)) == - false); - CHECK((canConvertNumber(1.8446744073709549568e+19)) == - true); - CHECK((canConvertNumber(1.8446744073709551616e+19)) == + CHECK(canConvertNumber(0) == true); + CHECK(canConvertNumber(-4.9406564584124e-324) == false); + CHECK(canConvertNumber(1.844674407370954958e+19) == true); + CHECK(canConvertNumber(1.844674407370955166e+19) == false); } #endif diff --git a/extras/tests/catch/CMakeLists.txt b/extras/tests/catch/CMakeLists.txt index 776a07a00..0129af118 100644 --- a/extras/tests/catch/CMakeLists.txt +++ b/extras/tests/catch/CMakeLists.txt @@ -2,7 +2,7 @@ # Copyright Benoit Blanchon 2014-2021 # MIT License -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED OFF) add_library(catch @@ -15,7 +15,7 @@ target_include_directories(catch ${CMAKE_CURRENT_SOURCE_DIR} ) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - # prevent "xxx will change in GCC x.x" with arm-linux-gnueabihf-gcc - target_compile_options(catch PRIVATE -Wno-psabi) +if(MINGW) + # prevent "too many sections (32837)" with MinGW + target_compile_options(catch PRIVATE -Wa,-mbig-obj) endif() diff --git a/extras/tests/catch/catch.hpp b/extras/tests/catch/catch.hpp index fe13018da..9b309bddc 100644 --- a/extras/tests/catch/catch.hpp +++ b/extras/tests/catch/catch.hpp @@ -1,17 +1,21 @@ /* - * Catch v1.12.2 - * Generated: 2023-01-17 08:45:40.979381 + * Catch v2.13.10 + * Generated: 2022-10-16 11:01:23.452308 * ---------------------------------------------------------- * 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) 2022 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 13 +#define CATCH_VERSION_PATCH 10 #ifdef __clang__ # pragma clang system_header @@ -19,36 +23,69 @@ # 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 + +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html +#ifdef __APPLE__ +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && 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 +93,106 @@ # 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(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED +// start catch_common.h -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// 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__ +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) && !defined(__CUDACC__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ # endif -# 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 push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) -# endif +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_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__ //////////////////////////////////////////////////////////////////////////////// -// 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 +// 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__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS #endif #ifdef __OS400__ @@ -150,6 +200,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 +226,245 @@ // 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)) -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -#endif // __BORLANDC__ +# endif +#endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ +// Visual C++ +#if defined(_MSC_VER) -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ +// 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 -#endif // __DMC__ +# if !defined(__clang__) // Handle Clang masquerading for msvc -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif +// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) +# endif // __clang__ -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below +#endif // _MSC_VER -#endif // __GNUC__ +#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 //////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH - -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +// 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 -#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 - -#endif // _MSC_VER - //////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ -// 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 - +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN #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 ) +//////////////////////////////////////////////////////////////////////////////// -// 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 ) +// 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 +// 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 -# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif -# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# 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) + # include + # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif + # 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) -# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# endif +#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_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_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 -# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# 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 -# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# 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_CPP11_LONG_LONG) -# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG -# 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_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 +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif -#endif // __cplusplus >= 201103L +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif -// 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 +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #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 + +#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_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 + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS #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 + +#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_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TUPLE + +#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_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -# define CATCH_CONFIG_VARIADIC_MACROS + +#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_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 + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER #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 + +// 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_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(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #endif -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS #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 +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS #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) -# define CATCH_CONFIG_WINDOWS_SEH +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS #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) -# define CATCH_CONFIG_POSIX_SIGNALS +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS #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 +// 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 -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) +#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 -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override +#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_OVERRIDE +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) #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 +473,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 ); + struct SourceLineInfo { - std::size_t m_count; - std::string m_label; - }; + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} - struct SourceLineInfo { + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - 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; + 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 +522,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,363 +540,812 @@ 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 +// start catch_interfaces_testcase.h -#include +#include namespace Catch { - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); }; - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); + class TestCase; + struct IConfig; - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; - IGeneratorsForTest* createGeneratorsForTest(); + 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 namespace Catch +} -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED +// end catch_interfaces_testcase.h +// start catch_stringref.h -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif +#include +#include +#include +#include namespace Catch { - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { + /// 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: - 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 ); } + using size_type = std::size_t; + using const_iterator = const char*; private: - T* m_p; - }; + static constexpr char const* const s_empty = ""; - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; - template - struct SharedImpl : T { + StringRef( char const* rawChars ) noexcept; - SharedImpl() : m_rc( 0 ){} + 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() ) + {} - virtual void addRef() const { - ++m_rc; + explicit operator std::string() const { + return std::string(m_start, m_size); } - virtual void release() const { - if( --m_rc == 0 ) - delete this; + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); } - mutable unsigned int m_rc; - }; + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } -} // end namespace Catch + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } -#ifdef __clang__ -#pragma clang diagnostic pop -#endif + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; -namespace Catch { + 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; - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; - struct IContext - { - virtual ~IContext(); + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } - 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; + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } }; - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr const& config ) = 0; - }; + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( std::string const& streamName ); + 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 ); } -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED +// end catch_stringref.h +// start catch_preprocessor.hpp -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED -#include +#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__))) -namespace Catch { +#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 - class TestSpec; +#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 - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) - class TestCase; - struct IConfig; +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; +#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, _3, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#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