diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 34dfb55..4562c02 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -12,32 +12,32 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout code
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: install python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
- python-version: '3.8'
+ python-version: '3.11'
- name: linter
run: |
- pip install cpplint
+ pip install cpplint==2.0.0
make lint
test:
runs-on: ubuntu-latest
steps:
- name: checkout code
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: install python
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
- python-version: '3.8'
+ python-version: '3.11'
- name: install tools
run: |
- pip install platformio==5.1.1
+ pip install platformio==6.1.10
sudo apt-get update && sudo apt-get install -y lcov
- name: run tests
@@ -47,10 +47,10 @@ jobs:
make clean coverage OPT=-O0
- name: Upload coverage to coveralls
- uses: coverallsapp/github-action@v1.1.2
+ uses: coverallsapp/github-action@v2.2.3
with:
github-token: ${{ secrets.github_token }}
- path-to-lcov: test/coverage.info
+ file: test/coverage.lcov
- name: build examples
run: make ci
diff --git a/.gitignore b/.gitignore
index db89cb9..8f7de42 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+.envrc
+.venv/
.pio/
**/.vscode
test/bin
@@ -13,6 +15,7 @@ test/bin
*.gcov
*.gcno
*.gcda
+*.lcov
test/coverage.info
test/report
**/tags
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 014921a..5067819 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,64 @@
# JLed changelog (github.com/jandelgado/jled)
+## [2024-12-01] 4.15.0
+
+* new: `Update()` methods now optionally return the last brightness value
+ calculated and written out to the LED. See `examples/last_brightness`
+
+## [2024-09-21] 4.14
+
+* new: make `JLed::Update(unit32_t t)` public, allowing optimizations and
+ simplified tests
+
+## [2023-09-10] 4.13.1
+
+* fix: `Update()` sometimes returning wrong state (https://github.com/jandelgado/jled/issues/122)
+
+## [2023-08-20] 4.13.0
+
+* new: `Stop()` takes optional parameter allowing to turn LED fully off
+
+## [2023-06-29] 4.12.2
+
+* fix: `JLedSequence` starting again after call to `Stop` (https://github.com/jandelgado/jled/issues/115)
+
+## [2023-01-11] 4.12.1
+
+* fix: add missing keywords to keywords.txt
+
+## [2022-11-13] 4.12.0
+
+* new: add `MinBrightness` method and scale output to interval defined by
+ `MinBrightness` and `MaxBrightness`.
+
+## [2022-11-13] 4.11.1
+
+* improve: reduce memory consumption of JLed objects by 3 bytes, simplify
+ state management.
+
+## [2022-03-29] 4.11.0
+
+* change: `JLedSequence` objects are now assignable, making switching
+ effects easier. See https://github.com/jandelgado/jled-example-switch-sequence for an example.
+
+## [2022-03-24] 4.10.0
+
+* new: `On`, `Off` and `Set` now take an optional `duration` value, making
+ these effects behave like any other in this regard. This allows to add
+ an `On` effect to a `JLedSequence` for a specific amount of time.
+
+## [2022-02-24] 4.9.1
+
+* fix: make sure JLedSequence methods like `Repeat` and `Forever` are chainable
+ like in the `JLed` class
+
## [2022-02-13] 4.9.0
* new: support ESP-IDF platform for the ESP32 (#87, thanks to @troky for the
initial work). See also repositories
https://github.com/jandelgado/jled-esp-idf-example and
https://github.com/jandelgado/jled-esp-idf-platformio-example
-
+
## [2021-10-18] 4.8.0
* new: make `Breathe` method more flexible (#78, thanks to @boraozgen)
@@ -54,12 +106,12 @@
## [2019-08-30] 4.2.1
-* fix: make sure memory alignment is correct (caused hard fault on
+* fix: make sure memory alignment is correct (caused hard fault on
SAMD21). Fixes #27.
## [2019-06-20] 4.2.0
-* changing an effect resets the Jled object so it starts over with the
+* changing an effect resets the Jled object so it starts over with the
new effect (see #25). Prior to this change, calling `Reset()` was
necessary.
@@ -109,10 +161,10 @@ In addition to the changes introduced with `v4.0.0-rc0` and `v4.0.0-rc1`, the
### Added
-* `JLed::Reset()` - resets the led to it's initial state allowing to
+* `JLed::Reset()` - resets the led to it's initial state allowing to
to start over
* `JLed::IsRunning()` - return true if effect is active, else false
-* new class `JLedSequence` to update JLed objects simultanously or
+* new class `JLedSequence` to update JLed objects simultanously or
sequentially. See [README](README.md#controlling-a-group-of-leds) for details.
* added new [morse example](examples/morse)
* clean separation between hardware specific and common code, making
@@ -125,7 +177,7 @@ In addition to the changes introduced with `v4.0.0-rc0` and `v4.0.0-rc1`, the
BrightnessEvaluator. Migration of code should be straight forward, see
below
-#### old brightness function
+#### old brightness function
In JLed version prio to version 4.0.0, a function pointer was used to specify
a user provided brightness function.
@@ -177,7 +229,7 @@ JLed led = JLed(LED_BUILTIN).UserFunc(&userEffect);
## [2018-09-22] v2.3.0
* ESP8266 platform: scaling from 8 to 10 bit improved. The scaling makes sure
- that 0 is mapped to 0 and 255 is mapped to 1023, preserving min/max
+ that 0 is mapped to 0 and 255 is mapped to 1023, preserving min/max
relationships in both ranges.
## [2018-06-09] v2.2.3
diff --git a/Makefile b/Makefile
index 7bb93af..5891c20 100644
--- a/Makefile
+++ b/Makefile
@@ -1,20 +1,22 @@
# use this makefile to build with platformio
#
-.PHONY: all clean upload monitor lint test ci
+.PHONY: phony
# some of the examples use LED_BUILTIN which is not defined for ESP32
CIOPTS=--board=uno --board=esp01 --board=nano33ble --lib="src"
CIOPTS_MBED=--board=nucleo_f401re -Oframework=mbed --lib="src"
CIOPTSALL=--board=esp32dev --board=uno --board=nano33ble --board=esp01 --lib="src"
-all:
+all: phony
pio run
-lint:
- cpplint --extensions=cpp,h,ino $(shell find . -maxdepth 3 \( ! -regex '.*/\..*' \) \
+lint: phony
+ cpplint --filter -readability/check \
+ --exclude test/catch2 \
+ --extensions=cpp,h,ino $(shell find . -maxdepth 3 \( ! -regex '.*/\..*' \) \
-type f -a \( -name "*\.cpp" -o -name "*\.h" -o -name "*\.ino" \) )
-ci:
+ci: phony
pio ci $(CIOPTS) examples/custom_hal/custom_hal.ino
pio ci $(CIOPTS_MBED) examples/multiled_mbed/multiled_mbed.cpp
pio ci $(CIOPTS) --lib="examples/morse" examples/morse/morse.ino
@@ -27,21 +29,22 @@ ci:
pio ci $(CIOPTSALL) examples/fade_on/fade_on.ino
pio ci $(CIOPTSALL) examples/sequence/sequence.ino
-envdump:
+envdump: phony
-pio run --target envdump
-clean:
+clean: phony
-pio run --target clean
- rm -f {test,src}/{*.o,*.gcno,*.gcda}
+ cd test && make clean
+ rm -f src/{*.o,*.gcno,*.gcda}
-upload:
+upload: phony
pio run --target upload
-monitor:
+monitor: phony
pio device monitor
-test:
+test: phony
$(MAKE) -C test coverage OPT=-O0
-tags:
+tags: phony
ctags -R
diff --git a/README.md b/README.md
index c1e6937..8dd0639 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+
+Preferring Python? I just released jled-circuitpython,
+a JLed implementation for CircuitPython and MicroPython.
+ |
+
# JLed - Advanced LED Library
![run tests](https://github.com/jandelgado/jled/workflows/run%20tests/badge.svg)
@@ -16,13 +21,12 @@ and someone did a [video tutorial for JLed](https://youtu.be/x5V2vdpZq1w) - Tha
Interactive JLed playground |
- |
-
+ | |
+
|
-
## Example
```c++
@@ -48,6 +52,7 @@ void loop() {
* [Arduino IDE](#arduino-ide)
* [PlatformIO](#platformio)
* [Usage](#usage)
+ * [Output pipeline](#output-pipeline)
* [Effects](#effects)
* [Static on and off](#static-on-and-off)
* [Static on example](#static-on-example)
@@ -60,6 +65,8 @@ void loop() {
* [FadeOn](#fadeon)
* [FadeOn example](#fadeon-example)
* [FadeOff](#fadeoff)
+ * [Fade](#fade)
+ * [Fade example](#fade-example)
* [User provided brightness function](#user-provided-brightness-function)
* [User provided brightness function example](#user-provided-brightness-function-example)
* [Delays and repetitions](#delays-and-repetitions)
@@ -73,7 +80,7 @@ void loop() {
* [Immediate Stop](#immediate-stop)
* [Misc functions](#misc-functions)
* [Low active for inverted output](#low-active-for-inverted-output)
- * [Maximum brightness level](#maximum-brightness-level)
+ * [Minimum- and Maximum brightness level](#minimum--and-maximum-brightness-level)
* [Controlling a group of LEDs](#controlling-a-group-of-leds)
* [Framework notes](#framework-notes)
* [Platform notes](#platform-notes)
@@ -84,8 +91,8 @@ void loop() {
* [Arduino framework](#arduino-framework)
* [Raspberry Pi Pico](#raspberry-pi-pico)
* [Example sketches](#example-sketches)
- * [PlatformIO](#platformio-1)
- * [Arduino IDE](#arduino-ide-1)
+ * [Building examples with PlatformIO](#building-examples-with-platformio)
+ * [Building examples with the Arduino IDE](#building-examples-with-the-arduino-ide)
* [Extending](#extending)
* [Support new hardware](#support-new-hardware)
* [Unit tests](#unit-tests)
@@ -151,22 +158,47 @@ the only argument. Further configuration of the LED object is done using a fluen
interface, e.g. `JLed led = JLed(13).Breathe(2000).DelayAfter(1000).Repeat(5)`.
See the examples section below for further details.
+#### Output pipeline
+
+First the configured effect (e.g. `Fade`) is evaluated for the current time
+`t`. JLed internally uses unsigned bytes to represent brightness values,
+ranging from 0 to 255. Next, the value is scaled to the limits set by
+`MinBrightness` and `MaxBrightness` (optionally). When the effect is configured
+for a low-active LED using `LowActive`, the brightness value will be inverted,
+i.e., the value will be subtracted from 255. Finally the value is passed to the
+hardware abstraction, which might scale it to the resolution used by the actual
+device (e.g. 10 bits for an ESP8266). Finally the brightness value is written
+out to the configure GPIO.
+
+```text
+┌───────────┐ ┌────────────┐ ┌─────────┐ ┌────────┐ ┌─────────┐ ┌────────┐
+│ Evaluate │ │ Scale to │ │ Low │YES │ Invert │ │Scale for│ │Write to│
+│ effect(t) ├───►│ [min, max] ├───►│ active? ├───►│ signal ├───►│Hardware ├───►│ GPIO │
+└───────────┘ └────────────┘ └────┬────┘ └────────┘ └───▲─────┘ └────────┘
+ │ NO │
+ └───────────────────────────┘
+```
+
### Effects
#### Static on and off
-Calling `On()` turns the LED on. To immediately turn a LED on, make a call
-like `JLed(LED_BUILTIN).On().Update()`.
+Calling `On(uint16_t period=1)` turns the LED on. To immediately turn a LED on,
+make a call like `JLed(LED_BUILTIN).On().Update()`. The `period` is optional
+and defaults to 1ms.
-`Off()` works like `On()`, except that it turns the LED off, i.e. it sets the
+`Off()` works like `On()`, except that it turns the LED off, i.e., it sets the
brightness to 0.
-Use the `Set(uint8_t brightness)` method to set the brightness to the given
-value, i.e. `Set(255)` is equivalent to calling `On()` and `Set(0)` is
-equivalent to calling `Off()`.
+Use the `Set(uint8_t brightness, uint16_t period=1)` method to set the
+brightness to the given value, i.e., `Set(255)` is equivalent to calling `On()`
+and `Set(0)` is equivalent to calling `Off()`.
-Technically `Set`, `On` and `Off` are effects with a period of 1ms that
-set the brightness to a constant value.
+Technically, `Set`, `On` and `Off` are effects with a default period of 1ms, that
+set the brightness to a constant value. Specifying a different period has an
+effect on when the `Update()` method will be done updating the effect and
+return false (like for any other effects). This is important when for example
+in a `JLedSequence` the LED should stay on for a given amount of time.
##### Static on example
@@ -225,7 +257,8 @@ void loop() {
}
```
-It is also possible to specify fade-on, on and fade-off durations for the breathing mode to customize the effect.
+It is also possible to specify fade-on, on- and fade-off durations for the
+breathing mode to customize the effect.
```c++
// LED will fade-on in 500ms, stay on for 1000ms, and fade-off in 500ms.
@@ -235,25 +268,25 @@ auto led = JLed(13).Breathe(500, 1000, 500).DelayAfter(1000).Forever();
#### Candle
-In candle mode, the random flickering of a candle or fire is simulated.
+In candle mode, the random flickering of a candle or fire is simulated.
The builder method has the following signature:
`Candle(uint8_t speed, uint8_t jitter, uin16_t period)`
-* `speed` - controls the speed of the effect. 0 for fastest, increasing speed
+* `speed` - controls the speed of the effect. 0 for fastest, increasing speed
divides into halve per increment. The default value is 7.
* `jitter` - the amount of jittering. 0 none (constant on), 255 maximum. Default
value is 15.
* `period` - Period of effect in ms. The default value is 65535 ms.
The default settings simulate a candle. For a fire effect for example use
-call the method with `Candle(5 /*speed*/, 100 /* jitter*/)`.
+call the method with `Candle(5 /*speed*/, 100 /* jitter*/)`.
##### Candle example
```c++
#include
-// Candle on LED pin 13 (PWM capable).
+// Candle on LED pin 13 (PWM capable).
auto led = JLed(13).Candle();
void setup() { }
@@ -273,7 +306,6 @@ period 1000):
[![fadeon function](doc/fadeon_plot.png)](https://www.wolframalpha.com/input/?i=plot+(exp(sin((t-1000%2F2.)*PI%2F1000))-0.36787944)*108.0++t%3D0+to+1000)
-
##### FadeOn example
```c++
@@ -293,9 +325,33 @@ void loop() {
In FadeOff mode, the LED is smoothly faded off using PWM. The fade starts at
100% brightness. Internally it is implemented as a mirrored version of the
-FadeOn function, i.e. FadeOn(t) = FadeOff(period-t). The `FadeOff()` method
+FadeOn function, i.e., FadeOff(t) = FadeOn(period-t). The `FadeOff()` method
takes the period of the effect as argument.
+#### Fade
+
+The Fade effect allows to fade from any start value `from` to any target value
+`to` with the given duration. Internally it sets up a `FadeOn` or `FadeOff`
+effect and `MinBrightness` and `MaxBrightness` values properly. The `Fade`
+method take three arguments: `from`, `to` and `duration`.
+
+
+
+##### Fade example
+
+```c++
+#include
+
+// fade from 100 to 200 with period 1000
+auto led = JLed(9).Fade(100, 200, 1000);
+
+void setup() { }
+
+void loop() {
+ led.Update();
+}
+```
+
#### User provided brightness function
It is also possible to provide a user defined brightness evaluator. The class
@@ -307,7 +363,7 @@ two methods:
as an unsigned byte, where 0 means LED off and 255 means full brightness.
* `uint16_t Period() const` - period of the effect.
-All time values are specified in milliseconds.
+All time values are specified in milliseconds.
The [user_func](examples/user_func) example demonstrates a simple user provided
brightness function, while the [morse](examples/morse) example shows how a more
@@ -354,8 +410,29 @@ specified by `DelayAfter()` method.
##### Update
-Call `Update()` periodically to update the state of the LED. `Update` returns
-`true` if the effect is active, and `false` when it finished.
+Call `Update(int16_t *pLast=nullptr)` or `Update(uint32_t t, int16_t *pLast=nullptr)`
+to periodically update the state of the LED.
+
+`Update` returns `true`, if the effect is active, or `false` when it finished.
+`Update()` is a shortcut to call `Update(uint32_t t)` with the current time in
+milliseconds.
+
+To obtain the value of the last written brightness value (after applying min-
+and max-brightness transformations), pass an additional optional pointer
+`*pLast` , where this value will be stored, when it was written. Example:
+
+```c++
+int16_t lastVal = -1;
+led.Update(&lastVal);
+if (lastVal != -1) {
+ // the LED was updated with the brightness value now stored in lastVal
+ ...
+}
+```
+
+Most of the time just calling `Update()` without any parameters is what you want.
+
+See [last_brightness](examples/last_brightness) example for a working example.
##### IsRunning
@@ -369,30 +446,44 @@ you want to start-over an effect.
##### Immediate Stop
Call `Stop()` to immediately turn the LED off and stop any running effects.
-Further calls to `Update()` will have no effect unless the Led is reset (using
-`Reset()`) or a new effect activated.
+Further calls to `Update()` will have no effect, unless the Led is reset using
+`Reset()` or a new effect is activated. By default, `Stop()` sets the current
+brightness level to `MinBrightness`.
+
+`Stop()` takes an optional argument `mode` of type `JLed::eStopMode`:
+
+* if set to `JLed::eStopMode::KEEP_CURRENT`, the LEDs current level will be kept
+* if set to `JLed::eStopMode::FULL_OFF` the level of the LED is set to `0`,
+ regardless of what `MinBrightness` is set to, effectively turning the LED off
+* if set to `JLed::eStopMode::TO_MIN_BRIGHTNESS` (default behavior), the LED
+ will set to the value of `MinBrightness`
+
+```c++
+// stop the effect and set the brightness level to 0, regardless of min brightness
+led.Stop(JLed::eStopMode::FULL_OFF);
+```
#### Misc functions
##### Low active for inverted output
Use the `LowActive()` method when the connected LED is low active. All output
-will be inverted by JLed (i.e. instead of x, the value of 255-x will be set).
-
-##### Maximum brightness level
+will be inverted by JLed (i.e., instead of x, the value of 255-x will be set).
-The `MaxBrightness(uint8_t level)` method is used to set the maximum brightness
-level of the LED. A level of 255 (the default) is full brightness, while 0
-effectively turns the LED off.
+##### Minimum- and Maximum brightness level
-The `uint_8 MaxBrightness() const` method returns the current maximum
-brightness level. Since currently only the upper 5 bits of the provided
-brighness value are used, the lower 3 bits returned are always 0.
+The `MaxBrightness(uint8_t level)` method is used to set the maximum brightness
+level of the LED. A level of 255 (the default) is full brightness, while 0
+effectively turns the LED off. In the same way, the `MinBrightness(uint8_t level)`
+method sets the minimum brightness level. The default minimum level is 0. If
+minimum or maximum brightness levels are set, the output value is scaled to be
+within the interval defined by `[minimum brightness, maximum brightness]`: a
+value of 0 will be mapped to the minimum brightness level, a value of 255 will
+be mapped to the maximum brightness level.
-If you want to programmatically increment or decrement the maximum brightness
-level, use the `JLed::kBrightnessStep` constant (which is defined as `1 <<
-(8-JLed::kBitsBrightness)` as the increment (instead of the hard wired value
-`8`) to be independent of the current JLed implementation using 5 bits.
+The `uint_8 MaxBrightness() const` method returns the current maximum
+brightness level. `uint8_t MinBrightness() const` returns the current minimum
+brightness level.
### Controlling a group of LEDs
@@ -428,10 +519,10 @@ The `JLedSequence` provides the following methods:
else `false`.
* Use the `Repeat(n)` method to specify the number of repetitions. The default
value is 1 repetition. The `Forever()` methods sets to repeat the sequence
- forever.
-* `Stop()` - turns off all `JLed` objects controlled by the sequence and
+ forever.
+* `Stop()` - turns off all `JLed` objects controlled by the sequence and
stops the sequence. Further calls to `Update()` will have no effect.
-* `Reset()` - Resets all `JLed` objects controlled by the sequence and
+* `Reset()` - Resets all `JLed` objects controlled by the sequence and
the sequence, resulting in a start-over.
## Framework notes
@@ -446,7 +537,7 @@ framework:
platform=ststm32
board = nucleo_f401re
framework = mbed
-build_flags = -Isrc
+build_flags = -Isrc
src_filter = +<../../src/> +<./>
upload_protocol=stlink
```
@@ -468,7 +559,7 @@ src_dir = examples/multiled_mbed
The DAC of the ESP8266 operates with 10 bits, every value JLed writes out gets
automatically scaled to 10 bits, since JLed internally only uses 8 bits. The
-scaling methods make sure that min/max relationships are preserved, i.e. 0 is
+scaling methods make sure that min/max relationships are preserved, i.e., 0 is
mapped to 0 and 255 is mapped to 1023. When using a user-defined brightness
function on the ESP8266, 8-bit values must be returned, all scaling is done by
JLed transparently for the application, yielding platform-independent code.
@@ -498,8 +589,8 @@ so it should be avoided and is normally not necessary.
For completeness, the full signature of the Esp32Hal constructor is
```
-Esp32Hal(PinType pin,
- int chan = kAutoSelectChan,
+Esp32Hal(PinType pin,
+ int chan = kAutoSelectChan,
uint16_t freq = 5000,
ledc_timer_t timer = LEDC_TIMER_0)
```
@@ -528,9 +619,14 @@ necessary to upload sketches to the microcontroller.
### Raspberry Pi Pico
-When using JLed on a Raspberry Pi Pico, the Pico-SDK and tools must be
-installed. The Pico supports up to 16 PWM channels in parallel. See
-the [pico-demo](examples/raspi_pico) for an example and build instructions.
+When using JLed on a Raspberry Pi Pico, the Pico-SDK and tools can be
+used. The Pico supports up to 16 PWM channels in parallel. See
+the [pico-demo](examples/raspi_pico) for an example and build instructions when
+the Pico-SDK is used.
+
+A probably easier approach is to use the Arduino platform. See
+[platformio.ini](platformio.ini) for details (look for
+`env:raspberrypi_pico_w`, which targets the Raspberry Pi Pico W.
## Example sketches
@@ -542,20 +638,25 @@ Example sketches are provided in the [examples](examples/) directory.
* [Candle effect](examples/candle)
* [Fade LED on](examples/fade_on)
* [Fade LED off](examples/fade_off)
+* [Fade from-to effect](examples/fade_from_to)
+* [Pulse effect](examples/pulse)
* [Controlling multiple LEDs in parallel](examples/multiled)
* [Controlling multiple LEDs in parallel (mbed)](examples/multiled_mbed)
* [Controlling multiple LEDs sequentially](examples/sequence)
* [Simple User provided effect](examples/user_func)
* [Morsecode example](examples/morse)
+* [Last brightness value example](examples/last_brightness)
* [Custom HAL example](examples/custom_hal)
+* [Custom PCA9685 HAL](https://github.com/jandelgado/jled-pca9685-hal)
+* [Dynamically switch sequences](https://github.com/jandelgado/jled-example-switch-sequence)
* [JLed compiled to WASM and running in the browser](https://jandelgado.github.io/jled-wasm)
* [Raspberry Pi Pico Demo](examples/raspi_pico)
* [ESP32 ESP-IDF example](https://github.com/jandelgado/jled-esp-idf-example)
* [ESP32 ESP-IDF PlatformIO example](https://github.com/jandelgado/jled-esp-idf-platformio-example)
-### PlatformIO
+### Building examples with PlatformIO
-To build an example using [the PlatformIO ide](http://platformio.org/),
+To build an example using [the PlatformIO ide](http://platformio.org/),
uncomment the example to be built in the [platformio.ini](platformio.ini)
project file, e.g.:
@@ -566,7 +667,7 @@ src_dir = examples/hello
;src_dir = examples/breathe
```
-### Arduino IDE
+### Building examples with the Arduino IDE
To build an example sketch in the Arduino IDE, select an example from
the `File` > `Examples` > `JLed` menu.
@@ -594,8 +695,8 @@ the host-based provided unit tests [is provided here](test/README.md).
* add code
* add [unit test(s)](test/)
* add [documentation](README.md)
-* make sure the cpp [linter](https://github.com/cpplint/cpplint) does not
- report any problems (run `make lint`). Hint: use `clang-format` with the
+* make sure the cpp [linter](https://github.com/cpplint/cpplint) does not
+ report any problems (run `make lint`). Hint: use `clang-format` with the
provided [settings](.clang-format)
* commit changes
* submit a PR
@@ -619,9 +720,8 @@ Just 'reconfigure' the `JLed` with any of the effect methods (e.g. `FadeOn`,
## Author and Copyright
-Copyright 2017, 2018 by Jan Delgado, jdelgado[at]gmx.net.
+Copyright 2017-2022 by Jan Delgado, jdelgado[at]gmx.net.
## License
[MIT](LICENSE)
-
diff --git a/devbox.json b/devbox.json
new file mode 100644
index 0000000..e24a8ed
--- /dev/null
+++ b/devbox.json
@@ -0,0 +1,18 @@
+{
+ "packages": [
+ "python@3.13",
+ "lcov@1.16",
+ "pipx",
+ "cpplint@2.0.0"
+ ],
+ "shell": {
+ "init_hook": [
+ ". $VENV_DIR/bin/activate"
+ ],
+ "scripts": {
+ "test": [
+ "echo \"Error: no test specified\" && exit 1"
+ ]
+ }
+ }
+}
diff --git a/devbox.lock b/devbox.lock
new file mode 100644
index 0000000..5e96396
--- /dev/null
+++ b/devbox.lock
@@ -0,0 +1,150 @@
+{
+ "lockfile_version": "1",
+ "packages": {
+ "cpplint@2.0.0": {
+ "last_modified": "2024-11-03T14:18:04Z",
+ "resolved": "github:NixOS/nixpkgs/4ae2e647537bcdbb82265469442713d066675275#cpplint",
+ "source": "devbox-search",
+ "version": "2.0.0",
+ "systems": {
+ "aarch64-darwin": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/70gc21bl3grda63djlks6x1f5g8h89xk-cpplint-2.0.0",
+ "default": true
+ },
+ {
+ "name": "dist",
+ "path": "/nix/store/3sq5396dcbg3r06g9zci1w4rxql1xf0k-cpplint-2.0.0-dist"
+ }
+ ],
+ "store_path": "/nix/store/70gc21bl3grda63djlks6x1f5g8h89xk-cpplint-2.0.0"
+ },
+ "aarch64-linux": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/3fcbszvn75zwim2n3785bflrwww38l42-cpplint-2.0.0",
+ "default": true
+ },
+ {
+ "name": "dist",
+ "path": "/nix/store/fqrmkx6q4q290hildy4l6gi2pzwzwinw-cpplint-2.0.0-dist"
+ }
+ ],
+ "store_path": "/nix/store/3fcbszvn75zwim2n3785bflrwww38l42-cpplint-2.0.0"
+ },
+ "x86_64-darwin": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/m675bxwgh3wmr0gix5g6xnhkidlql0ii-cpplint-2.0.0",
+ "default": true
+ },
+ {
+ "name": "dist",
+ "path": "/nix/store/2bpdwa3r1kfzf4jkd4i24njxy3pr3xnv-cpplint-2.0.0-dist"
+ }
+ ],
+ "store_path": "/nix/store/m675bxwgh3wmr0gix5g6xnhkidlql0ii-cpplint-2.0.0"
+ },
+ "x86_64-linux": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/vrv52827v0b6h4k3nl7k9zg4ld182khg-cpplint-2.0.0",
+ "default": true
+ },
+ {
+ "name": "dist",
+ "path": "/nix/store/132q2dd3wkkgdpybwzhybm7hbad0g097-cpplint-2.0.0-dist"
+ }
+ ],
+ "store_path": "/nix/store/vrv52827v0b6h4k3nl7k9zg4ld182khg-cpplint-2.0.0"
+ }
+ }
+ },
+ "lcov@1.16": {
+ "last_modified": "2024-03-22T11:26:23Z",
+ "resolved": "github:NixOS/nixpkgs/a3ed7406349a9335cb4c2a71369b697cecd9d351#lcov",
+ "source": "devbox-search",
+ "version": "1.16",
+ "systems": {
+ "aarch64-darwin": {
+ "store_path": "/nix/store/cwjgl90nkg79za5gx41yg4663w7iyj0y-lcov-1.16"
+ },
+ "aarch64-linux": {
+ "store_path": "/nix/store/81axjrgg3cjx09kdb25psiiyz60zacqw-lcov-1.16"
+ },
+ "x86_64-darwin": {
+ "store_path": "/nix/store/5jir4n0q72z9p2h9sxwb2rcam3j165wp-lcov-1.16"
+ },
+ "x86_64-linux": {
+ "store_path": "/nix/store/qfdwnjp77xlvg0jqfv1dl8b40xpv230k-lcov-1.16"
+ }
+ }
+ },
+ "pipx": {
+ "resolved": "github:NixOS/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c#pipx",
+ "source": "nixpkg"
+ },
+ "python@3.13": {
+ "last_modified": "2024-11-28T07:51:56Z",
+ "plugin_version": "0.0.4",
+ "resolved": "github:NixOS/nixpkgs/226216574ada4c3ecefcbbec41f39ce4655f78ef#python313",
+ "source": "devbox-search",
+ "version": "3.13.0",
+ "systems": {
+ "aarch64-darwin": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/fbyrkq5n04a9hn5zs26vrmqjzdx73d4g-python3-3.13.0",
+ "default": true
+ }
+ ],
+ "store_path": "/nix/store/fbyrkq5n04a9hn5zs26vrmqjzdx73d4g-python3-3.13.0"
+ },
+ "aarch64-linux": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/jbz9fj3sp5c8bf0s6d0bkjjj9mslxsrc-python3-3.13.0",
+ "default": true
+ },
+ {
+ "name": "debug",
+ "path": "/nix/store/60jgy93wj50wwimmhm2p53pzaiap8ypm-python3-3.13.0-debug"
+ }
+ ],
+ "store_path": "/nix/store/jbz9fj3sp5c8bf0s6d0bkjjj9mslxsrc-python3-3.13.0"
+ },
+ "x86_64-darwin": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/c7j1vxcdcqswsddm5m1n2n4z5zfhmbq2-python3-3.13.0",
+ "default": true
+ }
+ ],
+ "store_path": "/nix/store/c7j1vxcdcqswsddm5m1n2n4z5zfhmbq2-python3-3.13.0"
+ },
+ "x86_64-linux": {
+ "outputs": [
+ {
+ "name": "out",
+ "path": "/nix/store/0b83hlniyfbpha92k2j0w93mxdalv8kb-python3-3.13.0",
+ "default": true
+ },
+ {
+ "name": "debug",
+ "path": "/nix/store/xzhxhqs8my0yvfi09aj1s9i1s9nrmpvg-python3-3.13.0-debug"
+ }
+ ],
+ "store_path": "/nix/store/0b83hlniyfbpha92k2j0w93mxdalv8kb-python3-3.13.0"
+ }
+ }
+ }
+ }
+}
diff --git a/doc/cheat_sheet.jpg b/doc/cheat_sheet.jpg
index c20c587..1d31fdd 100644
Binary files a/doc/cheat_sheet.jpg and b/doc/cheat_sheet.jpg differ
diff --git a/doc/fade_from-to.png b/doc/fade_from-to.png
new file mode 100644
index 0000000..05c351c
Binary files /dev/null and b/doc/fade_from-to.png differ
diff --git a/examples/fade_from_to/fade_from_to.ino b/examples/fade_from_to/fade_from_to.ino
new file mode 100644
index 0000000..16251da
--- /dev/null
+++ b/examples/fade_from_to/fade_from_to.ino
@@ -0,0 +1,23 @@
+// JLed fade from-to example. Example randomly fades to a new level with
+// a random duration.
+// Copyright 2022 by Jan Delgado. All rights reserved.
+// https://github.com/jandelgado/jled
+#include
+
+auto led = JLed(5).On(1); // start with LED turned on
+
+void setup() {}
+
+void loop() {
+ static uint8_t last_to = 255;
+
+ if (!led.Update()) {
+ // when effect is done (Update() returns false),
+ // reconfigure fade effect using random values
+ auto new_from = last_to;
+ auto new_to = jled::rand8();
+ auto duration = 250 + jled::rand8() * 4;
+ last_to = new_to;
+ led.Fade(new_from, new_to, duration).Repeat(1);
+ }
+}
diff --git a/examples/last_brightness/last_brightness.ino b/examples/last_brightness/last_brightness.ino
new file mode 100644
index 0000000..b5cb71a
--- /dev/null
+++ b/examples/last_brightness/last_brightness.ino
@@ -0,0 +1,38 @@
+// Stops an effect when a button is pressed (and hold). When the button is
+// released, the LED will fade to off with starting the brightness value it had
+// when the effect was stopped.
+//
+// dependency: arduinogetstarted/ezButton@1.0.6 to control the button
+//
+// Copyright 2024 by Jan Delgado. All rights reserved.
+// https://github.com/jandelgado/jled
+//
+#include // arduinogetstarted/ezButton@1.0.6
+#include
+
+constexpr auto LED_PIN = 16;
+constexpr auto BUTTON_PIN = 18;
+
+auto button = ezButton(BUTTON_PIN);
+
+// start with a pulse effect
+auto led =
+ JLed(LED_PIN).DelayBefore(1000).Breathe(2000).Forever().MinBrightness(25);
+
+void setup() {}
+
+void loop() {
+ static int16_t lastBrightness = 0;
+
+ button.loop();
+ led.Update(&lastBrightness);
+
+ if (button.isPressed()) {
+ // when the button is pressed, stop the effect on led, but keep the LED
+ // on with it's current brightness ...
+ led.Stop(JLed::KEEP_CURRENT);
+ } else if (button.isReleased()) {
+ // when the button is released, fade from the last brightness to 0
+ led = JLed(LED_PIN).Fade(lastBrightness, 0, 1000);
+ }
+}
diff --git a/examples/pulse/pulse.ino b/examples/pulse/pulse.ino
new file mode 100644
index 0000000..824c16c
--- /dev/null
+++ b/examples/pulse/pulse.ino
@@ -0,0 +1,12 @@
+// JLed pulse demo.
+// Copyright 2022 by Jan Delgado. All rights reserved.
+// https://github.com/jandelgado/jled
+#include
+
+// "pulse" LED on GPIO pin 5. The "pulse" is accomplished by setting
+// a minimal brightness so the LED will not be dark.
+auto led = JLed(5).Breathe(2000).MinBrightness(20).Forever().DelayAfter(500);
+
+void setup() {}
+
+void loop() { led.Update(); }
diff --git a/keywords.txt b/keywords.txt
index c9accb7..e4b458e 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -10,7 +10,11 @@
JLed KEYWORD1
JLedSequence KEYWORD1
+BlinkBrightnessEvaluator KEYWORD1
BrightnessEvaluator KEYWORD1
+BreatheBrightnessEvaluator KEYWORD1
+CandleBrightnessEvaluator KEYWORD1
+ConstantBrightnessEvaluator KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
@@ -29,6 +33,7 @@ Forever KEYWORD2
DelayBefore KEYWORD2
DelayAfter KEYWORD2
Forever KEYWORD2
+Hal KEYWORD2
IsForever KEYWORD2
IsRunning KEYWORD2
LowActive KEYWORD2
@@ -37,6 +42,7 @@ Stop KEYWORD2
Update KEYWORD2
UserFunc KEYWORD2
Reset KEYWORD2
+MinBrightness KEYWORD2
MaxBrightness KEYWORD2
#######################################
diff --git a/library.json b/library.json
index 20d5aed..448ad55 100644
--- a/library.json
+++ b/library.json
@@ -1,6 +1,6 @@
{
"name": "JLed",
- "version": "4.9.0",
+ "version": "4.15.0",
"description": "An embedded library to control LEDs",
"license": "MIT",
"frameworks": ["espidf", "arduino", "mbed"],
diff --git a/library.properties b/library.properties
index 1a0f0f3..f71cc0d 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=JLed
-version=4.9.0
+version=4.15.0
author=Jan Delgado
maintainer=Jan Delgado
sentence=An Arduino library to control LEDs
diff --git a/platformio.ini b/platformio.ini
index 23410e9..86f7718 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -12,51 +12,51 @@
; uncomment platform to build for
;default_envs = nucleo_f401re_mbed
;default_envs = nucleo_f401re
-default_envs = nanoatmega328
+;default_envs = nanoatmega328
;default_envs = nano33ble
;default_envs = nucleo_f401re
;default_envs = esp8266
-;default_envs = esp32
-;default_envs = sparkfun_samd21_dev_usb
+default_envs = esp32
;default_envs = sparkfun_samd21_dev_usb
+;default_envs = raspberrypi_pico_w
; uncomment example to build
-;src_dir = examples/hello
+src_dir = examples/hello
;src_dir = examples/morse
-src_dir = examples/breathe
+;src_dir = examples/breathe
;src_dir = examples/candle
;src_dir = examples/fade_on
;src_dir = examples/fade_off
;src_dir = examples/simple_on
+;src_dir = examples/last_brightness
;src_dir = examples/multiled
;src_dir = examples/multiled_mbed
;src_dir = examples/user_func
;src_dir = examples/sequence
;src_dir = examples/custom_hal
+;src_dir = examples/pulse
+;src_dir = examples/fade_from_to
+
+[env]
+build_flags = -Isrc
+build_src_filter = +<../../src/> +<./>
+;lib_deps = arduinogetstarted/ezButton@1.0.6
[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
-build_flags = -Isrc
-src_filter = +<../../src/> +<./>
[env:nucleo_f401re_mbed]
platform=ststm32
board = nucleo_f401re
framework = mbed
-build_flags = -Isrc
-src_filter = +<../../src/> +<./>
upload_protocol=stlink
[env:nucleo_f401re]
-# nucleo f401re arduino framework support only on master at the moment
platform=ststm32
-;platform=https://github.com/platformio/platform-ststm32.git
board = nucleo_f401re
framework = arduino
-build_flags = -Isrc
-src_filter = +<../../src/> +<./>
upload_protocol=stlink
debug_speed=auto
@@ -64,29 +64,29 @@ debug_speed=auto
platform = espressif8266
board = nodemcuv2
framework = arduino
-build_flags = -Isrc
-src_filter = +<../../src/> +<./>
[env:esp32]
lib_ldf_mode = off
platform = espressif32
board = esp32dev
framework = arduino
-build_flags = -Isrc
-src_filter = +<../../src/> +<./>
[env:sparkfun_samd21_dev_usb]
platform = atmelsam
framework = arduino
board = sparkfun_samd21_dev_usb
-build_flags = -Isrc
-src_filter = +<../../src/> +<./>
[env:nano33ble]
platform=https://github.com/platformio/platform-nordicnrf52.git
board = nano33ble
framework = arduino
-build_flags = -Isrc
-src_filter = +<../../src/> +<./>
upload_protocol=stlink
+[env:raspberrypi_pico_w]
+build_flags = ${env.build_flags} -D ARDUINO_RASPBERRY_PI_PICO_W
+platform = https://github.com/maxgerhardt/platform-raspberrypi.git
+board = rpipicow
+framework = arduino
+board_build.filesystem_size = 0.5m
+board_build.core = earlephilhower
+upload_protocol = picotool
diff --git a/src/esp32_hal.h b/src/esp32_hal.h
index 466fb77..7d235cb 100644
--- a/src/esp32_hal.h
+++ b/src/esp32_hal.h
@@ -133,7 +133,7 @@ class Esp32Hal {
}
uint32_t millis() const {
- return (uint32_t)(esp_timer_get_time() / 1000ULL);
+ return static_cast(esp_timer_get_time() / 1000ULL);
}
PinType chan() const { return chan_; }
diff --git a/src/jled.h b/src/jled.h
index 4b16a8a..41b21d1 100644
--- a/src/jled.h
+++ b/src/jled.h
@@ -58,8 +58,8 @@ class JLed : public TJLed {
};
// a group of JLed objects which can be controlled simultanously
-class JLedSequence : public TJLedSequence {
- using TJLedSequence::TJLedSequence;
+class JLedSequence : public TJLedSequence {
+ using TJLedSequence::TJLedSequence;
};
}; // namespace jled
diff --git a/src/jled_base.cpp b/src/jled_base.cpp
index 740f646..62d0358 100644
--- a/src/jled_base.cpp
+++ b/src/jled_base.cpp
@@ -26,13 +26,12 @@ namespace jled {
// pre-calculated fade-on function. This table samples the function
// y(x) = exp(sin((t - period / 2.) * PI / period)) - 0.36787944)
// * 108.
-// at x={0,32,...,256}. In FadeOnFunc() we us linear interpolation
-// to
+// at x={0,32,...,256}. In FadeOnFunc() we us linear interpolation to
// approximate the original function (so we do not need fp-ops).
// fade-off and breath functions are all derived from fade-on, see
// below.
static constexpr uint8_t kFadeOnTable[] = {0, 3, 13, 33, 68,
- 118, 179, 232, 255};
+ 118, 179, 232, 255}; // NOLINT
// https://www.wolframalpha.com/input/?i=plot+(exp(sin((x-100%2F2.)*PI%2F100))-0.36787944)*108.0++x%3D0+to+100
// The fade-on func is an approximation of
@@ -66,15 +65,25 @@ uint8_t rand8() {
return (uint8_t)rand_;
}
-// scale a byte by a factor, where only the lower 5 bits of factor are used.
-// i.e. the scaling factor is in the range [0,31]. scale5 has the following
-// properties:
-// scale5(x, f) = x*f / 32 for all x and f=0..30
-// scale5(x, 31) = x for all x
-uint8_t scale5(uint8_t val, uint8_t factor) {
- if (factor == 31)
- return val; // optimize for most common case (full brightness)
- return ((uint16_t)val * factor) >> 5;
+// scale a byte (val) by a byte (factor). scale8 has the following properties:
+// scale8(0, f) == 0 for all f
+// scale8(x, 255) == x for all x
+uint8_t scale8(uint8_t val, uint8_t factor) {
+ return (static_cast(val)*static_cast(factor))/255;
+}
+
+// interpolate a byte (val) to the interval [a,b].
+uint8_t lerp8by8(uint8_t val, uint8_t a, uint8_t b) {
+ if (a == 0 && b == 255) return val; // optimize for most common case
+ const uint8_t delta = b - a;
+ return a + scale8(val, delta);
+}
+
+// the inverse of lerp8by8: invlerp8by8(lerp8by8(x, a, b,), a, b,) = x
+uint8_t invlerp8by8(uint8_t val, uint8_t a, uint8_t b) {
+ const uint16_t delta = b - a;
+ if (delta == 0) return 0;
+ return (static_cast(val-a)*255)/(delta);
}
}; // namespace jled
diff --git a/src/jled_base.h b/src/jled_base.h
index 5d8eb46..1575dc1 100644
--- a/src/jled_base.h
+++ b/src/jled_base.h
@@ -44,7 +44,14 @@ static constexpr uint8_t kZeroBrightness = 0;
uint8_t fadeon_func(uint32_t t, uint16_t period);
uint8_t rand8();
void rand_seed(uint32_t s);
-uint8_t scale5(uint8_t val, uint8_t factor);
+uint8_t scale8(uint8_t val, uint8_t f);
+uint8_t lerp8by8(uint8_t val, uint8_t a, uint8_t b);
+uint8_t invlerp8by8(uint8_t val, uint8_t a, uint8_t b);
+
+template
+static constexpr T __max(T a, T b) {
+ return (a > b) ? a : b;
+}
// a function f(t,period,param) that calculates the LEDs brightness for a given
// point in time and the given period. param is an optionally user provided
@@ -66,14 +73,16 @@ class CloneableBrightnessEvaluator : public BrightnessEvaluator {
class ConstantBrightnessEvaluator : public CloneableBrightnessEvaluator {
uint8_t val_;
+ uint16_t duration_;
public:
ConstantBrightnessEvaluator() = delete;
- explicit ConstantBrightnessEvaluator(uint8_t val) : val_(val) {}
+ explicit ConstantBrightnessEvaluator(uint8_t val, uint16_t duration = 1)
+ : val_(val), duration_(duration) {}
BrightnessEvaluator* clone(void* ptr) const override {
return new (ptr) ConstantBrightnessEvaluator(*this);
}
- uint16_t Period() const override { return 1; }
+ uint16_t Period() const override { return duration_; }
uint8_t Eval(uint32_t) const override { return val_; }
};
@@ -94,36 +103,6 @@ class BlinkBrightnessEvaluator : public CloneableBrightnessEvaluator {
}
};
-// fade LED on
-class FadeOnBrightnessEvaluator : public CloneableBrightnessEvaluator {
- uint16_t period_;
-
- public:
- FadeOnBrightnessEvaluator() = delete;
- explicit FadeOnBrightnessEvaluator(uint16_t period) : period_(period) {}
- BrightnessEvaluator* clone(void* ptr) const override {
- return new (ptr) FadeOnBrightnessEvaluator(*this);
- }
- uint16_t Period() const override { return period_; }
- uint8_t Eval(uint32_t t) const override { return fadeon_func(t, period_); }
-};
-
-// fade LED off
-class FadeOffBrightnessEvaluator : public CloneableBrightnessEvaluator {
- uint16_t period_;
-
- public:
- FadeOffBrightnessEvaluator() = delete;
- explicit FadeOffBrightnessEvaluator(uint16_t period) : period_(period) {}
- BrightnessEvaluator* clone(void* ptr) const override {
- return new (ptr) FadeOffBrightnessEvaluator(*this);
- }
- uint16_t Period() const override { return period_; }
- uint8_t Eval(uint32_t t) const override {
- return fadeon_func(period_ - t, period_);
- }
-};
-
// The breathe func is composed by fade-on, on and fade-off phases. For fading
// we approximate the following function:
// y(x) = exp(sin((t-period/4.) * 2. * PI / period)) - 0.36787944) * 108.)
@@ -134,15 +113,21 @@ class BreatheBrightnessEvaluator : public CloneableBrightnessEvaluator {
uint16_t duration_fade_on_;
uint16_t duration_on_;
uint16_t duration_fade_off_;
+ uint8_t from_;
+ uint8_t to_;
public:
BreatheBrightnessEvaluator() = delete;
explicit BreatheBrightnessEvaluator(uint16_t duration_fade_on,
uint16_t duration_on,
- uint16_t duration_fade_off)
+ uint16_t duration_fade_off,
+ uint8_t from = 0,
+ uint8_t to = kFullBrightness)
: duration_fade_on_(duration_fade_on),
duration_on_(duration_on),
- duration_fade_off_(duration_fade_off) {}
+ duration_fade_off_(duration_fade_off),
+ from_(from),
+ to_(to) {}
BrightnessEvaluator* clone(void* ptr) const override {
return new (ptr) BreatheBrightnessEvaluator(*this);
}
@@ -150,15 +135,21 @@ class BreatheBrightnessEvaluator : public CloneableBrightnessEvaluator {
return duration_fade_on_ + duration_on_ + duration_fade_off_;
}
uint8_t Eval(uint32_t t) const override {
+ uint8_t val = 0;
if (t < duration_fade_on_)
- return fadeon_func(t, duration_fade_on_);
+ val = fadeon_func(t, duration_fade_on_);
else if (t < duration_fade_on_ + duration_on_)
- return kFullBrightness;
- else if (t < Period())
- return fadeon_func(Period() - t, duration_fade_off_);
+ val = kFullBrightness;
else
- return kZeroBrightness;
+ val = fadeon_func(Period() - t, duration_fade_off_);
+ return lerp8by8(val, from_, to_);
}
+
+ uint16_t DurationFadeOn() const { return duration_fade_on_; }
+ uint16_t DurationFadeOff() const { return duration_fade_off_; }
+ uint16_t DurationOn() const { return duration_on_; }
+ uint8_t From() const { return from_; }
+ uint8_t To() const { return to_; }
};
class CandleBrightnessEvaluator : public CloneableBrightnessEvaluator {
@@ -205,8 +196,12 @@ class TJLed {
// Hardware abstraction giving access to the MCU
HalType hal_;
+ // Evaluate effect(t) and scale to be within [minBrightness, maxBrightness]
+ // assumes brigthness_eval_ is set as it is not checked here.
+ uint8_t Eval(uint32_t t) const { return brightness_eval_->Eval(t); }
+
+ // Write val out to the "hardware", inverting signal when active-low is set.
void Write(uint8_t val) {
- val = scale5(val, maxBrightness_);
hal_.analogWrite(IsLowActive() ? kFullBrightness - val : val);
}
@@ -214,9 +209,10 @@ class TJLed {
TJLed() = delete;
explicit TJLed(const HalType& hal)
: hal_{hal},
- state_{ST_RUNNING},
+ state_{ST_INIT},
bLowActive_{false},
- maxBrightness_{(1 << kBitsBrightness) - 1} {}
+ minBrightness_{0},
+ maxBrightness_{255} {}
explicit TJLed(typename HalType::PinType pin) : TJLed{HalType{pin}} {}
@@ -225,6 +221,7 @@ class TJLed {
B& operator=(const TJLed& rLed) {
state_ = rLed.state_;
bLowActive_ = rLed.bLowActive_;
+ minBrightness_ = rLed.minBrightness_;
maxBrightness_ = rLed.maxBrightness_;
num_repetitions_ = rLed.num_repetitions_;
last_update_time_ = rLed.last_update_time_;
@@ -249,8 +246,6 @@ class TJLed {
HalType& Hal() { return hal_; }
- bool Update() { return Update(hal_.millis()); }
-
// Set physical LED polarity to be low active. This inverts every
// signal physically output to a pin.
B& LowActive() {
@@ -261,29 +256,46 @@ class TJLed {
bool IsLowActive() const { return bLowActive_; }
// turn LED on
- B& On() { return Set(kFullBrightness); }
+ B& On(uint16_t duration = 1) { return Set(kFullBrightness, duration); }
// turn LED off
- B& Off() { return Set(kZeroBrightness); }
+ B& Off(uint16_t duration = 1) { return Set(kZeroBrightness, duration); }
- // Sets LED to given brightness
- B& Set(uint8_t brightness) {
+ // Sets LED to given brightness. As for every effect, a duration can be
+ // specified. Update() will return false after the duration elapsed.
+ B& Set(uint8_t brightness, uint16_t duration = 1) {
// note: we use placement new and therefore not need to keep track of
// mem allocated
- return SetBrightnessEval(new (brightness_eval_buf_)
- ConstantBrightnessEvaluator(brightness));
+ return SetBrightnessEval(
+ new (brightness_eval_buf_)
+ ConstantBrightnessEvaluator(brightness, duration));
}
// Fade LED on
- B& FadeOn(uint16_t duration) {
- return SetBrightnessEval(new (brightness_eval_buf_)
- FadeOnBrightnessEvaluator(duration));
+ B& FadeOn(uint16_t duration, uint8_t from = 0,
+ uint8_t to = kFullBrightness) {
+ return SetBrightnessEval(
+ new (brightness_eval_buf_)
+ BreatheBrightnessEvaluator(duration, 0, 0, from, to));
}
// Fade LED off - acutally is just inverted version of FadeOn()
- B& FadeOff(uint16_t duration) {
- return SetBrightnessEval(new (brightness_eval_buf_)
- FadeOffBrightnessEvaluator(duration));
+ B& FadeOff(uint16_t duration, uint8_t from = kFullBrightness,
+ uint8_t to = 0) {
+ return SetBrightnessEval(
+ new (brightness_eval_buf_)
+ BreatheBrightnessEvaluator(0, 0, duration, to, from));
+ }
+
+ // Fade from "from" to "to" with period "duration". Sets up the breathe
+ // effect with the proper parameters and sets Min/Max brightness to reflect
+ // levels specified by "from" and "to".
+ B& Fade(uint8_t from, uint8_t to, uint16_t duration) {
+ if (from < to) {
+ return FadeOn(duration, from, to);
+ } else {
+ return FadeOff(duration, from, to);
+ }
}
// Set effect to Breathe, with the given period time in ms.
@@ -343,8 +355,12 @@ class TJLed {
// Stop current effect and turn LED immeadiately off. Further calls to
// Update() will have no effect.
- B& Stop() {
- Write(kZeroBrightness);
+ enum eStopMode { TO_MIN_BRIGHTNESS = 0, FULL_OFF, KEEP_CURRENT };
+ B& Stop(eStopMode mode = eStopMode::TO_MIN_BRIGHTNESS) {
+ if (mode != eStopMode::KEEP_CURRENT) {
+ Write(mode == eStopMode::FULL_OFF ? kZeroBrightness
+ : minBrightness_);
+ }
state_ = ST_STOPPED;
return static_cast(*this);
}
@@ -353,28 +369,37 @@ class TJLed {
// Reset to inital state
B& Reset() {
- time_start_ = kTimeUndef;
- last_update_time_ = kTimeUndef;
- state_ = ST_RUNNING;
+ time_start_ = 0;
+ last_update_time_ = 0;
+ state_ = ST_INIT;
return static_cast(*this);
}
- // Sets the maximum brightness level. 255 is full brightness, 0 turns the
- // effect off. Currently, only upper 5 bits of the provided value are used
- // and stored.
- B& MaxBrightness(uint8_t level) {
- maxBrightness_ = level >> (8 - kBitsBrightness);
+ // Sets the minimum brightness level (ranging from 0 to 255).
+ B& MinBrightness(uint8_t level) {
+ minBrightness_ = level;
return static_cast(*this);
}
- // Returns current maximum brightness level. Since currently only upper 5
- // bits are used, lower 3 bits will always be 0.
- uint8_t MaxBrightness() const {
- return maxBrightness_ << (8 - kBitsBrightness);
+ // Returns current minimum brightness level.
+ uint8_t MinBrightness() const { return minBrightness_; }
+
+ // Sets the minimum brightness level (ranging from 0 to 255).
+ B& MaxBrightness(uint8_t level) {
+ maxBrightness_ = level;
+ return static_cast(*this);
}
- protected:
- // update brightness of LED using the given brightness evaluator
+ // Returns current maximum brightness level.
+ uint8_t MaxBrightness() const { return maxBrightness_; }
+
+ // update brightness of LED using the given brightness evaluator and the
+ // current time. If the optional pLast pointer is set, then the actual
+ // brightness value (if an update happened), will be returned through
+ // the pointer. The value returned will be the calculated value after
+ // min- and max-brightness scaling was applied, which is the value that
+ // is written to the output.
+ //
// (brightness) ________________
// on 255 | ¸-'
// | ¸-'
@@ -383,104 +408,142 @@ class TJLed {
// |<-delay before->|<--period-->|<-delay after-> (time)
// | func(t) |
// |<- num_repetitions times ->
- bool Update(uint32_t now) {
- if (state_ == ST_STOPPED || !brightness_eval_) return false;
+ bool Update(int16_t* pLast = nullptr) {
+ return Update(hal_.millis(), pLast);
+ }
- // no need to process updates twice during one time tick.
- if (last_update_time_ == now) return true;
+ bool Update(uint32_t t, int16_t* pLast = nullptr) {
+ if (state_ == ST_STOPPED || !brightness_eval_) return false;
- if (last_update_time_ == kTimeUndef) {
- time_start_ = now + delay_before_;
+ if (state_ == ST_INIT) {
+ time_start_ = t + delay_before_;
+ state_ = ST_RUNNING;
+ } else {
+ // no need to process updates twice during one time tick.
+ if (!timeChangedSinceLastUpdate(t)) return true;
}
- last_update_time_ = now;
- if ((int32_t)(now - time_start_) < 0) return true;
+ trackLastUpdateTime(t);
+
+ if (static_cast(t - time_start_) < 0) return true;
+
+ auto writeCur = [this](uint32_t t, int16_t* p) {
+ const auto val = lerp8by8(Eval(t), minBrightness_, maxBrightness_);
+ if (p) {
+ *p = val;
+ }
+ Write(val);
+ };
// t cycles in range [0..period+delay_after-1]
const auto period = brightness_eval_->Period();
- const auto t = (now - time_start_) % (period + delay_after_);
+ if (!IsForever()) {
+ const auto time_end = time_start_ +
+ static_cast(period + delay_after_) *
+ num_repetitions_ -
+ 1;
+
+ if (static_cast(t - time_end) >= 0) {
+ // make sure final value of t = (period-1) is set
+ state_ = ST_STOPPED;
+ writeCur(period - 1, pLast);
+ return false;
+ }
+ }
+
+ t = (t - time_start_) % (period + delay_after_);
if (t < period) {
state_ = ST_RUNNING;
- Write(brightness_eval_->Eval(t));
+ writeCur(t, pLast);
} else {
if (state_ == ST_RUNNING) {
// when in delay after phase, just call Write()
// once at the beginning.
state_ = ST_IN_DELAY_AFTER_PHASE;
- Write(brightness_eval_->Eval(period - 1));
+ writeCur(period - 1, pLast);
}
}
-
- if (IsForever()) return true;
-
- const auto time_end =
- time_start_ + (uint32_t)(period + delay_after_) * num_repetitions_ -
- 1;
-
- if ((int32_t)(now - time_end) >= 0) {
- // make sure final value of t = (period-1) is set
- state_ = ST_STOPPED;
- Write(brightness_eval_->Eval(period - 1));
- return false;
- }
return true;
}
+ protected:
+ // test if time stored in last_update_time_ differs from provided timestamp.
+ bool inline timeChangedSinceLastUpdate(uint32_t now) {
+ return (now & 255) != last_update_time_;
+ }
+
+ void trackLastUpdateTime(uint32_t t) { last_update_time_ = (t & 255); }
+
B& SetBrightnessEval(BrightnessEvaluator* be) {
brightness_eval_ = be;
// start over after the brightness evaluator changed
return Reset();
}
+ public:
+ // Number of bits used to control brightness with Min/MaxBrightness().
+ static constexpr uint8_t kBitsBrightness = 8;
+ static constexpr uint8_t kBrightnessStep = 1;
+
private:
static constexpr uint8_t ST_STOPPED = 0;
- static constexpr uint8_t ST_RUNNING = 1;
- static constexpr uint8_t ST_IN_DELAY_AFTER_PHASE = 2;
+ static constexpr uint8_t ST_INIT = 1;
+ static constexpr uint8_t ST_RUNNING = 2;
+ static constexpr uint8_t ST_IN_DELAY_AFTER_PHASE = 3;
uint8_t state_ : 2;
uint8_t bLowActive_ : 1;
-
- // Number of bits used to control brightness with MaxBrightness(). Using
- // only 5 bits here saves us a byte, since summing up with previous defs.
- public:
- static constexpr uint8_t kBitsBrightness = 5;
- static constexpr uint8_t kBrightnessStep = 1 << (8 - kBitsBrightness);
-
- private:
- uint8_t maxBrightness_ : kBitsBrightness;
+ uint8_t minBrightness_;
+ uint8_t maxBrightness_;
// this is where the BrightnessEvaluator object will be stored using
// placment new. Set MAX_SIZE to class occupying most memory
- static constexpr auto MAX_SIZE = sizeof(CandleBrightnessEvaluator);
+ static constexpr auto MAX_SIZE =
+ __max(sizeof(CandleBrightnessEvaluator),
+ __max(sizeof(BreatheBrightnessEvaluator),
+ __max(sizeof(ConstantBrightnessEvaluator), // NOLINT
+ sizeof(BlinkBrightnessEvaluator))));
alignas(alignof(
CloneableBrightnessEvaluator)) char brightness_eval_buf_[MAX_SIZE];
static constexpr uint16_t kRepeatForever = 65535;
uint16_t num_repetitions_ = 1;
- static constexpr uint32_t kTimeUndef = -1;
- uint32_t last_update_time_ = kTimeUndef;
- uint32_t time_start_ = kTimeUndef;
+ // We store the timestamp the effect was last updated to avoid multiple
+ // updates when called during the same time tick. Only the lower 8 bits of
+ // the timestamp are used (which saves us 3 bytes of memory per JLed
+ // instance), resulting in limited accuracy, which may lead to false
+ // negatives if Update() is not called for a longer time (i.e. > 255ms),
+ // which should not be a problem at all.
+ uint8_t last_update_time_ = 0;
+ uint32_t time_start_ = 0;
uint16_t delay_before_ = 0; // delay before the first effect starts
uint16_t delay_after_ = 0; // delay after each repetition
};
-template T* ptr(T &obj) {return &obj;} // NOLINT
-template T* ptr(T *obj) {return obj;}
+template
+T* ptr(T& obj) { // NOLINT
+ return &obj;
+}
+template
+T* ptr(T* obj) {
+ return obj;
+}
// a group of JLed objects which can be controlled simultanously, in parallel
// or sequentially.
-template
+template
class TJLedSequence {
protected:
// update all leds parallel. Returns true while any of the JLeds is
// active, else false
bool UpdateParallel() {
auto result = false;
+ uint32_t t = ptr(leds_[0])->Hal().millis();
for (auto i = 0u; i < n_; i++) {
- result |= ptr(leds_[i])->Update();
+ result |= ptr(leds_[i])->Update(t);
}
return result;
}
@@ -488,13 +551,10 @@ class TJLedSequence {
// update all leds sequentially. Returns true while any of the JLeds is
// active, else false
bool UpdateSequentially() {
- if (cur_ >= n_) {
- return false;
- }
if (!ptr(leds_[cur_])->Update()) {
return ++cur_ < n_;
}
- return true;;
+ return true;
}
void ResetLeds() {
@@ -503,24 +563,24 @@ class TJLedSequence {
}
}
-
public:
enum eMode { SEQUENCE, PARALLEL };
TJLedSequence() = delete;
template
- TJLedSequence(eMode mode, T (&leds)[N]) : TJLedSequence(mode, leds, N) {}
+ TJLedSequence(eMode mode, L (&leds)[N]) : TJLedSequence(mode, leds, N) {}
- TJLedSequence(eMode mode, T* leds, size_t n)
+ TJLedSequence(eMode mode, L* leds, size_t n)
: mode_{mode}, leds_{leds}, cur_{0}, n_{n} {}
bool Update() {
- if (!is_running_) {
+ if (!is_running_ || n_ < 1) {
return false;
}
- const auto led_running = (mode_ == eMode::PARALLEL) ? UpdateParallel()
- : UpdateSequentially();
+ const auto led_running = (mode_ == eMode::PARALLEL)
+ ? UpdateParallel()
+ : UpdateSequentially();
if (led_running) {
return true;
}
@@ -529,7 +589,7 @@ class TJLedSequence {
cur_ = 0;
ResetLeds();
- is_running_ = ++iteration_ < num_repetitions_ ||
+ is_running_ = ++iteration_ < num_repetitions_ ||
num_repetitions_ == kRepeatForever;
return is_running_;
@@ -543,26 +603,27 @@ class TJLedSequence {
}
void Stop() {
+ is_running_ = false;
for (auto i = 0u; i < n_; i++) {
- leds_[i].Stop();
+ ptr(leds_[i])->Stop();
}
}
// set number of repetitions for the sequence
- TJLedSequence Repeat(uint16_t num_repetitions) {
+ B& Repeat(uint16_t num_repetitions) {
num_repetitions_ = num_repetitions;
- return *this;
+ return static_cast(*this);
}
// repeat Forever
- TJLedSequence Forever() { return Repeat(kRepeatForever); }
+ B& Forever() { return Repeat(kRepeatForever); }
bool IsForever() const { return num_repetitions_ == kRepeatForever; }
private:
- const eMode mode_;
- T* leds_;
+ eMode mode_;
+ L* leds_;
size_t cur_;
- const size_t n_;
+ size_t n_;
static constexpr uint16_t kRepeatForever = 65535;
uint16_t num_repetitions_ = 1;
uint16_t iteration_ = 0;
@@ -570,5 +631,4 @@ class TJLedSequence {
};
}; // namespace jled
-
#endif // SRC_JLED_BASE_H_
diff --git a/src/pico_hal.h b/src/pico_hal.h
index 9b85173..9e2b68c 100644
--- a/src/pico_hal.h
+++ b/src/pico_hal.h
@@ -43,7 +43,8 @@ class PicoHal {
uint32_t *top_) {
// Set the frequency, making "top_" as large as possible for maximum
// resolution.
- *div = (uint32_t)(16 * clock_get_hz(clk_sys) / (uint32_t)freq);
+ *div = static_cast(16 * clock_get_hz(clk_sys) /
+ static_cast(freq));
*top_ = 1;
for (;;) {
// Try a few small prime factors to get close to the desired
@@ -100,7 +101,7 @@ class PicoHal {
void analogWrite(uint8_t val) const {
set_pwm_duty(slice_num_, channel_, top_,
- (uint32_t)(DUTY_100_PCT / 255) * val);
+ static_cast(DUTY_100_PCT / 255) * val);
}
uint32_t millis() const { return to_ms_since_boot(get_absolute_time()); }
diff --git a/test/Makefile b/test/Makefile
index 9802d39..592451e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,5 +1,8 @@
# JLed unit tests Makefile
# run `make coverage` to run all test and calculate coverage
+#
+.PHONY: phony
+
CFLAGS=-std=c++14 -c -Wall -Wextra -I. -I../src -I./esp-idf \
--coverage -fno-inline \
-fno-inline-small-functions -fno-default-inline -g -fmax-errors=5 \
@@ -8,29 +11,31 @@ CFLAGS=-std=c++14 -c -Wall -Wextra -I. -I../src -I./esp-idf \
LDFLAGS=-fprofile-arcs -ftest-coverage
-TEST_ARDUINO_MOCK_SRC=Arduino.cpp test_arduino_mock.cpp test_main.cpp
+CATCH=catch2/catch_amalgamated.cpp
+
+TEST_ARDUINO_MOCK_SRC=Arduino.cpp test_arduino_mock.cpp test_main.cpp ${CATCH}
TEST_ARDUINO_MOCK_OBJECTS=$(TEST_ARDUINO_MOCK_SRC:.cpp=.o)
-TEST_JLED_SRC=Arduino.cpp test_jled.cpp test_main.cpp ../src/jled_base.cpp
+TEST_JLED_SRC=Arduino.cpp test_jled.cpp test_main.cpp ../src/jled_base.cpp ${CATCH}
TEST_JLED_OBJECTS=$(TEST_JLED_SRC:.cpp=.o)
-TEST_JLED_SEQUENCE_SRC=Arduino.cpp test_jled_sequence.cpp test_main.cpp ../src/jled_base.cpp
+TEST_JLED_SEQUENCE_SRC=Arduino.cpp test_jled_sequence.cpp test_main.cpp ../src/jled_base.cpp ${CATCH}
TEST_JLED_SEQUENCE_OBJECTS=$(TEST_JLED_SEQUENCE_SRC:.cpp=.o)
TEST_ESP32_SRC=esp-idf/esp_timer.cpp esp-idf/driver/ledc.cpp \
- test_esp32_hal.cpp ../src/esp32_hal.cpp test_main.cpp
+ test_esp32_hal.cpp ../src/esp32_hal.cpp test_main.cpp ${CATCH}
TEST_ESP32_OBJECTS=$(TEST_ESP32_SRC:.cpp=.o)
-TEST_ESP8266_SRC=Arduino.cpp test_esp8266_hal.cpp test_main.cpp
+TEST_ESP8266_SRC=Arduino.cpp test_esp8266_hal.cpp test_main.cpp ${CATCH}
TEST_ESP8266_OBJECTS=$(TEST_ESP8266_SRC:.cpp=.o)
-TEST_MBED_SRC=mbed.cpp test_mbed_hal.cpp test_main.cpp
+TEST_MBED_SRC=mbed.cpp test_mbed_hal.cpp test_main.cpp ${CATCH}
TEST_MBED_OBJECTS=$(TEST_MBED_SRC:.cpp=.o)
-TEST_ARDUINO_SRC=Arduino.cpp test_arduino_hal.cpp test_main.cpp
+TEST_ARDUINO_SRC=Arduino.cpp test_arduino_hal.cpp test_main.cpp ${CATCH}
TEST_ARDUINO_OBJECTS=$(TEST_ARDUINO_SRC:.cpp=.o)
-TEST_MORSE_SRC=test_example_morse.cpp test_main.cpp
+TEST_MORSE_SRC=test_example_morse.cpp test_main.cpp ${CATCH}
TEST_MORSE_OBJECTS=$(TEST_MORSE_SRC:.cpp=.o)
@@ -67,10 +72,10 @@ bin/test_example_morse: $(TEST_MORSE_OBJECTS)
$(CXX) -o $@ $(LDFLAGS) $(TEST_MORSE_OBJECTS)
coverage: test
- lcov --config-file=.lcovrc --directory ../src --directory .. --capture --output-file coverage.info --no-external
- lcov --config-file=.lcovrc --list coverage.info
+ lcov --config-file=.lcovrc --directory ../src --directory .. --capture --output-file coverage.lcov --no-external
+ lcov --config-file=.lcovrc --list coverage.lcov
mkdir -p report
- genhtml coverage.info -o report
+ genhtml coverage.lcov -o report
test: depend all
./bin/test_jled
@@ -90,8 +95,8 @@ test: depend all
bin:
mkdir -p bin
-clean:
- rm -f coverage.info *.{gcov,gcda,gcno,o} ../src/*.{gcov,gcda,gcno,o} .depend
+clean: phony
+ rm -f {./,esp-idf,esp-idf/driver,catch2}/{*.gcov,*.gcda,*.gcno,*.o} .depend
clobber: clean
rm -f bin/*
diff --git a/test/catch.hpp b/test/catch.hpp
deleted file mode 100644
index 7e706f9..0000000
--- a/test/catch.hpp
+++ /dev/null
@@ -1,17959 +0,0 @@
-/*
- * Catch v2.13.7
- * Generated: 2021-07-28 20:29:27.753164
- * ----------------------------------------------------------
- * This file has been merged from multiple headers. Please don't edit it directly
- * Copyright (c) 2021 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 CATCH_VERSION_MAJOR 2
-#define CATCH_VERSION_MINOR 13
-#define CATCH_VERSION_PATCH 7
-
-#ifdef __clang__
-# pragma clang system_header
-#elif defined __GNUC__
-# pragma GCC system_header
-#endif
-
-// 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 push
-# pragma clang diagnostic ignored "-Wpadded"
-# pragma clang diagnostic ignored "-Wswitch-enum"
-# pragma clang diagnostic ignored "-Wcovered-switch-default"
-# endif
-#elif defined __GNUC__
- // 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
-# define CLARA_CONFIG_MAIN
-# endif
-#endif
-
-// start catch_user_interfaces.h
-
-namespace Catch {
- unsigned int rngSeed();
-}
-
-// end catch_user_interfaces.h
-// start catch_tag_alias_autoregistrar.h
-
-// start catch_common.h
-
-// start catch_compiler_capabilities.h
-
-// Detect a number of compiler features - by compiler
-// The following features are defined:
-//
-// 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_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.
-
-#ifdef __cplusplus
-
-# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
-# define CATCH_CPP14_OR_GREATER
-# endif
-
-# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
-# define CATCH_CPP17_OR_GREATER
-# endif
-
-#endif
-
-// 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
-
-#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_ZERO_VARIADIC_WARNINGS \
- _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
-
-# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
- _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
-
-#endif // __clang__
-
-////////////////////////////////////////////////////////////////////////////////
-// Assume that non-Windows platforms support posix signals by default
-#if !defined(CATCH_PLATFORM_WINDOWS)
- #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-// We know some environments not to support full POSIX signals
-#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
- #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
-#endif
-
-#ifdef __OS400__
-# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
-# 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__
-
-// Required for some versions of Cygwin to declare gettimeofday
-// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
-# define _BSD_SOURCE
-// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
-// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
-# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
- && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
-
-# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
-
-# endif
-#endif // __CYGWIN__
-
-////////////////////////////////////////////////////////////////////////////////
-// Visual C++
-#if defined(_MSC_VER)
-
-# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
-# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
-
-// Universal Windows platform does not support SEH
-// Or console colours (or console at all...)
-# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
-# define CATCH_CONFIG_COLOUR_NONE
-# else
-# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
-# endif
-
-// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
-// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
-// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
-# if !defined(__clang__) // Handle Clang masquerading for msvc
-# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
-# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-# endif // MSVC_TRADITIONAL
-# endif // __clang__
-
-#endif // _MSC_VER
-
-#if defined(_REENTRANT) || defined(_MSC_VER)
-// Enable async processing, as -pthread is specified or no additional linking is required
-# define CATCH_INTERNAL_CONFIG_USE_ASYNC
-#endif // _MSC_VER
-
-////////////////////////////////////////////////////////////////////////////////
-// 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
-
-////////////////////////////////////////////////////////////////////////////////
-// DJGPP
-#ifdef __DJGPP__
-# 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
-// 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
-
-////////////////////////////////////////////////////////////////////////////////
-
-// 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
-
-// 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)
-
-#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
-
-#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
-# define CATCH_CONFIG_CPP11_TO_STRING
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
-# define CATCH_CONFIG_CPP17_OPTIONAL
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
-# define CATCH_CONFIG_CPP17_STRING_VIEW
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
-# define CATCH_CONFIG_CPP17_VARIANT
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
-# define CATCH_CONFIG_CPP17_BYTE
-#endif
-
-#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
-# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
-# define CATCH_CONFIG_NEW_CAPTURE
-#endif
-
-#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
-# define CATCH_CONFIG_DISABLE_EXCEPTIONS
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
-# define CATCH_CONFIG_POLYFILL_ISNAN
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
-# define CATCH_CONFIG_USE_ASYNC
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
-# define CATCH_CONFIG_ANDROID_LOGWRITE
-#endif
-
-#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
-# define CATCH_CONFIG_GLOBAL_NEXTAFTER
-#endif
-
-// Even if we do not think the compiler has that warning, we still have
-// to provide a macro that can be used by the code.
-#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
-# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
-#endif
-#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
-# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-#endif
-#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
-# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
-#endif
-#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
-# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
-#endif
-#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
-# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
-#endif
-#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
-# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
-#endif
-
-// The goal of this macro is to avoid evaluation of the arguments, but
-// still have the compiler warn on problems inside...
-#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
-# define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
-#endif
-
-#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
-# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
-#elif defined(__clang__) && (__clang_major__ < 5)
-# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
-#endif
-
-#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
-# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
-#endif
-
-#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
-#define CATCH_TRY if ((true))
-#define CATCH_CATCH_ALL if ((false))
-#define CATCH_CATCH_ANON(type) if ((false))
-#else
-#define CATCH_TRY try
-#define CATCH_CATCH_ALL 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 )
-#ifdef CATCH_CONFIG_COUNTER
-# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
-#else
-# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
-#endif
-
-#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 CaseSensitive { enum Choice {
- Yes,
- No
- }; };
-
- class NonCopyable {
- NonCopyable( NonCopyable const& ) = delete;
- NonCopyable( NonCopyable && ) = delete;
- NonCopyable& operator = ( NonCopyable const& ) = delete;
- NonCopyable& operator = ( NonCopyable && ) = delete;
-
- protected:
- NonCopyable();
- virtual ~NonCopyable();
- };
-
- struct SourceLineInfo {
-
- SourceLineInfo() = delete;
- SourceLineInfo( char const* _file, std::size_t _line ) noexcept
- : file( _file ),
- line( _line )
- {}
-
- SourceLineInfo( SourceLineInfo const& other ) = default;
- SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
- SourceLineInfo( SourceLineInfo&& ) noexcept = default;
- SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
-
- bool empty() const noexcept { return file[0] == '\0'; }
- bool operator == ( SourceLineInfo const& other ) const noexcept;
- bool operator < ( SourceLineInfo const& other ) const noexcept;
-
- char const* file;
- std::size_t line;
- };
-
- 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
- // >> stuff +StreamEndStop
- struct StreamEndStop {
- std::string operator+() const;
- };
- template
- T const& operator + ( T const& value, StreamEndStop ) {
- return value;
- }
-}
-
-#define CATCH_INTERNAL_LINEINFO \
- ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) )
-
-// end catch_common.h
-namespace Catch {
-
- struct RegistrarForTagAliases {
- RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
- };
-
-} // 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_STOP_WARNINGS_SUPPRESSION
-
-// end catch_tag_alias_autoregistrar.h
-// start catch_test_registry.h
-
-// start catch_interfaces_testcase.h
-
-#include
-
-namespace Catch {
-
- class TestSpec;
-
- struct ITestInvoker {
- virtual void invoke () const = 0;
- virtual ~ITestInvoker();
- };
-
- class TestCase;
- struct IConfig;
-
- struct ITestCaseRegistry {
- virtual ~ITestCaseRegistry();
- virtual std::vector const& getAllTests() const = 0;
- virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0;
- };
-
- bool isThrowSafe( TestCase const& testCase, IConfig const& config );
- bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
- std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config );
- std::vector const& getAllTestCasesSorted( IConfig const& config );
-
-}
-
-// end catch_interfaces_testcase.h
-// start catch_stringref.h
-
-#include
-#include
-#include
-#include
-
-namespace Catch {
-
- /// A non-owning string class (similar to the forthcoming std::string_view)
- /// Note that, because a StringRef may be a substring of another string,
- /// it may not be null terminated.
- class StringRef {
- public:
- using size_type = std::size_t;
- using const_iterator = const char*;
-
- private:
- static constexpr char const* const s_empty = "";
-
- char const* m_start = s_empty;
- size_type m_size = 0;
-
- public: // construction
- constexpr StringRef() noexcept = default;
-
- StringRef( char const* rawChars ) noexcept;
-
- constexpr StringRef( char const* rawChars, size_type size ) noexcept
- : m_start( rawChars ),
- m_size( size )
- {}
-
- StringRef( std::string const& stdString ) noexcept
- : m_start( stdString.c_str() ),
- m_size( stdString.size() )
- {}
-
- explicit operator std::string() const {
- return std::string(m_start, m_size);
- }
-
- public: // operators
- auto operator == ( StringRef const& other ) const noexcept -> bool;
- auto operator != (StringRef const& other) const noexcept -> bool {
- return !(*this == other);
- }
-
- auto operator[] ( size_type index ) const noexcept -> char {
- assert(index < m_size);
- return m_start[index];
- }
-
- public: // named queries
- constexpr auto empty() const noexcept -> bool {
- return m_size == 0;
- }
- constexpr auto size() const noexcept -> size_type {
- return m_size;
- }
-
- // Returns the current start pointer. If the StringRef is not
- // null-terminated, throws std::domain_exception
- auto c_str() const -> char const*;
-
- public: // substrings and searches
- // Returns a substring of [start, start + length).
- // If start + length > size(), then the substring is [start, size()).
- // If start > size(), then the substring is empty.
- auto substr( size_type start, size_type length ) const noexcept -> StringRef;
-
- // Returns the current start pointer. May not be null-terminated.
- auto data() const noexcept -> char const*;
-
- constexpr auto isNullTerminated() const noexcept -> bool {
- return m_start[m_size] == '\0';
- }
-
- public: // iterators
- constexpr const_iterator begin() const { return m_start; }
- constexpr const_iterator end() const { return m_start + m_size; }
- };
-
- auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
- auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
-
- constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
- return StringRef( rawChars, size );
- }
-} // namespace Catch
-
-constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
- return Catch::StringRef( rawChars, size );
-}
-
-// end catch_stringref.h
-// start catch_preprocessor.hpp
-
-
-#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
-#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
-#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
-#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
-#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
-#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
-
-#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
-// MSVC needs more evaluations
-#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
-#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
-#else
-#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
-#endif
-
-#define CATCH_REC_END(...)
-#define CATCH_REC_OUT
-
-#define CATCH_EMPTY()
-#define CATCH_DEFER(id) id CATCH_EMPTY()
-
-#define CATCH_REC_GET_END2() 0, CATCH_REC_END
-#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
-#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
-#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
-#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
-#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
-
-#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
-#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
-#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
-
-#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
-#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
-#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
-
-// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
-// and passes userdata as the first parameter to each invocation,
-// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
-#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
-
-#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
-
-#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
-#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
-#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
-#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
-#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
-#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
-#else
-// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
-#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
-#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
-#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
-#endif
-
-#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
-#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
-
-#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper())
-#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
-#else
-#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper()))
-#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
-#endif
-
-#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
- CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
-
-#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
-#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
-#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
-#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)
-#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)
-#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)
-#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _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 class Final, template< typename...> class...Containers, typename...Types>\
- struct create, TypeList> { using type = typename append, typename rewrap, Types...>::type...>::type; };\
- template class Final, template class List, typename...Ts>\
- struct convert> { using type = typename append,TypeList...>::type; };
-
-#define INTERNAL_CATCH_NTTP_1(signature, ...)\
- template struct Nttp{};\
- template\
- constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
- template class...> struct NttpTemplateTypeList{};\
- template class...Cs>\
- constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList { return {}; } \
- \
- template< template class Container, template class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
- struct rewrap, List<__VA_ARGS__>> { using type = TypeList>; };\
- template< template class Container, template class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
- struct rewrap, List<__VA_ARGS__>, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\
- template class Final, template class...Containers, typename...Types>\
- struct create, TypeList> { using type = typename append, typename rewrap, Types...>::type...>::type; };
-
-#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
-#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
- template\
- static void TestName()
-#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
- template\
- static void TestName()
-
-#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
-#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
- template\
- static void TestName()
-#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
- template\
- static void TestName()
-
-#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
- template\
- void reg_test(TypeList, Catch::NameAndTags nameAndTags)\
- {\
- Catch::AutoReg( Catch::makeTestInvoker(&TestFunc), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
- }
-
-#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
- template\
- void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
- {\
- Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
- }
-
-#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
- template\
- void reg_test(TypeList, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
- {\
- Catch::AutoReg( Catch::makeTestInvoker(&TestName::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
- }
-
-#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
- template\
- void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
- {\
- Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
- }
-
-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
- template \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
- void test();\
- }
-
-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
- template \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
- void test();\
- }
-
-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
- template \
- void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName::test()
-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
- template \
- void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
-#define INTERNAL_CATCH_NTTP_0
-#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0)
-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)
-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)
-#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)
-#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)
-#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)
-#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)
-#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)
-#else
-#define INTERNAL_CATCH_NTTP_0(signature)
-#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__))
-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
-#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
-#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
-#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
-#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
-#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
-#endif
-
-// end catch_preprocessor.hpp
-// start catch_meta.hpp
-
-
-#include
-
-namespace Catch {
- template
- struct always_false : std::false_type {};
-
- template struct true_given : std::true_type {};
- struct is_callable_tester {
- template
- true_given()(std::declval()...))> static test(int);
- template
- std::false_type static test(...);
- };
-
- template
- struct is_callable;
-
- template
- struct is_callable : decltype(is_callable_tester::test(0)) {};
-
-#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
- // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
- // replaced with std::invoke_result here.
- template
- using FunctionReturnType = std::remove_reference_t>>;
-#else
- // Keep ::type here because we still support C++11
- template
- using FunctionReturnType = typename std::remove_reference::type>::type>::type;
-#endif
-
-} // namespace Catch
-
-namespace mpl_{
- struct na;
-}
-
-// end catch_meta.hpp
-namespace Catch {
-
-template
-class TestInvokerAsMethod : public ITestInvoker {
- void (C::*m_testAsMethod)();
-public:
- TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
-
- void invoke() const override {
- C obj;
- (obj.*m_testAsMethod)();
- }
-};
-
-auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
-
-template
-auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
- return new(std::nothrow) TestInvokerAsMethod( testAsMethod );
-}
-
-struct NameAndTags {
- NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
- StringRef name;
- StringRef tags;
-};
-
-struct AutoReg : NonCopyable {
- AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
- ~AutoReg();
-};
-
-} // end namespace Catch
-
-#if defined(CATCH_CONFIG_DISABLE)
- #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
- static void TestName()
- #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
- namespace{ \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
- void test(); \
- }; \
- } \
- void TestName::test()
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \
- INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
- namespace{ \
- namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
- INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
- } \
- } \
- INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )
- #else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
- #endif
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )
- #else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
- #endif
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
- #else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
- #endif
-
- #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
- #else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
- #endif
-#endif
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
- static void TestName(); \
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- static void TestName()
- #define INTERNAL_CATCH_TESTCASE( ... ) \
- INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
- void test(); \
- }; \
- Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
- } \
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- void TestName::test()
- #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
- INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
-
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
- INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
- namespace {\
- namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
- INTERNAL_CATCH_TYPE_GEN\
- INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
- INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
- template \
- struct TestName{\
- TestName(){\
- int index = 0; \
- constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
- using expander = int[];\
- (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
- }\
- };\
- static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
- TestName();\
- return 0;\
- }();\
- }\
- }\
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )
-#else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
-#endif
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )
-#else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
-#endif
-
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
- template static void TestFuncName(); \
- namespace {\
- namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
- INTERNAL_CATCH_TYPE_GEN \
- INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
- template \
- struct TestName { \
- void reg_tests() { \
- int index = 0; \
- using expander = int[]; \
- constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
- constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
- constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\
- } \
- }; \
- static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
- using TestInit = typename create()), TypeList>::type; \
- TestInit t; \
- t.reg_tests(); \
- return 0; \
- }(); \
- } \
- } \
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- template \
- static void TestFuncName()
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
- INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__)
-#else
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) )
-#endif
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
- INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__)
-#else
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
-#endif
-
- #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
- template static void TestFunc(); \
- namespace {\
- namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
- INTERNAL_CATCH_TYPE_GEN\
- template \
- struct TestName { \
- void reg_tests() { \
- int index = 0; \
- using expander = int[]; \
- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
- } \
- };\
- static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
- using TestInit = typename convert::type; \
- TestInit t; \
- t.reg_tests(); \
- return 0; \
- }(); \
- }}\
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- template \
- static void TestFunc()
-
- #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
- INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList )
-
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
- namespace {\
- namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
- INTERNAL_CATCH_TYPE_GEN\
- INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
- INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
- INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
- template \
- struct TestNameClass{\
- TestNameClass(){\
- int index = 0; \
- constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
- using expander = int[];\
- (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
- }\
- };\
- static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
- TestNameClass();\
- return 0;\
- }();\
- }\
- }\
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
-#else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
-#endif
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
- INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
-#else
- #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
-#endif
-
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
- template \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \
- void test();\
- };\
- namespace {\
- namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
- INTERNAL_CATCH_TYPE_GEN \
- INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
- template\
- struct TestNameClass{\
- void reg_tests(){\
- int index = 0;\
- using expander = int[];\
- constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
- constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
- constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \
- }\
- };\
- static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
- using TestInit = typename create()), TypeList>::type;\
- TestInit t;\
- t.reg_tests();\
- return 0;\
- }(); \
- }\
- }\
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- template \
- void TestName::test()
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
- INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
-#else
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
-#endif
-
-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
- INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
-#else
- #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
- INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
-#endif
-
- #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
- CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
- CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
- template \
- struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \
- void test();\
- };\
- namespace {\
- namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
- INTERNAL_CATCH_TYPE_GEN\
- template\
- struct TestNameClass{\
- void reg_tests(){\
- int index = 0;\
- using expander = int[];\
- (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
- }\
- };\
- static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
- using TestInit = typename convert::type;\
- TestInit t;\
- t.reg_tests();\
- return 0;\
- }(); \
- }}\
- CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
- template \
- void TestName::test()
-
-#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
- INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList )
-
-// end catch_test_registry.h
-// start catch_capture.hpp
-
-// start catch_assertionhandler.h
-
-// start catch_assertioninfo.h
-
-// start catch_result_type.h
-
-namespace Catch {
-
- // ResultWas::OfType enum
- struct ResultWas { enum OfType {
- Unknown = -1,
- Ok = 0,
- Info = 1,
- Warning = 2,
-
- FailureBit = 0x10,
-
- ExpressionFailed = FailureBit | 1,
- ExplicitFailure = FailureBit | 2,
-
- Exception = 0x100 | FailureBit,
-
- ThrewException = Exception | 1,
- DidntThrowException = Exception | 2,
-
- FatalErrorCondition = 0x200 | FailureBit
-
- }; };
-
- bool isOk( ResultWas::OfType resultType );
- bool isJustInfo( int flags );
-
- // ResultDisposition::Flags enum
- struct ResultDisposition { enum Flags {
- Normal = 0x01,
-
- ContinueOnFailure = 0x02, // Failures fail test, but execution continues
- FalseTest = 0x04, // Prefix expression with !
- SuppressFail = 0x08 // Failures are reported but do not fail the test
- }; };
-
- ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
-
- bool shouldContinueOnFailure( int flags );
- inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
- bool shouldSuppressFailure( int flags );
-
-} // end namespace Catch
-
-// end catch_result_type.h
-namespace Catch {
-
- struct AssertionInfo
- {
- StringRef macroName;
- SourceLineInfo lineInfo;
- StringRef capturedExpression;
- ResultDisposition::Flags resultDisposition;
-
- // We want to delete this constructor but a compiler bug in 4.8 means
- // the struct is then treated as non-aggregate
- //AssertionInfo() = delete;
- };
-
-} // end namespace Catch
-
-// end catch_assertioninfo.h
-// start catch_decomposer.h
-
-// start catch_tostring.h
-
-#include
-#include
-#include
-#include
-// start catch_stream.h
-
-#include
-#include
-#include
-
-namespace Catch {
-
- std::ostream& cout();
- std::ostream& cerr();
- std::ostream& clog();
-
- class StringRef;
-
- struct IStream {
- virtual ~IStream();
- virtual std::ostream& stream() const = 0;
- };
-
- auto makeStream( StringRef const &filename ) -> IStream const*;
-
- class ReusableStringStream : NonCopyable {
- std::size_t m_index;
- std::ostream* m_oss;
- public:
- ReusableStringStream();
- ~ReusableStringStream();
-
- auto str() const -> std::string;
-
- template
- auto operator << ( T const& value ) -> ReusableStringStream& {
- *m_oss << value;
- return *this;
- }
- auto get() -> std::ostream& { return *m_oss; }
- };
-}
-
-// end catch_stream.h
-// start catch_interfaces_enum_values_registry.h
-
-#include
-
-namespace Catch {
-
- namespace Detail {
- struct EnumInfo {
- StringRef m_name;
- std::vector> m_values;
-
- ~EnumInfo();
-
- StringRef lookup( int value ) const;
- };
- } // namespace Detail
-
- struct IMutableEnumValuesRegistry {
- virtual ~IMutableEnumValuesRegistry();
-
- virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector const& values ) = 0;
-
- template
- Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list values ) {
- static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
- std::vector intValues;
- intValues.reserve( values.size() );
- for( auto enumValue : values )
- intValues.push_back( static_cast( enumValue ) );
- return registerEnum( enumName, allEnums, intValues );
- }
- };
-
-} // Catch
-
-// end catch_interfaces_enum_values_registry.h
-
-#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
-#include
-#endif
-
-#ifdef __OBJC__
-// start catch_objc_arc.hpp
-
-#import
-
-#ifdef __has_feature
-#define CATCH_ARC_ENABLED __has_feature(objc_arc)
-#else
-#define CATCH_ARC_ENABLED 0
-#endif
-
-void arcSafeRelease( NSObject* obj );
-id performOptionalSelector( id obj, SEL sel );
-
-#if !CATCH_ARC_ENABLED
-inline void arcSafeRelease( NSObject* obj ) {
- [obj release];
-}
-inline id performOptionalSelector( id obj, SEL sel ) {
- if( [obj respondsToSelector: sel] )
- return [obj performSelector: sel];
- return nil;
-}
-#define CATCH_UNSAFE_UNRETAINED
-#define CATCH_ARC_STRONG
-#else
-inline void arcSafeRelease( NSObject* ){}
-inline id performOptionalSelector( id obj, SEL sel ) {
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
-#endif
- if( [obj respondsToSelector: sel] )
- return [obj performSelector: sel];
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
- return nil;
-}
-#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
-#define CATCH_ARC_STRONG __strong
-#endif
-
-// end catch_objc_arc.hpp
-#endif
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
-#endif
-
-namespace Catch {
- namespace Detail {
-
- extern const std::string unprintableString;
-
- std::string rawMemoryToString( const void *object, std::size_t size );
-
- template
- std::string rawMemoryToString( const T& object ) {
- return rawMemoryToString( &object, sizeof(object) );
- }
-
- template
- class IsStreamInsertable {
- template
- static auto test(int)
- -> decltype(std::declval() << std::declval(), std::true_type());
-
- template
- static auto test(...)->std::false_type;
-
- public:
- static const bool value = decltype(test(0))::value;
- };
-
- template
- std::string convertUnknownEnumToString( E e );
-
- template
- typename std::enable_if<
- !std::is_enum::value && !std::is_base_of::value,
- std::string>::type convertUnstreamable( T const& ) {
- return Detail::unprintableString;
- }
- template
- typename std::enable_if<
- !std::is_enum::value && std::is_base_of::value,
- std::string>::type convertUnstreamable(T const& ex) {
- return ex.what();
- }
-
- template
- typename std::enable_if<
- std::is_enum::value
- , std::string>::type convertUnstreamable( T const& value ) {
- return convertUnknownEnumToString( value );
- }
-
-#if defined(_MANAGED)
- //! Convert a CLR string to a utf8 std::string
- template
- std::string clrReferenceToString( T^ ref ) {
- if (ref == nullptr)
- return std::string("null");
- auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
- cli::pin_ptr p = &bytes[0];
- return std::string(reinterpret_cast(p), bytes->Length);
- }
-#endif
-
- } // namespace Detail
-
- // If we decide for C++14, change these to enable_if_ts
- template
- struct StringMaker {
- template
- static
- typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type
- convert(const Fake& value) {
- ReusableStringStream rss;
- // NB: call using the function-like syntax to avoid ambiguity with
- // user-defined templated operator<< under clang.
- rss.operator<<(value);
- return rss.str();
- }
-
- template
- static
- typename std::enable_if::value, std::string>::type
- convert( const Fake& value ) {
-#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
- return Detail::convertUnstreamable(value);
-#else
- return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
-#endif
- }
- };
-
- namespace Detail {
-
- // This function dispatches all stringification requests inside of Catch.
- // Should be preferably called fully qualified, like ::Catch::Detail::stringify
- template
- std::string stringify(const T& e) {
- return ::Catch::StringMaker::type>::type>::convert(e);
- }
-
- template
- std::string convertUnknownEnumToString( E e ) {
- return ::Catch::Detail::stringify(static_cast::type>(e));
- }
-
-#if defined(_MANAGED)
- template
- std::string stringify( T^ e ) {
- return ::Catch::StringMaker::convert(e);
- }
-#endif
-
- } // namespace Detail
-
- // Some predefined specializations
-
- template<>
- struct StringMaker {
- static std::string convert(const std::string& str);
- };
-
-#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
- template<>
- struct StringMaker {
- static std::string convert(std::string_view str);
- };
-#endif
-
- template<>
- struct StringMaker {
- static std::string convert(char const * str);
- };
- template<>
- struct StringMaker {
- static std::string convert(char * str);
- };
-
-#ifdef CATCH_CONFIG_WCHAR
- template<>
- struct StringMaker {
- static std::string convert(const std::wstring& wstr);
- };
-
-# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
- template<>
- struct StringMaker {
- static std::string convert(std::wstring_view str);
- };
-# endif
-
- template<>
- struct StringMaker {
- static std::string convert(wchar_t const * str);
- };
- template<>
- struct StringMaker {
- static std::string convert(wchar_t * str);
- };
-#endif
-
- // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
- // while keeping string semantics?
- template
- struct StringMaker {
- static std::string convert(char const* str) {
- return ::Catch::Detail::stringify(std::string{ str });
- }
- };
- template
- struct StringMaker {
- static std::string convert(signed char const* str) {
- return ::Catch::Detail::stringify(std::string{ reinterpret_cast