diff --git a/Docs/API/html/_jinx_8h.html b/Docs/API/html/_jinx_8h.html index 0e5e1ce..5ae9227 100644 --- a/Docs/API/html/_jinx_8h.html +++ b/Docs/API/html/_jinx_8h.html @@ -213,7 +213,7 @@  Minor version number.
  -const uint32_t Jinx::PatchNumber = 4 +const uint32_t Jinx::PatchNumber = 10  Patch number.
  diff --git a/Docs/API/html/_jinx_8h_source.html b/Docs/API/html/_jinx_8h_source.html index 3813243..4d5a7a1 100644 --- a/Docs/API/html/_jinx_8h_source.html +++ b/Docs/API/html/_jinx_8h_source.html @@ -69,7 +69,7 @@
Jinx.h
-Go to the documentation of this file.
1 /*
2 The MIT License (MIT)
3 
4 Copyright (c) 2016 James Boer
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24 
25 #pragma once
26 #ifndef JINX_H__
27 #define JINX_H__
28 
46 // Platform definitions
47 #if defined(_WIN32) || defined(_WIN64)
48 #define JINX_WINDOWS
49 #define JINX_USE_FROM_CHARS
50 #pragma warning(push)
51 #pragma warning(disable : 4530) // Silence warnings if exceptions are disabled
52 #endif
53 
54 #if defined(__linux__) || defined(__linux)
55 #define JINX_LINUX
56 #endif
57 
58 #ifdef __APPLE__
59 #ifdef __MACH__
60 #define JINX_MACOS
61 #endif
62 #endif
63 
64 /*
65 On macOS, use of std::any is restricted to applications targeting versions 10.14 and up (Mohave) due to
66 limitations in std::any_cast. As such, Jinx provides optional void * aliases in place of std::any in
67 case a project wishes to target macOS clients earlier than 10.14.
68 */
69 #define JINX_USE_ANY
70 
71 #include <memory>
72 #include <functional>
73 #include <vector>
74 #include <map>
75 #include <string>
76 #include <cstddef>
77 #include <limits>
78 #include <cstring>
79 #include <cassert>
80 #ifdef JINX_USE_ANY
81 #include <any>
82 #endif
83 
84 #ifdef JINX_WINDOWS
85 #pragma warning(pop)
86 #endif
87 
88 #include "JxMemory.h"
89 #include "JxTypes.h"
90 #include "JxBuffer.h"
91 #include "JxCollection.h"
92 #include "JxCoroutine.h"
93 #include "JxVariant.h"
94 
95 #ifndef inline_t
96 #define inline_t
97 #endif
98 
100 namespace Jinx
101 {
103  const uint32_t MajorVersion = 1;
104 
106  const uint32_t MinorVersion = 3;
107 
109  const uint32_t PatchNumber = 4;
110 
111  // Forward declaration
112  class IScript;
113 
114  // Shared pointer to script object
115  using ScriptPtr = std::shared_ptr<IScript>;
116 
117  // Function parameters
118  using Parameters = std::vector<Variant, Allocator<Variant>>;
119 
120  // Signature for native function callback
121  using FunctionCallback = std::function<Variant(ScriptPtr, const Parameters &)>;
122 
123 #ifdef JINX_USE_ANY
124  using Any = std::any;
125 #define JinxAny std::any
126 #define JinxAnyCast std::any_cast
127 #else
128  using Any = void *;
129 #define JinxAny Jinx::Any
130 #define JinxAnyCast reinterpret_cast
131 #endif
132 
134  enum class Visibility
135  {
137  Public,
139  Private
140  };
141 
143  enum class Access
144  {
146  ReadWrite,
148  ReadOnly,
149  };
150 
152  enum class LogLevel
153  {
155  Info,
157  Warning,
159  Error,
160  };
161 
163 
169  class ILibrary
170  {
171  public:
172 
174 
182  virtual bool RegisterFunction(Visibility visibility, const String & name, FunctionCallback function) = 0;
183 
185 
194  virtual bool RegisterProperty(Visibility visibility, Access access, const String & name, const Variant & value) = 0;
195 
197 
202  virtual Variant GetProperty(const String & name) const = 0;
203 
205 
210  virtual void SetProperty(const String & name, const Variant & value) = 0;
211 
212  protected:
213  virtual ~ILibrary() {}
214  };
215 
217  using LibraryPtr = std::shared_ptr<ILibrary>;
218 
219 
221 
228  class IScript
229  {
230  public:
231 
233 
238  virtual bool Execute() = 0;
239 
241 
245  virtual bool IsFinished() const = 0;
246 
248 
253  virtual Variant GetVariable(const String & name) const = 0;
254 
256 
260  virtual void SetVariable(const String & name, const Variant & value) = 0;
261 
263 
269  virtual RuntimeID FindFunction(LibraryPtr library, const String & name) = 0;
270 
272 
277  virtual Variant CallFunction(RuntimeID id, Parameters params) = 0;
278 
280 
286  virtual CoroutinePtr CallAsyncFunction(RuntimeID id, Parameters params) = 0;
287 
289 
293  virtual const String & GetName() const = 0;
294 
296 
300  virtual Any GetUserContext() const = 0;
301 
303 
306  virtual LibraryPtr GetLibrary() const = 0;
307 
308  protected:
309  virtual ~IScript() {}
310  };
311 
313 
320  {
322  uint64_t compilationTimeNs = 0;
324  uint64_t executionTimeNs = 0;
326  uint64_t perfTimeNs = 0;
330  uint64_t scriptExecutionCount = 0;
332  uint64_t scriptCompletionCount = 0;
334  uint64_t instructionCount = 0;
335  };
336 
338 
341  class IRuntime
342  {
343  public:
344 
346 
357  virtual BufferPtr Compile(const char * scriptText, String name = String(), std::initializer_list<String> libraries = {}) = 0;
358 
360 
368  virtual ScriptPtr CreateScript(BufferPtr bytecode, Any userContext = nullptr) = 0;
369 
371 
380  virtual ScriptPtr CreateScript(const char * scriptText, Any userContext = nullptr, String name = String(), std::initializer_list<String> libraries = {}) = 0;
381 
383 
393  virtual ScriptPtr ExecuteScript(const char * scriptText, Any userContext = nullptr, String name = String(), std::initializer_list<String> libraries = {}) = 0;
394 
396 
401  virtual LibraryPtr GetLibrary(const String & name) = 0;
402 
404 
410  virtual PerformanceStats GetScriptPerformanceStats(bool resetStats = true) = 0;
411 
412  // Strip debug info from bytecode
420  virtual BufferPtr StripDebugInfo(BufferPtr bytecode) const = 0;
421 
422  protected:
423  virtual ~IRuntime() {}
424  };
425 
427  using RuntimePtr = std::shared_ptr<IRuntime>;
428 
429 
431 
435 
436 
438  using AllocFn = std::function<void *(size_t bytes)>;
439 
441  using ReallocFn = std::function<void *(void *, size_t newBytes, size_t currBytes)>;
442 
444  using FreeFn = std::function<void(void *, size_t bytes)>;
445 
447  using LogFn = std::function<void(LogLevel level, const char * msg)>;
448 
449 
451 
457  {
461  bool enableLogging = true;
463  bool logSymbols = false;
465  bool logBytecode = false;
467  bool enableDebugInfo = true;
475  uint32_t maxInstructions = 2000;
478  };
479 
481  String GetVersionString();
482 
484 
491  void Initialize(const GlobalParams & params);
492 
493 }
494 
495 #endif // JINX_H__
virtual Variant GetVariable(const String &name) const =0
Get a variable by name.
+Go to the documentation of this file.
1 /*
2 The MIT License (MIT)
3 
4 Copyright (c) 2016 James Boer
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24 
25 #pragma once
26 #ifndef JINX_H__
27 #define JINX_H__
28 
46 // Platform definitions
47 #if defined(_WIN32) || defined(_WIN64)
48 #define JINX_WINDOWS
49 #define JINX_USE_FROM_CHARS
50 #pragma warning(push)
51 #pragma warning(disable : 4530) // Silence warnings if exceptions are disabled
52 #endif
53 
54 #if defined(__linux__) || defined(__linux)
55 #define JINX_LINUX
56 #endif
57 
58 #ifdef __APPLE__
59 #ifdef __MACH__
60 #define JINX_MACOS
61 #endif
62 #endif
63 
64 /*
65 On macOS, use of std::any is restricted to applications targeting versions 10.14 and up (Mohave) due to
66 limitations in std::any_cast. As such, Jinx provides optional void * aliases in place of std::any in
67 case a project wishes to target macOS clients earlier than 10.14.
68 */
69 #define JINX_USE_ANY
70 
71 #include <memory>
72 #include <functional>
73 #include <vector>
74 #include <map>
75 #include <string>
76 #include <cstddef>
77 #include <limits>
78 #include <cstring>
79 #include <cassert>
80 #ifdef JINX_USE_ANY
81 #include <any>
82 #endif
83 
84 #ifdef JINX_WINDOWS
85 #pragma warning(pop)
86 #endif
87 
88 #include "JxMemory.h"
89 #include "JxTypes.h"
90 #include "JxBuffer.h"
91 #include "JxCollection.h"
92 #include "JxCoroutine.h"
93 #include "JxVariant.h"
94 
95 #ifndef inline_t
96 #define inline_t
97 #endif
98 
100 namespace Jinx
101 {
103  const uint32_t MajorVersion = 1;
104 
106  const uint32_t MinorVersion = 3;
107 
109  const uint32_t PatchNumber = 10;
110 
111  // Forward declaration
112  class IScript;
113 
114  // Shared pointer to script object
115  using ScriptPtr = std::shared_ptr<IScript>;
116 
117  // Function parameters
118  using Parameters = std::vector<Variant, Allocator<Variant>>;
119 
120  // Signature for native function callback
121  using FunctionCallback = std::function<Variant(ScriptPtr, const Parameters &)>;
122 
123 #ifdef JINX_USE_ANY
124  using Any = std::any;
125 #define JinxAny std::any
126 #define JinxAnyCast std::any_cast
127 #else
128  using Any = void *;
129 #define JinxAny Jinx::Any
130 #define JinxAnyCast reinterpret_cast
131 #endif
132 
134  enum class Visibility
135  {
137  Public,
139  Private
140  };
141 
143  enum class Access
144  {
146  ReadWrite,
148  ReadOnly,
149  };
150 
152  enum class LogLevel
153  {
155  Info,
157  Warning,
159  Error,
160  };
161 
163 
169  class ILibrary
170  {
171  public:
172 
174 
182  virtual bool RegisterFunction(Visibility visibility, const String & name, FunctionCallback function) = 0;
183 
185 
194  virtual bool RegisterProperty(Visibility visibility, Access access, const String & name, const Variant & value) = 0;
195 
197 
202  virtual Variant GetProperty(const String & name) const = 0;
203 
205 
210  virtual void SetProperty(const String & name, const Variant & value) = 0;
211 
212  protected:
213  virtual ~ILibrary() {}
214  };
215 
217  using LibraryPtr = std::shared_ptr<ILibrary>;
218 
219 
221 
228  class IScript
229  {
230  public:
231 
233 
238  virtual bool Execute() = 0;
239 
241 
245  virtual bool IsFinished() const = 0;
246 
248 
253  virtual Variant GetVariable(const String & name) const = 0;
254 
256 
260  virtual void SetVariable(const String & name, const Variant & value) = 0;
261 
263 
269  virtual RuntimeID FindFunction(LibraryPtr library, const String & name) = 0;
270 
272 
277  virtual Variant CallFunction(RuntimeID id, Parameters params) = 0;
278 
280 
286  virtual CoroutinePtr CallAsyncFunction(RuntimeID id, Parameters params) = 0;
287 
289 
293  virtual const String & GetName() const = 0;
294 
296 
300  virtual Any GetUserContext() const = 0;
301 
303 
306  virtual LibraryPtr GetLibrary() const = 0;
307 
308  protected:
309  virtual ~IScript() {}
310  };
311 
313 
320  {
322  uint64_t compilationTimeNs = 0;
324  uint64_t executionTimeNs = 0;
326  uint64_t perfTimeNs = 0;
330  uint64_t scriptExecutionCount = 0;
332  uint64_t scriptCompletionCount = 0;
334  uint64_t instructionCount = 0;
335  };
336 
338 
341  class IRuntime
342  {
343  public:
344 
346 
357  virtual BufferPtr Compile(const char * scriptText, String name = String(), std::initializer_list<String> libraries = {}) = 0;
358 
360 
368  virtual ScriptPtr CreateScript(BufferPtr bytecode, Any userContext = nullptr) = 0;
369 
371 
380  virtual ScriptPtr CreateScript(const char * scriptText, Any userContext = nullptr, String name = String(), std::initializer_list<String> libraries = {}) = 0;
381 
383 
393  virtual ScriptPtr ExecuteScript(const char * scriptText, Any userContext = nullptr, String name = String(), std::initializer_list<String> libraries = {}) = 0;
394 
396 
401  virtual LibraryPtr GetLibrary(const String & name) = 0;
402 
404 
410  virtual PerformanceStats GetScriptPerformanceStats(bool resetStats = true) = 0;
411 
412  // Strip debug info from bytecode
420  virtual BufferPtr StripDebugInfo(BufferPtr bytecode) const = 0;
421 
422  protected:
423  virtual ~IRuntime() {}
424  };
425 
427  using RuntimePtr = std::shared_ptr<IRuntime>;
428 
429 
431 
435 
436 
438  using AllocFn = std::function<void *(size_t bytes)>;
439 
441  using ReallocFn = std::function<void *(void *, size_t newBytes, size_t currBytes)>;
442 
444  using FreeFn = std::function<void(void *, size_t bytes)>;
445 
447  using LogFn = std::function<void(LogLevel level, const char * msg)>;
448 
449 
451 
457  {
461  bool enableLogging = true;
463  bool logSymbols = false;
465  bool logBytecode = false;
467  bool enableDebugInfo = true;
475  uint32_t maxInstructions = 2000;
478  };
479 
481  String GetVersionString();
482 
484 
491  void Initialize(const GlobalParams & params);
492 
493 }
494 
495 #endif // JINX_H__
virtual Variant GetVariable(const String &name) const =0
Get a variable by name.
std::shared_ptr< ILibrary > LibraryPtr
Shared pointer to library object.
Definition: Jinx.h:217
uint64_t scriptCompilationCount
Number of scripts compiled.
Definition: Jinx.h:328
std::function< void(LogLevel level, const char *msg)> LogFn
Prototype for global logging function callback.
Definition: Jinx.h:447
diff --git a/Docs/Changelog.md b/Docs/Changelog.md index 662a739..4f59c37 100644 --- a/Docs/Changelog.md +++ b/Docs/Changelog.md @@ -1,6 +1,11 @@ # Change Log All notable changes to this project will be documented in this file. +## [1.3.10] - 2023-01-05 + +- Updated Catch2 to fix several compilation issues +- Correct error in tutorial about precedence of functions + ## [1.3.9] - 2022-06-17 - Fixed issue with duplicate non-local function registration diff --git a/Docs/Tutorial.docx b/Docs/Tutorial.docx index 25b3bd0..0792fcf 100644 Binary files a/Docs/Tutorial.docx and b/Docs/Tutorial.docx differ diff --git a/Docs/Tutorial.htm b/Docs/Tutorial.htm index c6c33bb..7c772a3 100644 Binary files a/Docs/Tutorial.htm and b/Docs/Tutorial.htm differ diff --git a/Docs/Tutorial.pdf b/Docs/Tutorial.pdf index b7b940a..415a42e 100644 Binary files a/Docs/Tutorial.pdf and b/Docs/Tutorial.pdf differ diff --git a/Include/Jinx.hpp b/Include/Jinx.hpp index 28922cf..a052c7e 100644 --- a/Include/Jinx.hpp +++ b/Include/Jinx.hpp @@ -768,7 +768,7 @@ namespace Jinx const uint32_t MinorVersion = 3; /// Patch number - const uint32_t PatchNumber = 9; + const uint32_t PatchNumber = 10; // Forward declaration class IScript; @@ -5604,6 +5604,7 @@ namespace Jinx::Impl inline uint32_t Parser::GetOperatorPrecedence(Opcode opcode) const { + // Lower values mean higher precedence switch (opcode) { case Opcode::Multiply: return 1; diff --git a/README.md b/README.md index 7da8b28..290da91 100644 --- a/README.md +++ b/README.md @@ -45,5 +45,5 @@ There is a [more comprehensive tutorial](https://jamesboer.github.io/Jinx/Tutori ## Jinx Status -Jinx was released as 1.0.0 (stable) on January 1, 2019, after three years of development, refinement, and testing. Additional work, for the immediate future, will be restricted to bug fixing or critical refinements, with the intention of retaining backwards compatibility. +Jinx was released as 1.0.0 (stable) on January 1, 2019, after three years of development, refinement, and testing. Since then, mostly minor language features and API enhancements have been edded. Additional work, for the immediate future, will be restricted to bug fixing or critical refinements, with the intention of retaining backwards compatibility. diff --git a/Source/Jinx.h b/Source/Jinx.h index d42b19a..713d874 100644 --- a/Source/Jinx.h +++ b/Source/Jinx.h @@ -106,7 +106,7 @@ namespace Jinx const uint32_t MinorVersion = 3; /// Patch number - const uint32_t PatchNumber = 9; + const uint32_t PatchNumber = 10; // Forward declaration class IScript; diff --git a/Source/JxParser.cpp b/Source/JxParser.cpp index 9cb8abd..c247e2b 100644 --- a/Source/JxParser.cpp +++ b/Source/JxParser.cpp @@ -167,6 +167,7 @@ namespace Jinx::Impl inline_t uint32_t Parser::GetOperatorPrecedence(Opcode opcode) const { + // Lower values mean higher precedence switch (opcode) { case Opcode::Multiply: return 1; diff --git a/Tests/UnitTests/TestCasts.cpp b/Tests/UnitTests/TestCasts.cpp index 308d3c0..a4d28ca 100644 --- a/Tests/UnitTests/TestCasts.cpp +++ b/Tests/UnitTests/TestCasts.cpp @@ -90,4 +90,4 @@ TEST_CASE("Test Casts", "[Casts]") REQUIRE(script->GetVariable("a").GetGuid() == guid); } -} \ No newline at end of file +} diff --git a/Tests/UnitTests/UnitTest.h b/Tests/UnitTests/UnitTest.h index 0b9f0c9..45b0197 100644 --- a/Tests/UnitTests/UnitTest.h +++ b/Tests/UnitTests/UnitTest.h @@ -39,4 +39,4 @@ Jinx::ScriptPtr TestCreateScript(const char * scriptText, Jinx::RuntimePtr runti Jinx::ScriptPtr TestExecuteScript(const char * scriptText, Jinx::RuntimePtr runtime = nullptr, JinxAny userContext = nullptr); bool TestExecuteScript(Jinx::ScriptPtr script); -#endif // UNIT_TESTS_H____ \ No newline at end of file +#endif // UNIT_TESTS_H____ diff --git a/Tests/UnitTests/catch.hpp b/Tests/UnitTests/catch.hpp index 4191607..d2a1242 100644 --- a/Tests/UnitTests/catch.hpp +++ b/Tests/UnitTests/catch.hpp @@ -1,9 +1,9 @@ /* - * Catch v2.4.1 - * Generated: 2018-09-28 15:50:15.645795 + * Catch v2.13.9 + * Generated: 2022-04-12 22:37:23.260201 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2018 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) @@ -14,8 +14,8 @@ #define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 4 -#define CATCH_VERSION_PATCH 1 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 9 #ifdef __clang__ # pragma clang system_header @@ -36,10 +36,11 @@ # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ - // GCC likes to warn on REQUIREs, and we cannot suppress them - // locally because g++'s support for _Pragma is lacking in older, - // still supported, versions -# 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" @@ -65,13 +66,16 @@ #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 TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif +# 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 @@ -131,30 +135,51 @@ namespace Catch { #endif -#if defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +// 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" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + #endif -#ifdef __clang__ +#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 + +# 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_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_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" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic pop" ) +# 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__ @@ -179,6 +204,7 @@ namespace Catch { // 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 //////////////////////////////////////////////////////////////////////////////// @@ -203,20 +229,16 @@ namespace Catch { // 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)) + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING # endif #endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ -#ifdef _MSC_VER - -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif +#if defined(_MSC_VER) // Universal Windows platform does not support SEH // Or console colours (or console at all...) @@ -226,6 +248,25 @@ namespace Catch { # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # endif +# if !defined(__clang__) // Handle Clang masquerading for msvc + +// 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 + +// 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__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// @@ -240,6 +281,12 @@ namespace Catch { # define CATCH_INTERNAL_CONFIG_NO_WCHAR #endif // __DJGPP__ +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + //////////////////////////////////////////////////////////////////////////////// // Use of __COUNTER__ is suppressed during code analysis in @@ -252,30 +299,56 @@ namespace Catch { #endif //////////////////////////////////////////////////////////////////////////////// -// Check if string_view is available and usable -// The check is split apart to work around v140 (VS2015) preprocessor issue... -#if defined(__has_include) -#if __has_include() && defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE #endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER #endif -//////////////////////////////////////////////////////////////////////////////// -// Check if variant is available and usable +// Various stdlib support checks that require __has_include #if defined(__has_include) -# 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) -# endif // defined(__clang__) && (__clang_major__ < 8) -# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // __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) #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) # define CATCH_CONFIG_COUNTER @@ -296,8 +369,8 @@ namespace Catch { # define CATCH_CONFIG_CPP11_TO_STRING #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL #endif #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) @@ -308,6 +381,10 @@ namespace Catch { # define CATCH_CONFIG_CPP17_VARIANT #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #endif @@ -320,17 +397,57 @@ namespace Catch { # define CATCH_CONFIG_DISABLE_EXCEPTIONS #endif +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) @@ -343,6 +460,10 @@ namespace Catch { #define CATCH_CATCH_ANON(type) catch (type) #endif +#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 ) @@ -356,6 +477,10 @@ namespace Catch { #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 CaseSensitive { enum Choice { @@ -382,12 +507,12 @@ namespace Catch { line( _line ) {} - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - bool empty() const noexcept; + bool empty() const noexcept { return file[0] == '\0'; } bool operator == ( SourceLineInfo const& other ) const noexcept; bool operator < ( SourceLineInfo const& other ) const noexcept; @@ -397,6 +522,11 @@ namespace Catch { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + // 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 @@ -423,9 +553,10 @@ namespace Catch { } // end namespace Catch #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_UNSUPPRESS_GLOBALS_WARNINGS + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // end catch_tag_alias_autoregistrar.h // start catch_test_registry.h @@ -433,7 +564,6 @@ namespace Catch { // start catch_interfaces_testcase.h #include -#include namespace Catch { @@ -444,8 +574,6 @@ namespace Catch { virtual ~ITestInvoker(); }; - using ITestCasePtr = std::shared_ptr; - class TestCase; struct IConfig; @@ -455,6 +583,7 @@ namespace Catch { virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); @@ -467,55 +596,30 @@ namespace Catch { #include #include #include +#include namespace Catch { - class StringData; - /// 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. c_str() must return a null terminated - /// string, however, and so the StringRef will internally take ownership - /// (taking a copy), if necessary. In theory this ownership is not externally - /// visible - but it does mean (substring) StringRefs should not be shared between - /// threads. + /// it may not be null terminated. class StringRef { public: using size_type = std::size_t; + using const_iterator = const char*; private: - friend struct StringRefTestAccess; - - char const* m_start; - size_type m_size; - - char* m_data = nullptr; - - void takeOwnership(); - static constexpr char const* const s_empty = ""; - public: // construction/ assignment - StringRef() noexcept - : StringRef( s_empty, 0 ) - {} - - StringRef( StringRef const& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ) - {} + char const* m_start = s_empty; + size_type m_size = 0; - StringRef( StringRef&& other ) noexcept - : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - other.m_data = nullptr; - } + public: // construction + constexpr StringRef() noexcept = default; StringRef( char const* rawChars ) noexcept; - StringRef( char const* rawChars, size_type size ) noexcept + constexpr StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) {} @@ -525,69 +629,333 @@ namespace Catch { m_size( stdString.size() ) {} - ~StringRef() noexcept { - delete[] m_data; - } - - auto operator = ( StringRef const &other ) noexcept -> StringRef& { - delete[] m_data; - m_data = nullptr; - m_start = other.m_start; - m_size = other.m_size; - return *this; + explicit operator std::string() const { + return std::string(m_start, m_size); } - operator std::string() const; - - void swap( StringRef& other ) noexcept; - public: // operators auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } - auto operator[] ( size_type index ) const noexcept -> char; + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } public: // named queries - auto empty() const noexcept -> bool { + constexpr auto empty() const noexcept -> bool { return m_size == 0; } - auto size() const noexcept -> size_type { + constexpr auto size() const noexcept -> size_type { return m_size; } - auto numberOfCharacters() const noexcept -> size_type; + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception auto c_str() const -> char const*; public: // substrings and searches - auto substr( size_type start, size_type size ) const noexcept -> StringRef; + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; - // Returns the current start pointer. - // Note that the pointer can change when if the StringRef is a substring - auto currentData() const noexcept -> char const*; + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; - private: // ownership queries - may not be consistent between calls - auto isOwned() const noexcept -> bool; - auto isSubstring() const noexcept -> bool; - }; + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; - auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; - auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { return StringRef( rawChars, size ); } - } // namespace Catch -inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { return Catch::StringRef( rawChars, size ); } // end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _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