home readme diff tree note docs

0commit 0bbc98204176a8855677486887f32637baf46b73
1Author: lakefox <mason@lakefox.net>
2Date:   Sun Feb 1 14:11:59 2026 -0700
3
4    ParseSelectorParts works
5
6diff --git a/Makefile b/Makefile
7index e30b7f0..7ff62e0 100755
8--- a/Makefile
9+++ b/Makefile
10@@ -1,16 +1,7 @@
11 # --- Variables ---
12-#CCFLAGS = -std=c++2b -O3
13-CCFLAGS = -Wall -Wextra -std=c++2b -g -O0 -fsanitize=address,undefined -fno-omit-frame-pointer
14-# -O2 -Wall -Wformat -Wformat=2 -Wconversion -Wimplicit-fallthrough \
15-# -Werror=format-security \
16-# -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 \
17-# -D_GLIBCXX_ASSERTIONS \
18-# -fstrict-flex-arrays=3 \
19-# -fstack-clash-protection -fstack-protector-strong \
20-# -Wl,-z,nodlopen -Wl,-z,noexecstack \
21-# -Wl,-z,relro -Wl,-z,now \
22-# -Wl,--as-needed -Wl,--no-copy-dt-needed-entries
23-CC = clang++
24+#CCFLAGS = -std=c23 -O3
25+CCFLAGS = -Wall -Wextra -std=c23 -g -O0 -fsanitize=address,undefined -fno-omit-frame-pointer
26+CC = clang
27 
28 .PHONY: all clean all_tests
29 
30@@ -19,11 +10,11 @@ all: main
31 build:
32 	mkdir -p build
33 
34-main: main.cc build/grim.o build/parser.o 
35+main: main.c build/grim.o build/parser.o 
36 	${CC} ${CCFLAGS} main.cc -Iinclude/ build/grim.o build/parser.o -o main
37 
38-build/grim.o: src/grim.cc include/grim.h | build
39-	${CC} ${CCFLAGS} -Iinclude/ -c src/grim.cc -o build/grim.o
40+build/grim.o: src/grim.c include/grim.h | build
41+	${CC} ${CCFLAGS} -Iinclude/ -c src/grim.c -o build/grim.o
42 
43 build/parser.o: src/parser.cc include/parser.h | build
44 	${CC} ${CCFLAGS} -Iinclude/ -c src/parser.cc -o build/parser.o
45@@ -52,52 +43,9 @@ bench_%: build/%
46 	@echo "--- Running $* ---"
47 	@./build/$*
48 
49-build/css_unit_test: tests/css_unit.cc build/grim.o build/catch.o build/parser.o | build
50-	${CC} ${CCFLAGS} -Iinclude/ tests/css_unit.cc build/grim.o build/catch.o build/parser.o -o build/css_unit_test 
51+build/parseselectorparts_playground: playground/parseselectorparts.c build/grim.o | build
52+	${CC} ${CCFLAGS} -Iinclude/ playground/parseselectorparts.c build/grim.o -o build/parseselectorparts_playground
53 
54-build/html_node_test: tests/html_node.cc build/grim.o build/catch.o build/parser.o | build
55-	${CC} ${CCFLAGS} -Iinclude/ tests/html_node.cc build/grim.o build/catch.o build/parser.o -o build/html_node_test 
56-
57-build/css_selector_test: tests/css_selector.cc build/grim.o build/catch.o build/parser.o | build
58-	${CC} ${CCFLAGS} -Iinclude/ tests/css_selector.cc build/grim.o build/catch.o build/parser.o -o build/css_selector_test 
59-
60-build/html_parser_test: tests/html_parser.cc build/grim.o build/parser.o build/catch.o | build
61-	${CC} ${CCFLAGS} -Iinclude/ tests/html_parser.cc build/grim.o build/parser.o build/catch.o -o build/html_parser_test
62-
63-build/css_parser_test: tests/css_parser.cc build/grim.o build/parser.o build/catch.o | build
64-	${CC} ${CCFLAGS} -Iinclude/ tests/css_parser.cc build/grim.o build/parser.o build/catch.o -o build/css_parser_test
65-
66-build/query_select_test: tests/query_select.cc build/grim.o build/parser.o build/catch.o | build
67-	${CC} ${CCFLAGS} -Iinclude/ tests/query_select.cc build/grim.o build/parser.o build/catch.o -o build/query_select_test
68-
69-build/windowunitlength_test: tests/windowunitlength.cc build/grim.o build/parser.o build/catch.o | build
70-	${CC} ${CCFLAGS} -Iinclude/ tests/windowunitlength.cc build/grim.o build/parser.o build/catch.o -o build/windowunitlength_test
71-
72-build/unitvalue_test: tests/unitvalue.cc build/grim.o build/parser.o build/catch.o | build
73-	${CC} ${CCFLAGS} -Iinclude/ tests/unitvalue.cc build/grim.o build/parser.o build/catch.o -o build/unitvalue_test
74-
75-
76-build/catch.o: ./include/catch_amalgamated.cpp ./include/catch_amalgamated.hpp | build
77-	${CC} ${CCFLAGS} -Iinclude/ -c include/catch_amalgamated.cpp -o build/catch.o
78-
79-# --- Playground ---
80-build/parseselectorparts_playground: playground/parseselectorparts.cc build/grim.o build/parser.o | build
81-	${CC} ${CCFLAGS} -Iinclude/ playground/parseselectorparts.cc build/grim.o build/parser.o -o build/parseselectorparts_playground
82-
83-build/testselector_playground: playground/testselector.cc build/grim.o build/parser.o | build
84-	${CC} ${CCFLAGS} -Iinclude/ playground/testselector.cc build/grim.o build/parser.o -o build/testselector_playground
85-
86-build/css_parser_playground: playground/css_parser.cc build/grim.o build/parser.o | build
87-	${CC} ${CCFLAGS} -Iinclude/ playground/css_parser.cc build/grim.o build/parser.o -o build/css_parser_playground
88-	
89-build/css_unit_playground: playground/css_unit.cc build/grim.o build/parser.o | build
90-	${CC} ${CCFLAGS} -Iinclude/ playground/css_unit.cc build/grim.o build/parser.o -o build/css_unit_playground
91-
92-build/window_playground: playground/window.cc build/grim.o build/parser.o | build
93-	${CC} ${CCFLAGS} -Iinclude/ playground/window.cc build/grim.o build/parser.o -o build/window_playground
94-
95-build/unitvalue_playground: playground/unitvalue.cc build/grim.o build/parser.o | build
96-	${CC} ${CCFLAGS} -Iinclude/ playground/unitvalue.cc build/grim.o build/parser.o -o build/unitvalue_playground
97 
98 
99 # --- Prebuild ---
100diff --git a/include/catch_amalgamated.cpp b/include/catch_amalgamated.cpp
101deleted file mode 100644
102index 892d637..0000000
103--- a/include/catch_amalgamated.cpp
104+++ /dev/null
105@@ -1,12083 +0,0 @@
106-
107-//              Copyright Catch2 Authors
108-// Distributed under the Boost Software License, Version 1.0.
109-//   (See accompanying file LICENSE.txt or copy at
110-//        https://www.boost.org/LICENSE_1_0.txt)
111-
112-// SPDX-License-Identifier: BSL-1.0
113-
114-//  Catch v3.11.0
115-//  Generated: 2025-09-30 10:49:12.549018
116-//  ----------------------------------------------------------
117-//  This file is an amalgamation of multiple different files.
118-//  You probably shouldn't edit it directly.
119-//  ----------------------------------------------------------
120-
121-#include "catch_amalgamated.hpp"
122-
123-
124-#ifndef CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
125-#define CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
126-
127-
128-#if defined(CATCH_PLATFORM_WINDOWS)
129-
130-// We might end up with the define made globally through the compiler,
131-// and we don't want to trigger warnings for this
132-#if !defined(NOMINMAX)
133-#  define NOMINMAX
134-#endif
135-#if !defined(WIN32_LEAN_AND_MEAN)
136-#  define WIN32_LEAN_AND_MEAN
137-#endif
138-
139-#include <windows.h>
140-
141-#endif // defined(CATCH_PLATFORM_WINDOWS)
142-
143-#endif // CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
144-
145-
146-
147-
148-namespace Catch {
149-    namespace Benchmark {
150-        namespace Detail {
151-            ChronometerConcept::~ChronometerConcept() = default;
152-        } // namespace Detail
153-    } // namespace Benchmark
154-} // namespace Catch
155-
156-
157-// Adapted from donated nonius code.
158-
159-
160-#include <vector>
161-
162-namespace Catch {
163-    namespace Benchmark {
164-        namespace Detail {
165-            SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last) {
166-                if (!cfg.benchmarkNoAnalysis()) {
167-                    std::vector<double> samples;
168-                    samples.reserve(static_cast<size_t>(last - first));
169-                    for (auto current = first; current != last; ++current) {
170-                        samples.push_back( current->count() );
171-                    }
172-
173-                    auto analysis = Catch::Benchmark::Detail::analyse_samples(
174-                        cfg.benchmarkConfidenceInterval(),
175-                        cfg.benchmarkResamples(),
176-                        samples.data(),
177-                        samples.data() + samples.size() );
178-                    auto outliers = Catch::Benchmark::Detail::classify_outliers(
179-                        samples.data(), samples.data() + samples.size() );
180-
181-                    auto wrap_estimate = [](Estimate<double> e) {
182-                        return Estimate<FDuration> {
183-                            FDuration(e.point),
184-                                FDuration(e.lower_bound),
185-                                FDuration(e.upper_bound),
186-                                e.confidence_interval,
187-                        };
188-                    };
189-                    std::vector<FDuration> samples2;
190-                    samples2.reserve(samples.size());
191-                    for (auto s : samples) {
192-                        samples2.push_back( FDuration( s ) );
193-                    }
194-
195-                    return {
196-                        CATCH_MOVE(samples2),
197-                        wrap_estimate(analysis.mean),
198-                        wrap_estimate(analysis.standard_deviation),
199-                        outliers,
200-                        analysis.outlier_variance,
201-                    };
202-                } else {
203-                    std::vector<FDuration> samples;
204-                    samples.reserve(static_cast<size_t>(last - first));
205-
206-                    FDuration mean = FDuration(0);
207-                    int i = 0;
208-                    for (auto it = first; it < last; ++it, ++i) {
209-                        samples.push_back(*it);
210-                        mean += *it;
211-                    }
212-                    mean /= i;
213-
214-                    return SampleAnalysis{
215-                        CATCH_MOVE(samples),
216-                        Estimate<FDuration>{ mean, mean, mean, 0.0 },
217-                        Estimate<FDuration>{ FDuration( 0 ),
218-                                             FDuration( 0 ),
219-                                             FDuration( 0 ),
220-                                             0.0 },
221-                        OutlierClassification{},
222-                        0.0
223-                    };
224-                }
225-            }
226-        } // namespace Detail
227-    } // namespace Benchmark
228-} // namespace Catch
229-
230-
231-
232-
233-namespace Catch {
234-    namespace Benchmark {
235-        namespace Detail {
236-            struct do_nothing {
237-                void operator()() const {}
238-            };
239-
240-            BenchmarkFunction::callable::~callable() = default;
241-            BenchmarkFunction::BenchmarkFunction():
242-                f( new model<do_nothing>{ {} } ){}
243-        } // namespace Detail
244-    } // namespace Benchmark
245-} // namespace Catch
246-
247-
248-
249-
250-#include <exception>
251-
252-namespace Catch {
253-    namespace Benchmark {
254-        namespace Detail {
255-            struct optimized_away_error : std::exception {
256-                const char* what() const noexcept override;
257-            };
258-
259-            const char* optimized_away_error::what() const noexcept {
260-                return "could not measure benchmark, maybe it was optimized away";
261-            }
262-
263-            void throw_optimized_away_error() {
264-                Catch::throw_exception(optimized_away_error{});
265-            }
266-
267-        } // namespace Detail
268-    } // namespace Benchmark
269-} // namespace Catch
270-
271-
272-// Adapted from donated nonius code.
273-
274-
275-
276-#include <algorithm>
277-#include <cassert>
278-#include <cmath>
279-#include <cstddef>
280-#include <numeric>
281-#include <random>
282-
283-
284-#if defined(CATCH_CONFIG_USE_ASYNC)
285-#include <future>
286-#endif
287-
288-namespace Catch {
289-    namespace Benchmark {
290-        namespace Detail {
291-            namespace {
292-
293-                template <typename URng, typename Estimator>
294-                static sample
295-                resample( URng& rng,
296-                          unsigned int resamples,
297-                          double const* first,
298-                          double const* last,
299-                          Estimator& estimator ) {
300-                    auto n = static_cast<size_t>( last - first );
301-                    Catch::uniform_integer_distribution<size_t> dist( 0, n - 1 );
302-
303-                    sample out;
304-                    out.reserve( resamples );
305-                    std::vector<double> resampled;
306-                    resampled.reserve( n );
307-                    for ( size_t i = 0; i < resamples; ++i ) {
308-                        resampled.clear();
309-                        for ( size_t s = 0; s < n; ++s ) {
310-                            resampled.push_back( first[dist( rng )] );
311-                        }
312-                        const auto estimate =
313-                            estimator( resampled.data(), resampled.data() + resampled.size() );
314-                        out.push_back( estimate );
315-                    }
316-                    std::sort( out.begin(), out.end() );
317-                    return out;
318-                }
319-
320-                static double outlier_variance( Estimate<double> mean,
321-                                                Estimate<double> stddev,
322-                                                int n ) {
323-                    double sb = stddev.point;
324-                    double mn = mean.point / n;
325-                    double mg_min = mn / 2.;
326-                    double sg = (std::min)( mg_min / 4., sb / std::sqrt( n ) );
327-                    double sg2 = sg * sg;
328-                    double sb2 = sb * sb;
329-
330-                    auto c_max = [n, mn, sb2, sg2]( double x ) -> double {
331-                        double k = mn - x;
332-                        double d = k * k;
333-                        double nd = n * d;
334-                        double k0 = -n * nd;
335-                        double k1 = sb2 - n * sg2 + nd;
336-                        double det = k1 * k1 - 4 * sg2 * k0;
337-                        return static_cast<int>( -2. * k0 /
338-                                                 ( k1 + std::sqrt( det ) ) );
339-                    };
340-
341-                    auto var_out = [n, sb2, sg2]( double c ) {
342-                        double nc = n - c;
343-                        return ( nc / n ) * ( sb2 - nc * sg2 );
344-                    };
345-
346-                    return (std::min)( var_out( 1 ),
347-                                       var_out(
348-                                           (std::min)( c_max( 0. ),
349-                                                       c_max( mg_min ) ) ) ) /
350-                           sb2;
351-                }
352-
353-                static double erf_inv( double x ) {
354-                    // Code accompanying the article "Approximating the erfinv
355-                    // function" in GPU Computing Gems, Volume 2
356-                    double w, p;
357-
358-                    w = -log( ( 1.0 - x ) * ( 1.0 + x ) );
359-
360-                    if ( w < 6.250000 ) {
361-                        w = w - 3.125000;
362-                        p = -3.6444120640178196996e-21;
363-                        p = -1.685059138182016589e-19 + p * w;
364-                        p = 1.2858480715256400167e-18 + p * w;
365-                        p = 1.115787767802518096e-17 + p * w;
366-                        p = -1.333171662854620906e-16 + p * w;
367-                        p = 2.0972767875968561637e-17 + p * w;
368-                        p = 6.6376381343583238325e-15 + p * w;
369-                        p = -4.0545662729752068639e-14 + p * w;
370-                        p = -8.1519341976054721522e-14 + p * w;
371-                        p = 2.6335093153082322977e-12 + p * w;
372-                        p = -1.2975133253453532498e-11 + p * w;
373-                        p = -5.4154120542946279317e-11 + p * w;
374-                        p = 1.051212273321532285e-09 + p * w;
375-                        p = -4.1126339803469836976e-09 + p * w;
376-                        p = -2.9070369957882005086e-08 + p * w;
377-                        p = 4.2347877827932403518e-07 + p * w;
378-                        p = -1.3654692000834678645e-06 + p * w;
379-                        p = -1.3882523362786468719e-05 + p * w;
380-                        p = 0.0001867342080340571352 + p * w;
381-                        p = -0.00074070253416626697512 + p * w;
382-                        p = -0.0060336708714301490533 + p * w;
383-                        p = 0.24015818242558961693 + p * w;
384-                        p = 1.6536545626831027356 + p * w;
385-                    } else if ( w < 16.000000 ) {
386-                        w = sqrt( w ) - 3.250000;
387-                        p = 2.2137376921775787049e-09;
388-                        p = 9.0756561938885390979e-08 + p * w;
389-                        p = -2.7517406297064545428e-07 + p * w;
390-                        p = 1.8239629214389227755e-08 + p * w;
391-                        p = 1.5027403968909827627e-06 + p * w;
392-                        p = -4.013867526981545969e-06 + p * w;
393-                        p = 2.9234449089955446044e-06 + p * w;
394-                        p = 1.2475304481671778723e-05 + p * w;
395-                        p = -4.7318229009055733981e-05 + p * w;
396-                        p = 6.8284851459573175448e-05 + p * w;
397-                        p = 2.4031110387097893999e-05 + p * w;
398-                        p = -0.0003550375203628474796 + p * w;
399-                        p = 0.00095328937973738049703 + p * w;
400-                        p = -0.0016882755560235047313 + p * w;
401-                        p = 0.0024914420961078508066 + p * w;
402-                        p = -0.0037512085075692412107 + p * w;
403-                        p = 0.005370914553590063617 + p * w;
404-                        p = 1.0052589676941592334 + p * w;
405-                        p = 3.0838856104922207635 + p * w;
406-                    } else {
407-                        w = sqrt( w ) - 5.000000;
408-                        p = -2.7109920616438573243e-11;
409-                        p = -2.5556418169965252055e-10 + p * w;
410-                        p = 1.5076572693500548083e-09 + p * w;
411-                        p = -3.7894654401267369937e-09 + p * w;
412-                        p = 7.6157012080783393804e-09 + p * w;
413-                        p = -1.4960026627149240478e-08 + p * w;
414-                        p = 2.9147953450901080826e-08 + p * w;
415-                        p = -6.7711997758452339498e-08 + p * w;
416-                        p = 2.2900482228026654717e-07 + p * w;
417-                        p = -9.9298272942317002539e-07 + p * w;
418-                        p = 4.5260625972231537039e-06 + p * w;
419-                        p = -1.9681778105531670567e-05 + p * w;
420-                        p = 7.5995277030017761139e-05 + p * w;
421-                        p = -0.00021503011930044477347 + p * w;
422-                        p = -0.00013871931833623122026 + p * w;
423-                        p = 1.0103004648645343977 + p * w;
424-                        p = 4.8499064014085844221 + p * w;
425-                    }
426-                    return p * x;
427-                }
428-
429-                static double
430-                standard_deviation( double const* first, double const* last ) {
431-                    auto m = Catch::Benchmark::Detail::mean( first, last );
432-                    double variance =
433-                        std::accumulate( first,
434-                                         last,
435-                                         0.,
436-                                         [m]( double a, double b ) {
437-                                             double diff = b - m;
438-                                             return a + diff * diff;
439-                                         } ) /
440-                        static_cast<double>( last - first );
441-                    return std::sqrt( variance );
442-                }
443-
444-                static sample jackknife( double ( *estimator )( double const*,
445-                                                                double const* ),
446-                                         double* first,
447-                                         double* last ) {
448-                    const auto second = first + 1;
449-                    sample results;
450-                    results.reserve( static_cast<size_t>( last - first ) );
451-
452-                    for ( auto it = first; it != last; ++it ) {
453-                        std::iter_swap( it, first );
454-                        results.push_back( estimator( second, last ) );
455-                    }
456-
457-                    return results;
458-                }
459-
460-
461-            } // namespace
462-        }     // namespace Detail
463-    }         // namespace Benchmark
464-} // namespace Catch
465-
466-namespace Catch {
467-    namespace Benchmark {
468-        namespace Detail {
469-
470-            double weighted_average_quantile( int k,
471-                                              int q,
472-                                              double* first,
473-                                              double* last ) {
474-                auto count = last - first;
475-                double idx = static_cast<double>((count - 1) * k) / static_cast<double>(q);
476-                int j = static_cast<int>(idx);
477-                double g = idx - j;
478-                std::nth_element(first, first + j, last);
479-                auto xj = first[j];
480-                if ( Catch::Detail::directCompare( g, 0 ) ) {
481-                    return xj;
482-                }
483-
484-                auto xj1 = *std::min_element(first + (j + 1), last);
485-                return xj + g * (xj1 - xj);
486-            }
487-
488-            OutlierClassification
489-            classify_outliers( double const* first, double const* last ) {
490-                std::vector<double> copy( first, last );
491-
492-                auto q1 = weighted_average_quantile( 1, 4, copy.data(), copy.data() + copy.size() );
493-                auto q3 = weighted_average_quantile( 3, 4, copy.data(), copy.data() + copy.size() );
494-                auto iqr = q3 - q1;
495-                auto los = q1 - ( iqr * 3. );
496-                auto lom = q1 - ( iqr * 1.5 );
497-                auto him = q3 + ( iqr * 1.5 );
498-                auto his = q3 + ( iqr * 3. );
499-
500-                OutlierClassification o;
501-                for ( ; first != last; ++first ) {
502-                    const double t = *first;
503-                    if ( t < los ) {
504-                        ++o.low_severe;
505-                    } else if ( t < lom ) {
506-                        ++o.low_mild;
507-                    } else if ( t > his ) {
508-                        ++o.high_severe;
509-                    } else if ( t > him ) {
510-                        ++o.high_mild;
511-                    }
512-                    ++o.samples_seen;
513-                }
514-                return o;
515-            }
516-
517-            double mean( double const* first, double const* last ) {
518-                auto count = last - first;
519-                double sum = 0.;
520-                while (first != last) {
521-                    sum += *first;
522-                    ++first;
523-                }
524-                return sum / static_cast<double>(count);
525-            }
526-
527-            double normal_cdf( double x ) {
528-                return std::erfc( -x / std::sqrt( 2.0 ) ) / 2.0;
529-            }
530-
531-            double erfc_inv(double x) {
532-                return erf_inv(1.0 - x);
533-            }
534-
535-            double normal_quantile(double p) {
536-                static const double ROOT_TWO = std::sqrt(2.0);
537-
538-                double result = 0.0;
539-                assert(p >= 0 && p <= 1);
540-                if (p < 0 || p > 1) {
541-                    return result;
542-                }
543-
544-                result = -erfc_inv(2.0 * p);
545-                // result *= normal distribution standard deviation (1.0) * sqrt(2)
546-                result *= /*sd * */ ROOT_TWO;
547-                // result += normal disttribution mean (0)
548-                return result;
549-            }
550-
551-            Estimate<double>
552-            bootstrap( double confidence_level,
553-                       double* first,
554-                       double* last,
555-                       sample const& resample,
556-                       double ( *estimator )( double const*, double const* ) ) {
557-                auto n_samples = last - first;
558-
559-                double point = estimator( first, last );
560-                // Degenerate case with a single sample
561-                if ( n_samples == 1 )
562-                    return { point, point, point, confidence_level };
563-
564-                sample jack = jackknife( estimator, first, last );
565-                double jack_mean =
566-                    mean( jack.data(), jack.data() + jack.size() );
567-                double sum_squares = 0, sum_cubes = 0;
568-                for ( double x : jack ) {
569-                    auto difference = jack_mean - x;
570-                    auto square = difference * difference;
571-                    auto cube = square * difference;
572-                    sum_squares += square;
573-                    sum_cubes += cube;
574-                }
575-
576-                double accel = sum_cubes / ( 6 * std::pow( sum_squares, 1.5 ) );
577-                long n = static_cast<long>( resample.size() );
578-                double prob_n = static_cast<double>(
579-                    std::count_if( resample.begin(),
580-                                   resample.end(),
581-                                   [point]( double x ) { return x < point; } )) /
582-                    static_cast<double>( n );
583-                // degenerate case with uniform samples
584-                if ( Catch::Detail::directCompare( prob_n, 0. ) ) {
585-                    return { point, point, point, confidence_level };
586-                }
587-
588-                double bias = normal_quantile( prob_n );
589-                double z1 = normal_quantile( ( 1. - confidence_level ) / 2. );
590-
591-                auto cumn = [n]( double x ) -> long {
592-                    return std::lround( normal_cdf( x ) *
593-                                        static_cast<double>( n ) );
594-                };
595-                auto a = [bias, accel]( double b ) {
596-                    return bias + b / ( 1. - accel * b );
597-                };
598-                double b1 = bias + z1;
599-                double b2 = bias - z1;
600-                double a1 = a( b1 );
601-                double a2 = a( b2 );
602-                auto lo = static_cast<size_t>( (std::max)( cumn( a1 ), 0l ) );
603-                auto hi =
604-                    static_cast<size_t>( (std::min)( cumn( a2 ), n - 1 ) );
605-
606-                return { point, resample[lo], resample[hi], confidence_level };
607-            }
608-
609-            bootstrap_analysis analyse_samples(double confidence_level,
610-                                               unsigned int n_resamples,
611-                                               double* first,
612-                                               double* last) {
613-                auto mean = &Detail::mean;
614-                auto stddev = &standard_deviation;
615-
616-#if defined(CATCH_CONFIG_USE_ASYNC)
617-                auto Estimate = [=](double(*f)(double const*, double const*)) {
618-                    std::random_device rd;
619-                    auto seed = rd();
620-                    return std::async(std::launch::async, [=] {
621-                        SimplePcg32 rng( seed );
622-                        auto resampled = resample(rng, n_resamples, first, last, f);
623-                        return bootstrap(confidence_level, first, last, resampled, f);
624-                    });
625-                };
626-
627-                auto mean_future = Estimate(mean);
628-                auto stddev_future = Estimate(stddev);
629-
630-                auto mean_estimate = mean_future.get();
631-                auto stddev_estimate = stddev_future.get();
632-#else
633-                auto Estimate = [=](double(*f)(double const* , double const*)) {
634-                    std::random_device rd;
635-                    auto seed = rd();
636-                    SimplePcg32 rng( seed );
637-                    auto resampled = resample(rng, n_resamples, first, last, f);
638-                    return bootstrap(confidence_level, first, last, resampled, f);
639-                };
640-
641-                auto mean_estimate = Estimate(mean);
642-                auto stddev_estimate = Estimate(stddev);
643-#endif // CATCH_USE_ASYNC
644-
645-                auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
646-                double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n);
647-
648-                return { mean_estimate, stddev_estimate, outlier_variance };
649-            }
650-        } // namespace Detail
651-    } // namespace Benchmark
652-} // namespace Catch
653-
654-
655-
656-#include <cmath>
657-#include <limits>
658-
659-namespace {
660-
661-// Performs equivalent check of std::fabs(lhs - rhs) <= margin
662-// But without the subtraction to allow for INFINITY in comparison
663-bool marginComparison(double lhs, double rhs, double margin) {
664-    return (lhs + margin >= rhs) && (rhs + margin >= lhs);
665-}
666-
667-}
668-
669-namespace Catch {
670-
671-    Approx::Approx ( double value )
672-    :   m_epsilon( static_cast<double>(std::numeric_limits<float>::epsilon())*100. ),
673-        m_margin( 0.0 ),
674-        m_scale( 0.0 ),
675-        m_value( value )
676-    {}
677-
678-    Approx Approx::custom() {
679-        return Approx( 0 );
680-    }
681-
682-    Approx Approx::operator-() const {
683-        auto temp(*this);
684-        temp.m_value = -temp.m_value;
685-        return temp;
686-    }
687-
688-
689-    std::string Approx::toString() const {
690-        ReusableStringStream rss;
691-        rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
692-        return rss.str();
693-    }
694-
695-    bool Approx::equalityComparisonImpl(const double other) const {
696-        // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
697-        // Thanks to Richard Harris for his help refining the scaled margin value
698-        return marginComparison(m_value, other, m_margin)
699-            || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
700-    }
701-
702-    void Approx::setMargin(double newMargin) {
703-        CATCH_ENFORCE(newMargin >= 0,
704-            "Invalid Approx::margin: " << newMargin << '.'
705-            << " Approx::Margin has to be non-negative.");
706-        m_margin = newMargin;
707-    }
708-
709-    void Approx::setEpsilon(double newEpsilon) {
710-        CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
711-            "Invalid Approx::epsilon: " << newEpsilon << '.'
712-            << " Approx::epsilon has to be in [0, 1]");
713-        m_epsilon = newEpsilon;
714-    }
715-
716-namespace literals {
717-    Approx operator ""_a(long double val) {
718-        return Approx(val);
719-    }
720-    Approx operator ""_a(unsigned long long val) {
721-        return Approx(val);
722-    }
723-} // end namespace literals
724-
725-std::string StringMaker<Catch::Approx>::convert(Catch::Approx const& value) {
726-    return value.toString();
727-}
728-
729-} // end namespace Catch
730-
731-
732-
733-namespace Catch {
734-
735-    AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const& _lazyExpression):
736-        lazyExpression(_lazyExpression),
737-        resultType(_resultType) {}
738-
739-    std::string AssertionResultData::reconstructExpression() const {
740-
741-        if( reconstructedExpression.empty() ) {
742-            if( lazyExpression ) {
743-                ReusableStringStream rss;
744-                rss << lazyExpression;
745-                reconstructedExpression = rss.str();
746-            }
747-        }
748-        return reconstructedExpression;
749-    }
750-
751-    AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData&& data )
752-    :   m_info( info ),
753-        m_resultData( CATCH_MOVE(data) )
754-    {}
755-
756-    // Result was a success
757-    bool AssertionResult::succeeded() const {
758-        return Catch::isOk( m_resultData.resultType );
759-    }
760-
761-    // Result was a success, or failure is suppressed
762-    bool AssertionResult::isOk() const {
763-        return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
764-    }
765-
766-    ResultWas::OfType AssertionResult::getResultType() const {
767-        return m_resultData.resultType;
768-    }
769-
770-    bool AssertionResult::hasExpression() const {
771-        return !m_info.capturedExpression.empty();
772-    }
773-
774-    bool AssertionResult::hasMessage() const {
775-        return !m_resultData.message.empty();
776-    }
777-
778-    std::string AssertionResult::getExpression() const {
779-        // Possibly overallocating by 3 characters should be basically free
780-        std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
781-        if (isFalseTest(m_info.resultDisposition)) {
782-            expr += "!(";
783-        }
784-        expr += m_info.capturedExpression;
785-        if (isFalseTest(m_info.resultDisposition)) {
786-            expr += ')';
787-        }
788-        return expr;
789-    }
790-
791-    std::string AssertionResult::getExpressionInMacro() const {
792-        if ( m_info.macroName.empty() ) {
793-            return static_cast<std::string>( m_info.capturedExpression );
794-        }
795-        std::string expr;
796-        expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
797-        expr += m_info.macroName;
798-        expr += "( ";
799-        expr += m_info.capturedExpression;
800-        expr += " )";
801-        return expr;
802-    }
803-
804-    bool AssertionResult::hasExpandedExpression() const {
805-        return hasExpression() && getExpandedExpression() != getExpression();
806-    }
807-
808-    std::string AssertionResult::getExpandedExpression() const {
809-        std::string expr = m_resultData.reconstructExpression();
810-        return expr.empty()
811-                ? getExpression()
812-                : expr;
813-    }
814-
815-    StringRef AssertionResult::getMessage() const {
816-        return m_resultData.message;
817-    }
818-    SourceLineInfo AssertionResult::getSourceInfo() const {
819-        return m_info.lineInfo;
820-    }
821-
822-    StringRef AssertionResult::getTestMacroName() const {
823-        return m_info.macroName;
824-    }
825-
826-} // end namespace Catch
827-
828-
829-
830-#include <fstream>
831-
832-namespace Catch {
833-
834-    namespace {
835-        static bool enableBazelEnvSupport() {
836-#if defined( CATCH_CONFIG_BAZEL_SUPPORT )
837-            return true;
838-#else
839-            return Detail::getEnv( "BAZEL_TEST" ) != nullptr;
840-#endif
841-        }
842-
843-        struct bazelShardingOptions {
844-            unsigned int shardIndex, shardCount;
845-            std::string shardFilePath;
846-        };
847-
848-        static Optional<bazelShardingOptions> readBazelShardingOptions() {
849-            const auto bazelShardIndex = Detail::getEnv( "TEST_SHARD_INDEX" );
850-            const auto bazelShardTotal = Detail::getEnv( "TEST_TOTAL_SHARDS" );
851-            const auto bazelShardInfoFile = Detail::getEnv( "TEST_SHARD_STATUS_FILE" );
852-
853-
854-            const bool has_all =
855-                bazelShardIndex && bazelShardTotal && bazelShardInfoFile;
856-            if ( !has_all ) {
857-                // We provide nice warning message if the input is
858-                // misconfigured.
859-                auto warn = []( const char* env_var ) {
860-                    Catch::cerr()
861-                        << "Warning: Bazel shard configuration is missing '"
862-                        << env_var << "'. Shard configuration is skipped.\n";
863-                };
864-                if ( !bazelShardIndex ) {
865-                    warn( "TEST_SHARD_INDEX" );
866-                }
867-                if ( !bazelShardTotal ) {
868-                    warn( "TEST_TOTAL_SHARDS" );
869-                }
870-                if ( !bazelShardInfoFile ) {
871-                    warn( "TEST_SHARD_STATUS_FILE" );
872-                }
873-                return {};
874-            }
875-
876-            auto shardIndex = parseUInt( bazelShardIndex );
877-            if ( !shardIndex ) {
878-                Catch::cerr()
879-                    << "Warning: could not parse 'TEST_SHARD_INDEX' ('" << bazelShardIndex
880-                    << "') as unsigned int.\n";
881-                return {};
882-            }
883-            auto shardTotal = parseUInt( bazelShardTotal );
884-            if ( !shardTotal ) {
885-                Catch::cerr()
886-                    << "Warning: could not parse 'TEST_TOTAL_SHARD' ('"
887-                    << bazelShardTotal << "') as unsigned int.\n";
888-                return {};
889-            }
890-
891-            return bazelShardingOptions{
892-                *shardIndex, *shardTotal, bazelShardInfoFile };
893-
894-        }
895-    } // end namespace
896-
897-
898-    bool operator==( ProcessedReporterSpec const& lhs,
899-                     ProcessedReporterSpec const& rhs ) {
900-        return lhs.name == rhs.name &&
901-               lhs.outputFilename == rhs.outputFilename &&
902-               lhs.colourMode == rhs.colourMode &&
903-               lhs.customOptions == rhs.customOptions;
904-    }
905-
906-    Config::Config( ConfigData const& data ):
907-        m_data( data ) {
908-        // We need to trim filter specs to avoid trouble with superfluous
909-        // whitespace (esp. important for bdd macros, as those are manually
910-        // aligned with whitespace).
911-
912-        for (auto& elem : m_data.testsOrTags) {
913-            elem = trim(elem);
914-        }
915-        for (auto& elem : m_data.sectionsToRun) {
916-            elem = trim(elem);
917-        }
918-
919-        // Insert the default reporter if user hasn't asked for a specific one
920-        if ( m_data.reporterSpecifications.empty() ) {
921-#if defined( CATCH_CONFIG_DEFAULT_REPORTER )
922-            const auto default_spec = CATCH_CONFIG_DEFAULT_REPORTER;
923-#else
924-            const auto default_spec = "console";
925-#endif
926-            auto parsed = parseReporterSpec(default_spec);
927-            CATCH_ENFORCE( parsed,
928-                           "Cannot parse the provided default reporter spec: '"
929-                               << default_spec << '\'' );
930-            m_data.reporterSpecifications.push_back( std::move( *parsed ) );
931-        }
932-
933-        // Reading bazel env vars can change some parts of the config data,
934-        // so we have to process the bazel env before acting on the config.
935-        if ( enableBazelEnvSupport() ) {
936-            readBazelEnvVars();
937-        }
938-
939-        // Bazel support can modify the test specs, so parsing has to happen
940-        // after reading Bazel env vars.
941-        TestSpecParser parser( ITagAliasRegistry::get() );
942-        if ( !m_data.testsOrTags.empty() ) {
943-            m_hasTestFilters = true;
944-            for ( auto const& testOrTags : m_data.testsOrTags ) {
945-                parser.parse( testOrTags );
946-            }
947-        }
948-        m_testSpec = parser.testSpec();
949-
950-
951-        // We now fixup the reporter specs to handle default output spec,
952-        // default colour spec, etc
953-        bool defaultOutputUsed = false;
954-        for ( auto const& reporterSpec : m_data.reporterSpecifications ) {
955-            // We do the default-output check separately, while always
956-            // using the default output below to make the code simpler
957-            // and avoid superfluous copies.
958-            if ( reporterSpec.outputFile().none() ) {
959-                CATCH_ENFORCE( !defaultOutputUsed,
960-                               "Internal error: cannot use default output for "
961-                               "multiple reporters" );
962-                defaultOutputUsed = true;
963-            }
964-
965-            m_processedReporterSpecs.push_back( ProcessedReporterSpec{
966-                reporterSpec.name(),
967-                reporterSpec.outputFile() ? *reporterSpec.outputFile()
968-                                          : data.defaultOutputFilename,
969-                reporterSpec.colourMode().valueOr( data.defaultColourMode ),
970-                reporterSpec.customOptions() } );
971-        }
972-    }
973-
974-    Config::~Config() = default;
975-
976-
977-    bool Config::listTests() const          { return m_data.listTests; }
978-    bool Config::listTags() const           { return m_data.listTags; }
979-    bool Config::listReporters() const      { return m_data.listReporters; }
980-    bool Config::listListeners() const      { return m_data.listListeners; }
981-
982-    std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
983-    std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
984-
985-    std::vector<ReporterSpec> const& Config::getReporterSpecs() const {
986-        return m_data.reporterSpecifications;
987-    }
988-
989-    std::vector<ProcessedReporterSpec> const&
990-    Config::getProcessedReporterSpecs() const {
991-        return m_processedReporterSpecs;
992-    }
993-
994-    TestSpec const& Config::testSpec() const { return m_testSpec; }
995-    bool Config::hasTestFilters() const { return m_hasTestFilters; }
996-
997-    bool Config::showHelp() const { return m_data.showHelp; }
998-
999-    std::string const& Config::getExitGuardFilePath() const { return m_data.prematureExitGuardFilePath; }
1000-
1001-    // IConfig interface
1002-    bool Config::allowThrows() const                   { return !m_data.noThrow; }
1003-    StringRef Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
1004-    bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }
1005-    bool Config::warnAboutMissingAssertions() const {
1006-        return !!( m_data.warnings & WarnAbout::NoAssertions );
1007-    }
1008-    bool Config::warnAboutUnmatchedTestSpecs() const {
1009-        return !!( m_data.warnings & WarnAbout::UnmatchedTestSpec );
1010-    }
1011-    bool Config::zeroTestsCountAsSuccess() const       { return m_data.allowZeroTests; }
1012-    ShowDurations Config::showDurations() const        { return m_data.showDurations; }
1013-    double Config::minDuration() const                 { return m_data.minDuration; }
1014-    TestRunOrder Config::runOrder() const              { return m_data.runOrder; }
1015-    uint32_t Config::rngSeed() const                   { return m_data.rngSeed; }
1016-    unsigned int Config::shardCount() const            { return m_data.shardCount; }
1017-    unsigned int Config::shardIndex() const            { return m_data.shardIndex; }
1018-    ColourMode Config::defaultColourMode() const       { return m_data.defaultColourMode; }
1019-    bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; }
1020-    int Config::abortAfter() const                     { return m_data.abortAfter; }
1021-    bool Config::showInvisibles() const                { return m_data.showInvisibles; }
1022-    Verbosity Config::verbosity() const                { return m_data.verbosity; }
1023-
1024-    bool Config::skipBenchmarks() const                           { return m_data.skipBenchmarks; }
1025-    bool Config::benchmarkNoAnalysis() const                      { return m_data.benchmarkNoAnalysis; }
1026-    unsigned int Config::benchmarkSamples() const                 { return m_data.benchmarkSamples; }
1027-    double Config::benchmarkConfidenceInterval() const            { return m_data.benchmarkConfidenceInterval; }
1028-    unsigned int Config::benchmarkResamples() const               { return m_data.benchmarkResamples; }
1029-    std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
1030-
1031-    void Config::readBazelEnvVars() {
1032-        // Register a JUnit reporter for Bazel. Bazel sets an environment
1033-        // variable with the path to XML output. If this file is written to
1034-        // during test, Bazel will not generate a default XML output.
1035-        // This allows the XML output file to contain higher level of detail
1036-        // than what is possible otherwise.
1037-        const auto bazelOutputFile = Detail::getEnv( "XML_OUTPUT_FILE" );
1038-
1039-        if ( bazelOutputFile ) {
1040-            m_data.reporterSpecifications.push_back(
1041-                { "junit", std::string( bazelOutputFile ), {}, {} } );
1042-        }
1043-
1044-        const auto bazelTestSpec = Detail::getEnv( "TESTBRIDGE_TEST_ONLY" );
1045-        if ( bazelTestSpec ) {
1046-            // Presumably the test spec from environment should overwrite
1047-            // the one we got from CLI (if we got any)
1048-            m_data.testsOrTags.clear();
1049-            m_data.testsOrTags.push_back( bazelTestSpec );
1050-        }
1051-
1052-        const auto bazelShardOptions = readBazelShardingOptions();
1053-        if ( bazelShardOptions ) {
1054-            std::ofstream f( bazelShardOptions->shardFilePath,
1055-                             std::ios_base::out | std::ios_base::trunc );
1056-            if ( f.is_open() ) {
1057-                f << "";
1058-                m_data.shardIndex = bazelShardOptions->shardIndex;
1059-                m_data.shardCount = bazelShardOptions->shardCount;
1060-            }
1061-        }
1062-
1063-        const auto bazelExitGuardFile = Detail::getEnv( "TEST_PREMATURE_EXIT_FILE" );
1064-        if (bazelExitGuardFile) {
1065-            m_data.prematureExitGuardFilePath = bazelExitGuardFile;
1066-        }
1067-
1068-        const auto bazelRandomSeed = Detail::getEnv( "TEST_RANDOM_SEED" );
1069-        if ( bazelRandomSeed ) {
1070-            auto parsedSeed = parseUInt( bazelRandomSeed, 0 );
1071-            if ( !parsedSeed ) {
1072-                // Currently we handle issues with parsing other Bazel Env
1073-                // options by warning and ignoring the issue. So we do the
1074-                // same for random seed option.
1075-                Catch::cerr()
1076-                    << "Warning: could not parse 'TEST_RANDOM_SEED' ('"
1077-                    << bazelRandomSeed << "') as proper seed.\n";
1078-            } else {
1079-                m_data.rngSeed = *parsedSeed;
1080-            }
1081-        }
1082-    }
1083-
1084-} // end namespace Catch
1085-
1086-
1087-
1088-
1089-
1090-namespace Catch {
1091-    std::uint32_t getSeed() {
1092-        return getCurrentContext().getConfig()->rngSeed();
1093-    }
1094-}
1095-
1096-
1097-
1098-#include <cassert>
1099-#include <stack>
1100-
1101-namespace Catch {
1102-
1103-    ////////////////////////////////////////////////////////////////////////////
1104-
1105-
1106-    ScopedMessage::ScopedMessage( MessageBuilder&& builder ):
1107-        m_messageId( builder.m_info.sequence ) {
1108-        MessageInfo info( CATCH_MOVE( builder.m_info ) );
1109-        info.message = builder.m_stream.str();
1110-        IResultCapture::pushScopedMessage( CATCH_MOVE( info ) );
1111-    }
1112-
1113-    ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
1114-        m_messageId( old.m_messageId ) {
1115-        old.m_moved = true;
1116-    }
1117-
1118-    ScopedMessage::~ScopedMessage() {
1119-        if ( !m_moved ) { IResultCapture::popScopedMessage( m_messageId ); }
1120-    }
1121-
1122-
1123-    Capturer::Capturer( StringRef macroName,
1124-                        SourceLineInfo const& lineInfo,
1125-                        ResultWas::OfType resultType,
1126-                        StringRef names ) {
1127-        auto trimmed = [&] (size_t start, size_t end) {
1128-            while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
1129-                ++start;
1130-            }
1131-            while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {
1132-                --end;
1133-            }
1134-            return names.substr(start, end - start + 1);
1135-        };
1136-        auto skipq = [&] (size_t start, char quote) {
1137-            for (auto i = start + 1; i < names.size() ; ++i) {
1138-                if (names[i] == quote)
1139-                    return i;
1140-                if (names[i] == '\\')
1141-                    ++i;
1142-            }
1143-            CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");
1144-        };
1145-
1146-        size_t start = 0;
1147-        std::stack<char> openings;
1148-        for (size_t pos = 0; pos < names.size(); ++pos) {
1149-            char c = names[pos];
1150-            switch (c) {
1151-            case '[':
1152-            case '{':
1153-            case '(':
1154-            // It is basically impossible to disambiguate between
1155-            // comparison and start of template args in this context
1156-//            case '<':
1157-                openings.push(c);
1158-                break;
1159-            case ']':
1160-            case '}':
1161-            case ')':
1162-//           case '>':
1163-                openings.pop();
1164-                break;
1165-            case '"':
1166-            case '\'':
1167-                pos = skipq(pos, c);
1168-                break;
1169-            case ',':
1170-                if (start != pos && openings.empty()) {
1171-                    m_messages.emplace_back(macroName, lineInfo, resultType);
1172-                    m_messages.back().message += trimmed(start, pos);
1173-                    m_messages.back().message += " := "_sr;
1174-                    start = pos;
1175-                }
1176-                break;
1177-            default:; // noop
1178-            }
1179-        }
1180-        assert(openings.empty() && "Mismatched openings");
1181-        m_messages.emplace_back(macroName, lineInfo, resultType);
1182-        m_messages.back().message += trimmed(start, names.size() - 1);
1183-        m_messages.back().message += " := "_sr;
1184-    }
1185-    Capturer::~Capturer() {
1186-        assert( m_captured == m_messages.size() );
1187-        for (auto const& message : m_messages) {
1188-            IResultCapture::popScopedMessage( message.sequence );
1189-        }
1190-    }
1191-
1192-    void Capturer::captureValue( size_t index, std::string const& value ) {
1193-        assert( index < m_messages.size() );
1194-        m_messages[index].message += value;
1195-        IResultCapture::pushScopedMessage( CATCH_MOVE( m_messages[index] ) );
1196-        m_captured++;
1197-    }
1198-
1199-} // end namespace Catch
1200-
1201-
1202-
1203-
1204-#include <exception>
1205-
1206-namespace Catch {
1207-
1208-    namespace {
1209-
1210-        class RegistryHub : public IRegistryHub,
1211-                            public IMutableRegistryHub,
1212-                            private Detail::NonCopyable {
1213-
1214-        public: // IRegistryHub
1215-            RegistryHub() = default;
1216-            ReporterRegistry const& getReporterRegistry() const override {
1217-                return m_reporterRegistry;
1218-            }
1219-            ITestCaseRegistry const& getTestCaseRegistry() const override {
1220-                return m_testCaseRegistry;
1221-            }
1222-            IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
1223-                return m_exceptionTranslatorRegistry;
1224-            }
1225-            ITagAliasRegistry const& getTagAliasRegistry() const override {
1226-                return m_tagAliasRegistry;
1227-            }
1228-            StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
1229-                return m_exceptionRegistry;
1230-            }
1231-
1232-        public: // IMutableRegistryHub
1233-            void registerReporter( std::string const& name, IReporterFactoryPtr factory ) override {
1234-                m_reporterRegistry.registerReporter( name, CATCH_MOVE(factory) );
1235-            }
1236-            void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) override {
1237-                m_reporterRegistry.registerListener( CATCH_MOVE(factory) );
1238-            }
1239-            void registerTest( Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker ) override {
1240-                m_testCaseRegistry.registerTest( CATCH_MOVE(testInfo), CATCH_MOVE(invoker) );
1241-            }
1242-            void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) override {
1243-                m_exceptionTranslatorRegistry.registerTranslator( CATCH_MOVE(translator) );
1244-            }
1245-            void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
1246-                m_tagAliasRegistry.add( alias, tag, lineInfo );
1247-            }
1248-            void registerStartupException() noexcept override {
1249-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
1250-                m_exceptionRegistry.add(std::current_exception());
1251-#else
1252-                CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
1253-#endif
1254-            }
1255-            IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
1256-                return m_enumValuesRegistry;
1257-            }
1258-
1259-        private:
1260-            TestRegistry m_testCaseRegistry;
1261-            ReporterRegistry m_reporterRegistry;
1262-            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
1263-            TagAliasRegistry m_tagAliasRegistry;
1264-            StartupExceptionRegistry m_exceptionRegistry;
1265-            Detail::EnumValuesRegistry m_enumValuesRegistry;
1266-        };
1267-    }
1268-
1269-    using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
1270-
1271-    IRegistryHub const& getRegistryHub() {
1272-        return RegistryHubSingleton::get();
1273-    }
1274-    IMutableRegistryHub& getMutableRegistryHub() {
1275-        return RegistryHubSingleton::getMutable();
1276-    }
1277-    void cleanUp() {
1278-        cleanupSingletons();
1279-    }
1280-    std::string translateActiveException() {
1281-        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
1282-    }
1283-
1284-
1285-} // end namespace Catch
1286-
1287-
1288-
1289-#include <cassert>
1290-#include <cstdio>
1291-#include <cstdlib>
1292-#include <exception>
1293-#include <iomanip>
1294-#include <set>
1295-
1296-namespace Catch {
1297-
1298-    namespace {
1299-        IEventListenerPtr createReporter(std::string const& reporterName, ReporterConfig&& config) {
1300-            auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config));
1301-            CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << '\'');
1302-
1303-            return reporter;
1304-        }
1305-
1306-        IEventListenerPtr prepareReporters(Config const* config) {
1307-            if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()
1308-                    && config->getProcessedReporterSpecs().size() == 1) {
1309-                auto const& spec = config->getProcessedReporterSpecs()[0];
1310-                return createReporter(
1311-                    spec.name,
1312-                    ReporterConfig( config,
1313-                                    makeStream( spec.outputFilename ),
1314-                                    spec.colourMode,
1315-                                    spec.customOptions ) );
1316-            }
1317-
1318-            auto multi = Detail::make_unique<MultiReporter>(config);
1319-
1320-            auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
1321-            for (auto const& listener : listeners) {
1322-                multi->addListener(listener->create(config));
1323-            }
1324-
1325-            for ( auto const& reporterSpec : config->getProcessedReporterSpecs() ) {
1326-                multi->addReporter( createReporter(
1327-                    reporterSpec.name,
1328-                    ReporterConfig( config,
1329-                                    makeStream( reporterSpec.outputFilename ),
1330-                                    reporterSpec.colourMode,
1331-                                    reporterSpec.customOptions ) ) );
1332-            }
1333-
1334-            return multi;
1335-        }
1336-
1337-        class TestGroup {
1338-        public:
1339-            explicit TestGroup(IEventListenerPtr&& reporter, Config const* config):
1340-                m_reporter(reporter.get()),
1341-                m_config{config},
1342-                m_context{config, CATCH_MOVE(reporter)} {
1343-
1344-                assert( m_config->testSpec().getInvalidSpecs().empty() &&
1345-                        "Invalid test specs should be handled before running tests" );
1346-
1347-                auto const& allTestCases = getAllTestCasesSorted(*m_config);
1348-                auto const& testSpec = m_config->testSpec();
1349-                if ( !testSpec.hasFilters() ) {
1350-                    for ( auto const& test : allTestCases ) {
1351-                        if ( !test.getTestCaseInfo().isHidden() ) {
1352-                            m_tests.emplace( &test );
1353-                        }
1354-                    }
1355-                } else {
1356-                    m_matches =
1357-                        testSpec.matchesByFilter( allTestCases, *m_config );
1358-                    for ( auto const& match : m_matches ) {
1359-                        m_tests.insert( match.tests.begin(),
1360-                                        match.tests.end() );
1361-                    }
1362-                }
1363-
1364-                m_tests = createShard(m_tests, m_config->shardCount(), m_config->shardIndex());
1365-            }
1366-
1367-            Totals execute() {
1368-                Totals totals;
1369-                for (auto const& testCase : m_tests) {
1370-                    if (!m_context.aborting())
1371-                        totals += m_context.runTest(*testCase);
1372-                    else
1373-                        m_reporter->skipTest(testCase->getTestCaseInfo());
1374-                }
1375-
1376-                for (auto const& match : m_matches) {
1377-                    if (match.tests.empty()) {
1378-                        m_unmatchedTestSpecs = true;
1379-                        m_reporter->noMatchingTestCases( match.name );
1380-                    }
1381-                }
1382-
1383-                return totals;
1384-            }
1385-
1386-            bool hadUnmatchedTestSpecs() const {
1387-                return m_unmatchedTestSpecs;
1388-            }
1389-
1390-
1391-        private:
1392-            IEventListener* m_reporter;
1393-            Config const* m_config;
1394-            RunContext m_context;
1395-            std::set<TestCaseHandle const*> m_tests;
1396-            TestSpec::Matches m_matches;
1397-            bool m_unmatchedTestSpecs = false;
1398-        };
1399-
1400-        void applyFilenamesAsTags() {
1401-            for (auto const& testInfo : getRegistryHub().getTestCaseRegistry().getAllInfos()) {
1402-                testInfo->addFilenameTag();
1403-            }
1404-        }
1405-
1406-        // Creates empty file at path. The path must be writable, we do not
1407-        // try to create directories in path because that's hard in C++14.
1408-        void setUpGuardFile( std::string const& guardFilePath ) {
1409-            if ( !guardFilePath.empty() ) {
1410-#if defined( _MSC_VER )
1411-                std::FILE* file = nullptr;
1412-                if ( fopen_s( &file, guardFilePath.c_str(), "w" ) ) {
1413-                    char msgBuffer[100];
1414-                    const auto err = errno;
1415-                    std::string errMsg;
1416-                    if ( !strerror_s( msgBuffer, err ) ) {
1417-                        errMsg = msgBuffer;
1418-                    } else {
1419-                        errMsg = "Could not translate errno to a string";
1420-                    }
1421-
1422-#else
1423-                std::FILE* file = std::fopen( guardFilePath.c_str(), "w" );
1424-                if ( !file ) {
1425-                    const auto err = errno;
1426-                    const char* errMsg = std::strerror( err );
1427-#endif
1428-
1429-                    CATCH_RUNTIME_ERROR( "Could not open the exit guard file '"
1430-                                         << guardFilePath << "' because '"
1431-                                         << errMsg << "' (" << err << ')' );
1432-                }
1433-                const int ret = std::fclose( file );
1434-                CATCH_ENFORCE(
1435-                    ret == 0,
1436-                    "Error when closing the exit guard file: " << ret );
1437-            }
1438-        }
1439-
1440-        // Removes file at path. Assuming we created it in setUpGuardFile.
1441-        void tearDownGuardFile( std::string const& guardFilePath ) {
1442-            if ( !guardFilePath.empty() ) {
1443-                const int ret = std::remove( guardFilePath.c_str() );
1444-                CATCH_ENFORCE(
1445-                    ret == 0,
1446-                    "Error when removing the exit guard file: " << ret );
1447-            }
1448-        }
1449-
1450-    } // anon namespace
1451-
1452-    Session::Session() {
1453-        static bool alreadyInstantiated = false;
1454-        if( alreadyInstantiated ) {
1455-            CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
1456-            CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
1457-        }
1458-
1459-        // There cannot be exceptions at startup in no-exception mode.
1460-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
1461-        const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
1462-        if ( !exceptions.empty() ) {
1463-            config();
1464-            getCurrentMutableContext().setConfig(m_config.get());
1465-
1466-            m_startupExceptions = true;
1467-            auto errStream = makeStream( "%stderr" );
1468-            auto colourImpl = makeColourImpl(
1469-                ColourMode::PlatformDefault, errStream.get() );
1470-            auto guard = colourImpl->guardColour( Colour::Red );
1471-            errStream->stream() << "Errors occurred during startup!" << '\n';
1472-            // iterate over all exceptions and notify user
1473-            for ( const auto& ex_ptr : exceptions ) {
1474-                try {
1475-                    std::rethrow_exception(ex_ptr);
1476-                } catch ( std::exception const& ex ) {
1477-                    errStream->stream() << TextFlow::Column( ex.what() ).indent(2) << '\n';
1478-                }
1479-            }
1480-        }
1481-#endif
1482-
1483-        alreadyInstantiated = true;
1484-        m_cli = makeCommandLineParser( m_configData );
1485-    }
1486-    Session::~Session() {
1487-        Catch::cleanUp();
1488-    }
1489-
1490-    void Session::showHelp() const {
1491-        Catch::cout()
1492-                << "\nCatch2 v" << libraryVersion() << '\n'
1493-                << m_cli << '\n'
1494-                << "For more detailed usage please see the project docs\n\n" << std::flush;
1495-    }
1496-    void Session::libIdentify() {
1497-        Catch::cout()
1498-                << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
1499-                << std::left << std::setw(16) << "category: " << "testframework\n"
1500-                << std::left << std::setw(16) << "framework: " << "Catch2\n"
1501-                << std::left << std::setw(16) << "version: " << libraryVersion() << '\n' << std::flush;
1502-    }
1503-
1504-    int Session::applyCommandLine( int argc, char const * const * argv ) {
1505-        if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; }
1506-
1507-        auto result = m_cli.parse( Clara::Args( argc, argv ) );
1508-
1509-        if( !result ) {
1510-            config();
1511-            getCurrentMutableContext().setConfig(m_config.get());
1512-            auto errStream = makeStream( "%stderr" );
1513-            auto colour = makeColourImpl( ColourMode::PlatformDefault, errStream.get() );
1514-
1515-            errStream->stream()
1516-                << colour->guardColour( Colour::Red )
1517-                << "\nError(s) in input:\n"
1518-                << TextFlow::Column( result.errorMessage() ).indent( 2 )
1519-                << "\n\n";
1520-            errStream->stream() << "Run with -? for usage\n\n" << std::flush;
1521-            return UnspecifiedErrorExitCode;
1522-        }
1523-
1524-        if( m_configData.showHelp )
1525-            showHelp();
1526-        if( m_configData.libIdentify )
1527-            libIdentify();
1528-
1529-        m_config.reset();
1530-        return 0;
1531-    }
1532-
1533-#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
1534-    int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
1535-
1536-        char **utf8Argv = new char *[ argc ];
1537-
1538-        for ( int i = 0; i < argc; ++i ) {
1539-            int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
1540-
1541-            utf8Argv[ i ] = new char[ bufSize ];
1542-
1543-            WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
1544-        }
1545-
1546-        int returnCode = applyCommandLine( argc, utf8Argv );
1547-
1548-        for ( int i = 0; i < argc; ++i )
1549-            delete [] utf8Argv[ i ];
1550-
1551-        delete [] utf8Argv;
1552-
1553-        return returnCode;
1554-    }
1555-#endif
1556-
1557-    void Session::useConfigData( ConfigData const& configData ) {
1558-        m_configData = configData;
1559-        m_config.reset();
1560-    }
1561-
1562-    int Session::run() {
1563-        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
1564-            Catch::cout() << "...waiting for enter/ return before starting\n" << std::flush;
1565-            static_cast<void>(std::getchar());
1566-        }
1567-        int exitCode = runInternal();
1568-
1569-        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
1570-            Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << '\n' << std::flush;
1571-            static_cast<void>(std::getchar());
1572-        }
1573-        return exitCode;
1574-    }
1575-
1576-    Clara::Parser const& Session::cli() const {
1577-        return m_cli;
1578-    }
1579-    void Session::cli( Clara::Parser const& newParser ) {
1580-        m_cli = newParser;
1581-    }
1582-    ConfigData& Session::configData() {
1583-        return m_configData;
1584-    }
1585-    Config& Session::config() {
1586-        if( !m_config )
1587-            m_config = Detail::make_unique<Config>( m_configData );
1588-        return *m_config;
1589-    }
1590-
1591-    int Session::runInternal() {
1592-        if ( m_startupExceptions ) { return UnspecifiedErrorExitCode; }
1593-
1594-        if (m_configData.showHelp || m_configData.libIdentify) {
1595-            return 0;
1596-        }
1597-
1598-        if ( m_configData.shardIndex >= m_configData.shardCount ) {
1599-            Catch::cerr() << "The shard count (" << m_configData.shardCount
1600-                          << ") must be greater than the shard index ("
1601-                          << m_configData.shardIndex << ")\n"
1602-                          << std::flush;
1603-            return UnspecifiedErrorExitCode;
1604-        }
1605-
1606-        CATCH_TRY {
1607-            config(); // Force config to be constructed
1608-
1609-            // We need to retrieve potential Bazel config with the full Config
1610-            // constructor, so we have to create the guard file after it is created.
1611-            setUpGuardFile( m_config->getExitGuardFilePath() );
1612-
1613-            seedRng( *m_config );
1614-
1615-            if (m_configData.filenamesAsTags) {
1616-                applyFilenamesAsTags();
1617-            }
1618-
1619-            // Set up global config instance before we start calling into other functions
1620-            getCurrentMutableContext().setConfig(m_config.get());
1621-
1622-            // Create reporter(s) so we can route listings through them
1623-            auto reporter = prepareReporters(m_config.get());
1624-
1625-            auto const& invalidSpecs = m_config->testSpec().getInvalidSpecs();
1626-            if ( !invalidSpecs.empty() ) {
1627-                for ( auto const& spec : invalidSpecs ) {
1628-                    reporter->reportInvalidTestSpec( spec );
1629-                }
1630-                return InvalidTestSpecExitCode;
1631-            }
1632-
1633-
1634-            // Handle list request
1635-            if (list(*reporter, *m_config)) {
1636-                return 0;
1637-            }
1638-
1639-            TestGroup tests { CATCH_MOVE(reporter), m_config.get() };
1640-            auto const totals = tests.execute();
1641-
1642-            // If we got here, running the tests finished normally-enough.
1643-            // They might've failed, but that would've been reported elsewhere.
1644-            tearDownGuardFile( m_config->getExitGuardFilePath() );
1645-
1646-            if ( tests.hadUnmatchedTestSpecs()
1647-                && m_config->warnAboutUnmatchedTestSpecs() ) {
1648-                return UnmatchedTestSpecExitCode;
1649-            }
1650-
1651-            if ( totals.testCases.total() == 0
1652-                && !m_config->zeroTestsCountAsSuccess() ) {
1653-                return NoTestsRunExitCode;
1654-            }
1655-
1656-            if ( totals.testCases.total() > 0 &&
1657-                 totals.testCases.total() == totals.testCases.skipped
1658-                && !m_config->zeroTestsCountAsSuccess() ) {
1659-                return AllTestsSkippedExitCode;
1660-            }
1661-
1662-            if ( totals.assertions.failed ) { return TestFailureExitCode; }
1663-            return 0;
1664-
1665-        }
1666-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
1667-        catch( std::exception& ex ) {
1668-            Catch::cerr() << ex.what() << '\n' << std::flush;
1669-            return UnspecifiedErrorExitCode;
1670-        }
1671-#endif
1672-    }
1673-
1674-} // end namespace Catch
1675-
1676-
1677-
1678-
1679-namespace Catch {
1680-
1681-    RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
1682-        CATCH_TRY {
1683-            getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
1684-        } CATCH_CATCH_ALL {
1685-            // Do not throw when constructing global objects, instead register the exception to be processed later
1686-            getMutableRegistryHub().registerStartupException();
1687-        }
1688-    }
1689-
1690-}
1691-
1692-
1693-
1694-#include <cassert>
1695-#include <cctype>
1696-#include <algorithm>
1697-
1698-namespace Catch {
1699-
1700-    namespace {
1701-        using TCP_underlying_type = uint8_t;
1702-        static_assert(sizeof(TestCaseProperties) == sizeof(TCP_underlying_type),
1703-                      "The size of the TestCaseProperties is different from the assumed size");
1704-
1705-        constexpr TestCaseProperties operator|(TestCaseProperties lhs, TestCaseProperties rhs) {
1706-            return static_cast<TestCaseProperties>(
1707-                static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
1708-            );
1709-        }
1710-
1711-        constexpr TestCaseProperties& operator|=(TestCaseProperties& lhs, TestCaseProperties rhs) {
1712-            lhs = static_cast<TestCaseProperties>(
1713-                static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
1714-            );
1715-            return lhs;
1716-        }
1717-
1718-        constexpr TestCaseProperties operator&(TestCaseProperties lhs, TestCaseProperties rhs) {
1719-            return static_cast<TestCaseProperties>(
1720-                static_cast<TCP_underlying_type>(lhs) & static_cast<TCP_underlying_type>(rhs)
1721-            );
1722-        }
1723-
1724-        constexpr bool applies(TestCaseProperties tcp) {
1725-            static_assert(static_cast<TCP_underlying_type>(TestCaseProperties::None) == 0,
1726-                          "TestCaseProperties::None must be equal to 0");
1727-            return tcp != TestCaseProperties::None;
1728-        }
1729-
1730-        TestCaseProperties parseSpecialTag( StringRef tag ) {
1731-            if( !tag.empty() && tag[0] == '.' )
1732-                return TestCaseProperties::IsHidden;
1733-            else if( tag == "!throws"_sr )
1734-                return TestCaseProperties::Throws;
1735-            else if( tag == "!shouldfail"_sr )
1736-                return TestCaseProperties::ShouldFail;
1737-            else if( tag == "!mayfail"_sr )
1738-                return TestCaseProperties::MayFail;
1739-            else if( tag == "!nonportable"_sr )
1740-                return TestCaseProperties::NonPortable;
1741-            else if( tag == "!benchmark"_sr )
1742-                return TestCaseProperties::Benchmark | TestCaseProperties::IsHidden;
1743-            else
1744-                return TestCaseProperties::None;
1745-        }
1746-        bool isReservedTag( StringRef tag ) {
1747-            return parseSpecialTag( tag ) == TestCaseProperties::None
1748-                && tag.size() > 0
1749-                && !std::isalnum( static_cast<unsigned char>(tag[0]) );
1750-        }
1751-        void enforceNotReservedTag( StringRef tag, SourceLineInfo const& _lineInfo ) {
1752-            CATCH_ENFORCE( !isReservedTag(tag),
1753-                          "Tag name: [" << tag << "] is not allowed.\n"
1754-                          << "Tag names starting with non alphanumeric characters are reserved\n"
1755-                          << _lineInfo );
1756-        }
1757-
1758-        std::string makeDefaultName() {
1759-            static size_t counter = 0;
1760-            return "Anonymous test case " + std::to_string(++counter);
1761-        }
1762-
1763-        constexpr StringRef extractFilenamePart(StringRef filename) {
1764-            size_t lastDot = filename.size();
1765-            while (lastDot > 0 && filename[lastDot - 1] != '.') {
1766-                --lastDot;
1767-            }
1768-            // In theory we could have filename without any extension in it
1769-            if ( lastDot == 0 ) { return StringRef(); }
1770-
1771-            --lastDot;
1772-            size_t nameStart = lastDot;
1773-            while (nameStart > 0 && filename[nameStart - 1] != '/' && filename[nameStart - 1] != '\\') {
1774-                --nameStart;
1775-            }
1776-
1777-            return filename.substr(nameStart, lastDot - nameStart);
1778-        }
1779-
1780-        // Returns the upper bound on size of extra tags ([#file]+[.])
1781-        constexpr size_t sizeOfExtraTags(StringRef filepath) {
1782-            // [.] is 3, [#] is another 3
1783-            const size_t extras = 3 + 3;
1784-            return extractFilenamePart(filepath).size() + extras;
1785-        }
1786-    } // end unnamed namespace
1787-
1788-    bool operator<(  Tag const& lhs, Tag const& rhs ) {
1789-        Detail::CaseInsensitiveLess cmp;
1790-        return cmp( lhs.original, rhs.original );
1791-    }
1792-    bool operator==( Tag const& lhs, Tag const& rhs ) {
1793-        Detail::CaseInsensitiveEqualTo cmp;
1794-        return cmp( lhs.original, rhs.original );
1795-    }
1796-
1797-    Detail::unique_ptr<TestCaseInfo>
1798-        makeTestCaseInfo(StringRef _className,
1799-                         NameAndTags const& nameAndTags,
1800-                         SourceLineInfo const& _lineInfo ) {
1801-        return Detail::make_unique<TestCaseInfo>(_className, nameAndTags, _lineInfo);
1802-    }
1803-
1804-    TestCaseInfo::TestCaseInfo(StringRef _className,
1805-                               NameAndTags const& _nameAndTags,
1806-                               SourceLineInfo const& _lineInfo):
1807-        name( _nameAndTags.name.empty() ? makeDefaultName() : _nameAndTags.name ),
1808-        className( _className ),
1809-        lineInfo( _lineInfo )
1810-    {
1811-        StringRef originalTags = _nameAndTags.tags;
1812-        // We need to reserve enough space to store all of the tags
1813-        // (including optional hidden tag and filename tag)
1814-        auto requiredSize = originalTags.size() + sizeOfExtraTags(_lineInfo.file);
1815-        backingTags.reserve(requiredSize);
1816-
1817-        // We cannot copy the tags directly, as we need to normalize
1818-        // some tags, so that [.foo] is copied as [.][foo].
1819-        size_t tagStart = 0;
1820-        size_t tagEnd = 0;
1821-        bool inTag = false;
1822-        for (size_t idx = 0; idx < originalTags.size(); ++idx) {
1823-            auto c = originalTags[idx];
1824-            if (c == '[') {
1825-                CATCH_ENFORCE(
1826-                    !inTag,
1827-                    "Found '[' inside a tag while registering test case '"
1828-                        << _nameAndTags.name << "' at " << _lineInfo );
1829-
1830-                inTag = true;
1831-                tagStart = idx;
1832-            }
1833-            if (c == ']') {
1834-                CATCH_ENFORCE(
1835-                    inTag,
1836-                    "Found unmatched ']' while registering test case '"
1837-                        << _nameAndTags.name << "' at " << _lineInfo );
1838-
1839-                inTag = false;
1840-                tagEnd = idx;
1841-                assert(tagStart < tagEnd);
1842-
1843-                // We need to check the tag for special meanings, copy
1844-                // it over to backing storage and actually reference the
1845-                // backing storage in the saved tags
1846-                StringRef tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1);
1847-                CATCH_ENFORCE( !tagStr.empty(),
1848-                               "Found an empty tag while registering test case '"
1849-                                   << _nameAndTags.name << "' at "
1850-                                   << _lineInfo );
1851-
1852-                enforceNotReservedTag(tagStr, lineInfo);
1853-                properties |= parseSpecialTag(tagStr);
1854-                // When copying a tag to the backing storage, we need to
1855-                // check if it is a merged hide tag, such as [.foo], and
1856-                // if it is, we need to handle it as if it was [foo].
1857-                if (tagStr.size() > 1 && tagStr[0] == '.') {
1858-                    tagStr = tagStr.substr(1, tagStr.size() - 1);
1859-                }
1860-                // We skip over dealing with the [.] tag, as we will add
1861-                // it later unconditionally and then sort and unique all
1862-                // the tags.
1863-                internalAppendTag(tagStr);
1864-            }
1865-        }
1866-        CATCH_ENFORCE( !inTag,
1867-                       "Found an unclosed tag while registering test case '"
1868-                           << _nameAndTags.name << "' at " << _lineInfo );
1869-
1870-
1871-        // Add [.] if relevant
1872-        if (isHidden()) {
1873-            internalAppendTag("."_sr);
1874-        }
1875-
1876-        // Sort and prepare tags
1877-        std::sort(begin(tags), end(tags));
1878-        tags.erase(std::unique(begin(tags), end(tags)),
1879-                   end(tags));
1880-    }
1881-
1882-    bool TestCaseInfo::isHidden() const {
1883-        return applies( properties & TestCaseProperties::IsHidden );
1884-    }
1885-    bool TestCaseInfo::throws() const {
1886-        return applies( properties & TestCaseProperties::Throws );
1887-    }
1888-    bool TestCaseInfo::okToFail() const {
1889-        return applies( properties & (TestCaseProperties::ShouldFail | TestCaseProperties::MayFail ) );
1890-    }
1891-    bool TestCaseInfo::expectedToFail() const {
1892-        return applies( properties & (TestCaseProperties::ShouldFail) );
1893-    }
1894-
1895-    void TestCaseInfo::addFilenameTag() {
1896-        std::string combined("#");
1897-        combined += extractFilenamePart(lineInfo.file);
1898-        internalAppendTag(combined);
1899-    }
1900-
1901-    std::string TestCaseInfo::tagsAsString() const {
1902-        std::string ret;
1903-        // '[' and ']' per tag
1904-        std::size_t full_size = 2 * tags.size();
1905-        for (const auto& tag : tags) {
1906-            full_size += tag.original.size();
1907-        }
1908-        ret.reserve(full_size);
1909-        for (const auto& tag : tags) {
1910-            ret.push_back('[');
1911-            ret += tag.original;
1912-            ret.push_back(']');
1913-        }
1914-
1915-        return ret;
1916-    }
1917-
1918-    void TestCaseInfo::internalAppendTag(StringRef tagStr) {
1919-        backingTags += '[';
1920-        const auto backingStart = backingTags.size();
1921-        backingTags += tagStr;
1922-        const auto backingEnd = backingTags.size();
1923-        backingTags += ']';
1924-        tags.emplace_back(StringRef(backingTags.c_str() + backingStart, backingEnd - backingStart));
1925-    }
1926-
1927-    bool operator<( TestCaseInfo const& lhs, TestCaseInfo const& rhs ) {
1928-        // We want to avoid redoing the string comparisons multiple times,
1929-        // so we store the result of a three-way comparison before using
1930-        // it in the actual comparison logic.
1931-        const auto cmpName = lhs.name.compare( rhs.name );
1932-        if ( cmpName != 0 ) {
1933-            return cmpName < 0;
1934-        }
1935-        const auto cmpClassName = lhs.className.compare( rhs.className );
1936-        if ( cmpClassName != 0 ) {
1937-            return cmpClassName < 0;
1938-        }
1939-        return lhs.tags < rhs.tags;
1940-    }
1941-
1942-} // end namespace Catch
1943-
1944-
1945-
1946-#include <algorithm>
1947-#include <string>
1948-#include <vector>
1949-#include <ostream>
1950-
1951-namespace Catch {
1952-
1953-    TestSpec::Pattern::Pattern( std::string const& name )
1954-    : m_name( name )
1955-    {}
1956-
1957-    TestSpec::Pattern::~Pattern() = default;
1958-
1959-    std::string const& TestSpec::Pattern::name() const {
1960-        return m_name;
1961-    }
1962-
1963-
1964-    TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
1965-    : Pattern( filterString )
1966-    , m_wildcardPattern( toLower( name ), CaseSensitive::No )
1967-    {}
1968-
1969-    bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
1970-        return m_wildcardPattern.matches( testCase.name );
1971-    }
1972-
1973-    void TestSpec::NamePattern::serializeTo( std::ostream& out ) const {
1974-        out << '"' << name() << '"';
1975-    }
1976-
1977-
1978-    TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
1979-    : Pattern( filterString )
1980-    , m_tag( tag )
1981-    {}
1982-
1983-    bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
1984-        return std::find( begin( testCase.tags ),
1985-                          end( testCase.tags ),
1986-                          Tag( m_tag ) ) != end( testCase.tags );
1987-    }
1988-
1989-    void TestSpec::TagPattern::serializeTo( std::ostream& out ) const {
1990-        out << name();
1991-    }
1992-
1993-    bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
1994-        bool should_use = !testCase.isHidden();
1995-        for (auto const& pattern : m_required) {
1996-            should_use = true;
1997-            if (!pattern->matches(testCase)) {
1998-                return false;
1999-            }
2000-        }
2001-        for (auto const& pattern : m_forbidden) {
2002-            if (pattern->matches(testCase)) {
2003-                return false;
2004-            }
2005-        }
2006-        return should_use;
2007-    }
2008-
2009-    void TestSpec::Filter::serializeTo( std::ostream& out ) const {
2010-        bool first = true;
2011-        for ( auto const& pattern : m_required ) {
2012-            if ( !first ) {
2013-                out << ' ';
2014-            }
2015-            out << *pattern;
2016-            first = false;
2017-        }
2018-        for ( auto const& pattern : m_forbidden ) {
2019-            if ( !first ) {
2020-                out << ' ';
2021-            }
2022-            out << *pattern;
2023-            first = false;
2024-        }
2025-    }
2026-
2027-
2028-    std::string TestSpec::extractFilterName( Filter const& filter ) {
2029-        Catch::ReusableStringStream sstr;
2030-        sstr << filter;
2031-        return sstr.str();
2032-    }
2033-
2034-    bool TestSpec::hasFilters() const {
2035-        return !m_filters.empty();
2036-    }
2037-
2038-    bool TestSpec::matches( TestCaseInfo const& testCase ) const {
2039-        return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
2040-    }
2041-
2042-    TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const {
2043-        Matches matches;
2044-        matches.reserve( m_filters.size() );
2045-        for ( auto const& filter : m_filters ) {
2046-            std::vector<TestCaseHandle const*> currentMatches;
2047-            for ( auto const& test : testCases )
2048-                if ( isThrowSafe( test, config ) &&
2049-                     filter.matches( test.getTestCaseInfo() ) )
2050-                    currentMatches.emplace_back( &test );
2051-            matches.push_back(
2052-                FilterMatch{ extractFilterName( filter ), currentMatches } );
2053-        }
2054-        return matches;
2055-    }
2056-
2057-    const TestSpec::vectorStrings& TestSpec::getInvalidSpecs() const {
2058-        return m_invalidSpecs;
2059-    }
2060-
2061-    void TestSpec::serializeTo( std::ostream& out ) const {
2062-        bool first = true;
2063-        for ( auto const& filter : m_filters ) {
2064-            if ( !first ) {
2065-                out << ',';
2066-            }
2067-            out << filter;
2068-            first = false;
2069-        }
2070-    }
2071-
2072-}
2073-
2074-
2075-
2076-#include <chrono>
2077-
2078-namespace Catch {
2079-
2080-    namespace {
2081-        static auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
2082-            return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
2083-        }
2084-    } // end unnamed namespace
2085-
2086-    void Timer::start() {
2087-       m_nanoseconds = getCurrentNanosecondsSinceEpoch();
2088-    }
2089-    auto Timer::getElapsedNanoseconds() const -> uint64_t {
2090-        return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
2091-    }
2092-    auto Timer::getElapsedMicroseconds() const -> uint64_t {
2093-        return getElapsedNanoseconds()/1000;
2094-    }
2095-    auto Timer::getElapsedMilliseconds() const -> unsigned int {
2096-        return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
2097-    }
2098-    auto Timer::getElapsedSeconds() const -> double {
2099-        return static_cast<double>(getElapsedMicroseconds())/1000000.0;
2100-    }
2101-
2102-
2103-} // namespace Catch
2104-
2105-
2106-
2107-
2108-#include <iomanip>
2109-
2110-namespace Catch {
2111-
2112-namespace Detail {
2113-
2114-    namespace {
2115-        const int hexThreshold = 255;
2116-
2117-        struct Endianness {
2118-            enum Arch : uint8_t {
2119-                Big,
2120-                Little
2121-            };
2122-
2123-            static Arch which() {
2124-                int one = 1;
2125-                // If the lowest byte we read is non-zero, we can assume
2126-                // that little endian format is used.
2127-                auto value = *reinterpret_cast<char*>(&one);
2128-                return value ? Little : Big;
2129-            }
2130-        };
2131-
2132-        template<typename T>
2133-        std::string fpToString(T value, int precision) {
2134-            if (Catch::isnan(value)) {
2135-                return "nan";
2136-            }
2137-
2138-            ReusableStringStream rss;
2139-            rss << std::setprecision(precision)
2140-                << std::fixed
2141-                << value;
2142-            std::string d = rss.str();
2143-            std::size_t i = d.find_last_not_of('0');
2144-            if (i != std::string::npos && i != d.size() - 1) {
2145-                if (d[i] == '.')
2146-                    i++;
2147-                d = d.substr(0, i + 1);
2148-            }
2149-            return d;
2150-        }
2151-    } // end unnamed namespace
2152-
2153-    std::string convertIntoString(StringRef string, bool escapeInvisibles) {
2154-        std::string ret;
2155-        // This is enough for the "don't escape invisibles" case, and a good
2156-        // lower bound on the "escape invisibles" case.
2157-        ret.reserve( string.size() + 2 );
2158-
2159-        if ( !escapeInvisibles ) {
2160-            ret += '"';
2161-            ret += string;
2162-            ret += '"';
2163-            return ret;
2164-        }
2165-
2166-        size_t last_start = 0;
2167-        auto write_to = [&]( size_t idx ) {
2168-            if ( last_start < idx ) {
2169-                ret += string.substr( last_start, idx - last_start );
2170-            }
2171-            last_start = idx + 1;
2172-        };
2173-
2174-        ret += '"';
2175-        for ( size_t i = 0; i < string.size(); ++i ) {
2176-            const char c = string[i];
2177-            if ( c == '\r' || c == '\n' || c == '\t' || c == '\f' ) {
2178-                write_to( i );
2179-                if ( c == '\r' ) { ret.append( "\\r" ); }
2180-                if ( c == '\n' ) { ret.append( "\\n" ); }
2181-                if ( c == '\t' ) { ret.append( "\\t" ); }
2182-                if ( c == '\f' ) { ret.append( "\\f" ); }
2183-            }
2184-        }
2185-        write_to( string.size() );
2186-        ret += '"';
2187-
2188-        return ret;
2189-    }
2190-
2191-    std::string convertIntoString(StringRef string) {
2192-        return convertIntoString(string, getCurrentContext().getConfig()->showInvisibles());
2193-    }
2194-
2195-    std::string rawMemoryToString( const void *object, std::size_t size ) {
2196-        // Reverse order for little endian architectures
2197-        int i = 0, end = static_cast<int>( size ), inc = 1;
2198-        if( Endianness::which() == Endianness::Little ) {
2199-            i = end-1;
2200-            end = inc = -1;
2201-        }
2202-
2203-        unsigned char const *bytes = static_cast<unsigned char const *>(object);
2204-        ReusableStringStream rss;
2205-        rss << "0x" << std::setfill('0') << std::hex;
2206-        for( ; i != end; i += inc )
2207-             rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
2208-       return rss.str();
2209-    }
2210-
2211-    std::string makeExceptionHappenedString() {
2212-        return "{ stringification failed with an exception: \"" +
2213-               translateActiveException() + "\" }";
2214-
2215-    }
2216-
2217-} // end Detail namespace
2218-
2219-
2220-
2221-//// ======================================================= ////
2222-//
2223-//   Out-of-line defs for full specialization of StringMaker
2224-//
2225-//// ======================================================= ////
2226-
2227-std::string StringMaker<std::string>::convert(const std::string& str) {
2228-    return Detail::convertIntoString( str );
2229-}
2230-
2231-#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2232-std::string StringMaker<std::string_view>::convert(std::string_view str) {
2233-    return Detail::convertIntoString( StringRef( str.data(), str.size() ) );
2234-}
2235-#endif
2236-
2237-std::string StringMaker<char const*>::convert(char const* str) {
2238-    if (str) {
2239-        return Detail::convertIntoString( str );
2240-    } else {
2241-        return{ "{null string}" };
2242-    }
2243-}
2244-std::string StringMaker<char*>::convert(char* str) { // NOLINT(readability-non-const-parameter)
2245-    if (str) {
2246-        return Detail::convertIntoString( str );
2247-    } else {
2248-        return{ "{null string}" };
2249-    }
2250-}
2251-
2252-#ifdef CATCH_CONFIG_WCHAR
2253-std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
2254-    std::string s;
2255-    s.reserve(wstr.size());
2256-    for (auto c : wstr) {
2257-        s += (c <= 0xff) ? static_cast<char>(c) : '?';
2258-    }
2259-    return ::Catch::Detail::stringify(s);
2260-}
2261-
2262-# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2263-std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
2264-    return StringMaker<std::wstring>::convert(std::wstring(str));
2265-}
2266-# endif
2267-
2268-std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
2269-    if (str) {
2270-        return ::Catch::Detail::stringify(std::wstring{ str });
2271-    } else {
2272-        return{ "{null string}" };
2273-    }
2274-}
2275-std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
2276-    if (str) {
2277-        return ::Catch::Detail::stringify(std::wstring{ str });
2278-    } else {
2279-        return{ "{null string}" };
2280-    }
2281-}
2282-#endif
2283-
2284-#if defined(CATCH_CONFIG_CPP17_BYTE)
2285-#include <cstddef>
2286-std::string StringMaker<std::byte>::convert(std::byte value) {
2287-    return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
2288-}
2289-#endif // defined(CATCH_CONFIG_CPP17_BYTE)
2290-
2291-std::string StringMaker<int>::convert(int value) {
2292-    return ::Catch::Detail::stringify(static_cast<long long>(value));
2293-}
2294-std::string StringMaker<long>::convert(long value) {
2295-    return ::Catch::Detail::stringify(static_cast<long long>(value));
2296-}
2297-std::string StringMaker<long long>::convert(long long value) {
2298-    ReusableStringStream rss;
2299-    rss << value;
2300-    if (value > Detail::hexThreshold) {
2301-        rss << " (0x" << std::hex << value << ')';
2302-    }
2303-    return rss.str();
2304-}
2305-
2306-std::string StringMaker<unsigned int>::convert(unsigned int value) {
2307-    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
2308-}
2309-std::string StringMaker<unsigned long>::convert(unsigned long value) {
2310-    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
2311-}
2312-std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
2313-    ReusableStringStream rss;
2314-    rss << value;
2315-    if (value > Detail::hexThreshold) {
2316-        rss << " (0x" << std::hex << value << ')';
2317-    }
2318-    return rss.str();
2319-}
2320-
2321-std::string StringMaker<signed char>::convert(signed char value) {
2322-    if (value == '\r') {
2323-        return "'\\r'";
2324-    } else if (value == '\f') {
2325-        return "'\\f'";
2326-    } else if (value == '\n') {
2327-        return "'\\n'";
2328-    } else if (value == '\t') {
2329-        return "'\\t'";
2330-    } else if ('\0' <= value && value < ' ') {
2331-        return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
2332-    } else {
2333-        char chstr[] = "' '";
2334-        chstr[1] = value;
2335-        return chstr;
2336-    }
2337-}
2338-std::string StringMaker<char>::convert(char c) {
2339-    return ::Catch::Detail::stringify(static_cast<signed char>(c));
2340-}
2341-std::string StringMaker<unsigned char>::convert(unsigned char value) {
2342-    return ::Catch::Detail::stringify(static_cast<char>(value));
2343-}
2344-
2345-int StringMaker<float>::precision = std::numeric_limits<float>::max_digits10;
2346-
2347-std::string StringMaker<float>::convert(float value) {
2348-    return Detail::fpToString(value, precision) + 'f';
2349-}
2350-
2351-int StringMaker<double>::precision = std::numeric_limits<double>::max_digits10;
2352-
2353-std::string StringMaker<double>::convert(double value) {
2354-    return Detail::fpToString(value, precision);
2355-}
2356-
2357-} // end namespace Catch
2358-
2359-
2360-
2361-namespace Catch {
2362-
2363-    Counts Counts::operator - ( Counts const& other ) const {
2364-        Counts diff;
2365-        diff.passed = passed - other.passed;
2366-        diff.failed = failed - other.failed;
2367-        diff.failedButOk = failedButOk - other.failedButOk;
2368-        diff.skipped = skipped - other.skipped;
2369-        return diff;
2370-    }
2371-
2372-    Counts& Counts::operator += ( Counts const& other ) {
2373-        passed += other.passed;
2374-        failed += other.failed;
2375-        failedButOk += other.failedButOk;
2376-        skipped += other.skipped;
2377-        return *this;
2378-    }
2379-
2380-    std::uint64_t Counts::total() const {
2381-        return passed + failed + failedButOk + skipped;
2382-    }
2383-    bool Counts::allPassed() const {
2384-        return failed == 0 && failedButOk == 0 && skipped == 0;
2385-    }
2386-    bool Counts::allOk() const {
2387-        return failed == 0;
2388-    }
2389-
2390-    Totals Totals::operator - ( Totals const& other ) const {
2391-        Totals diff;
2392-        diff.assertions = assertions - other.assertions;
2393-        diff.testCases = testCases - other.testCases;
2394-        return diff;
2395-    }
2396-
2397-    Totals& Totals::operator += ( Totals const& other ) {
2398-        assertions += other.assertions;
2399-        testCases += other.testCases;
2400-        return *this;
2401-    }
2402-
2403-    Totals Totals::delta( Totals const& prevTotals ) const {
2404-        Totals diff = *this - prevTotals;
2405-        if( diff.assertions.failed > 0 )
2406-            ++diff.testCases.failed;
2407-        else if( diff.assertions.failedButOk > 0 )
2408-            ++diff.testCases.failedButOk;
2409-        else if ( diff.assertions.skipped > 0 )
2410-            ++ diff.testCases.skipped;
2411-        else
2412-            ++diff.testCases.passed;
2413-        return diff;
2414-    }
2415-
2416-}
2417-
2418-
2419-
2420-
2421-namespace Catch {
2422-    namespace Detail {
2423-        void registerTranslatorImpl(
2424-            Detail::unique_ptr<IExceptionTranslator>&& translator ) {
2425-            getMutableRegistryHub().registerTranslator(
2426-                CATCH_MOVE( translator ) );
2427-        }
2428-    } // namespace Detail
2429-} // namespace Catch
2430-
2431-
2432-#include <ostream>
2433-
2434-namespace Catch {
2435-
2436-    Version::Version
2437-        (   unsigned int _majorVersion,
2438-            unsigned int _minorVersion,
2439-            unsigned int _patchNumber,
2440-            char const * const _branchName,
2441-            unsigned int _buildNumber )
2442-    :   majorVersion( _majorVersion ),
2443-        minorVersion( _minorVersion ),
2444-        patchNumber( _patchNumber ),
2445-        branchName( _branchName ),
2446-        buildNumber( _buildNumber )
2447-    {}
2448-
2449-    std::ostream& operator << ( std::ostream& os, Version const& version ) {
2450-        os  << version.majorVersion << '.'
2451-            << version.minorVersion << '.'
2452-            << version.patchNumber;
2453-        // branchName is never null -> 0th char is \0 if it is empty
2454-        if (version.branchName[0]) {
2455-            os << '-' << version.branchName
2456-               << '.' << version.buildNumber;
2457-        }
2458-        return os;
2459-    }
2460-
2461-    Version const& libraryVersion() {
2462-        static Version version( 3, 11, 0, "", 0 );
2463-        return version;
2464-    }
2465-
2466-}
2467-
2468-
2469-
2470-
2471-namespace Catch {
2472-
2473-    const char* GeneratorException::what() const noexcept {
2474-        return m_msg;
2475-    }
2476-
2477-} // end namespace Catch
2478-
2479-
2480-
2481-
2482-namespace Catch {
2483-
2484-    IGeneratorTracker::~IGeneratorTracker() = default;
2485-
2486-namespace Generators {
2487-
2488-namespace Detail {
2489-
2490-    [[noreturn]]
2491-    void throw_generator_exception(char const* msg) {
2492-        Catch::throw_exception(GeneratorException{ msg });
2493-    }
2494-} // end namespace Detail
2495-
2496-    GeneratorUntypedBase::~GeneratorUntypedBase() = default;
2497-
2498-    IGeneratorTracker* acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) {
2499-        return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
2500-    }
2501-
2502-    IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
2503-                                 SourceLineInfo lineInfo,
2504-                                 GeneratorBasePtr&& generator ) {
2505-        return getResultCapture().createGeneratorTracker(
2506-            generatorName, lineInfo, CATCH_MOVE( generator ) );
2507-    }
2508-
2509-} // namespace Generators
2510-} // namespace Catch
2511-
2512-
2513-
2514-
2515-#include <random>
2516-
2517-namespace Catch {
2518-    namespace Generators {
2519-        namespace Detail {
2520-            std::uint32_t getSeed() { return sharedRng()(); }
2521-        } // namespace Detail
2522-
2523-        struct RandomFloatingGenerator<long double>::PImpl {
2524-            PImpl( long double a, long double b, uint32_t seed ):
2525-                rng( seed ), dist( a, b ) {}
2526-
2527-            Catch::SimplePcg32 rng;
2528-            std::uniform_real_distribution<long double> dist;
2529-        };
2530-
2531-        RandomFloatingGenerator<long double>::RandomFloatingGenerator(
2532-            long double a, long double b, std::uint32_t seed) :
2533-            m_pimpl(Catch::Detail::make_unique<PImpl>(a, b, seed)) {
2534-            static_cast<void>( next() );
2535-        }
2536-
2537-        RandomFloatingGenerator<long double>::~RandomFloatingGenerator() =
2538-            default;
2539-        bool RandomFloatingGenerator<long double>::next() {
2540-            m_current_number = m_pimpl->dist( m_pimpl->rng );
2541-            return true;
2542-        }
2543-    } // namespace Generators
2544-} // namespace Catch
2545-
2546-
2547-
2548-
2549-namespace Catch {
2550-    namespace Detail {
2551-        void missingCaptureInstance() {
2552-            CATCH_INTERNAL_ERROR( "No result capture instance" );
2553-        }
2554-    } // namespace Detail
2555-
2556-    IResultCapture::~IResultCapture() = default;
2557-} // namespace Catch
2558-
2559-
2560-
2561-
2562-namespace Catch {
2563-    IConfig::~IConfig() = default;
2564-}
2565-
2566-
2567-
2568-
2569-namespace Catch {
2570-    IExceptionTranslator::~IExceptionTranslator() = default;
2571-    IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
2572-}
2573-
2574-
2575-
2576-#include <string>
2577-
2578-namespace Catch {
2579-    namespace Generators {
2580-
2581-        bool GeneratorUntypedBase::countedNext() {
2582-            auto ret = next();
2583-            if ( ret ) {
2584-                m_stringReprCache.clear();
2585-                ++m_currentElementIndex;
2586-            }
2587-            return ret;
2588-        }
2589-
2590-        StringRef GeneratorUntypedBase::currentElementAsString() const {
2591-            if ( m_stringReprCache.empty() ) {
2592-                m_stringReprCache = stringifyImpl();
2593-            }
2594-            return m_stringReprCache;
2595-        }
2596-
2597-    } // namespace Generators
2598-} // namespace Catch
2599-
2600-
2601-
2602-
2603-namespace Catch {
2604-    IRegistryHub::~IRegistryHub() = default;
2605-    IMutableRegistryHub::~IMutableRegistryHub() = default;
2606-}
2607-
2608-
2609-
2610-#include <cassert>
2611-
2612-namespace Catch {
2613-
2614-    ReporterConfig::ReporterConfig(
2615-        IConfig const* _fullConfig,
2616-        Detail::unique_ptr<IStream> _stream,
2617-        ColourMode colourMode,
2618-        std::map<std::string, std::string> customOptions ):
2619-        m_stream( CATCH_MOVE(_stream) ),
2620-        m_fullConfig( _fullConfig ),
2621-        m_colourMode( colourMode ),
2622-        m_customOptions( CATCH_MOVE( customOptions ) ) {}
2623-
2624-    Detail::unique_ptr<IStream> ReporterConfig::takeStream() && {
2625-        assert( m_stream );
2626-        return CATCH_MOVE( m_stream );
2627-    }
2628-    IConfig const * ReporterConfig::fullConfig() const { return m_fullConfig; }
2629-    ColourMode ReporterConfig::colourMode() const { return m_colourMode; }
2630-
2631-    std::map<std::string, std::string> const&
2632-    ReporterConfig::customOptions() const {
2633-        return m_customOptions;
2634-    }
2635-
2636-    ReporterConfig::~ReporterConfig() = default;
2637-
2638-    AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
2639-                                    std::vector<MessageInfo> const& _infoMessages,
2640-                                    Totals const& _totals )
2641-    :   assertionResult( _assertionResult ),
2642-        infoMessages( _infoMessages ),
2643-        totals( _totals )
2644-    {
2645-        if( assertionResult.hasMessage() ) {
2646-            // Copy message into messages list.
2647-            // !TBD This should have been done earlier, somewhere
2648-            MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
2649-            builder.m_info.message = static_cast<std::string>(assertionResult.getMessage());
2650-
2651-            infoMessages.push_back( CATCH_MOVE(builder.m_info) );
2652-        }
2653-    }
2654-
2655-    SectionStats::SectionStats(  SectionInfo&& _sectionInfo,
2656-                                 Counts const& _assertions,
2657-                                 double _durationInSeconds,
2658-                                 bool _missingAssertions )
2659-    :   sectionInfo( CATCH_MOVE(_sectionInfo) ),
2660-        assertions( _assertions ),
2661-        durationInSeconds( _durationInSeconds ),
2662-        missingAssertions( _missingAssertions )
2663-    {}
2664-
2665-
2666-    TestCaseStats::TestCaseStats(  TestCaseInfo const& _testInfo,
2667-                                   Totals const& _totals,
2668-                                   std::string&& _stdOut,
2669-                                   std::string&& _stdErr,
2670-                                   bool _aborting )
2671-    : testInfo( &_testInfo ),
2672-        totals( _totals ),
2673-        stdOut( CATCH_MOVE(_stdOut) ),
2674-        stdErr( CATCH_MOVE(_stdErr) ),
2675-        aborting( _aborting )
2676-    {}
2677-
2678-
2679-    TestRunStats::TestRunStats(   TestRunInfo const& _runInfo,
2680-                    Totals const& _totals,
2681-                    bool _aborting )
2682-    :   runInfo( _runInfo ),
2683-        totals( _totals ),
2684-        aborting( _aborting )
2685-    {}
2686-
2687-    IEventListener::~IEventListener() = default;
2688-
2689-} // end namespace Catch
2690-
2691-
2692-
2693-
2694-namespace Catch {
2695-    IReporterFactory::~IReporterFactory() = default;
2696-    EventListenerFactory::~EventListenerFactory() = default;
2697-}
2698-
2699-
2700-
2701-
2702-namespace Catch {
2703-    ITestCaseRegistry::~ITestCaseRegistry() = default;
2704-}
2705-
2706-
2707-
2708-namespace Catch {
2709-
2710-    AssertionHandler::AssertionHandler
2711-        (   StringRef macroName,
2712-            SourceLineInfo const& lineInfo,
2713-            StringRef capturedExpression,
2714-            ResultDisposition::Flags resultDisposition )
2715-    :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
2716-        m_resultCapture( getResultCapture() )
2717-    {
2718-        m_resultCapture.notifyAssertionStarted( m_assertionInfo );
2719-    }
2720-
2721-    void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
2722-        m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
2723-    }
2724-    void AssertionHandler::handleMessage(ResultWas::OfType resultType, std::string&& message) {
2725-        m_resultCapture.handleMessage( m_assertionInfo, resultType, CATCH_MOVE(message), m_reaction );
2726-    }
2727-
2728-    auto AssertionHandler::allowThrows() const -> bool {
2729-        return getCurrentContext().getConfig()->allowThrows();
2730-    }
2731-
2732-    void AssertionHandler::complete() {
2733-        m_completed = true;
2734-        if( m_reaction.shouldDebugBreak ) {
2735-
2736-            // If you find your debugger stopping you here then go one level up on the
2737-            // call-stack for the code that caused it (typically a failed assertion)
2738-
2739-            // (To go back to the test and change execution, jump over the throw, next)
2740-            CATCH_BREAK_INTO_DEBUGGER();
2741-        }
2742-        if (m_reaction.shouldThrow) {
2743-            throw_test_failure_exception();
2744-        }
2745-        if ( m_reaction.shouldSkip ) {
2746-            throw_test_skip_exception();
2747-        }
2748-    }
2749-
2750-    void AssertionHandler::handleUnexpectedInflightException() {
2751-        m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
2752-    }
2753-
2754-    void AssertionHandler::handleExceptionThrownAsExpected() {
2755-        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
2756-    }
2757-    void AssertionHandler::handleExceptionNotThrownAsExpected() {
2758-        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
2759-    }
2760-
2761-    void AssertionHandler::handleUnexpectedExceptionNotThrown() {
2762-        m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
2763-    }
2764-
2765-    void AssertionHandler::handleThrowingCallSkipped() {
2766-        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
2767-    }
2768-
2769-    // This is the overload that takes a string and infers the Equals matcher from it
2770-    // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
2771-    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str ) {
2772-        handleExceptionMatchExpr( handler, Matchers::Equals( str ) );
2773-    }
2774-
2775-} // namespace Catch
2776-
2777-
2778-
2779-
2780-#include <algorithm>
2781-
2782-namespace Catch {
2783-    namespace Detail {
2784-
2785-        bool CaseInsensitiveLess::operator()( StringRef lhs,
2786-                                              StringRef rhs ) const {
2787-            return std::lexicographical_compare(
2788-                lhs.begin(), lhs.end(),
2789-                rhs.begin(), rhs.end(),
2790-                []( char l, char r ) { return toLower( l ) < toLower( r ); } );
2791-        }
2792-
2793-        bool
2794-        CaseInsensitiveEqualTo::operator()( StringRef lhs,
2795-                                            StringRef rhs ) const {
2796-            return std::equal(
2797-                lhs.begin(), lhs.end(),
2798-                rhs.begin(), rhs.end(),
2799-                []( char l, char r ) { return toLower( l ) == toLower( r ); } );
2800-        }
2801-
2802-    } // namespace Detail
2803-} // namespace Catch
2804-
2805-
2806-
2807-
2808-#include <algorithm>
2809-#include <ostream>
2810-
2811-namespace {
2812-    bool isOptPrefix( char c ) {
2813-        return c == '-'
2814-#ifdef CATCH_PLATFORM_WINDOWS
2815-               || c == '/'
2816-#endif
2817-            ;
2818-    }
2819-
2820-    Catch::StringRef normaliseOpt( Catch::StringRef optName ) {
2821-        if ( optName[0] == '-'
2822-#if defined(CATCH_PLATFORM_WINDOWS)
2823-             || optName[0] == '/'
2824-#endif
2825-        ) {
2826-            return optName.substr( 1, optName.size() );
2827-        }
2828-
2829-        return optName;
2830-    }
2831-
2832-    static size_t find_first_separator(Catch::StringRef sr) {
2833-        auto is_separator = []( char c ) {
2834-            return c == ' ' || c == ':' || c == '=';
2835-        };
2836-        size_t pos = 0;
2837-        while (pos < sr.size()) {
2838-            if (is_separator(sr[pos])) { return pos; }
2839-            ++pos;
2840-        }
2841-
2842-        return Catch::StringRef::npos;
2843-    }
2844-
2845-} // namespace
2846-
2847-namespace Catch {
2848-    namespace Clara {
2849-        namespace Detail {
2850-
2851-            void TokenStream::loadBuffer() {
2852-                m_tokenBuffer.clear();
2853-
2854-                // Skip any empty strings
2855-                while ( it != itEnd && it->empty() ) {
2856-                    ++it;
2857-                }
2858-
2859-                if ( it != itEnd ) {
2860-                    StringRef next = *it;
2861-                    if ( isOptPrefix( next[0] ) ) {
2862-                        auto delimiterPos = find_first_separator(next);
2863-                        if ( delimiterPos != StringRef::npos ) {
2864-                            m_tokenBuffer.push_back(
2865-                                { TokenType::Option,
2866-                                  next.substr( 0, delimiterPos ) } );
2867-                            m_tokenBuffer.push_back(
2868-                                { TokenType::Argument,
2869-                                  next.substr( delimiterPos + 1, next.size() ) } );
2870-                        } else {
2871-                            if ( next.size() > 1 && next[1] != '-' && next.size() > 2 ) {
2872-                                // Combined short args, e.g. "-ab" for "-a -b"
2873-                                for ( size_t i = 1; i < next.size(); ++i ) {
2874-                                    m_tokenBuffer.push_back(
2875-                                        { TokenType::Option,
2876-                                          next.substr( i, 1 ) } );
2877-                                }
2878-                            } else {
2879-                                m_tokenBuffer.push_back(
2880-                                    { TokenType::Option, next } );
2881-                            }
2882-                        }
2883-                    } else {
2884-                        m_tokenBuffer.push_back(
2885-                            { TokenType::Argument, next } );
2886-                    }
2887-                }
2888-            }
2889-
2890-            TokenStream::TokenStream( Args const& args ):
2891-                TokenStream( args.m_args.begin(), args.m_args.end() ) {}
2892-
2893-            TokenStream::TokenStream( Iterator it_, Iterator itEnd_ ):
2894-                it( it_ ), itEnd( itEnd_ ) {
2895-                loadBuffer();
2896-            }
2897-
2898-            TokenStream& TokenStream::operator++() {
2899-                if ( m_tokenBuffer.size() >= 2 ) {
2900-                    m_tokenBuffer.erase( m_tokenBuffer.begin() );
2901-                } else {
2902-                    if ( it != itEnd )
2903-                        ++it;
2904-                    loadBuffer();
2905-                }
2906-                return *this;
2907-            }
2908-
2909-            ParserResult convertInto( std::string const& source,
2910-                                      std::string& target ) {
2911-                target = source;
2912-                return ParserResult::ok( ParseResultType::Matched );
2913-            }
2914-
2915-            ParserResult convertInto( std::string const& source,
2916-                                      bool& target ) {
2917-                std::string srcLC = toLower( source );
2918-
2919-                if ( srcLC == "y" || srcLC == "1" || srcLC == "true" ||
2920-                     srcLC == "yes" || srcLC == "on" ) {
2921-                    target = true;
2922-                } else if ( srcLC == "n" || srcLC == "0" || srcLC == "false" ||
2923-                            srcLC == "no" || srcLC == "off" ) {
2924-                    target = false;
2925-                } else {
2926-                    return ParserResult::runtimeError(
2927-                        "Expected a boolean value but did not recognise: '" +
2928-                        source + '\'' );
2929-                }
2930-                return ParserResult::ok( ParseResultType::Matched );
2931-            }
2932-
2933-            size_t ParserBase::cardinality() const { return 1; }
2934-
2935-            InternalParseResult ParserBase::parse( Args const& args ) const {
2936-                return parse( static_cast<std::string>(args.exeName()), TokenStream( args ) );
2937-            }
2938-
2939-            ParseState::ParseState( ParseResultType type,
2940-                                    TokenStream remainingTokens ):
2941-                m_type( type ), m_remainingTokens( CATCH_MOVE(remainingTokens) ) {}
2942-
2943-            ParserResult BoundFlagRef::setFlag( bool flag ) {
2944-                m_ref = flag;
2945-                return ParserResult::ok( ParseResultType::Matched );
2946-            }
2947-
2948-            ResultBase::~ResultBase() = default;
2949-
2950-            bool BoundRef::isContainer() const { return false; }
2951-
2952-            bool BoundRef::isFlag() const { return false; }
2953-
2954-            bool BoundFlagRefBase::isFlag() const { return true; }
2955-
2956-} // namespace Detail
2957-
2958-        Detail::InternalParseResult Arg::parse(std::string const&,
2959-                                               Detail::TokenStream tokens) const {
2960-            auto validationResult = validate();
2961-            if (!validationResult)
2962-                return Detail::InternalParseResult(validationResult);
2963-
2964-            auto token = *tokens;
2965-            if (token.type != Detail::TokenType::Argument)
2966-                return Detail::InternalParseResult::ok(Detail::ParseState(
2967-                    ParseResultType::NoMatch, CATCH_MOVE(tokens)));
2968-
2969-            assert(!m_ref->isFlag());
2970-            auto valueRef =
2971-                static_cast<Detail::BoundValueRefBase*>(m_ref.get());
2972-
2973-            auto result = valueRef->setValue(static_cast<std::string>(token.token));
2974-            if ( !result )
2975-                return Detail::InternalParseResult( result );
2976-            else
2977-                return Detail::InternalParseResult::ok(
2978-                    Detail::ParseState( ParseResultType::Matched,
2979-                                        CATCH_MOVE( ++tokens ) ) );
2980-        }
2981-
2982-        Opt::Opt(bool& ref) :
2983-            ParserRefImpl(std::make_shared<Detail::BoundFlagRef>(ref)) {}
2984-
2985-        Detail::HelpColumns Opt::getHelpColumns() const {
2986-            ReusableStringStream oss;
2987-            bool first = true;
2988-            for (auto const& opt : m_optNames) {
2989-                if (first)
2990-                    first = false;
2991-                else
2992-                    oss << ", ";
2993-                oss << opt;
2994-            }
2995-            if (!m_hint.empty())
2996-                oss << " <" << m_hint << '>';
2997-            return { oss.str(), m_description };
2998-        }
2999-
3000-        bool Opt::isMatch(StringRef optToken) const {
3001-            auto normalisedToken = normaliseOpt(optToken);
3002-            for (auto const& name : m_optNames) {
3003-                if (normaliseOpt(name) == normalisedToken)
3004-                    return true;
3005-            }
3006-            return false;
3007-        }
3008-
3009-        Detail::InternalParseResult Opt::parse(std::string const&,
3010-                                       Detail::TokenStream tokens) const {
3011-            auto validationResult = validate();
3012-            if (!validationResult)
3013-                return Detail::InternalParseResult(validationResult);
3014-
3015-            if (tokens &&
3016-                tokens->type == Detail::TokenType::Option) {
3017-                auto const& token = *tokens;
3018-                if (isMatch(token.token)) {
3019-                    if (m_ref->isFlag()) {
3020-                        auto flagRef =
3021-                            static_cast<Detail::BoundFlagRefBase*>(
3022-                                m_ref.get());
3023-                        auto result = flagRef->setFlag(true);
3024-                        if (!result)
3025-                            return Detail::InternalParseResult(result);
3026-                        if (result.value() ==
3027-                            ParseResultType::ShortCircuitAll)
3028-                            return Detail::InternalParseResult::ok(Detail::ParseState(
3029-                                result.value(), CATCH_MOVE(tokens)));
3030-                    } else {
3031-                        auto valueRef =
3032-                            static_cast<Detail::BoundValueRefBase*>(
3033-                                m_ref.get());
3034-                        ++tokens;
3035-                        if (!tokens)
3036-                            return Detail::InternalParseResult::runtimeError(
3037-                                "Expected argument following " +
3038-                                token.token);
3039-                        auto const& argToken = *tokens;
3040-                        if (argToken.type != Detail::TokenType::Argument)
3041-                            return Detail::InternalParseResult::runtimeError(
3042-                                "Expected argument following " +
3043-                                token.token);
3044-                        const auto result = valueRef->setValue(static_cast<std::string>(argToken.token));
3045-                        if (!result)
3046-                            return Detail::InternalParseResult(result);
3047-                        if (result.value() ==
3048-                            ParseResultType::ShortCircuitAll)
3049-                            return Detail::InternalParseResult::ok(Detail::ParseState(
3050-                                result.value(), CATCH_MOVE(tokens)));
3051-                    }
3052-                    return Detail::InternalParseResult::ok(Detail::ParseState(
3053-                        ParseResultType::Matched, CATCH_MOVE(++tokens)));
3054-                }
3055-            }
3056-            return Detail::InternalParseResult::ok(
3057-                Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
3058-        }
3059-
3060-        Detail::Result Opt::validate() const {
3061-            if (m_optNames.empty())
3062-                return Detail::Result::logicError("No options supplied to Opt");
3063-            for (auto const& name : m_optNames) {
3064-                if (name.empty())
3065-                    return Detail::Result::logicError(
3066-                        "Option name cannot be empty");
3067-#ifdef CATCH_PLATFORM_WINDOWS
3068-                if (name[0] != '-' && name[0] != '/')
3069-                    return Detail::Result::logicError(
3070-                        "Option name must begin with '-' or '/'");
3071-#else
3072-                if (name[0] != '-')
3073-                    return Detail::Result::logicError(
3074-                        "Option name must begin with '-'");
3075-#endif
3076-            }
3077-            return ParserRefImpl::validate();
3078-        }
3079-
3080-        ExeName::ExeName() :
3081-            m_name(std::make_shared<std::string>("<executable>")) {}
3082-
3083-        ExeName::ExeName(std::string& ref) : ExeName() {
3084-            m_ref = std::make_shared<Detail::BoundValueRef<std::string>>(ref);
3085-        }
3086-
3087-        Detail::InternalParseResult
3088-            ExeName::parse(std::string const&,
3089-                           Detail::TokenStream tokens) const {
3090-            return Detail::InternalParseResult::ok(
3091-                Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
3092-        }
3093-
3094-        ParserResult ExeName::set(std::string const& newName) {
3095-            auto lastSlash = newName.find_last_of("\\/");
3096-            auto filename = (lastSlash == std::string::npos)
3097-                ? newName
3098-                : newName.substr(lastSlash + 1);
3099-
3100-            *m_name = filename;
3101-            if (m_ref)
3102-                return m_ref->setValue(filename);
3103-            else
3104-                return ParserResult::ok(ParseResultType::Matched);
3105-        }
3106-
3107-
3108-
3109-
3110-        Parser& Parser::operator|=( Parser const& other ) {
3111-            m_options.insert( m_options.end(),
3112-                              other.m_options.begin(),
3113-                              other.m_options.end() );
3114-            m_args.insert(
3115-                m_args.end(), other.m_args.begin(), other.m_args.end() );
3116-            return *this;
3117-        }
3118-
3119-        std::vector<Detail::HelpColumns> Parser::getHelpColumns() const {
3120-            std::vector<Detail::HelpColumns> cols;
3121-            cols.reserve( m_options.size() );
3122-            for ( auto const& o : m_options ) {
3123-                cols.push_back(o.getHelpColumns());
3124-            }
3125-            return cols;
3126-        }
3127-
3128-        void Parser::writeToStream( std::ostream& os ) const {
3129-            if ( !m_exeName.name().empty() ) {
3130-                os << "usage:\n"
3131-                   << "  " << m_exeName.name() << ' ';
3132-                bool required = true, first = true;
3133-                for ( auto const& arg : m_args ) {
3134-                    if ( first )
3135-                        first = false;
3136-                    else
3137-                        os << ' ';
3138-                    if ( arg.isOptional() && required ) {
3139-                        os << '[';
3140-                        required = false;
3141-                    }
3142-                    os << '<' << arg.hint() << '>';
3143-                    if ( arg.cardinality() == 0 )
3144-                        os << " ... ";
3145-                }
3146-                if ( !required )
3147-                    os << ']';
3148-                if ( !m_options.empty() )
3149-                    os << " options";
3150-                os << "\n\nwhere options are:\n";
3151-            }
3152-
3153-            auto rows = getHelpColumns();
3154-            size_t consoleWidth = CATCH_CONFIG_CONSOLE_WIDTH;
3155-            size_t optWidth = 0;
3156-            for ( auto const& cols : rows )
3157-                optWidth = ( std::max )( optWidth, cols.left.size() + 2 );
3158-
3159-            optWidth = ( std::min )( optWidth, consoleWidth / 2 );
3160-
3161-            for ( auto& cols : rows ) {
3162-                auto row = TextFlow::Column( CATCH_MOVE(cols.left) )
3163-                               .width( optWidth )
3164-                               .indent( 2 ) +
3165-                           TextFlow::Spacer( 4 ) +
3166-                           TextFlow::Column( static_cast<std::string>(cols.descriptions) )
3167-                               .width( consoleWidth - 7 - optWidth );
3168-                os << row << '\n';
3169-            }
3170-        }
3171-
3172-        Detail::Result Parser::validate() const {
3173-            for ( auto const& opt : m_options ) {
3174-                auto result = opt.validate();
3175-                if ( !result )
3176-                    return result;
3177-            }
3178-            for ( auto const& arg : m_args ) {
3179-                auto result = arg.validate();
3180-                if ( !result )
3181-                    return result;
3182-            }
3183-            return Detail::Result::ok();
3184-        }
3185-
3186-        Detail::InternalParseResult
3187-        Parser::parse( std::string const& exeName,
3188-                       Detail::TokenStream tokens ) const {
3189-
3190-            struct ParserInfo {
3191-                ParserBase const* parser = nullptr;
3192-                size_t count = 0;
3193-            };
3194-            std::vector<ParserInfo> parseInfos;
3195-            parseInfos.reserve( m_options.size() + m_args.size() );
3196-            for ( auto const& opt : m_options ) {
3197-                parseInfos.push_back( { &opt, 0 } );
3198-            }
3199-            for ( auto const& arg : m_args ) {
3200-                parseInfos.push_back( { &arg, 0 } );
3201-            }
3202-
3203-            m_exeName.set( exeName );
3204-
3205-            auto result = Detail::InternalParseResult::ok(
3206-                Detail::ParseState( ParseResultType::NoMatch, CATCH_MOVE(tokens) ) );
3207-            while ( result.value().remainingTokens() ) {
3208-                bool tokenParsed = false;
3209-
3210-                for ( auto& parseInfo : parseInfos ) {
3211-                    if ( parseInfo.parser->cardinality() == 0 ||
3212-                         parseInfo.count < parseInfo.parser->cardinality() ) {
3213-                        result = parseInfo.parser->parse(
3214-                            exeName, CATCH_MOVE(result).value().remainingTokens() );
3215-                        if ( !result )
3216-                            return result;
3217-                        if ( result.value().type() !=
3218-                             ParseResultType::NoMatch ) {
3219-                            tokenParsed = true;
3220-                            ++parseInfo.count;
3221-                            break;
3222-                        }
3223-                    }
3224-                }
3225-
3226-                if ( result.value().type() == ParseResultType::ShortCircuitAll )
3227-                    return result;
3228-                if ( !tokenParsed )
3229-                    return Detail::InternalParseResult::runtimeError(
3230-                        "Unrecognised token: " +
3231-                        result.value().remainingTokens()->token );
3232-            }
3233-            // !TBD Check missing required options
3234-            return result;
3235-        }
3236-
3237-        Args::Args(int argc, char const* const* argv) :
3238-            m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
3239-
3240-        Args::Args(std::initializer_list<StringRef> args) :
3241-            m_exeName(*args.begin()),
3242-            m_args(args.begin() + 1, args.end()) {}
3243-
3244-
3245-        Help::Help( bool& showHelpFlag ):
3246-            Opt( [&]( bool flag ) {
3247-                showHelpFlag = flag;
3248-                return ParserResult::ok( ParseResultType::ShortCircuitAll );
3249-            } ) {
3250-            static_cast<Opt&> ( *this )(
3251-                "display usage information" )["-?"]["-h"]["--help"]
3252-                .optional();
3253-        }
3254-
3255-    } // namespace Clara
3256-} // namespace Catch
3257-
3258-
3259-
3260-
3261-#include <fstream>
3262-#include <string>
3263-
3264-namespace Catch {
3265-
3266-    Clara::Parser makeCommandLineParser( ConfigData& config ) {
3267-
3268-        using namespace Clara;
3269-
3270-        auto const setWarning = [&]( std::string const& warning ) {
3271-            if ( warning == "NoAssertions" ) {
3272-                config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::NoAssertions);
3273-                return ParserResult::ok( ParseResultType::Matched );
3274-            } else if ( warning == "UnmatchedTestSpec" ) {
3275-                config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::UnmatchedTestSpec);
3276-                return ParserResult::ok( ParseResultType::Matched );
3277-            }
3278-
3279-            return ParserResult ::runtimeError(
3280-                "Unrecognised warning option: '" + warning + '\'' );
3281-        };
3282-        auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
3283-                std::ifstream f( filename.c_str() );
3284-                if( !f.is_open() )
3285-                    return ParserResult::runtimeError( "Unable to load input file: '" + filename + '\'' );
3286-
3287-                std::string line;
3288-                while( std::getline( f, line ) ) {
3289-                    line = trim(line);
3290-                    if( !line.empty() && !startsWith( line, '#' ) ) {
3291-                        if( !startsWith( line, '"' ) )
3292-                            line = '"' + CATCH_MOVE(line) + '"';
3293-                        config.testsOrTags.push_back( line );
3294-                        config.testsOrTags.emplace_back( "," );
3295-                    }
3296-                }
3297-                //Remove comma in the end
3298-                if(!config.testsOrTags.empty())
3299-                    config.testsOrTags.erase( config.testsOrTags.end()-1 );
3300-
3301-                return ParserResult::ok( ParseResultType::Matched );
3302-            };
3303-        auto const setTestOrder = [&]( std::string const& order ) {
3304-                if( startsWith( "declared", order ) )
3305-                    config.runOrder = TestRunOrder::Declared;
3306-                else if( startsWith( "lexical", order ) )
3307-                    config.runOrder = TestRunOrder::LexicographicallySorted;
3308-                else if( startsWith( "random", order ) )
3309-                    config.runOrder = TestRunOrder::Randomized;
3310-                else
3311-                    return ParserResult::runtimeError( "Unrecognised ordering: '" + order + '\'' );
3312-                return ParserResult::ok( ParseResultType::Matched );
3313-            };
3314-        auto const setRngSeed = [&]( std::string const& seed ) {
3315-                if( seed == "time" ) {
3316-                    config.rngSeed = generateRandomSeed(GenerateFrom::Time);
3317-                    return ParserResult::ok(ParseResultType::Matched);
3318-                } else if (seed == "random-device") {
3319-                    config.rngSeed = generateRandomSeed(GenerateFrom::RandomDevice);
3320-                    return ParserResult::ok(ParseResultType::Matched);
3321-                }
3322-
3323-                // TODO: ideally we should be parsing uint32_t directly
3324-                //       fix this later when we add new parse overload
3325-                auto parsedSeed = parseUInt( seed, 0 );
3326-                if ( !parsedSeed ) {
3327-                    return ParserResult::runtimeError( "Could not parse '" + seed + "' as seed" );
3328-                }
3329-                config.rngSeed = *parsedSeed;
3330-                return ParserResult::ok( ParseResultType::Matched );
3331-            };
3332-        auto const setDefaultColourMode = [&]( std::string const& colourMode ) {
3333-            Optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
3334-            if ( !maybeMode ) {
3335-                return ParserResult::runtimeError(
3336-                    "colour mode must be one of: default, ansi, win32, "
3337-                    "or none. '" +
3338-                    colourMode + "' is not recognised" );
3339-            }
3340-            auto mode = *maybeMode;
3341-            if ( !isColourImplAvailable( mode ) ) {
3342-                return ParserResult::runtimeError(
3343-                    "colour mode '" + colourMode +
3344-                    "' is not supported in this binary" );
3345-            }
3346-            config.defaultColourMode = mode;
3347-            return ParserResult::ok( ParseResultType::Matched );
3348-        };
3349-        auto const setWaitForKeypress = [&]( std::string const& keypress ) {
3350-                auto keypressLc = toLower( keypress );
3351-                if (keypressLc == "never")
3352-                    config.waitForKeypress = WaitForKeypress::Never;
3353-                else if( keypressLc == "start" )
3354-                    config.waitForKeypress = WaitForKeypress::BeforeStart;
3355-                else if( keypressLc == "exit" )
3356-                    config.waitForKeypress = WaitForKeypress::BeforeExit;
3357-                else if( keypressLc == "both" )
3358-                    config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
3359-                else
3360-                    return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );
3361-            return ParserResult::ok( ParseResultType::Matched );
3362-            };
3363-        auto const setVerbosity = [&]( std::string const& verbosity ) {
3364-            auto lcVerbosity = toLower( verbosity );
3365-            if( lcVerbosity == "quiet" )
3366-                config.verbosity = Verbosity::Quiet;
3367-            else if( lcVerbosity == "normal" )
3368-                config.verbosity = Verbosity::Normal;
3369-            else if( lcVerbosity == "high" )
3370-                config.verbosity = Verbosity::High;
3371-            else
3372-                return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + '\'' );
3373-            return ParserResult::ok( ParseResultType::Matched );
3374-        };
3375-        auto const setReporter = [&]( std::string const& userReporterSpec ) {
3376-            if ( userReporterSpec.empty() ) {
3377-                return ParserResult::runtimeError( "Received empty reporter spec." );
3378-            }
3379-
3380-            Optional<ReporterSpec> parsed =
3381-                parseReporterSpec( userReporterSpec );
3382-            if ( !parsed ) {
3383-                return ParserResult::runtimeError(
3384-                    "Could not parse reporter spec '" + userReporterSpec +
3385-                    "'" );
3386-            }
3387-
3388-            auto const& reporterSpec = *parsed;
3389-
3390-            auto const& factories =
3391-                getRegistryHub().getReporterRegistry().getFactories();
3392-            auto result = factories.find( reporterSpec.name() );
3393-
3394-            if ( result == factories.end() ) {
3395-                return ParserResult::runtimeError(
3396-                    "Unrecognized reporter, '" + reporterSpec.name() +
3397-                    "'. Check available with --list-reporters" );
3398-            }
3399-
3400-
3401-            const bool hadOutputFile = reporterSpec.outputFile().some();
3402-            config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) );
3403-            // It would be enough to check this only once at the very end, but
3404-            // there is  not a place where we could call this check, so do it
3405-            // every time it could fail. For valid inputs, this is still called
3406-            // at most once.
3407-            if (!hadOutputFile) {
3408-                int n_reporters_without_file = 0;
3409-                for (auto const& spec : config.reporterSpecifications) {
3410-                    if (spec.outputFile().none()) {
3411-                        n_reporters_without_file++;
3412-                    }
3413-                }
3414-                if (n_reporters_without_file > 1) {
3415-                    return ParserResult::runtimeError( "Only one reporter may have unspecified output file." );
3416-                }
3417-            }
3418-
3419-            return ParserResult::ok( ParseResultType::Matched );
3420-        };
3421-        auto const setShardCount = [&]( std::string const& shardCount ) {
3422-            auto parsedCount = parseUInt( shardCount );
3423-            if ( !parsedCount ) {
3424-                return ParserResult::runtimeError(
3425-                    "Could not parse '" + shardCount + "' as shard count" );
3426-            }
3427-            if ( *parsedCount == 0 ) {
3428-                return ParserResult::runtimeError(
3429-                    "Shard count must be positive" );
3430-            }
3431-            config.shardCount = *parsedCount;
3432-            return ParserResult::ok( ParseResultType::Matched );
3433-        };
3434-
3435-        auto const setShardIndex = [&](std::string const& shardIndex) {
3436-            auto parsedIndex = parseUInt( shardIndex );
3437-            if ( !parsedIndex ) {
3438-                return ParserResult::runtimeError(
3439-                    "Could not parse '" + shardIndex + "' as shard index" );
3440-            }
3441-            config.shardIndex = *parsedIndex;
3442-            return ParserResult::ok( ParseResultType::Matched );
3443-        };
3444-
3445-        auto cli
3446-            = ExeName( config.processName )
3447-            | Help( config.showHelp )
3448-            | Opt( config.showSuccessfulTests )
3449-                ["-s"]["--success"]
3450-                ( "include successful tests in output" )
3451-            | Opt( config.shouldDebugBreak )
3452-                ["-b"]["--break"]
3453-                ( "break into debugger on failure" )
3454-            | Opt( config.noThrow )
3455-                ["-e"]["--nothrow"]
3456-                ( "skip exception tests" )
3457-            | Opt( config.showInvisibles )
3458-                ["-i"]["--invisibles"]
3459-                ( "show invisibles (tabs, newlines)" )
3460-            | Opt( config.defaultOutputFilename, "filename" )
3461-                ["-o"]["--out"]
3462-                ( "default output filename" )
3463-            | Opt( accept_many, setReporter, "name[::key=value]*" )
3464-                ["-r"]["--reporter"]
3465-                ( "reporter to use (defaults to console)" )
3466-            | Opt( config.name, "name" )
3467-                ["-n"]["--name"]
3468-                ( "suite name" )
3469-            | Opt( [&]( bool ){ config.abortAfter = 1; } )
3470-                ["-a"]["--abort"]
3471-                ( "abort at first failure" )
3472-            | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
3473-                ["-x"]["--abortx"]
3474-                ( "abort after x failures" )
3475-            | Opt( accept_many, setWarning, "warning name" )
3476-                ["-w"]["--warn"]
3477-                ( "enable warnings" )
3478-            | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
3479-                ["-d"]["--durations"]
3480-                ( "show test durations" )
3481-            | Opt( config.minDuration, "seconds" )
3482-                ["-D"]["--min-duration"]
3483-                ( "show test durations for tests taking at least the given number of seconds" )
3484-            | Opt( loadTestNamesFromFile, "filename" )
3485-                ["-f"]["--input-file"]
3486-                ( "load test names to run from a file" )
3487-            | Opt( config.filenamesAsTags )
3488-                ["-#"]["--filenames-as-tags"]
3489-                ( "adds a tag for the filename" )
3490-            | Opt( config.sectionsToRun, "section name" )
3491-                ["-c"]["--section"]
3492-                ( "specify section to run" )
3493-            | Opt( setVerbosity, "quiet|normal|high" )
3494-                ["-v"]["--verbosity"]
3495-                ( "set output verbosity" )
3496-            | Opt( config.listTests )
3497-                ["--list-tests"]
3498-                ( "list all/matching test cases" )
3499-            | Opt( config.listTags )
3500-                ["--list-tags"]
3501-                ( "list all/matching tags" )
3502-            | Opt( config.listReporters )
3503-                ["--list-reporters"]
3504-                ( "list all available reporters" )
3505-            | Opt( config.listListeners )
3506-                ["--list-listeners"]
3507-                ( "list all listeners" )
3508-            | Opt( setTestOrder, "decl|lex|rand" )
3509-                ["--order"]
3510-                ( "test case order (defaults to decl)" )
3511-            | Opt( setRngSeed, "'time'|'random-device'|number" )
3512-                ["--rng-seed"]
3513-                ( "set a specific seed for random numbers" )
3514-            | Opt( setDefaultColourMode, "ansi|win32|none|default" )
3515-                ["--colour-mode"]
3516-                ( "what color mode should be used as default" )
3517-            | Opt( config.libIdentify )
3518-                ["--libidentify"]
3519-                ( "report name and version according to libidentify standard" )
3520-            | Opt( setWaitForKeypress, "never|start|exit|both" )
3521-                ["--wait-for-keypress"]
3522-                ( "waits for a keypress before exiting" )
3523-            | Opt( config.skipBenchmarks)
3524-                ["--skip-benchmarks"]
3525-                ( "disable running benchmarks")
3526-            | Opt( config.benchmarkSamples, "samples" )
3527-                ["--benchmark-samples"]
3528-                ( "number of samples to collect (default: 100)" )
3529-            | Opt( config.benchmarkResamples, "resamples" )
3530-                ["--benchmark-resamples"]
3531-                ( "number of resamples for the bootstrap (default: 100000)" )
3532-            | Opt( config.benchmarkConfidenceInterval, "confidence interval" )
3533-                ["--benchmark-confidence-interval"]
3534-                ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )
3535-            | Opt( config.benchmarkNoAnalysis )
3536-                ["--benchmark-no-analysis"]
3537-                ( "perform only measurements; do not perform any analysis" )
3538-            | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )
3539-                ["--benchmark-warmup-time"]
3540-                ( "amount of time in milliseconds spent on warming up each test (default: 100)" )
3541-            | Opt( setShardCount, "shard count" )
3542-                ["--shard-count"]
3543-                ( "split the tests to execute into this many groups" )
3544-            | Opt( setShardIndex, "shard index" )
3545-                ["--shard-index"]
3546-                ( "index of the group of tests to execute (see --shard-count)" )
3547-            | Opt( config.allowZeroTests )
3548-                ["--allow-running-no-tests"]
3549-                ( "Treat 'No tests run' as a success" )
3550-            | Opt( config.prematureExitGuardFilePath, "path" )
3551-                ["--premature-exit-guard-file"]
3552-                ( "create a file before running tests and delete it during clean exit" )
3553-            | Arg( config.testsOrTags, "test name|pattern|tags" )
3554-                ( "which test or tests to use" );
3555-
3556-        return cli;
3557-    }
3558-
3559-} // end namespace Catch
3560-
3561-
3562-#if defined(__clang__)
3563-#    pragma clang diagnostic push
3564-#    pragma clang diagnostic ignored "-Wexit-time-destructors"
3565-#endif
3566-
3567-
3568-
3569-#include <cassert>
3570-#include <ostream>
3571-#include <utility>
3572-
3573-namespace Catch {
3574-
3575-    ColourImpl::~ColourImpl() = default;
3576-
3577-    ColourImpl::ColourGuard ColourImpl::guardColour( Colour::Code colourCode ) {
3578-        return ColourGuard(colourCode, this );
3579-    }
3580-
3581-    void ColourImpl::ColourGuard::engageImpl( std::ostream& stream ) {
3582-        assert( &stream == &m_colourImpl->m_stream->stream() &&
3583-                "Engaging colour guard for different stream than used by the "
3584-                "parent colour implementation" );
3585-        static_cast<void>( stream );
3586-
3587-        m_engaged = true;
3588-        m_colourImpl->use( m_code );
3589-    }
3590-
3591-    ColourImpl::ColourGuard::ColourGuard( Colour::Code code,
3592-                                          ColourImpl const* colour ):
3593-        m_colourImpl( colour ), m_code( code ) {
3594-    }
3595-    ColourImpl::ColourGuard::ColourGuard( ColourGuard&& rhs ) noexcept:
3596-        m_colourImpl( rhs.m_colourImpl ),
3597-        m_code( rhs.m_code ),
3598-        m_engaged( rhs.m_engaged ) {
3599-        rhs.m_engaged = false;
3600-    }
3601-    ColourImpl::ColourGuard&
3602-    ColourImpl::ColourGuard::operator=( ColourGuard&& rhs ) noexcept {
3603-        using std::swap;
3604-        swap( m_colourImpl, rhs.m_colourImpl );
3605-        swap( m_code, rhs.m_code );
3606-        swap( m_engaged, rhs.m_engaged );
3607-
3608-        return *this;
3609-    }
3610-    ColourImpl::ColourGuard::~ColourGuard() {
3611-        if ( m_engaged ) {
3612-            m_colourImpl->use( Colour::None );
3613-        }
3614-    }
3615-
3616-    ColourImpl::ColourGuard&
3617-    ColourImpl::ColourGuard::engage( std::ostream& stream ) & {
3618-        engageImpl( stream );
3619-        return *this;
3620-    }
3621-
3622-    ColourImpl::ColourGuard&&
3623-    ColourImpl::ColourGuard::engage( std::ostream& stream ) && {
3624-        engageImpl( stream );
3625-        return CATCH_MOVE(*this);
3626-    }
3627-
3628-    namespace {
3629-        //! A do-nothing implementation of colour, used as fallback for unknown
3630-        //! platforms, and when the user asks to deactivate all colours.
3631-        class NoColourImpl final : public ColourImpl {
3632-        public:
3633-            NoColourImpl( IStream* stream ): ColourImpl( stream ) {}
3634-
3635-        private:
3636-            void use( Colour::Code ) const override {}
3637-        };
3638-    } // namespace
3639-
3640-
3641-} // namespace Catch
3642-
3643-
3644-#if defined ( CATCH_CONFIG_COLOUR_WIN32 ) /////////////////////////////////////////
3645-
3646-namespace Catch {
3647-namespace {
3648-
3649-    class Win32ColourImpl final : public ColourImpl {
3650-    public:
3651-        Win32ColourImpl(IStream* stream):
3652-            ColourImpl(stream) {
3653-            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
3654-            GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ),
3655-                                        &csbiInfo );
3656-            originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
3657-            originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
3658-        }
3659-
3660-        static bool useImplementationForStream(IStream const& stream) {
3661-            // Win32 text colour APIs can only be used on console streams
3662-            // We cannot check that the output hasn't been redirected,
3663-            // so we just check that the original stream is console stream.
3664-            return stream.isConsole();
3665-        }
3666-
3667-    private:
3668-        void use( Colour::Code _colourCode ) const override {
3669-            switch( _colourCode ) {
3670-                case Colour::None:      return setTextAttribute( originalForegroundAttributes );
3671-                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
3672-                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );
3673-                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );
3674-                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );
3675-                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
3676-                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
3677-                case Colour::Grey:      return setTextAttribute( 0 );
3678-
3679-                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );
3680-                case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
3681-                case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
3682-                case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
3683-                case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
3684-
3685-                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
3686-
3687-                default:
3688-                    CATCH_ERROR( "Unknown colour requested" );
3689-            }
3690-        }
3691-
3692-        void setTextAttribute( WORD _textAttribute ) const {
3693-            SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ),
3694-                                     _textAttribute |
3695-                                         originalBackgroundAttributes );
3696-        }
3697-        WORD originalForegroundAttributes;
3698-        WORD originalBackgroundAttributes;
3699-    };
3700-
3701-} // end anon namespace
3702-} // end namespace Catch
3703-
3704-#endif // Windows/ ANSI/ None
3705-
3706-
3707-#if defined( CATCH_PLATFORM_LINUX ) \
3708- || defined( CATCH_PLATFORM_MAC ) \
3709- || defined( __GLIBC__ ) \
3710- || defined( __FreeBSD__ ) \
3711- || defined( CATCH_PLATFORM_QNX )
3712-#    define CATCH_INTERNAL_HAS_ISATTY
3713-#    include <unistd.h>
3714-#endif
3715-
3716-namespace Catch {
3717-namespace {
3718-
3719-    class ANSIColourImpl final : public ColourImpl {
3720-    public:
3721-        ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {}
3722-
3723-        static bool useImplementationForStream(IStream const& stream) {
3724-            // This is kinda messy due to trying to support a bunch of
3725-            // different platforms at once.
3726-            // The basic idea is that if we are asked to do autodetection (as
3727-            // opposed to being told to use posixy colours outright), then we
3728-            // only want to use the colours if we are writing to console.
3729-            // However, console might be redirected, so we make an attempt at
3730-            // checking for that on platforms where we know how to do that.
3731-            bool useColour = stream.isConsole();
3732-#if defined( CATCH_INTERNAL_HAS_ISATTY ) && \
3733-    !( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) )
3734-            ErrnoGuard _; // for isatty
3735-            useColour = useColour && isatty( STDOUT_FILENO );
3736-#    endif
3737-#    if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE )
3738-            useColour = useColour && !isDebuggerActive();
3739-#    endif
3740-
3741-            return useColour;
3742-        }
3743-
3744-    private:
3745-        void use( Colour::Code _colourCode ) const override {
3746-            auto setColour = [&out =
3747-                                  m_stream->stream()]( char const* escapeCode ) {
3748-                // The escape sequence must be flushed to console, otherwise
3749-                // if stdin and stderr are intermixed, we'd get accidentally
3750-                // coloured output.
3751-                out << '\033' << escapeCode << std::flush;
3752-            };
3753-            switch( _colourCode ) {
3754-                case Colour::None:
3755-                case Colour::White:     return setColour( "[0m" );
3756-                case Colour::Red:       return setColour( "[0;31m" );
3757-                case Colour::Green:     return setColour( "[0;32m" );
3758-                case Colour::Blue:      return setColour( "[0;34m" );
3759-                case Colour::Cyan:      return setColour( "[0;36m" );
3760-                case Colour::Yellow:    return setColour( "[0;33m" );
3761-                case Colour::Grey:      return setColour( "[1;30m" );
3762-
3763-                case Colour::LightGrey:     return setColour( "[0;37m" );
3764-                case Colour::BrightRed:     return setColour( "[1;31m" );
3765-                case Colour::BrightGreen:   return setColour( "[1;32m" );
3766-                case Colour::BrightWhite:   return setColour( "[1;37m" );
3767-                case Colour::BrightYellow:  return setColour( "[1;33m" );
3768-
3769-                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
3770-                default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
3771-            }
3772-        }
3773-    };
3774-
3775-} // end anon namespace
3776-} // end namespace Catch
3777-
3778-namespace Catch {
3779-
3780-    Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
3781-                                                   IStream* stream ) {
3782-#if defined( CATCH_CONFIG_COLOUR_WIN32 )
3783-        if ( colourSelection == ColourMode::Win32 ) {
3784-            return Detail::make_unique<Win32ColourImpl>( stream );
3785-        }
3786-#endif
3787-        if ( colourSelection == ColourMode::ANSI ) {
3788-            return Detail::make_unique<ANSIColourImpl>( stream );
3789-        }
3790-        if ( colourSelection == ColourMode::None ) {
3791-            return Detail::make_unique<NoColourImpl>( stream );
3792-        }
3793-
3794-        if ( colourSelection == ColourMode::PlatformDefault) {
3795-#if defined( CATCH_CONFIG_COLOUR_WIN32 )
3796-            if ( Win32ColourImpl::useImplementationForStream( *stream ) ) {
3797-                return Detail::make_unique<Win32ColourImpl>( stream );
3798-            }
3799-#endif
3800-            if ( ANSIColourImpl::useImplementationForStream( *stream ) ) {
3801-                return Detail::make_unique<ANSIColourImpl>( stream );
3802-            }
3803-            return Detail::make_unique<NoColourImpl>( stream );
3804-        }
3805-
3806-        CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(colourSelection) );
3807-    }
3808-
3809-    bool isColourImplAvailable( ColourMode colourSelection ) {
3810-        switch ( colourSelection ) {
3811-#if defined( CATCH_CONFIG_COLOUR_WIN32 )
3812-        case ColourMode::Win32:
3813-#endif
3814-        case ColourMode::ANSI:
3815-        case ColourMode::None:
3816-        case ColourMode::PlatformDefault:
3817-            return true;
3818-        default:
3819-            return false;
3820-        }
3821-    }
3822-
3823-
3824-} // end namespace Catch
3825-
3826-#if defined(__clang__)
3827-#    pragma clang diagnostic pop
3828-#endif
3829-
3830-
3831-
3832-
3833-namespace Catch {
3834-
3835-    Context Context::currentContext;
3836-
3837-    Context& getCurrentMutableContext() {
3838-        return Context::currentContext;
3839-    }
3840-
3841-    SimplePcg32& sharedRng() {
3842-        static SimplePcg32 s_rng;
3843-        return s_rng;
3844-    }
3845-
3846-}
3847-
3848-
3849-
3850-
3851-
3852-#include <ostream>
3853-
3854-#if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
3855-#include <android/log.h>
3856-
3857-    namespace Catch {
3858-        void writeToDebugConsole( std::string const& text ) {
3859-            __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
3860-        }
3861-    }
3862-
3863-#elif defined(CATCH_PLATFORM_WINDOWS)
3864-
3865-    namespace Catch {
3866-        void writeToDebugConsole( std::string const& text ) {
3867-            ::OutputDebugStringA( text.c_str() );
3868-        }
3869-    }
3870-
3871-#else
3872-
3873-    namespace Catch {
3874-        void writeToDebugConsole( std::string const& text ) {
3875-            // !TBD: Need a version for Mac/ XCode and other IDEs
3876-            Catch::cout() << text;
3877-        }
3878-    }
3879-
3880-#endif // Platform
3881-
3882-
3883-
3884-#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
3885-
3886-#  include <cassert>
3887-#  include <sys/types.h>
3888-#  include <unistd.h>
3889-#  include <cstddef>
3890-#  include <ostream>
3891-
3892-#ifdef __apple_build_version__
3893-    // These headers will only compile with AppleClang (XCode)
3894-    // For other compilers (Clang, GCC, ... ) we need to exclude them
3895-#  include <sys/sysctl.h>
3896-#endif
3897-
3898-    namespace Catch {
3899-        #ifdef __apple_build_version__
3900-        // The following function is taken directly from the following technical note:
3901-        // https://developer.apple.com/library/archive/qa/qa1361/_index.html
3902-
3903-        // Returns true if the current process is being debugged (either
3904-        // running under the debugger or has a debugger attached post facto).
3905-        bool isDebuggerActive(){
3906-            int                 mib[4];
3907-            struct kinfo_proc   info;
3908-            std::size_t         size;
3909-
3910-            // Initialize the flags so that, if sysctl fails for some bizarre
3911-            // reason, we get a predictable result.
3912-
3913-            info.kp_proc.p_flag = 0;
3914-
3915-            // Initialize mib, which tells sysctl the info we want, in this case
3916-            // we're looking for information about a specific process ID.
3917-
3918-            mib[0] = CTL_KERN;
3919-            mib[1] = KERN_PROC;
3920-            mib[2] = KERN_PROC_PID;
3921-            mib[3] = getpid();
3922-
3923-            // Call sysctl.
3924-
3925-            size = sizeof(info);
3926-            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
3927-                Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n\n" << std::flush;
3928-                return false;
3929-            }
3930-
3931-            // We're being debugged if the P_TRACED flag is set.
3932-
3933-            return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
3934-        }
3935-        #else
3936-        bool isDebuggerActive() {
3937-            // We need to find another way to determine this for non-appleclang compilers on macOS
3938-            return false;
3939-        }
3940-        #endif
3941-    } // namespace Catch
3942-
3943-#elif defined(CATCH_PLATFORM_LINUX) || defined(CATCH_PLATFORM_QNX)
3944-    #include <fstream>
3945-    #include <string>
3946-
3947-    namespace Catch{
3948-        // The standard POSIX way of detecting a debugger is to attempt to
3949-        // ptrace() the process, but this needs to be done from a child and not
3950-        // this process itself to still allow attaching to this process later
3951-        // if wanted, so is rather heavy. Under Linux we have the PID of the
3952-        // "debugger" (which doesn't need to be gdb, of course, it could also
3953-        // be strace, for example) in /proc/$PID/status, so just get it from
3954-        // there instead.
3955-        bool isDebuggerActive(){
3956-            // Libstdc++ has a bug, where std::ifstream sets errno to 0
3957-            // This way our users can properly assert over errno values
3958-            ErrnoGuard guard;
3959-            std::ifstream in("/proc/self/status");
3960-            for( std::string line; std::getline(in, line); ) {
3961-                static const int PREFIX_LEN = 11;
3962-                if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
3963-                    // We're traced if the PID is not 0 and no other PID starts
3964-                    // with 0 digit, so it's enough to check for just a single
3965-                    // character.
3966-                    return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
3967-                }
3968-            }
3969-
3970-            return false;
3971-        }
3972-    } // namespace Catch
3973-#elif defined(_MSC_VER)
3974-    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
3975-    namespace Catch {
3976-        bool isDebuggerActive() {
3977-            return IsDebuggerPresent() != 0;
3978-        }
3979-    }
3980-#elif defined(__MINGW32__)
3981-    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
3982-    namespace Catch {
3983-        bool isDebuggerActive() {
3984-            return IsDebuggerPresent() != 0;
3985-        }
3986-    }
3987-#else
3988-    namespace Catch {
3989-       bool isDebuggerActive() { return false; }
3990-    }
3991-#endif // Platform
3992-
3993-
3994-
3995-
3996-namespace Catch {
3997-
3998-    void ITransientExpression::streamReconstructedExpression(
3999-        std::ostream& os ) const {
4000-        // We can't make this function pure virtual to keep ITransientExpression
4001-        // constexpr, so we write error message instead
4002-        os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression";
4003-    }
4004-
4005-    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
4006-        if( lhs.size() + rhs.size() < 40 &&
4007-                lhs.find('\n') == std::string::npos &&
4008-                rhs.find('\n') == std::string::npos )
4009-            os << lhs << ' ' << op << ' ' << rhs;
4010-        else
4011-            os << lhs << '\n' << op << '\n' << rhs;
4012-    }
4013-}
4014-
4015-
4016-
4017-#include <stdexcept>
4018-
4019-
4020-namespace Catch {
4021-#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
4022-    [[noreturn]]
4023-    void throw_exception(std::exception const& e) {
4024-        Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
4025-                      << "The message was: " << e.what() << '\n';
4026-        std::terminate();
4027-    }
4028-#endif
4029-
4030-    [[noreturn]]
4031-    void throw_logic_error(std::string const& msg) {
4032-        throw_exception(std::logic_error(msg));
4033-    }
4034-
4035-    [[noreturn]]
4036-    void throw_domain_error(std::string const& msg) {
4037-        throw_exception(std::domain_error(msg));
4038-    }
4039-
4040-    [[noreturn]]
4041-    void throw_runtime_error(std::string const& msg) {
4042-        throw_exception(std::runtime_error(msg));
4043-    }
4044-
4045-
4046-
4047-} // namespace Catch;
4048-
4049-
4050-
4051-#include <cassert>
4052-
4053-namespace Catch {
4054-
4055-    IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() = default;
4056-
4057-    namespace Detail {
4058-
4059-        namespace {
4060-            // Extracts the actual name part of an enum instance
4061-            // In other words, it returns the Blue part of Bikeshed::Colour::Blue
4062-            StringRef extractInstanceName(StringRef enumInstance) {
4063-                // Find last occurrence of ":"
4064-                size_t name_start = enumInstance.size();
4065-                while (name_start > 0 && enumInstance[name_start - 1] != ':') {
4066-                    --name_start;
4067-                }
4068-                return enumInstance.substr(name_start, enumInstance.size() - name_start);
4069-            }
4070-        }
4071-
4072-        std::vector<StringRef> parseEnums( StringRef enums ) {
4073-            auto enumValues = splitStringRef( enums, ',' );
4074-            std::vector<StringRef> parsed;
4075-            parsed.reserve( enumValues.size() );
4076-            for( auto const& enumValue : enumValues ) {
4077-                parsed.push_back(trim(extractInstanceName(enumValue)));
4078-            }
4079-            return parsed;
4080-        }
4081-
4082-        EnumInfo::~EnumInfo() = default;
4083-
4084-        StringRef EnumInfo::lookup( int value ) const {
4085-            for( auto const& valueToName : m_values ) {
4086-                if( valueToName.first == value )
4087-                    return valueToName.second;
4088-            }
4089-            return "{** unexpected enum value **}"_sr;
4090-        }
4091-
4092-        Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
4093-            auto enumInfo = Catch::Detail::make_unique<EnumInfo>();
4094-            enumInfo->m_name = enumName;
4095-            enumInfo->m_values.reserve( values.size() );
4096-
4097-            const auto valueNames = Catch::Detail::parseEnums( allValueNames );
4098-            assert( valueNames.size() == values.size() );
4099-            std::size_t i = 0;
4100-            for( auto value : values )
4101-                enumInfo->m_values.emplace_back(value, valueNames[i++]);
4102-
4103-            return enumInfo;
4104-        }
4105-
4106-        EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
4107-            m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
4108-            return *m_enumInfos.back();
4109-        }
4110-
4111-    } // Detail
4112-} // Catch
4113-
4114-
4115-
4116-
4117-
4118-#include <cerrno>
4119-
4120-namespace Catch {
4121-        ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
4122-        ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
4123-}
4124-
4125-
4126-
4127-#include <exception>
4128-
4129-namespace Catch {
4130-
4131-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
4132-    namespace {
4133-        static std::string tryTranslators(
4134-            std::vector<
4135-                Detail::unique_ptr<IExceptionTranslator const>> const& translators ) {
4136-            if ( translators.empty() ) {
4137-                std::rethrow_exception( std::current_exception() );
4138-            } else {
4139-                return translators[0]->translate( translators.begin() + 1,
4140-                                                  translators.end() );
4141-            }
4142-        }
4143-
4144-    }
4145-#endif //!defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
4146-
4147-    ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() = default;
4148-
4149-    void ExceptionTranslatorRegistry::registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) {
4150-        m_translators.push_back( CATCH_MOVE( translator ) );
4151-    }
4152-
4153-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
4154-    std::string ExceptionTranslatorRegistry::translateActiveException() const {
4155-        // Compiling a mixed mode project with MSVC means that CLR
4156-        // exceptions will be caught in (...) as well. However, these do
4157-        // do not fill-in std::current_exception and thus lead to crash
4158-        // when attempting rethrow.
4159-        // /EHa switch also causes structured exceptions to be caught
4160-        // here, but they fill-in current_exception properly, so
4161-        // at worst the output should be a little weird, instead of
4162-        // causing a crash.
4163-        if ( std::current_exception() == nullptr ) {
4164-            return "Non C++ exception. Possibly a CLR exception.";
4165-        }
4166-
4167-        // First we try user-registered translators. If none of them can
4168-        // handle the exception, it will be rethrown handled by our defaults.
4169-        try {
4170-            return tryTranslators(m_translators);
4171-        }
4172-        // To avoid having to handle TFE explicitly everywhere, we just
4173-        // rethrow it so that it goes back up the caller.
4174-        catch( TestFailureException& ) {
4175-            return "{ nested assertion failed }";
4176-        }
4177-        catch( TestSkipException& ) {
4178-            return "{ nested SKIP() called }";
4179-        }
4180-        catch( std::exception const& ex ) {
4181-            return ex.what();
4182-        }
4183-        catch( std::string const& msg ) {
4184-            return msg;
4185-        }
4186-        catch( const char* msg ) {
4187-            return msg;
4188-        }
4189-        catch(...) {
4190-            return "Unknown exception";
4191-        }
4192-    }
4193-
4194-#else // ^^ Exceptions are enabled // Exceptions are disabled vv
4195-    std::string ExceptionTranslatorRegistry::translateActiveException() const {
4196-        CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
4197-    }
4198-#endif
4199-
4200-}
4201-
4202-
4203-
4204-/** \file
4205- * This file provides platform specific implementations of FatalConditionHandler
4206- *
4207- * This means that there is a lot of conditional compilation, and platform
4208- * specific code. Currently, Catch2 supports a dummy handler (if no
4209- * handler is desired), and 2 platform specific handlers:
4210- *  * Windows' SEH
4211- *  * POSIX signals
4212- *
4213- * Consequently, various pieces of code below are compiled if either of
4214- * the platform specific handlers is enabled, or if none of them are
4215- * enabled. It is assumed that both cannot be enabled at the same time,
4216- * and doing so should cause a compilation error.
4217- *
4218- * If another platform specific handler is added, the compile guards
4219- * below will need to be updated taking these assumptions into account.
4220- */
4221-
4222-
4223-
4224-#include <algorithm>
4225-
4226-#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
4227-
4228-namespace Catch {
4229-
4230-    // If neither SEH nor signal handling is required, the handler impls
4231-    // do not have to do anything, and can be empty.
4232-    void FatalConditionHandler::engage_platform() {}
4233-    void FatalConditionHandler::disengage_platform() noexcept {}
4234-    FatalConditionHandler::FatalConditionHandler() = default;
4235-    FatalConditionHandler::~FatalConditionHandler() = default;
4236-
4237-} // end namespace Catch
4238-
4239-#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
4240-
4241-#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
4242-#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
4243-#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
4244-
4245-#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
4246-
4247-namespace {
4248-    //! Signals fatal error message to the run context
4249-    void reportFatal( char const * const message ) {
4250-        Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
4251-    }
4252-
4253-    //! Minimal size Catch2 needs for its own fatal error handling.
4254-    //! Picked empirically, so it might not be sufficient on all
4255-    //! platforms, and for all configurations.
4256-    constexpr std::size_t minStackSizeForErrors = 32 * 1024;
4257-} // end unnamed namespace
4258-
4259-#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
4260-
4261-#if defined( CATCH_CONFIG_WINDOWS_SEH )
4262-
4263-namespace Catch {
4264-
4265-    struct SignalDefs { DWORD id; const char* name; };
4266-
4267-    // There is no 1-1 mapping between signals and windows exceptions.
4268-    // Windows can easily distinguish between SO and SigSegV,
4269-    // but SigInt, SigTerm, etc are handled differently.
4270-    static constexpr SignalDefs signalDefs[] = {
4271-        { EXCEPTION_ILLEGAL_INSTRUCTION,  "SIGILL - Illegal instruction signal" },
4272-        { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
4273-        { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
4274-        { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
4275-    };
4276-
4277-    // Since we do not support multiple instantiations, we put these
4278-    // into global variables and rely on cleaning them up in outlined
4279-    // constructors/destructors
4280-    static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr;
4281-
4282-
4283-    static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
4284-        for (auto const& def : signalDefs) {
4285-            if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
4286-                reportFatal(def.name);
4287-            }
4288-        }
4289-        // If a filter was previously registered, invoke it
4290-        if (previousTopLevelExceptionFilter) {
4291-            return previousTopLevelExceptionFilter(ExceptionInfo);
4292-        }
4293-        // Otherwise, pass along all exceptions.
4294-        // This stops us from eating debugger breaks etc.
4295-        return EXCEPTION_CONTINUE_SEARCH;
4296-    }
4297-
4298-    // For MSVC, we reserve part of the stack memory for handling
4299-    // memory overflow structured exception.
4300-    FatalConditionHandler::FatalConditionHandler() {
4301-        ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
4302-        if (!SetThreadStackGuarantee(&guaranteeSize)) {
4303-            // We do not want to fully error out, because needing
4304-            // the stack reserve should be rare enough anyway.
4305-            Catch::cerr()
4306-                << "Failed to reserve piece of stack."
4307-                << " Stack overflows will not be reported successfully.";
4308-        }
4309-    }
4310-
4311-    // We do not attempt to unset the stack guarantee, because
4312-    // Windows does not support lowering the stack size guarantee.
4313-    FatalConditionHandler::~FatalConditionHandler() = default;
4314-
4315-
4316-    void FatalConditionHandler::engage_platform() {
4317-        // Register as a the top level exception filter.
4318-        previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
4319-    }
4320-
4321-    void FatalConditionHandler::disengage_platform() noexcept {
4322-        if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) {
4323-            Catch::cerr()
4324-                << "Unexpected SEH unhandled exception filter on disengage."
4325-                << " The filter was restored, but might be rolled back unexpectedly.";
4326-        }
4327-        previousTopLevelExceptionFilter = nullptr;
4328-    }
4329-
4330-} // end namespace Catch
4331-
4332-#endif // CATCH_CONFIG_WINDOWS_SEH
4333-
4334-#if defined( CATCH_CONFIG_POSIX_SIGNALS )
4335-
4336-#include <signal.h>
4337-
4338-namespace Catch {
4339-
4340-    struct SignalDefs {
4341-        int id;
4342-        const char* name;
4343-    };
4344-
4345-    static constexpr SignalDefs signalDefs[] = {
4346-        { SIGINT,  "SIGINT - Terminal interrupt signal" },
4347-        { SIGILL,  "SIGILL - Illegal instruction signal" },
4348-        { SIGFPE,  "SIGFPE - Floating point error signal" },
4349-        { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
4350-        { SIGTERM, "SIGTERM - Termination request signal" },
4351-        { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
4352-    };
4353-
4354-// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
4355-// which is zero initialization, but not explicit. We want to avoid
4356-// that.
4357-#if defined(__GNUC__)
4358-#    pragma GCC diagnostic push
4359-#    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4360-#endif
4361-
4362-    static char* altStackMem = nullptr;
4363-    static std::size_t altStackSize = 0;
4364-    static stack_t oldSigStack{};
4365-    static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
4366-
4367-    static void restorePreviousSignalHandlers() noexcept {
4368-        // We set signal handlers back to the previous ones. Hopefully
4369-        // nobody overwrote them in the meantime, and doesn't expect
4370-        // their signal handlers to live past ours given that they
4371-        // installed them after ours..
4372-        for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
4373-            sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
4374-        }
4375-        // Return the old stack
4376-        sigaltstack(&oldSigStack, nullptr);
4377-    }
4378-
4379-    static void handleSignal( int sig ) {
4380-        char const * name = "<unknown signal>";
4381-        for (auto const& def : signalDefs) {
4382-            if (sig == def.id) {
4383-                name = def.name;
4384-                break;
4385-            }
4386-        }
4387-        // We need to restore previous signal handlers and let them do
4388-        // their thing, so that the users can have the debugger break
4389-        // when a signal is raised, and so on.
4390-        restorePreviousSignalHandlers();
4391-        reportFatal( name );
4392-        raise( sig );
4393-    }
4394-
4395-    FatalConditionHandler::FatalConditionHandler() {
4396-        assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
4397-        if (altStackSize == 0) {
4398-            altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
4399-        }
4400-        altStackMem = new char[altStackSize]();
4401-    }
4402-
4403-    FatalConditionHandler::~FatalConditionHandler() {
4404-        delete[] altStackMem;
4405-        // We signal that another instance can be constructed by zeroing
4406-        // out the pointer.
4407-        altStackMem = nullptr;
4408-    }
4409-
4410-    void FatalConditionHandler::engage_platform() {
4411-        stack_t sigStack;
4412-        sigStack.ss_sp = altStackMem;
4413-        sigStack.ss_size = altStackSize;
4414-        sigStack.ss_flags = 0;
4415-        sigaltstack(&sigStack, &oldSigStack);
4416-        struct sigaction sa = { };
4417-
4418-        sa.sa_handler = handleSignal;
4419-        sa.sa_flags = SA_ONSTACK;
4420-        for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
4421-            sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
4422-        }
4423-    }
4424-
4425-#if defined(__GNUC__)
4426-#    pragma GCC diagnostic pop
4427-#endif
4428-
4429-
4430-    void FatalConditionHandler::disengage_platform() noexcept {
4431-        restorePreviousSignalHandlers();
4432-    }
4433-
4434-} // end namespace Catch
4435-
4436-#endif // CATCH_CONFIG_POSIX_SIGNALS
4437-
4438-
4439-
4440-
4441-#include <cstring>
4442-
4443-namespace Catch {
4444-    namespace Detail {
4445-
4446-        uint32_t convertToBits(float f) {
4447-            static_assert(sizeof(float) == sizeof(uint32_t), "Important ULP matcher assumption violated");
4448-            uint32_t i;
4449-            std::memcpy(&i, &f, sizeof(f));
4450-            return i;
4451-        }
4452-
4453-        uint64_t convertToBits(double d) {
4454-            static_assert(sizeof(double) == sizeof(uint64_t), "Important ULP matcher assumption violated");
4455-            uint64_t i;
4456-            std::memcpy(&i, &d, sizeof(d));
4457-            return i;
4458-        }
4459-
4460-#if defined( __GNUC__ ) || defined( __clang__ )
4461-#    pragma GCC diagnostic push
4462-#    pragma GCC diagnostic ignored "-Wfloat-equal"
4463-#endif
4464-        bool directCompare( float lhs, float rhs ) { return lhs == rhs; }
4465-        bool directCompare( double lhs, double rhs ) { return lhs == rhs; }
4466-#if defined( __GNUC__ ) || defined( __clang__ )
4467-#    pragma GCC diagnostic pop
4468-#endif
4469-
4470-
4471-    } // end namespace Detail
4472-} // end namespace Catch
4473-
4474-
4475-
4476-
4477-
4478-
4479-#include <cstdlib>
4480-
4481-namespace Catch {
4482-    namespace Detail {
4483-
4484-#if !defined (CATCH_CONFIG_GETENV)
4485-        char const* getEnv( char const* ) { return nullptr; }
4486-#else
4487-
4488-        char const* getEnv( char const* varName ) {
4489-#    if defined( _MSC_VER )
4490-#        pragma warning( push )
4491-#        pragma warning( disable : 4996 ) // use getenv_s instead of getenv
4492-#    endif
4493-
4494-            return std::getenv( varName );
4495-
4496-#    if defined( _MSC_VER )
4497-#        pragma warning( pop )
4498-#    endif
4499-        }
4500-#endif
4501-} // namespace Detail
4502-} // namespace Catch
4503-
4504-
4505-
4506-
4507-#include <cstdio>
4508-#include <fstream>
4509-
4510-namespace Catch {
4511-
4512-    Catch::IStream::~IStream() = default;
4513-
4514-namespace Detail {
4515-    namespace {
4516-        template<typename WriterF, std::size_t bufferSize=256>
4517-        class StreamBufImpl final : public std::streambuf {
4518-            char data[bufferSize];
4519-            WriterF m_writer;
4520-
4521-        public:
4522-            StreamBufImpl() {
4523-                setp( data, data + sizeof(data) );
4524-            }
4525-
4526-            ~StreamBufImpl() noexcept override {
4527-                StreamBufImpl::sync();
4528-            }
4529-
4530-        private:
4531-            int overflow( int c ) override {
4532-                sync();
4533-
4534-                if( c != EOF ) {
4535-                    if( pbase() == epptr() )
4536-                        m_writer( std::string( 1, static_cast<char>( c ) ) );
4537-                    else
4538-                        sputc( static_cast<char>( c ) );
4539-                }
4540-                return 0;
4541-            }
4542-
4543-            int sync() override {
4544-                if( pbase() != pptr() ) {
4545-                    m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
4546-                    setp( pbase(), epptr() );
4547-                }
4548-                return 0;
4549-            }
4550-        };
4551-
4552-        ///////////////////////////////////////////////////////////////////////////
4553-
4554-        struct OutputDebugWriter {
4555-
4556-            void operator()( std::string const& str ) {
4557-                if ( !str.empty() ) {
4558-                    writeToDebugConsole( str );
4559-                }
4560-            }
4561-        };
4562-
4563-        ///////////////////////////////////////////////////////////////////////////
4564-
4565-        class FileStream final : public IStream {
4566-            std::ofstream m_ofs;
4567-        public:
4568-            FileStream( std::string const& filename ) {
4569-                m_ofs.open( filename.c_str() );
4570-                CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' );
4571-                m_ofs << std::unitbuf;
4572-            }
4573-        public: // IStream
4574-            std::ostream& stream() override {
4575-                return m_ofs;
4576-            }
4577-        };
4578-
4579-        ///////////////////////////////////////////////////////////////////////////
4580-
4581-        class CoutStream final : public IStream {
4582-            std::ostream m_os;
4583-        public:
4584-            // Store the streambuf from cout up-front because
4585-            // cout may get redirected when running tests
4586-            CoutStream() : m_os( Catch::cout().rdbuf() ) {}
4587-
4588-        public: // IStream
4589-            std::ostream& stream() override { return m_os; }
4590-            bool isConsole() const override { return true; }
4591-        };
4592-
4593-        class CerrStream : public IStream {
4594-            std::ostream m_os;
4595-
4596-        public:
4597-            // Store the streambuf from cerr up-front because
4598-            // cout may get redirected when running tests
4599-            CerrStream(): m_os( Catch::cerr().rdbuf() ) {}
4600-
4601-        public: // IStream
4602-            std::ostream& stream() override { return m_os; }
4603-            bool isConsole() const override { return true; }
4604-        };
4605-
4606-        ///////////////////////////////////////////////////////////////////////////
4607-
4608-        class DebugOutStream final : public IStream {
4609-            Detail::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
4610-            std::ostream m_os;
4611-        public:
4612-            DebugOutStream()
4613-            :   m_streamBuf( Detail::make_unique<StreamBufImpl<OutputDebugWriter>>() ),
4614-                m_os( m_streamBuf.get() )
4615-            {}
4616-
4617-        public: // IStream
4618-            std::ostream& stream() override { return m_os; }
4619-        };
4620-
4621-    } // unnamed namespace
4622-} // namespace Detail
4623-
4624-    ///////////////////////////////////////////////////////////////////////////
4625-
4626-    auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream> {
4627-        if ( filename.empty() || filename == "-" ) {
4628-            return Detail::make_unique<Detail::CoutStream>();
4629-        }
4630-        if( filename[0] == '%' ) {
4631-            if ( filename == "%debug" ) {
4632-                return Detail::make_unique<Detail::DebugOutStream>();
4633-            } else if ( filename == "%stderr" ) {
4634-                return Detail::make_unique<Detail::CerrStream>();
4635-            } else if ( filename == "%stdout" ) {
4636-                return Detail::make_unique<Detail::CoutStream>();
4637-            } else {
4638-                CATCH_ERROR( "Unrecognised stream: '" << filename << '\'' );
4639-            }
4640-        }
4641-        return Detail::make_unique<Detail::FileStream>( filename );
4642-    }
4643-
4644-}
4645-
4646-
4647-
4648-namespace Catch {
4649-
4650-    namespace {
4651-        static bool needsEscape( char c ) {
4652-            return c == '"' || c == '\\' || c == '\b' || c == '\f' ||
4653-                   c == '\n' || c == '\r' || c == '\t';
4654-        }
4655-
4656-        static Catch::StringRef makeEscapeStringRef( char c ) {
4657-            if ( c == '"' ) {
4658-                return "\\\""_sr;
4659-            } else if ( c == '\\' ) {
4660-                return "\\\\"_sr;
4661-            } else if ( c == '\b' ) {
4662-                return "\\b"_sr;
4663-            } else if ( c == '\f' ) {
4664-                return "\\f"_sr;
4665-            } else if ( c == '\n' ) {
4666-                return "\\n"_sr;
4667-            } else if ( c == '\r' ) {
4668-                return "\\r"_sr;
4669-            } else if ( c == '\t' ) {
4670-                return "\\t"_sr;
4671-            }
4672-            Catch::Detail::Unreachable();
4673-        }
4674-    } // namespace
4675-
4676-    void JsonUtils::indent( std::ostream& os, std::uint64_t level ) {
4677-        for ( std::uint64_t i = 0; i < level; ++i ) {
4678-            os << "  ";
4679-        }
4680-    }
4681-    void JsonUtils::appendCommaNewline( std::ostream& os,
4682-                                        bool& should_comma,
4683-                                        std::uint64_t level ) {
4684-        if ( should_comma ) { os << ','; }
4685-        should_comma = true;
4686-        os << '\n';
4687-        indent( os, level );
4688-    }
4689-
4690-    JsonObjectWriter::JsonObjectWriter( std::ostream& os ):
4691-        JsonObjectWriter{ os, 0 } {}
4692-
4693-    JsonObjectWriter::JsonObjectWriter( std::ostream& os,
4694-                                        std::uint64_t indent_level ):
4695-        m_os{ os }, m_indent_level{ indent_level } {
4696-        m_os << '{';
4697-    }
4698-    JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ) noexcept:
4699-        m_os{ source.m_os },
4700-        m_indent_level{ source.m_indent_level },
4701-        m_should_comma{ source.m_should_comma },
4702-        m_active{ source.m_active } {
4703-        source.m_active = false;
4704-    }
4705-
4706-    JsonObjectWriter::~JsonObjectWriter() {
4707-        if ( !m_active ) { return; }
4708-
4709-        m_os << '\n';
4710-        JsonUtils::indent( m_os, m_indent_level );
4711-        m_os << '}';
4712-    }
4713-
4714-    JsonValueWriter JsonObjectWriter::write( StringRef key ) {
4715-        JsonUtils::appendCommaNewline(
4716-            m_os, m_should_comma, m_indent_level + 1 );
4717-
4718-        m_os << '"' << key << "\": ";
4719-        return JsonValueWriter{ m_os, m_indent_level + 1 };
4720-    }
4721-
4722-    JsonArrayWriter::JsonArrayWriter( std::ostream& os ):
4723-        JsonArrayWriter{ os, 0 } {}
4724-    JsonArrayWriter::JsonArrayWriter( std::ostream& os,
4725-                                      std::uint64_t indent_level ):
4726-        m_os{ os }, m_indent_level{ indent_level } {
4727-        m_os << '[';
4728-    }
4729-    JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ) noexcept:
4730-        m_os{ source.m_os },
4731-        m_indent_level{ source.m_indent_level },
4732-        m_should_comma{ source.m_should_comma },
4733-        m_active{ source.m_active } {
4734-        source.m_active = false;
4735-    }
4736-    JsonArrayWriter::~JsonArrayWriter() {
4737-        if ( !m_active ) { return; }
4738-
4739-        m_os << '\n';
4740-        JsonUtils::indent( m_os, m_indent_level );
4741-        m_os << ']';
4742-    }
4743-
4744-    JsonObjectWriter JsonArrayWriter::writeObject() {
4745-        JsonUtils::appendCommaNewline(
4746-            m_os, m_should_comma, m_indent_level + 1 );
4747-        return JsonObjectWriter{ m_os, m_indent_level + 1 };
4748-    }
4749-
4750-    JsonArrayWriter JsonArrayWriter::writeArray() {
4751-        JsonUtils::appendCommaNewline(
4752-            m_os, m_should_comma, m_indent_level + 1 );
4753-        return JsonArrayWriter{ m_os, m_indent_level + 1 };
4754-    }
4755-
4756-    JsonArrayWriter& JsonArrayWriter::write( bool value ) {
4757-        return writeImpl( value );
4758-    }
4759-
4760-    JsonValueWriter::JsonValueWriter( std::ostream& os ):
4761-        JsonValueWriter{ os, 0 } {}
4762-
4763-    JsonValueWriter::JsonValueWriter( std::ostream& os,
4764-                                      std::uint64_t indent_level ):
4765-        m_os{ os }, m_indent_level{ indent_level } {}
4766-
4767-    JsonObjectWriter JsonValueWriter::writeObject() && {
4768-        return JsonObjectWriter{ m_os, m_indent_level };
4769-    }
4770-
4771-    JsonArrayWriter JsonValueWriter::writeArray() && {
4772-        return JsonArrayWriter{ m_os, m_indent_level };
4773-    }
4774-
4775-    void JsonValueWriter::write( Catch::StringRef value ) && {
4776-        writeImpl( value, true );
4777-    }
4778-
4779-    void JsonValueWriter::write( bool value ) && {
4780-        writeImpl( value ? "true"_sr : "false"_sr, false );
4781-    }
4782-
4783-    void JsonValueWriter::writeImpl( Catch::StringRef value, bool quote ) {
4784-        if ( quote ) { m_os << '"'; }
4785-        size_t current_start = 0;
4786-        for ( size_t i = 0; i < value.size(); ++i ) {
4787-            if ( needsEscape( value[i] ) ) {
4788-                if ( current_start < i ) {
4789-                    m_os << value.substr( current_start, i - current_start );
4790-                }
4791-                m_os << makeEscapeStringRef( value[i] );
4792-                current_start = i + 1;
4793-            }
4794-        }
4795-        if ( current_start < value.size() ) {
4796-            m_os << value.substr( current_start, value.size() - current_start );
4797-        }
4798-        if ( quote ) { m_os << '"'; }
4799-    }
4800-
4801-} // namespace Catch
4802-
4803-
4804-
4805-
4806-namespace Catch {
4807-
4808-    auto operator << (std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream& {
4809-        if (lazyExpr.m_isNegated)
4810-            os << '!';
4811-
4812-        if (lazyExpr) {
4813-            if (lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression())
4814-                os << '(' << *lazyExpr.m_transientExpression << ')';
4815-            else
4816-                os << *lazyExpr.m_transientExpression;
4817-        } else {
4818-            os << "{** error - unchecked empty expression requested **}";
4819-        }
4820-        return os;
4821-    }
4822-
4823-} // namespace Catch
4824-
4825-
4826-
4827-
4828-#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
4829-#include <crtdbg.h>
4830-
4831-namespace Catch {
4832-
4833-    LeakDetector::LeakDetector() {
4834-        int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
4835-        flag |= _CRTDBG_LEAK_CHECK_DF;
4836-        flag |= _CRTDBG_ALLOC_MEM_DF;
4837-        _CrtSetDbgFlag(flag);
4838-        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
4839-        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
4840-        // Change this to leaking allocation's number to break there
4841-        _CrtSetBreakAlloc(-1);
4842-    }
4843-}
4844-
4845-#else // ^^ Windows crt debug heap enabled // Windows crt debug heap disabled vv
4846-
4847-    Catch::LeakDetector::LeakDetector() = default;
4848-
4849-#endif // CATCH_CONFIG_WINDOWS_CRTDBG
4850-
4851-Catch::LeakDetector::~LeakDetector() {
4852-    Catch::cleanUp();
4853-}
4854-
4855-
4856-
4857-
4858-namespace Catch {
4859-    namespace {
4860-
4861-        void listTests(IEventListener& reporter, IConfig const& config) {
4862-            auto const& testSpec = config.testSpec();
4863-            auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
4864-            reporter.listTests(matchedTestCases);
4865-        }
4866-
4867-        void listTags(IEventListener& reporter, IConfig const& config) {
4868-            auto const& testSpec = config.testSpec();
4869-            std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
4870-
4871-            std::map<StringRef, TagInfo, Detail::CaseInsensitiveLess> tagCounts;
4872-            for (auto const& testCase : matchedTestCases) {
4873-                for (auto const& tagName : testCase.getTestCaseInfo().tags) {
4874-                    auto it = tagCounts.find(tagName.original);
4875-                    if (it == tagCounts.end())
4876-                        it = tagCounts.insert(std::make_pair(tagName.original, TagInfo())).first;
4877-                    it->second.add(tagName.original);
4878-                }
4879-            }
4880-
4881-            std::vector<TagInfo> infos; infos.reserve(tagCounts.size());
4882-            for (auto& tagc : tagCounts) {
4883-                infos.push_back(CATCH_MOVE(tagc.second));
4884-            }
4885-
4886-            reporter.listTags(infos);
4887-        }
4888-
4889-        void listReporters(IEventListener& reporter) {
4890-            std::vector<ReporterDescription> descriptions;
4891-
4892-            auto const& factories = getRegistryHub().getReporterRegistry().getFactories();
4893-            descriptions.reserve(factories.size());
4894-            for (auto const& fac : factories) {
4895-                descriptions.push_back({ fac.first, fac.second->getDescription() });
4896-            }
4897-
4898-            reporter.listReporters(descriptions);
4899-        }
4900-
4901-        void listListeners(IEventListener& reporter) {
4902-            std::vector<ListenerDescription> descriptions;
4903-
4904-            auto const& factories =
4905-                getRegistryHub().getReporterRegistry().getListeners();
4906-            descriptions.reserve( factories.size() );
4907-            for ( auto const& fac : factories ) {
4908-                descriptions.push_back( { fac->getName(), fac->getDescription() } );
4909-            }
4910-
4911-            reporter.listListeners( descriptions );
4912-        }
4913-
4914-    } // end anonymous namespace
4915-
4916-    void TagInfo::add( StringRef spelling ) {
4917-        ++count;
4918-        spellings.insert( spelling );
4919-    }
4920-
4921-    std::string TagInfo::all() const {
4922-        // 2 per tag for brackets '[' and ']'
4923-        size_t size =  spellings.size() * 2;
4924-        for (auto const& spelling : spellings) {
4925-            size += spelling.size();
4926-        }
4927-
4928-        std::string out; out.reserve(size);
4929-        for (auto const& spelling : spellings) {
4930-            out += '[';
4931-            out += spelling;
4932-            out += ']';
4933-        }
4934-        return out;
4935-    }
4936-
4937-    bool list( IEventListener& reporter, Config const& config ) {
4938-        bool listed = false;
4939-        if (config.listTests()) {
4940-            listed = true;
4941-            listTests(reporter, config);
4942-        }
4943-        if (config.listTags()) {
4944-            listed = true;
4945-            listTags(reporter, config);
4946-        }
4947-        if (config.listReporters()) {
4948-            listed = true;
4949-            listReporters(reporter);
4950-        }
4951-        if ( config.listListeners() ) {
4952-            listed = true;
4953-            listListeners( reporter );
4954-        }
4955-        return listed;
4956-    }
4957-
4958-} // end namespace Catch
4959-
4960-
4961-
4962-namespace Catch {
4963-    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
4964-    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
4965-    static const LeakDetector leakDetector;
4966-    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
4967-}
4968-
4969-// Allow users of amalgamated .cpp file to remove our main and provide their own.
4970-#if !defined(CATCH_AMALGAMATED_CUSTOM_MAIN)
4971-
4972-#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
4973-// Standard C/C++ Win32 Unicode wmain entry point
4974-extern "C" int __cdecl wmain (int argc, wchar_t * argv[], wchar_t * []) {
4975-#else
4976-// Standard C/C++ main entry point
4977-int main (int argc, char * argv[]) {
4978-#endif
4979-
4980-    // We want to force the linker not to discard the global variable
4981-    // and its constructor, as it (optionally) registers leak detector
4982-    (void)&Catch::leakDetector;
4983-
4984-    return Catch::Session().run( argc, argv );
4985-}
4986-
4987-#endif // !defined(CATCH_AMALGAMATED_CUSTOM_MAIN
4988-
4989-
4990-
4991-
4992-namespace Catch {
4993-
4994-    MessageInfo::MessageInfo( StringRef _macroName,
4995-                              SourceLineInfo const& _lineInfo,
4996-                              ResultWas::OfType _type )
4997-    :   macroName( _macroName ),
4998-        lineInfo( _lineInfo ),
4999-        type( _type ),
5000-        sequence( ++globalCount )
5001-    {}
5002-
5003-    // Messages are owned by their individual threads, so the counter should be thread-local as well.
5004-    // Alternative consideration: atomic, so threads don't share IDs and things are easier to debug.
5005-    thread_local unsigned int MessageInfo::globalCount = 0;
5006-
5007-} // end namespace Catch
5008-
5009-
5010-
5011-#include <cstdio>
5012-#include <cstring>
5013-#include <iosfwd>
5014-#include <sstream>
5015-
5016-#if defined( CATCH_CONFIG_NEW_CAPTURE )
5017-#    if defined( _MSC_VER )
5018-#        include <io.h> //_dup and _dup2
5019-#        define dup _dup
5020-#        define dup2 _dup2
5021-#        define fileno _fileno
5022-#    else
5023-#        include <unistd.h> // dup and dup2
5024-#    endif
5025-#endif
5026-
5027-namespace Catch {
5028-
5029-    namespace {
5030-        //! A no-op implementation, used if no reporter wants output
5031-        //! redirection.
5032-        class NoopRedirect : public OutputRedirect {
5033-            void activateImpl() override {}
5034-            void deactivateImpl() override {}
5035-            std::string getStdout() override { return {}; }
5036-            std::string getStderr() override { return {}; }
5037-            void clearBuffers() override {}
5038-        };
5039-
5040-        /**
5041-         * Redirects specific stream's rdbuf with another's.
5042-         *
5043-         * Redirection can be stopped and started on-demand, assumes
5044-         * that the underlying stream's rdbuf aren't changed by other
5045-         * users.
5046-         */
5047-        class RedirectedStreamNew {
5048-            std::ostream& m_originalStream;
5049-            std::ostream& m_redirectionStream;
5050-            std::streambuf* m_prevBuf;
5051-
5052-        public:
5053-            RedirectedStreamNew( std::ostream& originalStream,
5054-                                 std::ostream& redirectionStream ):
5055-                m_originalStream( originalStream ),
5056-                m_redirectionStream( redirectionStream ),
5057-                m_prevBuf( m_originalStream.rdbuf() ) {}
5058-
5059-            void startRedirect() {
5060-                m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
5061-            }
5062-            void stopRedirect() { m_originalStream.rdbuf( m_prevBuf ); }
5063-        };
5064-
5065-        /**
5066-         * Redirects the `std::cout`, `std::cerr`, `std::clog` streams,
5067-         * but does not touch the actual `stdout`/`stderr` file descriptors.
5068-         */
5069-        class StreamRedirect : public OutputRedirect {
5070-            ReusableStringStream m_redirectedOut, m_redirectedErr;
5071-            RedirectedStreamNew m_cout, m_cerr, m_clog;
5072-
5073-        public:
5074-            StreamRedirect():
5075-                m_cout( Catch::cout(), m_redirectedOut.get() ),
5076-                m_cerr( Catch::cerr(), m_redirectedErr.get() ),
5077-                m_clog( Catch::clog(), m_redirectedErr.get() ) {}
5078-
5079-            void activateImpl() override {
5080-                m_cout.startRedirect();
5081-                m_cerr.startRedirect();
5082-                m_clog.startRedirect();
5083-            }
5084-            void deactivateImpl() override {
5085-                m_cout.stopRedirect();
5086-                m_cerr.stopRedirect();
5087-                m_clog.stopRedirect();
5088-            }
5089-            std::string getStdout() override { return m_redirectedOut.str(); }
5090-            std::string getStderr() override { return m_redirectedErr.str(); }
5091-            void clearBuffers() override {
5092-                m_redirectedOut.str( "" );
5093-                m_redirectedErr.str( "" );
5094-            }
5095-        };
5096-
5097-#if defined( CATCH_CONFIG_NEW_CAPTURE )
5098-
5099-        // Windows's implementation of std::tmpfile is terrible (it tries
5100-        // to create a file inside system folder, thus requiring elevated
5101-        // privileges for the binary), so we have to use tmpnam(_s) and
5102-        // create the file ourselves there.
5103-        class TempFile {
5104-        public:
5105-            TempFile( TempFile const& ) = delete;
5106-            TempFile& operator=( TempFile const& ) = delete;
5107-            TempFile( TempFile&& ) = delete;
5108-            TempFile& operator=( TempFile&& ) = delete;
5109-
5110-#    if defined( _MSC_VER )
5111-            TempFile() {
5112-                if ( tmpnam_s( m_buffer ) ) {
5113-                    CATCH_RUNTIME_ERROR( "Could not get a temp filename" );
5114-                }
5115-                if ( fopen_s( &m_file, m_buffer, "wb+" ) ) {
5116-                    char buffer[100];
5117-                    if ( strerror_s( buffer, errno ) ) {
5118-                        CATCH_RUNTIME_ERROR(
5119-                            "Could not translate errno to a string" );
5120-                    }
5121-                    CATCH_RUNTIME_ERROR( "Could not open the temp file: '"
5122-                                         << m_buffer
5123-                                         << "' because: " << buffer );
5124-                }
5125-            }
5126-#    else
5127-            TempFile() {
5128-                m_file = std::tmpfile();
5129-                if ( !m_file ) {
5130-                    CATCH_RUNTIME_ERROR( "Could not create a temp file." );
5131-                }
5132-            }
5133-#    endif
5134-
5135-            ~TempFile() {
5136-                // TBD: What to do about errors here?
5137-                std::fclose( m_file );
5138-                // We manually create the file on Windows only, on Linux
5139-                // it will be autodeleted
5140-#    if defined( _MSC_VER )
5141-                std::remove( m_buffer );
5142-#    endif
5143-            }
5144-
5145-            std::FILE* getFile() { return m_file; }
5146-            std::string getContents() {
5147-                ReusableStringStream sstr;
5148-                constexpr long buffer_size = 100;
5149-                char buffer[buffer_size + 1] = {};
5150-                long current_pos = ftell( m_file );
5151-                CATCH_ENFORCE( current_pos >= 0,
5152-                               "ftell failed, errno: " << errno );
5153-                std::rewind( m_file );
5154-                while ( current_pos > 0 ) {
5155-                    auto read_characters =
5156-                        std::fread( buffer,
5157-                                    1,
5158-                                    std::min( buffer_size, current_pos ),
5159-                                    m_file );
5160-                    buffer[read_characters] = '\0';
5161-                    sstr << buffer;
5162-                    current_pos -= static_cast<long>( read_characters );
5163-                }
5164-                return sstr.str();
5165-            }
5166-
5167-            void clear() { std::rewind( m_file ); }
5168-
5169-        private:
5170-            std::FILE* m_file = nullptr;
5171-            char m_buffer[L_tmpnam] = { 0 };
5172-        };
5173-
5174-        /**
5175-         * Redirects the actual `stdout`/`stderr` file descriptors.
5176-         *
5177-         * Works by replacing the file descriptors numbered 1 and 2
5178-         * with an open temporary file.
5179-         */
5180-        class FileRedirect : public OutputRedirect {
5181-            TempFile m_outFile, m_errFile;
5182-            int m_originalOut = -1;
5183-            int m_originalErr = -1;
5184-
5185-            // Flushes cout/cerr/clog streams and stdout/stderr FDs
5186-            void flushEverything() {
5187-                Catch::cout() << std::flush;
5188-                fflush( stdout );
5189-                // Since we support overriding these streams, we flush cerr
5190-                // even though std::cerr is unbuffered
5191-                Catch::cerr() << std::flush;
5192-                Catch::clog() << std::flush;
5193-                fflush( stderr );
5194-            }
5195-
5196-        public:
5197-            FileRedirect():
5198-                m_originalOut( dup( fileno( stdout ) ) ),
5199-                m_originalErr( dup( fileno( stderr ) ) ) {
5200-                CATCH_ENFORCE( m_originalOut >= 0, "Could not dup stdout" );
5201-                CATCH_ENFORCE( m_originalErr >= 0, "Could not dup stderr" );
5202-            }
5203-
5204-            std::string getStdout() override { return m_outFile.getContents(); }
5205-            std::string getStderr() override { return m_errFile.getContents(); }
5206-            void clearBuffers() override {
5207-                m_outFile.clear();
5208-                m_errFile.clear();
5209-            }
5210-
5211-            void activateImpl() override {
5212-                // We flush before starting redirect, to ensure that we do
5213-                // not capture the end of message sent before activation.
5214-                flushEverything();
5215-
5216-                int ret;
5217-                ret = dup2( fileno( m_outFile.getFile() ), fileno( stdout ) );
5218-                CATCH_ENFORCE( ret >= 0,
5219-                               "dup2 to stdout has failed, errno: " << errno );
5220-                ret = dup2( fileno( m_errFile.getFile() ), fileno( stderr ) );
5221-                CATCH_ENFORCE( ret >= 0,
5222-                               "dup2 to stderr has failed, errno: " << errno );
5223-            }
5224-            void deactivateImpl() override {
5225-                // We flush before ending redirect, to ensure that we
5226-                // capture all messages sent while the redirect was active.
5227-                flushEverything();
5228-
5229-                int ret;
5230-                ret = dup2( m_originalOut, fileno( stdout ) );
5231-                CATCH_ENFORCE(
5232-                    ret >= 0,
5233-                    "dup2 of original stdout has failed, errno: " << errno );
5234-                ret = dup2( m_originalErr, fileno( stderr ) );
5235-                CATCH_ENFORCE(
5236-                    ret >= 0,
5237-                    "dup2 of original stderr has failed, errno: " << errno );
5238-            }
5239-        };
5240-
5241-#endif // CATCH_CONFIG_NEW_CAPTURE
5242-
5243-    } // end namespace
5244-
5245-    bool isRedirectAvailable( OutputRedirect::Kind kind ) {
5246-        switch ( kind ) {
5247-        // These two are always available
5248-        case OutputRedirect::None:
5249-        case OutputRedirect::Streams:
5250-            return true;
5251-#if defined( CATCH_CONFIG_NEW_CAPTURE )
5252-        case OutputRedirect::FileDescriptors:
5253-            return true;
5254-#endif
5255-        default:
5256-            return false;
5257-        }
5258-    }
5259-
5260-    Detail::unique_ptr<OutputRedirect> makeOutputRedirect( bool actual ) {
5261-        if ( actual ) {
5262-            // TODO: Clean this up later
5263-#if defined( CATCH_CONFIG_NEW_CAPTURE )
5264-            return Detail::make_unique<FileRedirect>();
5265-#else
5266-            return Detail::make_unique<StreamRedirect>();
5267-#endif
5268-        } else {
5269-            return Detail::make_unique<NoopRedirect>();
5270-        }
5271-    }
5272-
5273-    RedirectGuard scopedActivate( OutputRedirect& redirectImpl ) {
5274-        return RedirectGuard( true, redirectImpl );
5275-    }
5276-
5277-    RedirectGuard scopedDeactivate( OutputRedirect& redirectImpl ) {
5278-        return RedirectGuard( false, redirectImpl );
5279-    }
5280-
5281-    OutputRedirect::~OutputRedirect() = default;
5282-
5283-    RedirectGuard::RedirectGuard( bool activate, OutputRedirect& redirectImpl ):
5284-        m_redirect( &redirectImpl ),
5285-        m_activate( activate ),
5286-        m_previouslyActive( redirectImpl.isActive() ) {
5287-
5288-        // Skip cases where there is no actual state change.
5289-        if ( m_activate == m_previouslyActive ) { return; }
5290-
5291-        if ( m_activate ) {
5292-            m_redirect->activate();
5293-        } else {
5294-            m_redirect->deactivate();
5295-        }
5296-    }
5297-
5298-    RedirectGuard::~RedirectGuard() noexcept( false ) {
5299-        if ( m_moved ) { return; }
5300-        // Skip cases where there is no actual state change.
5301-        if ( m_activate == m_previouslyActive ) { return; }
5302-
5303-        if ( m_activate ) {
5304-            m_redirect->deactivate();
5305-        } else {
5306-            m_redirect->activate();
5307-        }
5308-    }
5309-
5310-    RedirectGuard::RedirectGuard( RedirectGuard&& rhs ) noexcept:
5311-        m_redirect( rhs.m_redirect ),
5312-        m_activate( rhs.m_activate ),
5313-        m_previouslyActive( rhs.m_previouslyActive ),
5314-        m_moved( false ) {
5315-        rhs.m_moved = true;
5316-    }
5317-
5318-    RedirectGuard& RedirectGuard::operator=( RedirectGuard&& rhs ) noexcept {
5319-        m_redirect = rhs.m_redirect;
5320-        m_activate = rhs.m_activate;
5321-        m_previouslyActive = rhs.m_previouslyActive;
5322-        m_moved = false;
5323-        rhs.m_moved = true;
5324-        return *this;
5325-    }
5326-
5327-} // namespace Catch
5328-
5329-#if defined( CATCH_CONFIG_NEW_CAPTURE )
5330-#    if defined( _MSC_VER )
5331-#        undef dup
5332-#        undef dup2
5333-#        undef fileno
5334-#    endif
5335-#endif
5336-
5337-
5338-
5339-
5340-#include <limits>
5341-#include <stdexcept>
5342-
5343-namespace Catch {
5344-
5345-    Optional<unsigned int> parseUInt(std::string const& input, int base) {
5346-        auto trimmed = trim( input );
5347-        // std::stoull is annoying and accepts numbers starting with '-',
5348-        // it just negates them into unsigned int
5349-        if ( trimmed.empty() || trimmed[0] == '-' ) {
5350-            return {};
5351-        }
5352-
5353-        CATCH_TRY {
5354-            size_t pos = 0;
5355-            const auto ret = std::stoull( trimmed, &pos, base );
5356-
5357-            // We did not consume the whole input, so there is an issue
5358-            // This can be bunch of different stuff, like multiple numbers
5359-            // in the input, or invalid digits/characters and so on. Either
5360-            // way, we do not want to return the partially parsed result.
5361-            if ( pos != trimmed.size() ) {
5362-                return {};
5363-            }
5364-            // Too large
5365-            if ( ret > std::numeric_limits<unsigned int>::max() ) {
5366-                return {};
5367-            }
5368-            return static_cast<unsigned int>(ret);
5369-        }
5370-        CATCH_CATCH_ANON( std::invalid_argument const& ) {
5371-            // no conversion could be performed
5372-        }
5373-        CATCH_CATCH_ANON( std::out_of_range const& ) {
5374-            // the input does not fit into an unsigned long long
5375-        }
5376-        return {};
5377-    }
5378-
5379-} // namespace Catch
5380-
5381-
5382-
5383-
5384-#include <cmath>
5385-
5386-namespace Catch {
5387-
5388-#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
5389-    bool isnan(float f) {
5390-        return std::isnan(f);
5391-    }
5392-    bool isnan(double d) {
5393-        return std::isnan(d);
5394-    }
5395-#else
5396-    // For now we only use this for embarcadero
5397-    bool isnan(float f) {
5398-        return std::_isnan(f);
5399-    }
5400-    bool isnan(double d) {
5401-        return std::_isnan(d);
5402-    }
5403-#endif
5404-
5405-#if !defined( CATCH_CONFIG_GLOBAL_NEXTAFTER )
5406-    float nextafter( float x, float y ) { return std::nextafter( x, y ); }
5407-    double nextafter( double x, double y ) { return std::nextafter( x, y ); }
5408-#else
5409-    float nextafter( float x, float y ) { return ::nextafterf( x, y ); }
5410-    double nextafter( double x, double y ) { return ::nextafter( x, y ); }
5411-#endif
5412-
5413-} // end namespace Catch
5414-
5415-
5416-
5417-#if defined( __clang__ )
5418-#    define CATCH2_CLANG_NO_SANITIZE_INTEGER \
5419-        __attribute__( ( no_sanitize( "unsigned-integer-overflow" ) ) )
5420-#else
5421-#    define CATCH2_CLANG_NO_SANITIZE_INTEGER
5422-#endif
5423-namespace Catch {
5424-
5425-namespace {
5426-
5427-#if defined(_MSC_VER)
5428-#pragma warning(push)
5429-#pragma warning(disable:4146) // we negate uint32 during the rotate
5430-#endif
5431-        // Safe rotr implementation thanks to John Regehr
5432-        CATCH2_CLANG_NO_SANITIZE_INTEGER
5433-        uint32_t rotate_right(uint32_t val, uint32_t count) {
5434-            const uint32_t mask = 31;
5435-            count &= mask;
5436-            return (val >> count) | (val << (-count & mask));
5437-        }
5438-
5439-#if defined(_MSC_VER)
5440-#pragma warning(pop)
5441-#endif
5442-
5443-}
5444-
5445-
5446-    SimplePcg32::SimplePcg32(result_type seed_) {
5447-        seed(seed_);
5448-    }
5449-
5450-
5451-    void SimplePcg32::seed(result_type seed_) {
5452-        m_state = 0;
5453-        (*this)();
5454-        m_state += seed_;
5455-        (*this)();
5456-    }
5457-
5458-    void SimplePcg32::discard(uint64_t skip) {
5459-        // We could implement this to run in O(log n) steps, but this
5460-        // should suffice for our use case.
5461-        for (uint64_t s = 0; s < skip; ++s) {
5462-            static_cast<void>((*this)());
5463-        }
5464-    }
5465-
5466-    CATCH2_CLANG_NO_SANITIZE_INTEGER
5467-    SimplePcg32::result_type SimplePcg32::operator()() {
5468-        // prepare the output value
5469-        const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
5470-        const auto output = rotate_right(xorshifted, static_cast<uint32_t>(m_state >> 59u));
5471-
5472-        // advance state
5473-        m_state = m_state * 6364136223846793005ULL + s_inc;
5474-
5475-        return output;
5476-    }
5477-
5478-    bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
5479-        return lhs.m_state == rhs.m_state;
5480-    }
5481-
5482-    bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
5483-        return lhs.m_state != rhs.m_state;
5484-    }
5485-}
5486-
5487-
5488-
5489-
5490-
5491-#include <ctime>
5492-#include <random>
5493-
5494-namespace Catch {
5495-
5496-    std::uint32_t generateRandomSeed( GenerateFrom from ) {
5497-        switch ( from ) {
5498-        case GenerateFrom::Time:
5499-            return static_cast<std::uint32_t>( std::time( nullptr ) );
5500-
5501-        case GenerateFrom::Default:
5502-        case GenerateFrom::RandomDevice: {
5503-            std::random_device rd;
5504-            return Detail::fillBitsFrom<std::uint32_t>( rd );
5505-        }
5506-
5507-        default:
5508-            CATCH_ERROR("Unknown generation method");
5509-        }
5510-    }
5511-
5512-} // end namespace Catch
5513-
5514-
5515-
5516-
5517-namespace Catch {
5518-    struct ReporterRegistry::ReporterRegistryImpl {
5519-        std::vector<Detail::unique_ptr<EventListenerFactory>> listeners;
5520-        std::map<std::string, IReporterFactoryPtr, Detail::CaseInsensitiveLess>
5521-            factories;
5522-    };
5523-
5524-    ReporterRegistry::ReporterRegistry():
5525-        m_impl( Detail::make_unique<ReporterRegistryImpl>() ) {
5526-        // Because it is impossible to move out of initializer list,
5527-        // we have to add the elements manually
5528-        m_impl->factories["Automake"] =
5529-            Detail::make_unique<ReporterFactory<AutomakeReporter>>();
5530-        m_impl->factories["compact"] =
5531-            Detail::make_unique<ReporterFactory<CompactReporter>>();
5532-        m_impl->factories["console"] =
5533-            Detail::make_unique<ReporterFactory<ConsoleReporter>>();
5534-        m_impl->factories["JUnit"] =
5535-            Detail::make_unique<ReporterFactory<JunitReporter>>();
5536-        m_impl->factories["SonarQube"] =
5537-            Detail::make_unique<ReporterFactory<SonarQubeReporter>>();
5538-        m_impl->factories["TAP"] =
5539-            Detail::make_unique<ReporterFactory<TAPReporter>>();
5540-        m_impl->factories["TeamCity"] =
5541-            Detail::make_unique<ReporterFactory<TeamCityReporter>>();
5542-        m_impl->factories["XML"] =
5543-            Detail::make_unique<ReporterFactory<XmlReporter>>();
5544-        m_impl->factories["JSON"] =
5545-            Detail::make_unique<ReporterFactory<JsonReporter>>();
5546-    }
5547-
5548-    ReporterRegistry::~ReporterRegistry() = default;
5549-
5550-    IEventListenerPtr
5551-    ReporterRegistry::create( std::string const& name,
5552-                              ReporterConfig&& config ) const {
5553-        auto it = m_impl->factories.find( name );
5554-        if ( it == m_impl->factories.end() ) return nullptr;
5555-        return it->second->create( CATCH_MOVE( config ) );
5556-    }
5557-
5558-    void ReporterRegistry::registerReporter( std::string const& name,
5559-                                             IReporterFactoryPtr factory ) {
5560-        CATCH_ENFORCE( name.find( "::" ) == name.npos,
5561-                       "'::' is not allowed in reporter name: '" + name +
5562-                           '\'' );
5563-        auto ret = m_impl->factories.emplace( name, CATCH_MOVE( factory ) );
5564-        CATCH_ENFORCE( ret.second,
5565-                       "reporter using '" + name +
5566-                           "' as name was already registered" );
5567-    }
5568-    void ReporterRegistry::registerListener(
5569-        Detail::unique_ptr<EventListenerFactory> factory ) {
5570-        m_impl->listeners.push_back( CATCH_MOVE( factory ) );
5571-    }
5572-
5573-    std::map<std::string,
5574-             IReporterFactoryPtr,
5575-             Detail::CaseInsensitiveLess> const&
5576-    ReporterRegistry::getFactories() const {
5577-        return m_impl->factories;
5578-    }
5579-
5580-    std::vector<Detail::unique_ptr<EventListenerFactory>> const&
5581-    ReporterRegistry::getListeners() const {
5582-        return m_impl->listeners;
5583-    }
5584-} // namespace Catch
5585-
5586-
5587-
5588-
5589-
5590-#include <algorithm>
5591-
5592-namespace Catch {
5593-
5594-    namespace {
5595-        struct kvPair {
5596-            StringRef key, value;
5597-        };
5598-
5599-        kvPair splitKVPair(StringRef kvString) {
5600-            auto splitPos = static_cast<size_t>(
5601-                std::find( kvString.begin(), kvString.end(), '=' ) -
5602-                kvString.begin() );
5603-
5604-            return { kvString.substr( 0, splitPos ),
5605-                     kvString.substr( splitPos + 1, kvString.size() ) };
5606-        }
5607-    }
5608-
5609-    namespace Detail {
5610-        std::vector<std::string> splitReporterSpec( StringRef reporterSpec ) {
5611-            static constexpr auto separator = "::";
5612-            static constexpr size_t separatorSize = 2;
5613-
5614-            size_t separatorPos = 0;
5615-            auto findNextSeparator = [&reporterSpec]( size_t startPos ) {
5616-                static_assert(
5617-                    separatorSize == 2,
5618-                    "The code below currently assumes 2 char separator" );
5619-
5620-                auto currentPos = startPos;
5621-                do {
5622-                    while ( currentPos < reporterSpec.size() &&
5623-                            reporterSpec[currentPos] != separator[0] ) {
5624-                        ++currentPos;
5625-                    }
5626-                    if ( currentPos + 1 < reporterSpec.size() &&
5627-                         reporterSpec[currentPos + 1] == separator[1] ) {
5628-                        return currentPos;
5629-                    }
5630-                    ++currentPos;
5631-                } while ( currentPos < reporterSpec.size() );
5632-
5633-                return static_cast<size_t>( -1 );
5634-            };
5635-
5636-            std::vector<std::string> parts;
5637-
5638-            while ( separatorPos < reporterSpec.size() ) {
5639-                const auto nextSeparator = findNextSeparator( separatorPos );
5640-                parts.push_back( static_cast<std::string>( reporterSpec.substr(
5641-                    separatorPos, nextSeparator - separatorPos ) ) );
5642-
5643-                if ( nextSeparator == static_cast<size_t>( -1 ) ) {
5644-                    break;
5645-                }
5646-                separatorPos = nextSeparator + separatorSize;
5647-            }
5648-
5649-            // Handle a separator at the end.
5650-            // This is not a valid spec, but we want to do validation in a
5651-            // centralized place
5652-            if ( separatorPos == reporterSpec.size() ) {
5653-                parts.emplace_back();
5654-            }
5655-
5656-            return parts;
5657-        }
5658-
5659-        Optional<ColourMode> stringToColourMode( StringRef colourMode ) {
5660-            if ( colourMode == "default" ) {
5661-                return ColourMode::PlatformDefault;
5662-            } else if ( colourMode == "ansi" ) {
5663-                return ColourMode::ANSI;
5664-            } else if ( colourMode == "win32" ) {
5665-                return ColourMode::Win32;
5666-            } else if ( colourMode == "none" ) {
5667-                return ColourMode::None;
5668-            } else {
5669-                return {};
5670-            }
5671-        }
5672-    } // namespace Detail
5673-
5674-
5675-    bool operator==( ReporterSpec const& lhs, ReporterSpec const& rhs ) {
5676-        return lhs.m_name == rhs.m_name &&
5677-               lhs.m_outputFileName == rhs.m_outputFileName &&
5678-               lhs.m_colourMode == rhs.m_colourMode &&
5679-               lhs.m_customOptions == rhs.m_customOptions;
5680-    }
5681-
5682-    Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ) {
5683-        auto parts = Detail::splitReporterSpec( reporterSpec );
5684-
5685-        assert( parts.size() > 0 && "Split should never return empty vector" );
5686-
5687-        std::map<std::string, std::string> kvPairs;
5688-        Optional<std::string> outputFileName;
5689-        Optional<ColourMode> colourMode;
5690-
5691-        // First part is always reporter name, so we skip it
5692-        for ( size_t i = 1; i < parts.size(); ++i ) {
5693-            auto kv = splitKVPair( parts[i] );
5694-            auto key = kv.key, value = kv.value;
5695-
5696-            if ( key.empty() || value.empty() ) { // NOLINT(bugprone-branch-clone)
5697-                return {};
5698-            } else if ( key[0] == 'X' ) {
5699-                // This is a reporter-specific option, we don't check these
5700-                // apart from basic sanity checks
5701-                if ( key.size() == 1 ) {
5702-                    return {};
5703-                }
5704-
5705-                auto ret = kvPairs.emplace( std::string(kv.key), std::string(kv.value) );
5706-                if ( !ret.second ) {
5707-                    // Duplicated key. We might want to handle this differently,
5708-                    // e.g. by overwriting the existing value?
5709-                    return {};
5710-                }
5711-            } else if ( key == "out" ) {
5712-                // Duplicated key
5713-                if ( outputFileName ) {
5714-                    return {};
5715-                }
5716-                outputFileName = static_cast<std::string>( value );
5717-            } else if ( key == "colour-mode" ) {
5718-                // Duplicated key
5719-                if ( colourMode ) {
5720-                    return {};
5721-                }
5722-                colourMode = Detail::stringToColourMode( value );
5723-                // Parsing failed
5724-                if ( !colourMode ) {
5725-                    return {};
5726-                }
5727-            } else {
5728-                // Unrecognized option
5729-                return {};
5730-            }
5731-        }
5732-
5733-        return ReporterSpec{ CATCH_MOVE( parts[0] ),
5734-                             CATCH_MOVE( outputFileName ),
5735-                             CATCH_MOVE( colourMode ),
5736-                             CATCH_MOVE( kvPairs ) };
5737-    }
5738-
5739-ReporterSpec::ReporterSpec(
5740-        std::string name,
5741-        Optional<std::string> outputFileName,
5742-        Optional<ColourMode> colourMode,
5743-        std::map<std::string, std::string> customOptions ):
5744-        m_name( CATCH_MOVE( name ) ),
5745-        m_outputFileName( CATCH_MOVE( outputFileName ) ),
5746-        m_colourMode( CATCH_MOVE( colourMode ) ),
5747-        m_customOptions( CATCH_MOVE( customOptions ) ) {}
5748-
5749-} // namespace Catch
5750-
5751-
5752-
5753-#include <cstdio>
5754-#include <sstream>
5755-#include <tuple>
5756-#include <vector>
5757-
5758-namespace Catch {
5759-
5760-    // This class encapsulates the idea of a pool of ostringstreams that can be reused.
5761-    struct StringStreams {
5762-        std::vector<Detail::unique_ptr<std::ostringstream>> m_streams;
5763-        std::vector<std::size_t> m_unused;
5764-        std::ostringstream m_referenceStream; // Used for copy state/ flags from
5765-        Detail::Mutex m_mutex;
5766-
5767-        auto add() -> std::pair<std::size_t, std::ostringstream*> {
5768-            Detail::LockGuard _( m_mutex );
5769-            if( m_unused.empty() ) {
5770-                m_streams.push_back( Detail::make_unique<std::ostringstream>() );
5771-                return { m_streams.size()-1, m_streams.back().get() };
5772-            }
5773-            else {
5774-                auto index = m_unused.back();
5775-                m_unused.pop_back();
5776-                return { index, m_streams[index].get() };
5777-            }
5778-        }
5779-
5780-        void release( std::size_t index, std::ostream* originalPtr ) {
5781-            assert( originalPtr );
5782-            originalPtr->copyfmt( m_referenceStream );  // Restore initial flags and other state
5783-
5784-            Detail::LockGuard _( m_mutex );
5785-            assert( originalPtr == m_streams[index].get() && "Mismatch between release index and stream ptr" );
5786-            m_unused.push_back( index );
5787-        }
5788-    };
5789-
5790-    ReusableStringStream::ReusableStringStream() {
5791-        std::tie( m_index, m_oss ) =
5792-            Singleton<StringStreams>::getMutable().add();
5793-    }
5794-
5795-    ReusableStringStream::~ReusableStringStream() {
5796-        static_cast<std::ostringstream*>( m_oss )->str("");
5797-        m_oss->clear();
5798-        Singleton<StringStreams>::getMutable().release( m_index, m_oss );
5799-    }
5800-
5801-    std::string ReusableStringStream::str() const {
5802-        return static_cast<std::ostringstream*>( m_oss )->str();
5803-    }
5804-
5805-    void ReusableStringStream::str( std::string const& str ) {
5806-        static_cast<std::ostringstream*>( m_oss )->str( str );
5807-    }
5808-
5809-
5810-}
5811-
5812-
5813-
5814-
5815-#include <cassert>
5816-#include <algorithm>
5817-
5818-namespace Catch {
5819-
5820-    namespace Generators {
5821-        namespace {
5822-            struct GeneratorTracker final : TestCaseTracking::TrackerBase,
5823-                                      IGeneratorTracker {
5824-                GeneratorBasePtr m_generator;
5825-
5826-                GeneratorTracker(
5827-                    TestCaseTracking::NameAndLocation&& nameAndLocation,
5828-                    TrackerContext& ctx,
5829-                    ITracker* parent ):
5830-                    TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {}
5831-
5832-                static GeneratorTracker*
5833-                acquire( TrackerContext& ctx,
5834-                         TestCaseTracking::NameAndLocationRef const&
5835-                             nameAndLocation ) {
5836-                    GeneratorTracker* tracker;
5837-
5838-                    ITracker& currentTracker = ctx.currentTracker();
5839-                    // Under specific circumstances, the generator we want
5840-                    // to acquire is also the current tracker. If this is
5841-                    // the case, we have to avoid looking through current
5842-                    // tracker's children, and instead return the current
5843-                    // tracker.
5844-                    // A case where this check is important is e.g.
5845-                    //     for (int i = 0; i < 5; ++i) {
5846-                    //         int n = GENERATE(1, 2);
5847-                    //     }
5848-                    //
5849-                    // without it, the code above creates 5 nested generators.
5850-                    if ( currentTracker.nameAndLocation() == nameAndLocation ) {
5851-                        auto thisTracker = currentTracker.parent()->findChild(
5852-                            nameAndLocation );
5853-                        assert( thisTracker );
5854-                        assert( thisTracker->isGeneratorTracker() );
5855-                        tracker = static_cast<GeneratorTracker*>( thisTracker );
5856-                    } else if ( ITracker* childTracker =
5857-                                    currentTracker.findChild(
5858-                                        nameAndLocation ) ) {
5859-                        assert( childTracker );
5860-                        assert( childTracker->isGeneratorTracker() );
5861-                        tracker =
5862-                            static_cast<GeneratorTracker*>( childTracker );
5863-                    } else {
5864-                        return nullptr;
5865-                    }
5866-
5867-                    if ( !tracker->isComplete() ) { tracker->open(); }
5868-
5869-                    return tracker;
5870-                }
5871-
5872-                // TrackerBase interface
5873-                bool isGeneratorTracker() const override { return true; }
5874-                auto hasGenerator() const -> bool override {
5875-                    return !!m_generator;
5876-                }
5877-                void close() override {
5878-                    TrackerBase::close();
5879-                    // If a generator has a child (it is followed by a section)
5880-                    // and none of its children have started, then we must wait
5881-                    // until later to start consuming its values.
5882-                    // This catches cases where `GENERATE` is placed between two
5883-                    // `SECTION`s.
5884-                    // **The check for m_children.empty cannot be removed**.
5885-                    // doing so would break `GENERATE` _not_ followed by
5886-                    // `SECTION`s.
5887-                    const bool should_wait_for_child = [&]() {
5888-                        // No children -> nobody to wait for
5889-                        if ( m_children.empty() ) { return false; }
5890-                        // If at least one child started executing, don't wait
5891-                        if ( std::find_if(
5892-                                 m_children.begin(),
5893-                                 m_children.end(),
5894-                                 []( TestCaseTracking::ITrackerPtr const&
5895-                                         tracker ) {
5896-                                     return tracker->hasStarted();
5897-                                 } ) != m_children.end() ) {
5898-                            return false;
5899-                        }
5900-
5901-                        // No children have started. We need to check if they
5902-                        // _can_ start, and thus we should wait for them, or
5903-                        // they cannot start (due to filters), and we shouldn't
5904-                        // wait for them
5905-                        ITracker* parent = m_parent;
5906-                        // This is safe: there is always at least one section
5907-                        // tracker in a test case tracking tree
5908-                        while ( !parent->isSectionTracker() ) {
5909-                            parent = parent->parent();
5910-                        }
5911-                        assert( parent &&
5912-                                "Missing root (test case) level section" );
5913-
5914-                        auto const& parentSection =
5915-                            static_cast<SectionTracker const&>( *parent );
5916-                        auto const& filters = parentSection.getFilters();
5917-                        // No filters -> no restrictions on running sections
5918-                        if ( filters.empty() ) { return true; }
5919-
5920-                        for ( auto const& child : m_children ) {
5921-                            if ( child->isSectionTracker() &&
5922-                                 std::find( filters.begin(),
5923-                                            filters.end(),
5924-                                            static_cast<SectionTracker const&>(
5925-                                                *child )
5926-                                                .trimmedName() ) !=
5927-                                     filters.end() ) {
5928-                                return true;
5929-                            }
5930-                        }
5931-                        return false;
5932-                    }();
5933-
5934-                    // This check is a bit tricky, because m_generator->next()
5935-                    // has a side-effect, where it consumes generator's current
5936-                    // value, but we do not want to invoke the side-effect if
5937-                    // this generator is still waiting for any child to start.
5938-                    assert( m_generator && "Tracker without generator" );
5939-                    if ( should_wait_for_child ||
5940-                         ( m_runState == CompletedSuccessfully &&
5941-                           m_generator->countedNext() ) ) {
5942-                        m_children.clear();
5943-                        m_runState = Executing;
5944-                    }
5945-                }
5946-
5947-                // IGeneratorTracker interface
5948-                auto getGenerator() const -> GeneratorBasePtr const& override {
5949-                    return m_generator;
5950-                }
5951-                void setGenerator( GeneratorBasePtr&& generator ) override {
5952-                    m_generator = CATCH_MOVE( generator );
5953-                }
5954-            };
5955-        } // namespace
5956-    }
5957-
5958-    namespace Detail {
5959-        // Assertions are owned by the thread that is executing them.
5960-        // This allows for lock-free progress in common cases where we
5961-        // do not need to send the assertion events to the reporter.
5962-        // This also implies that messages are owned by their respective
5963-        // threads, and should not be shared across different threads.
5964-        //
5965-        // This implies that various pieces of metadata referring to last
5966-        // assertion result/source location/message handling, etc
5967-        // should also be thread local. For now we just use naked globals
5968-        // below, in the future we will want to allocate piece of memory
5969-        // from heap, to avoid consuming too much thread-local storage.
5970-
5971-        // This is used for the "if" part of CHECKED_IF/CHECKED_ELSE
5972-        static thread_local bool g_lastAssertionPassed = false;
5973-
5974-        // This is the source location for last encountered macro. It is
5975-        // used to provide the users with more precise location of error
5976-        // when an unexpected exception/fatal error happens.
5977-        static thread_local SourceLineInfo g_lastKnownLineInfo("DummyLocation", static_cast<size_t>(-1));
5978-
5979-        // Should we clear message scopes before sending off the messages to
5980-        // reporter? Set in `assertionPassedFastPath` to avoid doing the full
5981-        // clear there for performance reasons.
5982-        static thread_local bool g_clearMessageScopes = false;
5983-
5984-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
5985-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
5986-        // Actual messages to be provided to the reporter
5987-        static thread_local std::vector<MessageInfo> g_messages;
5988-
5989-        // Owners for the UNSCOPED_X information macro
5990-        static thread_local std::vector<ScopedMessage> g_messageScopes;
5991-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5992-
5993-    } // namespace Detail
5994-
5995-    RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter)
5996-    :   m_runInfo(_config->name()),
5997-        m_config(_config),
5998-        m_reporter(CATCH_MOVE(reporter)),
5999-        m_outputRedirect( makeOutputRedirect( m_reporter->getPreferences().shouldRedirectStdOut ) ),
6000-        m_abortAfterXFailedAssertions( m_config->abortAfter() ),
6001-        m_reportAssertionStarting( m_reporter->getPreferences().shouldReportAllAssertionStarts ),
6002-        m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ),
6003-        m_shouldDebugBreak( m_config->shouldDebugBreak() )
6004-    {
6005-        getCurrentMutableContext().setResultCapture( this );
6006-        m_reporter->testRunStarting(m_runInfo);
6007-    }
6008-
6009-    RunContext::~RunContext() {
6010-        updateTotalsFromAtomics();
6011-        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
6012-    }
6013-
6014-    Totals RunContext::runTest(TestCaseHandle const& testCase) {
6015-        updateTotalsFromAtomics();
6016-        const Totals prevTotals = m_totals;
6017-
6018-        auto const& testInfo = testCase.getTestCaseInfo();
6019-        m_reporter->testCaseStarting(testInfo);
6020-        testCase.prepareTestCase();
6021-        m_activeTestCase = &testCase;
6022-
6023-
6024-        ITracker& rootTracker = m_trackerContext.startRun();
6025-        assert(rootTracker.isSectionTracker());
6026-        static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
6027-
6028-        // We intentionally only seed the internal RNG once per test case,
6029-        // before it is first invoked. The reason for that is a complex
6030-        // interplay of generator/section implementation details and the
6031-        // Random*Generator types.
6032-        //
6033-        // The issue boils down to us needing to seed the Random*Generators
6034-        // with different seed each, so that they return different sequences
6035-        // of random numbers. We do this by giving them a number from the
6036-        // shared RNG instance as their seed.
6037-        //
6038-        // However, this runs into an issue if the reseeding happens each
6039-        // time the test case is entered (as opposed to first time only),
6040-        // because multiple generators could get the same seed, e.g. in
6041-        // ```cpp
6042-        // TEST_CASE() {
6043-        //     auto i = GENERATE(take(10, random(0, 100));
6044-        //     SECTION("A") {
6045-        //         auto j = GENERATE(take(10, random(0, 100));
6046-        //     }
6047-        //     SECTION("B") {
6048-        //         auto k = GENERATE(take(10, random(0, 100));
6049-        //     }
6050-        // }
6051-        // ```
6052-        // `i` and `j` would properly return values from different sequences,
6053-        // but `i` and `k` would return the same sequence, because their seed
6054-        // would be the same.
6055-        // (The reason their seeds would be the same is that the generator
6056-        //  for k would be initialized when the test case is entered the second
6057-        //  time, after the shared RNG instance was reset to the same value
6058-        //  it had when the generator for i was initialized.)
6059-        seedRng( *m_config );
6060-
6061-        uint64_t testRuns = 0;
6062-        std::string redirectedCout;
6063-        std::string redirectedCerr;
6064-        do {
6065-            m_trackerContext.startCycle();
6066-            m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo));
6067-
6068-            m_reporter->testCasePartialStarting(testInfo, testRuns);
6069-
6070-            updateTotalsFromAtomics();
6071-            const auto beforeRunTotals = m_totals;
6072-            runCurrentTest();
6073-            std::string oneRunCout = m_outputRedirect->getStdout();
6074-            std::string oneRunCerr = m_outputRedirect->getStderr();
6075-            m_outputRedirect->clearBuffers();
6076-            redirectedCout += oneRunCout;
6077-            redirectedCerr += oneRunCerr;
6078-
6079-            updateTotalsFromAtomics();
6080-            const auto singleRunTotals = m_totals.delta(beforeRunTotals);
6081-            auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
6082-            m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
6083-
6084-            ++testRuns;
6085-        } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
6086-
6087-        Totals deltaTotals = m_totals.delta(prevTotals);
6088-        if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
6089-            deltaTotals.assertions.failed++;
6090-            deltaTotals.testCases.passed--;
6091-            deltaTotals.testCases.failed++;
6092-        }
6093-        m_totals.testCases += deltaTotals.testCases;
6094-        testCase.tearDownTestCase();
6095-        m_reporter->testCaseEnded(TestCaseStats(testInfo,
6096-                                  deltaTotals,
6097-                                  CATCH_MOVE(redirectedCout),
6098-                                  CATCH_MOVE(redirectedCerr),
6099-                                  aborting()));
6100-
6101-        m_activeTestCase = nullptr;
6102-        m_testCaseTracker = nullptr;
6103-
6104-        return deltaTotals;
6105-    }
6106-
6107-
6108-    void RunContext::assertionEnded(AssertionResult&& result) {
6109-        Detail::g_lastKnownLineInfo = result.m_info.lineInfo;
6110-        if (result.getResultType() == ResultWas::Ok) {
6111-            m_atomicAssertionCount.passed++;
6112-            Detail::g_lastAssertionPassed = true;
6113-        } else if (result.getResultType() == ResultWas::ExplicitSkip) {
6114-            m_atomicAssertionCount.skipped++;
6115-            Detail::g_lastAssertionPassed = true;
6116-        } else if (!result.succeeded()) {
6117-            Detail::g_lastAssertionPassed = false;
6118-            if (result.isOk()) {
6119-            }
6120-            else if( m_activeTestCase->getTestCaseInfo().okToFail() ) // Read from a shared state established before the threads could start, this is fine
6121-                m_atomicAssertionCount.failedButOk++;
6122-            else
6123-                m_atomicAssertionCount.failed++;
6124-        }
6125-        else {
6126-            Detail::g_lastAssertionPassed = true;
6127-        }
6128-
6129-        if ( Detail::g_clearMessageScopes ) {
6130-            Detail::g_messageScopes.clear();
6131-            Detail::g_clearMessageScopes = false;
6132-        }
6133-
6134-        // From here, we are touching shared state and need mutex.
6135-        Detail::LockGuard lock( m_assertionMutex );
6136-        {
6137-            auto _ = scopedDeactivate( *m_outputRedirect );
6138-            updateTotalsFromAtomics();
6139-            m_reporter->assertionEnded( AssertionStats( result, Detail::g_messages, m_totals ) );
6140-        }
6141-
6142-        if ( result.getResultType() != ResultWas::Warning ) {
6143-            Detail::g_messageScopes.clear();
6144-        }
6145-
6146-        // Reset working state. assertion info will be reset after
6147-        // populateReaction is run if it is needed
6148-        m_lastResult = CATCH_MOVE( result );
6149-    }
6150-
6151-    void RunContext::notifyAssertionStarted( AssertionInfo const& info ) {
6152-        if (m_reportAssertionStarting) {
6153-            Detail::LockGuard lock( m_assertionMutex );
6154-            auto _ = scopedDeactivate( *m_outputRedirect );
6155-            m_reporter->assertionStarting( info );
6156-        }
6157-    }
6158-
6159-    bool RunContext::sectionStarted( StringRef sectionName,
6160-                                     SourceLineInfo const& sectionLineInfo,
6161-                                     Counts& assertions ) {
6162-        ITracker& sectionTracker =
6163-            SectionTracker::acquire( m_trackerContext,
6164-                                     TestCaseTracking::NameAndLocationRef(
6165-                                         sectionName, sectionLineInfo ) );
6166-
6167-        if (!sectionTracker.isOpen())
6168-            return false;
6169-        m_activeSections.push_back(&sectionTracker);
6170-
6171-        SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
6172-        Detail::g_lastKnownLineInfo = sectionLineInfo;
6173-
6174-        {
6175-            auto _ = scopedDeactivate( *m_outputRedirect );
6176-            m_reporter->sectionStarting( sectionInfo );
6177-        }
6178-
6179-        updateTotalsFromAtomics();
6180-        assertions = m_totals.assertions;
6181-
6182-        return true;
6183-    }
6184-    IGeneratorTracker*
6185-    RunContext::acquireGeneratorTracker( StringRef generatorName,
6186-                                         SourceLineInfo const& lineInfo ) {
6187-        auto* tracker = Generators::GeneratorTracker::acquire(
6188-            m_trackerContext,
6189-            TestCaseTracking::NameAndLocationRef(
6190-                 generatorName, lineInfo ) );
6191-        Detail::g_lastKnownLineInfo = lineInfo;
6192-        return tracker;
6193-    }
6194-
6195-    IGeneratorTracker* RunContext::createGeneratorTracker(
6196-        StringRef generatorName,
6197-        SourceLineInfo lineInfo,
6198-        Generators::GeneratorBasePtr&& generator ) {
6199-
6200-        auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast<std::string>( generatorName ), lineInfo );
6201-        auto& currentTracker = m_trackerContext.currentTracker();
6202-        assert(
6203-            currentTracker.nameAndLocation() != nameAndLoc &&
6204-            "Trying to create tracker for a generator that already has one" );
6205-
6206-        auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
6207-            CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker );
6208-        auto ret = newTracker.get();
6209-        currentTracker.addChild( CATCH_MOVE( newTracker ) );
6210-
6211-        ret->setGenerator( CATCH_MOVE( generator ) );
6212-        ret->open();
6213-        return ret;
6214-    }
6215-
6216-    bool RunContext::testForMissingAssertions(Counts& assertions) {
6217-        if (assertions.total() != 0)
6218-            return false;
6219-        if (!m_config->warnAboutMissingAssertions())
6220-            return false;
6221-        if (m_trackerContext.currentTracker().hasChildren())
6222-            return false;
6223-        m_atomicAssertionCount.failed++;
6224-        assertions.failed++;
6225-        return true;
6226-    }
6227-
6228-    void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
6229-        updateTotalsFromAtomics();
6230-        Counts assertions = m_totals.assertions - endInfo.prevAssertions;
6231-        bool missingAssertions = testForMissingAssertions(assertions);
6232-
6233-        if (!m_activeSections.empty()) {
6234-            m_activeSections.back()->close();
6235-            m_activeSections.pop_back();
6236-        }
6237-
6238-        {
6239-            auto _ = scopedDeactivate( *m_outputRedirect );
6240-            m_reporter->sectionEnded(
6241-                SectionStats( CATCH_MOVE( endInfo.sectionInfo ),
6242-                              assertions,
6243-                              endInfo.durationInSeconds,
6244-                              missingAssertions ) );
6245-        }
6246-    }
6247-
6248-    void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
6249-        if ( m_unfinishedSections.empty() ) {
6250-            m_activeSections.back()->fail();
6251-        } else {
6252-            m_activeSections.back()->close();
6253-        }
6254-        m_activeSections.pop_back();
6255-
6256-        m_unfinishedSections.push_back(CATCH_MOVE(endInfo));
6257-    }
6258-
6259-    void RunContext::benchmarkPreparing( StringRef name ) {
6260-        auto _ = scopedDeactivate( *m_outputRedirect );
6261-        m_reporter->benchmarkPreparing( name );
6262-    }
6263-    void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
6264-        auto _ = scopedDeactivate( *m_outputRedirect );
6265-        m_reporter->benchmarkStarting( info );
6266-    }
6267-    void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
6268-        auto _ = scopedDeactivate( *m_outputRedirect );
6269-        m_reporter->benchmarkEnded( stats );
6270-    }
6271-    void RunContext::benchmarkFailed( StringRef error ) {
6272-        auto _ = scopedDeactivate( *m_outputRedirect );
6273-        m_reporter->benchmarkFailed( error );
6274-    }
6275-
6276-    std::string RunContext::getCurrentTestName() const {
6277-        return m_activeTestCase
6278-            ? m_activeTestCase->getTestCaseInfo().name
6279-            : std::string();
6280-    }
6281-
6282-    const AssertionResult * RunContext::getLastResult() const {
6283-        // m_lastResult is updated inside the assertion slow-path, under
6284-        // a mutex, so the read needs to happen under mutex as well.
6285-
6286-        // TBD: The last result only makes sense if it is a thread-local
6287-        //      thing, because the answer is different per thread, like
6288-        //      last line info, whether last assertion passed, and so on.
6289-        //
6290-        //      However, the last result was also never updated in the
6291-        //      assertion fast path, so it was always somewhat broken,
6292-        //      and since IResultCapture::getLastResult is deprecated,
6293-        //      we will leave it as is, until it is finally removed.
6294-        Detail::LockGuard _( m_assertionMutex );
6295-        return &(*m_lastResult);
6296-    }
6297-
6298-    void RunContext::exceptionEarlyReported() {
6299-        m_shouldReportUnexpected = false;
6300-    }
6301-
6302-    void RunContext::handleFatalErrorCondition( StringRef message ) {
6303-        // We lock only when touching the reporters directly, to avoid
6304-        // deadlocks when we call into other functions that also want
6305-        // to lock the mutex before touching reporters.
6306-        //
6307-        // This does mean that we allow other threads to run while handling
6308-        // a fatal error, but this is all a best effort attempt anyway.
6309-        {
6310-            Detail::LockGuard lock( m_assertionMutex );
6311-            // TODO: scoped deactivate here? Just give up and do best effort?
6312-            //       the deactivation can break things further, OTOH so can the
6313-            //       capture
6314-            auto _ = scopedDeactivate( *m_outputRedirect );
6315-
6316-            // First notify reporter that bad things happened
6317-            m_reporter->fatalErrorEncountered( message );
6318-        }
6319-
6320-        // Don't rebuild the result -- the stringification itself can cause more fatal errors
6321-        // Instead, fake a result data.
6322-        AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
6323-        tempResult.message = static_cast<std::string>(message);
6324-        AssertionResult result( makeDummyAssertionInfo(),
6325-                                CATCH_MOVE( tempResult ) );
6326-
6327-        assertionEnded(CATCH_MOVE(result) );
6328-
6329-
6330-        // At this point we touch sections/test cases from this thread
6331-        // to try and end them. Technically that is not supported when
6332-        // using multiple threads, but the worst thing that can happen
6333-        // is that the process aborts harder :-D
6334-        Detail::LockGuard lock( m_assertionMutex );
6335-
6336-        // Best effort cleanup for sections that have not been destructed yet
6337-        // Since this is a fatal error, we have not had and won't have the opportunity to destruct them properly
6338-        while (!m_activeSections.empty()) {
6339-            auto const& nl = m_activeSections.back()->nameAndLocation();
6340-            SectionEndInfo endInfo{ SectionInfo(nl.location, nl.name), {}, 0.0 };
6341-            sectionEndedEarly(CATCH_MOVE(endInfo));
6342-        }
6343-        handleUnfinishedSections();
6344-
6345-        // Recreate section for test case (as we will lose the one that was in scope)
6346-        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6347-        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
6348-
6349-        Counts assertions;
6350-        assertions.failed = 1;
6351-        SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false);
6352-        m_reporter->sectionEnded( testCaseSectionStats );
6353-
6354-        auto const& testInfo = m_activeTestCase->getTestCaseInfo();
6355-
6356-        Totals deltaTotals;
6357-        deltaTotals.testCases.failed = 1;
6358-        deltaTotals.assertions.failed = 1;
6359-        m_reporter->testCaseEnded(TestCaseStats(testInfo,
6360-                                  deltaTotals,
6361-                                  std::string(),
6362-                                  std::string(),
6363-                                  false));
6364-        m_totals.testCases.failed++;
6365-        updateTotalsFromAtomics();
6366-        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
6367-    }
6368-
6369-    bool RunContext::lastAssertionPassed() {
6370-        return Detail::g_lastAssertionPassed;
6371-    }
6372-
6373-    void RunContext::assertionPassedFastPath(SourceLineInfo lineInfo) {
6374-        // We want to save the line info for better experience with unexpected assertions
6375-        Detail::g_lastKnownLineInfo = lineInfo;
6376-        ++m_atomicAssertionCount.passed;
6377-        Detail::g_lastAssertionPassed = true;
6378-        Detail::g_clearMessageScopes = true;
6379-    }
6380-
6381-    void RunContext::updateTotalsFromAtomics() {
6382-        m_totals.assertions = Counts{
6383-            m_atomicAssertionCount.passed,
6384-            m_atomicAssertionCount.failed,
6385-            m_atomicAssertionCount.failedButOk,
6386-            m_atomicAssertionCount.skipped,
6387-        };
6388-    }
6389-
6390-    bool RunContext::aborting() const {
6391-        return m_atomicAssertionCount.failed >= m_abortAfterXFailedAssertions;
6392-    }
6393-
6394-    void RunContext::runCurrentTest() {
6395-        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6396-        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
6397-        m_reporter->sectionStarting(testCaseSection);
6398-        updateTotalsFromAtomics();
6399-        Counts prevAssertions = m_totals.assertions;
6400-        double duration = 0;
6401-        m_shouldReportUnexpected = true;
6402-        Detail::g_lastKnownLineInfo = testCaseInfo.lineInfo;
6403-
6404-        Timer timer;
6405-        CATCH_TRY {
6406-            {
6407-                auto _ = scopedActivate( *m_outputRedirect );
6408-                timer.start();
6409-                invokeActiveTestCase();
6410-            }
6411-            duration = timer.getElapsedSeconds();
6412-        } CATCH_CATCH_ANON (TestFailureException&) {
6413-            // This just means the test was aborted due to failure
6414-        } CATCH_CATCH_ANON (TestSkipException&) {
6415-            // This just means the test was explicitly skipped
6416-        } CATCH_CATCH_ALL {
6417-            // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
6418-            // are reported without translation at the point of origin.
6419-            if ( m_shouldReportUnexpected ) {
6420-                AssertionReaction dummyReaction;
6421-                handleUnexpectedInflightException( makeDummyAssertionInfo(),
6422-                                                   translateActiveException(),
6423-                                                   dummyReaction );
6424-            }
6425-        }
6426-        updateTotalsFromAtomics();
6427-        Counts assertions = m_totals.assertions - prevAssertions;
6428-        bool missingAssertions = testForMissingAssertions(assertions);
6429-
6430-        m_testCaseTracker->close();
6431-        handleUnfinishedSections();
6432-        Detail::g_messageScopes.clear();
6433-        // TBD: At this point, m_messages should be empty. Do we want to
6434-        //      assert that this is true, or keep the defensive clear call?
6435-        Detail::g_messages.clear();
6436-
6437-        SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions);
6438-        m_reporter->sectionEnded(testCaseSectionStats);
6439-    }
6440-
6441-    void RunContext::invokeActiveTestCase() {
6442-        // We need to engage a handler for signals/structured exceptions
6443-        // before running the tests themselves, or the binary can crash
6444-        // without failed test being reported.
6445-        FatalConditionHandlerGuard _(&m_fatalConditionhandler);
6446-        // We keep having issue where some compilers warn about an unused
6447-        // variable, even though the type has non-trivial constructor and
6448-        // destructor. This is annoying and ugly, but it makes them stfu.
6449-        (void)_;
6450-
6451-        m_activeTestCase->invoke();
6452-    }
6453-
6454-    void RunContext::handleUnfinishedSections() {
6455-        // If sections ended prematurely due to an exception we stored their
6456-        // infos here so we can tear them down outside the unwind process.
6457-        for ( auto it = m_unfinishedSections.rbegin(),
6458-                   itEnd = m_unfinishedSections.rend();
6459-              it != itEnd;
6460-              ++it ) {
6461-            sectionEnded( CATCH_MOVE( *it ) );
6462-        }
6463-        m_unfinishedSections.clear();
6464-    }
6465-
6466-    void RunContext::handleExpr(
6467-        AssertionInfo const& info,
6468-        ITransientExpression const& expr,
6469-        AssertionReaction& reaction
6470-    ) {
6471-        bool negated = isFalseTest( info.resultDisposition );
6472-        bool result = expr.getResult() != negated;
6473-
6474-        if( result ) {
6475-            if (!m_includeSuccessfulResults) {
6476-                assertionPassedFastPath(info.lineInfo);
6477-            }
6478-            else {
6479-                reportExpr(info, ResultWas::Ok, &expr, negated);
6480-            }
6481-        }
6482-        else {
6483-            reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
6484-            populateReaction(
6485-                reaction, info.resultDisposition & ResultDisposition::Normal );
6486-        }
6487-    }
6488-    void RunContext::reportExpr(
6489-            AssertionInfo const &info,
6490-            ResultWas::OfType resultType,
6491-            ITransientExpression const *expr,
6492-            bool negated ) {
6493-
6494-        Detail::g_lastKnownLineInfo = info.lineInfo;
6495-        AssertionResultData data( resultType, LazyExpression( negated ) );
6496-
6497-        AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
6498-        assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
6499-
6500-        assertionEnded( CATCH_MOVE(assertionResult) );
6501-    }
6502-
6503-    void RunContext::handleMessage(
6504-            AssertionInfo const& info,
6505-            ResultWas::OfType resultType,
6506-            std::string&& message,
6507-            AssertionReaction& reaction
6508-    ) {
6509-        Detail::g_lastKnownLineInfo = info.lineInfo;
6510-
6511-        AssertionResultData data( resultType, LazyExpression( false ) );
6512-        data.message = CATCH_MOVE( message );
6513-        AssertionResult assertionResult{ info,
6514-                                         CATCH_MOVE( data ) };
6515-
6516-        const auto isOk = assertionResult.isOk();
6517-        assertionEnded( CATCH_MOVE(assertionResult) );
6518-        if ( !isOk ) {
6519-            populateReaction(
6520-                reaction, info.resultDisposition & ResultDisposition::Normal );
6521-        } else if ( resultType == ResultWas::ExplicitSkip ) {
6522-            // TODO: Need to handle this explicitly, as ExplicitSkip is
6523-            // considered "OK"
6524-            reaction.shouldSkip = true;
6525-        }
6526-    }
6527-
6528-    void RunContext::handleUnexpectedExceptionNotThrown(
6529-            AssertionInfo const& info,
6530-            AssertionReaction& reaction
6531-    ) {
6532-        handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
6533-    }
6534-
6535-    void RunContext::handleUnexpectedInflightException(
6536-            AssertionInfo const& info,
6537-            std::string&& message,
6538-            AssertionReaction& reaction
6539-    ) {
6540-        Detail::g_lastKnownLineInfo = info.lineInfo;
6541-
6542-        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
6543-        data.message = CATCH_MOVE(message);
6544-        AssertionResult assertionResult{ info, CATCH_MOVE(data) };
6545-        assertionEnded( CATCH_MOVE(assertionResult) );
6546-        populateReaction( reaction,
6547-                          info.resultDisposition & ResultDisposition::Normal );
6548-    }
6549-
6550-    void RunContext::populateReaction( AssertionReaction& reaction,
6551-                                       bool has_normal_disposition ) {
6552-        reaction.shouldDebugBreak = m_shouldDebugBreak;
6553-        reaction.shouldThrow = aborting() || has_normal_disposition;
6554-    }
6555-
6556-    AssertionInfo RunContext::makeDummyAssertionInfo() {
6557-        const bool testCaseJustStarted =
6558-            Detail::g_lastKnownLineInfo ==
6559-            m_activeTestCase->getTestCaseInfo().lineInfo;
6560-
6561-        return AssertionInfo{
6562-            testCaseJustStarted ? "TEST_CASE"_sr : StringRef(),
6563-            Detail::g_lastKnownLineInfo,
6564-            testCaseJustStarted ? StringRef() : "{Unknown expression after the reported line}"_sr,
6565-            ResultDisposition::Normal
6566-        };
6567-    }
6568-
6569-    void RunContext::handleIncomplete(
6570-            AssertionInfo const& info
6571-    ) {
6572-        using namespace std::string_literals;
6573-        Detail::g_lastKnownLineInfo = info.lineInfo;
6574-
6575-        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
6576-        data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
6577-        AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
6578-        assertionEnded( CATCH_MOVE(assertionResult) );
6579-    }
6580-
6581-    void RunContext::handleNonExpr(
6582-            AssertionInfo const &info,
6583-            ResultWas::OfType resultType,
6584-            AssertionReaction &reaction
6585-    ) {
6586-        AssertionResultData data( resultType, LazyExpression( false ) );
6587-        AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
6588-
6589-        const auto isOk = assertionResult.isOk();
6590-        if ( isOk && !m_includeSuccessfulResults ) {
6591-            assertionPassedFastPath( info.lineInfo );
6592-            return;
6593-        }
6594-
6595-        assertionEnded( CATCH_MOVE(assertionResult) );
6596-        if ( !isOk ) {
6597-            populateReaction(
6598-                reaction, info.resultDisposition & ResultDisposition::Normal );
6599-        }
6600-    }
6601-
6602-    void IResultCapture::pushScopedMessage( MessageInfo&& message ) {
6603-        Detail::g_messages.push_back( CATCH_MOVE( message ) );
6604-    }
6605-
6606-    void IResultCapture::popScopedMessage( unsigned int messageId ) {
6607-        // Note: On average, it would probably be better to look for the message
6608-        //       backwards. However, we do not expect to have to deal with more
6609-        //       messages than low single digits, so the optimization is tiny,
6610-        //       and we would have to hand-write the loop to avoid terrible
6611-        //       codegen of reverse iterators in debug mode.
6612-        Detail::g_messages.erase( std::find_if( Detail::g_messages.begin(),
6613-                                                Detail::g_messages.end(),
6614-                                                [=]( MessageInfo const& msg ) {
6615-                                                    return msg.sequence ==
6616-                                                           messageId;
6617-                                                } ) );
6618-    }
6619-
6620-    void IResultCapture::emplaceUnscopedMessage( MessageBuilder&& builder ) {
6621-        Detail::g_messageScopes.emplace_back( CATCH_MOVE( builder ) );
6622-    }
6623-
6624-    void seedRng(IConfig const& config) {
6625-        sharedRng().seed(config.rngSeed());
6626-    }
6627-
6628-    unsigned int rngSeed() {
6629-        return getCurrentContext().getConfig()->rngSeed();
6630-    }
6631-
6632-}
6633-
6634-
6635-
6636-namespace Catch {
6637-
6638-    Section::Section( SectionInfo&& info ):
6639-        m_info( CATCH_MOVE( info ) ),
6640-        m_sectionIncluded(
6641-            getResultCapture().sectionStarted( m_info.name, m_info.lineInfo, m_assertions ) ) {
6642-        // Non-"included" sections will not use the timing information
6643-        // anyway, so don't bother with the potential syscall.
6644-        if (m_sectionIncluded) {
6645-            m_timer.start();
6646-        }
6647-    }
6648-
6649-    Section::Section( SourceLineInfo const& _lineInfo,
6650-                      StringRef _name,
6651-                      const char* const ):
6652-        m_info( { "invalid", static_cast<std::size_t>( -1 ) }, std::string{} ),
6653-        m_sectionIncluded(
6654-            getResultCapture().sectionStarted( _name, _lineInfo, m_assertions ) ) {
6655-        // We delay initialization the SectionInfo member until we know
6656-        // this section needs it, so we avoid allocating std::string for name.
6657-        // We also delay timer start to avoid the potential syscall unless we
6658-        // will actually use the result.
6659-        if ( m_sectionIncluded ) {
6660-            m_info.name = static_cast<std::string>( _name );
6661-            m_info.lineInfo = _lineInfo;
6662-            m_timer.start();
6663-        }
6664-    }
6665-
6666-    Section::~Section() {
6667-        if( m_sectionIncluded ) {
6668-            SectionEndInfo endInfo{ CATCH_MOVE(m_info), m_assertions, m_timer.getElapsedSeconds() };
6669-            if ( uncaught_exceptions() ) {
6670-                getResultCapture().sectionEndedEarly( CATCH_MOVE(endInfo) );
6671-            } else {
6672-                getResultCapture().sectionEnded( CATCH_MOVE( endInfo ) );
6673-            }
6674-        }
6675-    }
6676-
6677-    // This indicates whether the section should be executed or not
6678-    Section::operator bool() const {
6679-        return m_sectionIncluded;
6680-    }
6681-
6682-
6683-} // end namespace Catch
6684-
6685-
6686-
6687-#include <vector>
6688-
6689-namespace Catch {
6690-
6691-    namespace {
6692-        static auto getSingletons() -> std::vector<ISingleton*>*& {
6693-            static std::vector<ISingleton*>* g_singletons = nullptr;
6694-            if( !g_singletons )
6695-                g_singletons = new std::vector<ISingleton*>();
6696-            return g_singletons;
6697-        }
6698-    }
6699-
6700-    ISingleton::~ISingleton() = default;
6701-
6702-    void addSingleton(ISingleton* singleton ) {
6703-        getSingletons()->push_back( singleton );
6704-    }
6705-    void cleanupSingletons() {
6706-        auto& singletons = getSingletons();
6707-        for( auto singleton : *singletons )
6708-            delete singleton;
6709-        delete singletons;
6710-        singletons = nullptr;
6711-    }
6712-
6713-} // namespace Catch
6714-
6715-
6716-
6717-#include <cstring>
6718-#include <ostream>
6719-
6720-namespace Catch {
6721-
6722-    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
6723-        return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
6724-    }
6725-    bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
6726-        // We can assume that the same file will usually have the same pointer.
6727-        // Thus, if the pointers are the same, there is no point in calling the strcmp
6728-        return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
6729-    }
6730-
6731-    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
6732-#ifndef __GNUG__
6733-        os << info.file << '(' << info.line << ')';
6734-#else
6735-        os << info.file << ':' << info.line;
6736-#endif
6737-        return os;
6738-    }
6739-
6740-} // end namespace Catch
6741-
6742-
6743-
6744-
6745-namespace Catch {
6746-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
6747-    void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
6748-        CATCH_TRY {
6749-            m_exceptions.push_back(exception);
6750-        } CATCH_CATCH_ALL {
6751-            // If we run out of memory during start-up there's really not a lot more we can do about it
6752-            std::terminate();
6753-        }
6754-    }
6755-
6756-    std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {
6757-        return m_exceptions;
6758-    }
6759-#endif
6760-
6761-} // end namespace Catch
6762-
6763-
6764-
6765-
6766-
6767-#include <iostream>
6768-
6769-namespace Catch {
6770-
6771-// If you #define this you must implement these functions
6772-#if !defined( CATCH_CONFIG_NOSTDOUT )
6773-    std::ostream& cout() { return std::cout; }
6774-    std::ostream& cerr() { return std::cerr; }
6775-    std::ostream& clog() { return std::clog; }
6776-#endif
6777-
6778-} // namespace Catch
6779-
6780-
6781-
6782-#include <ostream>
6783-#include <cstring>
6784-#include <cctype>
6785-#include <vector>
6786-
6787-namespace Catch {
6788-
6789-    bool startsWith( std::string const& s, std::string const& prefix ) {
6790-        return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
6791-    }
6792-    bool startsWith( StringRef s, char prefix ) {
6793-        return !s.empty() && s[0] == prefix;
6794-    }
6795-    bool endsWith( std::string const& s, std::string const& suffix ) {
6796-        return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
6797-    }
6798-    bool endsWith( std::string const& s, char suffix ) {
6799-        return !s.empty() && s[s.size()-1] == suffix;
6800-    }
6801-    bool contains( std::string const& s, std::string const& infix ) {
6802-        return s.find( infix ) != std::string::npos;
6803-    }
6804-    void toLowerInPlace( std::string& s ) {
6805-        for ( char& c : s ) {
6806-            c = toLower( c );
6807-        }
6808-    }
6809-    std::string toLower( std::string const& s ) {
6810-        std::string lc = s;
6811-        toLowerInPlace( lc );
6812-        return lc;
6813-    }
6814-    char toLower(char c) {
6815-        return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
6816-    }
6817-
6818-    std::string trim( std::string const& str ) {
6819-        static char const* whitespaceChars = "\n\r\t ";
6820-        std::string::size_type start = str.find_first_not_of( whitespaceChars );
6821-        std::string::size_type end = str.find_last_not_of( whitespaceChars );
6822-
6823-        return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
6824-    }
6825-
6826-    StringRef trim(StringRef ref) {
6827-        const auto is_ws = [](char c) {
6828-            return c == ' ' || c == '\t' || c == '\n' || c == '\r';
6829-        };
6830-        size_t real_begin = 0;
6831-        while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; }
6832-        size_t real_end = ref.size();
6833-        while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; }
6834-
6835-        return ref.substr(real_begin, real_end - real_begin);
6836-    }
6837-
6838-    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
6839-        std::size_t i = str.find( replaceThis );
6840-        if (i == std::string::npos) {
6841-            return false;
6842-        }
6843-        std::size_t copyBegin = 0;
6844-        std::string origStr = CATCH_MOVE(str);
6845-        str.clear();
6846-        // There is at least one replacement, so reserve with the best guess
6847-        // we can make without actually counting the number of occurrences.
6848-        str.reserve(origStr.size() - replaceThis.size() + withThis.size());
6849-        do {
6850-            str.append(origStr, copyBegin, i-copyBegin );
6851-            str += withThis;
6852-            copyBegin = i + replaceThis.size();
6853-            if( copyBegin < origStr.size() )
6854-                i = origStr.find( replaceThis, copyBegin );
6855-            else
6856-                i = std::string::npos;
6857-        } while( i != std::string::npos );
6858-        if ( copyBegin < origStr.size() ) {
6859-            str.append(origStr, copyBegin, origStr.size() );
6860-        }
6861-        return true;
6862-    }
6863-
6864-    std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {
6865-        std::vector<StringRef> subStrings;
6866-        std::size_t start = 0;
6867-        for(std::size_t pos = 0; pos < str.size(); ++pos ) {
6868-            if( str[pos] == delimiter ) {
6869-                if( pos - start > 1 )
6870-                    subStrings.push_back( str.substr( start, pos-start ) );
6871-                start = pos+1;
6872-            }
6873-        }
6874-        if( start < str.size() )
6875-            subStrings.push_back( str.substr( start, str.size()-start ) );
6876-        return subStrings;
6877-    }
6878-
6879-    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
6880-        os << pluraliser.m_count << ' ' << pluraliser.m_label;
6881-        if( pluraliser.m_count != 1 )
6882-            os << 's';
6883-        return os;
6884-    }
6885-
6886-}
6887-
6888-
6889-
6890-#include <algorithm>
6891-#include <ostream>
6892-#include <cstring>
6893-
6894-namespace Catch {
6895-    StringRef::StringRef( char const* rawChars ) noexcept
6896-    : StringRef( rawChars, std::strlen(rawChars) )
6897-    {}
6898-
6899-
6900-    bool StringRef::operator<(StringRef rhs) const noexcept {
6901-        if (m_size < rhs.m_size) {
6902-            return strncmp(m_start, rhs.m_start, m_size) <= 0;
6903-        }
6904-        return strncmp(m_start, rhs.m_start, rhs.m_size) < 0;
6905-    }
6906-
6907-    int StringRef::compare( StringRef rhs ) const {
6908-        auto cmpResult =
6909-            strncmp( m_start, rhs.m_start, std::min( m_size, rhs.m_size ) );
6910-
6911-        // This means that strncmp found a difference before the strings
6912-        // ended, and we can return it directly
6913-        if ( cmpResult != 0 ) {
6914-            return cmpResult;
6915-        }
6916-
6917-        // If strings are equal up to length, then their comparison results on
6918-        // their size
6919-        if ( m_size < rhs.m_size ) {
6920-            return -1;
6921-        } else if ( m_size > rhs.m_size ) {
6922-            return 1;
6923-        } else {
6924-            return 0;
6925-        }
6926-    }
6927-
6928-    auto operator << ( std::ostream& os, StringRef str ) -> std::ostream& {
6929-        return os.write(str.data(), static_cast<std::streamsize>(str.size()));
6930-    }
6931-
6932-    std::string operator+(StringRef lhs, StringRef rhs) {
6933-        std::string ret;
6934-        ret.reserve(lhs.size() + rhs.size());
6935-        ret += lhs;
6936-        ret += rhs;
6937-        return ret;
6938-    }
6939-
6940-    auto operator+=( std::string& lhs, StringRef rhs ) -> std::string& {
6941-        lhs.append(rhs.data(), rhs.size());
6942-        return lhs;
6943-    }
6944-
6945-} // namespace Catch
6946-
6947-
6948-
6949-namespace Catch {
6950-
6951-    TagAliasRegistry::~TagAliasRegistry() = default;
6952-
6953-    TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
6954-        auto it = m_registry.find( alias );
6955-        if( it != m_registry.end() )
6956-            return &(it->second);
6957-        else
6958-            return nullptr;
6959-    }
6960-
6961-    std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
6962-        std::string expandedTestSpec = unexpandedTestSpec;
6963-        for( auto const& registryKvp : m_registry ) {
6964-            std::size_t pos = expandedTestSpec.find( registryKvp.first );
6965-            if( pos != std::string::npos ) {
6966-                expandedTestSpec =  expandedTestSpec.substr( 0, pos ) +
6967-                                    registryKvp.second.tag +
6968-                                    expandedTestSpec.substr( pos + registryKvp.first.size() );
6969-            }
6970-        }
6971-        return expandedTestSpec;
6972-    }
6973-
6974-    void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
6975-        CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
6976-                      "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
6977-
6978-        CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
6979-                      "error: tag alias, '" << alias << "' already registered.\n"
6980-                      << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
6981-                      << "\tRedefined at: " << lineInfo );
6982-    }
6983-
6984-    ITagAliasRegistry::~ITagAliasRegistry() = default;
6985-
6986-    ITagAliasRegistry const& ITagAliasRegistry::get() {
6987-        return getRegistryHub().getTagAliasRegistry();
6988-    }
6989-
6990-} // end namespace Catch
6991-
6992-
6993-
6994-
6995-namespace Catch {
6996-    TestCaseInfoHasher::TestCaseInfoHasher( hash_t seed ): m_seed( seed ) {}
6997-
6998-    uint32_t TestCaseInfoHasher::operator()( TestCaseInfo const& t ) const {
6999-        // FNV-1a hash algorithm that is designed for uniqueness:
7000-        const hash_t prime = 1099511628211u;
7001-        hash_t hash = 14695981039346656037u;
7002-        for ( const char c : t.name ) {
7003-            hash ^= c;
7004-            hash *= prime;
7005-        }
7006-        for ( const char c : t.className ) {
7007-            hash ^= c;
7008-            hash *= prime;
7009-        }
7010-        for ( const Tag& tag : t.tags ) {
7011-            for ( const char c : tag.original ) {
7012-                hash ^= c;
7013-                hash *= prime;
7014-            }
7015-        }
7016-        hash ^= m_seed;
7017-        hash *= prime;
7018-        const uint32_t low{ static_cast<uint32_t>( hash ) };
7019-        const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
7020-        return low * high;
7021-    }
7022-} // namespace Catch
7023-
7024-
7025-
7026-
7027-#include <algorithm>
7028-#include <set>
7029-
7030-namespace Catch {
7031-
7032-    namespace {
7033-        static void enforceNoDuplicateTestCases(
7034-            std::vector<TestCaseHandle> const& tests ) {
7035-            auto testInfoCmp = []( TestCaseInfo const* lhs,
7036-                                   TestCaseInfo const* rhs ) {
7037-                return *lhs < *rhs;
7038-            };
7039-            std::set<TestCaseInfo const*, decltype( testInfoCmp )&> seenTests(
7040-                testInfoCmp );
7041-            for ( auto const& test : tests ) {
7042-                const auto infoPtr = &test.getTestCaseInfo();
7043-                const auto prev = seenTests.insert( infoPtr );
7044-                CATCH_ENFORCE( prev.second,
7045-                               "error: test case \""
7046-                                   << infoPtr->name << "\", with tags \""
7047-                                   << infoPtr->tagsAsString()
7048-                                   << "\" already defined.\n"
7049-                                   << "\tFirst seen at "
7050-                                   << ( *prev.first )->lineInfo << "\n"
7051-                                   << "\tRedefined at " << infoPtr->lineInfo );
7052-            }
7053-        }
7054-
7055-        static bool matchTest( TestCaseHandle const& testCase,
7056-                               TestSpec const& testSpec,
7057-                               IConfig const& config ) {
7058-            return testSpec.matches( testCase.getTestCaseInfo() ) &&
7059-                   isThrowSafe( testCase, config );
7060-        }
7061-
7062-    } // end unnamed namespace
7063-
7064-    std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ) {
7065-        switch (config.runOrder()) {
7066-        case TestRunOrder::Declared:
7067-            return unsortedTestCases;
7068-
7069-        case TestRunOrder::LexicographicallySorted: {
7070-            std::vector<TestCaseHandle> sorted = unsortedTestCases;
7071-            std::sort(
7072-                sorted.begin(),
7073-                sorted.end(),
7074-                []( TestCaseHandle const& lhs, TestCaseHandle const& rhs ) {
7075-                    return lhs.getTestCaseInfo() < rhs.getTestCaseInfo();
7076-                }
7077-            );
7078-            return sorted;
7079-        }
7080-        case TestRunOrder::Randomized: {
7081-            using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>;
7082-
7083-            TestCaseInfoHasher h{ config.rngSeed() };
7084-            std::vector<TestWithHash> indexed_tests;
7085-            indexed_tests.reserve(unsortedTestCases.size());
7086-
7087-            for (auto const& handle : unsortedTestCases) {
7088-                indexed_tests.emplace_back(h(handle.getTestCaseInfo()), handle);
7089-            }
7090-
7091-            std::sort( indexed_tests.begin(),
7092-                       indexed_tests.end(),
7093-                       []( TestWithHash const& lhs, TestWithHash const& rhs ) {
7094-                           if ( lhs.first == rhs.first ) {
7095-                               return lhs.second.getTestCaseInfo() <
7096-                                      rhs.second.getTestCaseInfo();
7097-                           }
7098-                           return lhs.first < rhs.first;
7099-                       } );
7100-
7101-            std::vector<TestCaseHandle> randomized;
7102-            randomized.reserve(indexed_tests.size());
7103-
7104-            for (auto const& indexed : indexed_tests) {
7105-                randomized.push_back(indexed.second);
7106-            }
7107-
7108-            return randomized;
7109-        }
7110-        }
7111-
7112-        CATCH_INTERNAL_ERROR("Unknown test order value!");
7113-    }
7114-
7115-    bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ) {
7116-        return !testCase.getTestCaseInfo().throws() || config.allowThrows();
7117-    }
7118-
7119-    std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
7120-        std::vector<TestCaseHandle> filtered;
7121-        filtered.reserve( testCases.size() );
7122-        for (auto const& testCase : testCases) {
7123-            if ((!testSpec.hasFilters() && !testCase.getTestCaseInfo().isHidden()) ||
7124-                (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
7125-                filtered.push_back(testCase);
7126-            }
7127-        }
7128-        return createShard(filtered, config.shardCount(), config.shardIndex());
7129-    }
7130-    std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config ) {
7131-        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
7132-    }
7133-
7134-    TestRegistry::~TestRegistry() = default;
7135-
7136-    void TestRegistry::registerTest(Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker) {
7137-        m_handles.emplace_back(testInfo.get(), testInvoker.get());
7138-        m_viewed_test_infos.push_back(testInfo.get());
7139-        m_owned_test_infos.push_back(CATCH_MOVE(testInfo));
7140-        m_invokers.push_back(CATCH_MOVE(testInvoker));
7141-    }
7142-
7143-    std::vector<TestCaseInfo*> const& TestRegistry::getAllInfos() const {
7144-        return m_viewed_test_infos;
7145-    }
7146-
7147-    std::vector<TestCaseHandle> const& TestRegistry::getAllTests() const {
7148-        return m_handles;
7149-    }
7150-    std::vector<TestCaseHandle> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
7151-        if( m_sortedFunctions.empty() )
7152-            enforceNoDuplicateTestCases( m_handles );
7153-
7154-        if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
7155-            m_sortedFunctions = sortTests( config, m_handles );
7156-            m_currentSortOrder = config.runOrder();
7157-        }
7158-        return m_sortedFunctions;
7159-    }
7160-
7161-} // end namespace Catch
7162-
7163-
7164-
7165-
7166-#include <algorithm>
7167-#include <cassert>
7168-
7169-#if defined(__clang__)
7170-#    pragma clang diagnostic push
7171-#    pragma clang diagnostic ignored "-Wexit-time-destructors"
7172-#endif
7173-
7174-namespace Catch {
7175-namespace TestCaseTracking {
7176-
7177-    NameAndLocation::NameAndLocation( std::string&& _name, SourceLineInfo const& _location )
7178-    :   name( CATCH_MOVE(_name) ),
7179-        location( _location )
7180-    {}
7181-
7182-
7183-    ITracker::~ITracker() = default;
7184-
7185-    void ITracker::markAsNeedingAnotherRun() {
7186-        m_runState = NeedsAnotherRun;
7187-    }
7188-
7189-    void ITracker::addChild( ITrackerPtr&& child ) {
7190-        m_children.push_back( CATCH_MOVE(child) );
7191-    }
7192-
7193-    ITracker* ITracker::findChild( NameAndLocationRef const& nameAndLocation ) {
7194-        auto it = std::find_if(
7195-            m_children.begin(),
7196-            m_children.end(),
7197-            [&nameAndLocation]( ITrackerPtr const& tracker ) {
7198-                auto const& tnameAndLoc = tracker->nameAndLocation();
7199-                if ( tnameAndLoc.location.line !=
7200-                     nameAndLocation.location.line ) {
7201-                    return false;
7202-                }
7203-                return tnameAndLoc == nameAndLocation;
7204-            } );
7205-        return ( it != m_children.end() ) ? it->get() : nullptr;
7206-    }
7207-
7208-    bool ITracker::isSectionTracker() const { return false; }
7209-    bool ITracker::isGeneratorTracker() const { return false; }
7210-
7211-    bool ITracker::isOpen() const {
7212-        return m_runState != NotStarted && !isComplete();
7213-    }
7214-
7215-    bool ITracker::hasStarted() const { return m_runState != NotStarted; }
7216-
7217-    void ITracker::openChild() {
7218-        if (m_runState != ExecutingChildren) {
7219-            m_runState = ExecutingChildren;
7220-            if (m_parent) {
7221-                m_parent->openChild();
7222-            }
7223-        }
7224-    }
7225-
7226-    ITracker& TrackerContext::startRun() {
7227-        using namespace std::string_literals;
7228-        m_rootTracker = Catch::Detail::make_unique<SectionTracker>(
7229-            NameAndLocation( "{root}"s, CATCH_INTERNAL_LINEINFO ),
7230-            *this,
7231-            nullptr );
7232-        m_currentTracker = nullptr;
7233-        m_runState = Executing;
7234-        return *m_rootTracker;
7235-    }
7236-
7237-    void TrackerContext::completeCycle() {
7238-        m_runState = CompletedCycle;
7239-    }
7240-
7241-    bool TrackerContext::completedCycle() const {
7242-        return m_runState == CompletedCycle;
7243-    }
7244-    void TrackerContext::setCurrentTracker( ITracker* tracker ) {
7245-        m_currentTracker = tracker;
7246-    }
7247-
7248-
7249-    TrackerBase::TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
7250-        ITracker(CATCH_MOVE(nameAndLocation), parent),
7251-        m_ctx( ctx )
7252-    {}
7253-
7254-    bool TrackerBase::isComplete() const {
7255-        return m_runState == CompletedSuccessfully || m_runState == Failed;
7256-    }
7257-
7258-    void TrackerBase::open() {
7259-        m_runState = Executing;
7260-        moveToThis();
7261-        if( m_parent )
7262-            m_parent->openChild();
7263-    }
7264-
7265-    void TrackerBase::close() {
7266-
7267-        // Close any still open children (e.g. generators)
7268-        while( &m_ctx.currentTracker() != this )
7269-            m_ctx.currentTracker().close();
7270-
7271-        switch( m_runState ) {
7272-            case NeedsAnotherRun:
7273-                break;
7274-
7275-            case Executing:
7276-                m_runState = CompletedSuccessfully;
7277-                break;
7278-            case ExecutingChildren:
7279-                if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )
7280-                    m_runState = CompletedSuccessfully;
7281-                break;
7282-
7283-            case NotStarted:
7284-            case CompletedSuccessfully:
7285-            case Failed:
7286-                CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
7287-
7288-            default:
7289-                CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
7290-        }
7291-        moveToParent();
7292-        m_ctx.completeCycle();
7293-    }
7294-    void TrackerBase::fail() {
7295-        m_runState = Failed;
7296-        if( m_parent )
7297-            m_parent->markAsNeedingAnotherRun();
7298-        moveToParent();
7299-        m_ctx.completeCycle();
7300-    }
7301-
7302-    void TrackerBase::moveToParent() {
7303-        assert( m_parent );
7304-        m_ctx.setCurrentTracker( m_parent );
7305-    }
7306-    void TrackerBase::moveToThis() {
7307-        m_ctx.setCurrentTracker( this );
7308-    }
7309-
7310-    SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
7311-    :   TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ),
7312-        m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name)))
7313-    {
7314-        if( parent ) {
7315-            while ( !parent->isSectionTracker() ) {
7316-                parent = parent->parent();
7317-            }
7318-
7319-            SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
7320-            addNextFilters( parentSection.m_filters );
7321-        }
7322-    }
7323-
7324-    bool SectionTracker::isComplete() const {
7325-        bool complete = true;
7326-
7327-        if (m_filters.empty()
7328-            || m_filters[0].empty()
7329-            || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
7330-            complete = TrackerBase::isComplete();
7331-        }
7332-        return complete;
7333-    }
7334-
7335-    bool SectionTracker::isSectionTracker() const { return true; }
7336-
7337-    SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ) {
7338-        SectionTracker* tracker;
7339-
7340-        ITracker& currentTracker = ctx.currentTracker();
7341-        if ( ITracker* childTracker =
7342-                 currentTracker.findChild( nameAndLocation ) ) {
7343-            assert( childTracker );
7344-            assert( childTracker->isSectionTracker() );
7345-            tracker = static_cast<SectionTracker*>( childTracker );
7346-        } else {
7347-            auto newTracker = Catch::Detail::make_unique<SectionTracker>(
7348-                NameAndLocation{ static_cast<std::string>(nameAndLocation.name),
7349-                                 nameAndLocation.location },
7350-                ctx,
7351-                &currentTracker );
7352-            tracker = newTracker.get();
7353-            currentTracker.addChild( CATCH_MOVE( newTracker ) );
7354-        }
7355-
7356-        if ( !ctx.completedCycle() ) {
7357-            tracker->tryOpen();
7358-        }
7359-
7360-        return *tracker;
7361-    }
7362-
7363-    void SectionTracker::tryOpen() {
7364-        if( !isComplete() )
7365-            open();
7366-    }
7367-
7368-    void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
7369-        if( !filters.empty() ) {
7370-            m_filters.reserve( m_filters.size() + filters.size() + 2 );
7371-            m_filters.emplace_back(StringRef{}); // Root - should never be consulted
7372-            m_filters.emplace_back(StringRef{}); // Test Case - not a section filter
7373-            m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
7374-        }
7375-    }
7376-    void SectionTracker::addNextFilters( std::vector<StringRef> const& filters ) {
7377-        if( filters.size() > 1 )
7378-            m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
7379-    }
7380-
7381-    StringRef SectionTracker::trimmedName() const {
7382-        return m_trimmed_name;
7383-    }
7384-
7385-} // namespace TestCaseTracking
7386-
7387-} // namespace Catch
7388-
7389-#if defined(__clang__)
7390-#    pragma clang diagnostic pop
7391-#endif
7392-
7393-
7394-
7395-
7396-namespace Catch {
7397-
7398-    void throw_test_failure_exception() {
7399-#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
7400-        throw TestFailureException{};
7401-#else
7402-        CATCH_ERROR( "Test failure requires aborting test!" );
7403-#endif
7404-    }
7405-
7406-    void throw_test_skip_exception() {
7407-#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
7408-        throw Catch::TestSkipException();
7409-#else
7410-        CATCH_ERROR( "Explicitly skipping tests during runtime requires exceptions" );
7411-#endif
7412-    }
7413-
7414-} // namespace Catch
7415-
7416-
7417-
7418-#include <algorithm>
7419-#include <iterator>
7420-
7421-namespace Catch {
7422-    void ITestInvoker::prepareTestCase() {}
7423-    void ITestInvoker::tearDownTestCase() {}
7424-    ITestInvoker::~ITestInvoker() = default;
7425-
7426-    namespace {
7427-        static StringRef extractClassName( StringRef classOrMethodName ) {
7428-            if ( !startsWith( classOrMethodName, '&' ) ) {
7429-                return classOrMethodName;
7430-            }
7431-
7432-            // Remove the leading '&' to avoid having to special case it later
7433-            const auto methodName =
7434-                classOrMethodName.substr( 1, classOrMethodName.size() );
7435-
7436-            auto reverseStart = std::make_reverse_iterator( methodName.end() );
7437-            auto reverseEnd = std::make_reverse_iterator( methodName.begin() );
7438-
7439-            // We make a simplifying assumption that ":" is only present
7440-            // in the input as part of "::" from C++ typenames (this is
7441-            // relatively safe assumption because the input is generated
7442-            // as stringification of type through preprocessor).
7443-            auto lastColons = std::find( reverseStart, reverseEnd, ':' ) + 1;
7444-            auto secondLastColons =
7445-                std::find( lastColons + 1, reverseEnd, ':' );
7446-
7447-            auto const startIdx = reverseEnd - secondLastColons;
7448-            auto const classNameSize = secondLastColons - lastColons - 1;
7449-
7450-            return methodName.substr(
7451-                static_cast<std::size_t>( startIdx ),
7452-                static_cast<std::size_t>( classNameSize ) );
7453-        }
7454-
7455-        class TestInvokerAsFunction final : public ITestInvoker {
7456-            using TestType = void ( * )();
7457-            TestType m_testAsFunction;
7458-
7459-        public:
7460-            constexpr TestInvokerAsFunction( TestType testAsFunction ) noexcept:
7461-                m_testAsFunction( testAsFunction ) {}
7462-
7463-            void invoke() const override { m_testAsFunction(); }
7464-        };
7465-
7466-    } // namespace
7467-
7468-    Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() ) {
7469-        return Detail::make_unique<TestInvokerAsFunction>( testAsFunction );
7470-    }
7471-
7472-    AutoReg::AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
7473-        CATCH_TRY {
7474-            getMutableRegistryHub()
7475-                    .registerTest(
7476-                        makeTestCaseInfo(
7477-                            extractClassName( classOrMethod ),
7478-                            nameAndTags,
7479-                            lineInfo),
7480-                        CATCH_MOVE(invoker)
7481-                    );
7482-        } CATCH_CATCH_ALL {
7483-            // Do not throw when constructing global objects, instead register the exception to be processed later
7484-            getMutableRegistryHub().registerStartupException();
7485-        }
7486-    }
7487-}
7488-
7489-
7490-
7491-
7492-
7493-namespace Catch {
7494-
7495-    TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
7496-
7497-    TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
7498-        m_mode = None;
7499-        m_exclusion = false;
7500-        m_arg = m_tagAliases->expandAliases( arg );
7501-        m_escapeChars.clear();
7502-        m_substring.reserve(m_arg.size());
7503-        m_patternName.reserve(m_arg.size());
7504-        m_realPatternPos = 0;
7505-
7506-        for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
7507-          //if visitChar fails
7508-           if( !visitChar( m_arg[m_pos] ) ){
7509-               m_testSpec.m_invalidSpecs.push_back(arg);
7510-               break;
7511-           }
7512-        endMode();
7513-        return *this;
7514-    }
7515-    TestSpec TestSpecParser::testSpec() {
7516-        addFilter();
7517-        return CATCH_MOVE(m_testSpec);
7518-    }
7519-    bool TestSpecParser::visitChar( char c ) {
7520-        if( (m_mode != EscapedName) && (c == '\\') ) {
7521-            escape();
7522-            addCharToPattern(c);
7523-            return true;
7524-        }else if((m_mode != EscapedName) && (c == ',') )  {
7525-            return separate();
7526-        }
7527-
7528-        switch( m_mode ) {
7529-        case None:
7530-            if( processNoneChar( c ) )
7531-                return true;
7532-            break;
7533-        case Name:
7534-            processNameChar( c );
7535-            break;
7536-        case EscapedName:
7537-            endMode();
7538-            addCharToPattern(c);
7539-            return true;
7540-        default:
7541-        case Tag:
7542-        case QuotedName:
7543-            if( processOtherChar( c ) )
7544-                return true;
7545-            break;
7546-        }
7547-
7548-        m_substring += c;
7549-        if( !isControlChar( c ) ) {
7550-            m_patternName += c;
7551-            m_realPatternPos++;
7552-        }
7553-        return true;
7554-    }
7555-    // Two of the processing methods return true to signal the caller to return
7556-    // without adding the given character to the current pattern strings
7557-    bool TestSpecParser::processNoneChar( char c ) {
7558-        switch( c ) {
7559-        case ' ':
7560-            return true;
7561-        case '~':
7562-            m_exclusion = true;
7563-            return false;
7564-        case '[':
7565-            startNewMode( Tag );
7566-            return false;
7567-        case '"':
7568-            startNewMode( QuotedName );
7569-            return false;
7570-        default:
7571-            startNewMode( Name );
7572-            return false;
7573-        }
7574-    }
7575-    void TestSpecParser::processNameChar( char c ) {
7576-        if( c == '[' ) {
7577-            if( m_substring == "exclude:" )
7578-                m_exclusion = true;
7579-            else
7580-                endMode();
7581-            startNewMode( Tag );
7582-        }
7583-    }
7584-    bool TestSpecParser::processOtherChar( char c ) {
7585-        if( !isControlChar( c ) )
7586-            return false;
7587-        m_substring += c;
7588-        endMode();
7589-        return true;
7590-    }
7591-    void TestSpecParser::startNewMode( Mode mode ) {
7592-        m_mode = mode;
7593-    }
7594-    void TestSpecParser::endMode() {
7595-        switch( m_mode ) {
7596-        case Name:
7597-        case QuotedName:
7598-            return addNamePattern();
7599-        case Tag:
7600-            return addTagPattern();
7601-        case EscapedName:
7602-            revertBackToLastMode();
7603-            return;
7604-        case None:
7605-        default:
7606-            return startNewMode( None );
7607-        }
7608-    }
7609-    void TestSpecParser::escape() {
7610-        saveLastMode();
7611-        m_mode = EscapedName;
7612-        m_escapeChars.push_back(m_realPatternPos);
7613-    }
7614-    bool TestSpecParser::isControlChar( char c ) const {
7615-        switch( m_mode ) {
7616-            default:
7617-                return false;
7618-            case None:
7619-                return c == '~';
7620-            case Name:
7621-                return c == '[';
7622-            case EscapedName:
7623-                return true;
7624-            case QuotedName:
7625-                return c == '"';
7626-            case Tag:
7627-                return c == '[' || c == ']';
7628-        }
7629-    }
7630-
7631-    void TestSpecParser::addFilter() {
7632-        if( !m_currentFilter.m_required.empty() || !m_currentFilter.m_forbidden.empty() ) {
7633-            m_testSpec.m_filters.push_back( CATCH_MOVE(m_currentFilter) );
7634-            m_currentFilter = TestSpec::Filter();
7635-        }
7636-    }
7637-
7638-    void TestSpecParser::saveLastMode() {
7639-      lastMode = m_mode;
7640-    }
7641-
7642-    void TestSpecParser::revertBackToLastMode() {
7643-      m_mode = lastMode;
7644-    }
7645-
7646-    bool TestSpecParser::separate() {
7647-      if( (m_mode==QuotedName) || (m_mode==Tag) ){
7648-         //invalid argument, signal failure to previous scope.
7649-         m_mode = None;
7650-         m_pos = m_arg.size();
7651-         m_substring.clear();
7652-         m_patternName.clear();
7653-         m_realPatternPos = 0;
7654-         return false;
7655-      }
7656-      endMode();
7657-      addFilter();
7658-      return true; //success
7659-    }
7660-
7661-    std::string TestSpecParser::preprocessPattern() {
7662-        std::string token = m_patternName;
7663-        for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
7664-            token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
7665-        m_escapeChars.clear();
7666-        if (startsWith(token, "exclude:")) {
7667-            m_exclusion = true;
7668-            token = token.substr(8);
7669-        }
7670-
7671-        m_patternName.clear();
7672-        m_realPatternPos = 0;
7673-
7674-        return token;
7675-    }
7676-
7677-    void TestSpecParser::addNamePattern() {
7678-        auto token = preprocessPattern();
7679-
7680-        if (!token.empty()) {
7681-            if (m_exclusion) {
7682-                m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::NamePattern>(token, m_substring));
7683-            } else {
7684-                m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::NamePattern>(token, m_substring));
7685-            }
7686-        }
7687-        m_substring.clear();
7688-        m_exclusion = false;
7689-        m_mode = None;
7690-    }
7691-
7692-    void TestSpecParser::addTagPattern() {
7693-        auto token = preprocessPattern();
7694-
7695-        if (!token.empty()) {
7696-            // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
7697-            // we have to create a separate hide tag and shorten the real one
7698-            if (token.size() > 1 && token[0] == '.') {
7699-                token.erase(token.begin());
7700-                if (m_exclusion) {
7701-                    m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
7702-                } else {
7703-                    m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
7704-                }
7705-            }
7706-            if (m_exclusion) {
7707-                m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
7708-            } else {
7709-                m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
7710-            }
7711-        }
7712-        m_substring.clear();
7713-        m_exclusion = false;
7714-        m_mode = None;
7715-    }
7716-
7717-} // namespace Catch
7718-
7719-
7720-
7721-#include <algorithm>
7722-#include <cstring>
7723-#include <ostream>
7724-
7725-namespace {
7726-    bool isWhitespace( char c ) {
7727-        return c == ' ' || c == '\t' || c == '\n' || c == '\r';
7728-    }
7729-
7730-    bool isBreakableBefore( char c ) {
7731-        static const char chars[] = "[({<|";
7732-        return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
7733-    }
7734-
7735-    bool isBreakableAfter( char c ) {
7736-        static const char chars[] = "])}>.,:;*+-=&/\\";
7737-        return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
7738-    }
7739-
7740-} // namespace
7741-
7742-namespace Catch {
7743-    namespace TextFlow {
7744-        void AnsiSkippingString::preprocessString() {
7745-            for ( auto it = m_string.begin(); it != m_string.end(); ) {
7746-                // try to read through an ansi sequence
7747-                while ( it != m_string.end() && *it == '\033' &&
7748-                        it + 1 != m_string.end() && *( it + 1 ) == '[' ) {
7749-                    auto cursor = it + 2;
7750-                    while ( cursor != m_string.end() &&
7751-                            ( isdigit( *cursor ) || *cursor == ';' ) ) {
7752-                        ++cursor;
7753-                    }
7754-                    if ( cursor == m_string.end() || *cursor != 'm' ) {
7755-                        break;
7756-                    }
7757-                    // 'm' -> 0xff
7758-                    *cursor = AnsiSkippingString::sentinel;
7759-                    // if we've read an ansi sequence, set the iterator and
7760-                    // return to the top of the loop
7761-                    it = cursor + 1;
7762-                }
7763-                if ( it != m_string.end() ) {
7764-                    ++m_size;
7765-                    ++it;
7766-                }
7767-            }
7768-        }
7769-
7770-        AnsiSkippingString::AnsiSkippingString( std::string const& text ):
7771-            m_string( text ) {
7772-            preprocessString();
7773-        }
7774-
7775-        AnsiSkippingString::AnsiSkippingString( std::string&& text ):
7776-            m_string( CATCH_MOVE( text ) ) {
7777-            preprocessString();
7778-        }
7779-
7780-        AnsiSkippingString::const_iterator AnsiSkippingString::begin() const {
7781-            return const_iterator( m_string );
7782-        }
7783-
7784-        AnsiSkippingString::const_iterator AnsiSkippingString::end() const {
7785-            return const_iterator( m_string, const_iterator::EndTag{} );
7786-        }
7787-
7788-        std::string AnsiSkippingString::substring( const_iterator begin,
7789-                                                   const_iterator end ) const {
7790-            // There's one caveat here to an otherwise simple substring: when
7791-            // making a begin iterator we might have skipped ansi sequences at
7792-            // the start. If `begin` here is a begin iterator, skipped over
7793-            // initial ansi sequences, we'll use the true beginning of the
7794-            // string. Lastly: We need to transform any chars we replaced with
7795-            // 0xff back to 'm'
7796-            auto str = std::string( begin == this->begin() ? m_string.begin()
7797-                                                           : begin.m_it,
7798-                                    end.m_it );
7799-            std::transform( str.begin(), str.end(), str.begin(), []( char c ) {
7800-                return c == AnsiSkippingString::sentinel ? 'm' : c;
7801-            } );
7802-            return str;
7803-        }
7804-
7805-        void AnsiSkippingString::const_iterator::tryParseAnsiEscapes() {
7806-            // check if we've landed on an ansi sequence, and if so read through
7807-            // it
7808-            while ( m_it != m_string->end() && *m_it == '\033' &&
7809-                    m_it + 1 != m_string->end() &&  *( m_it + 1 ) == '[' ) {
7810-                auto cursor = m_it + 2;
7811-                while ( cursor != m_string->end() &&
7812-                        ( isdigit( *cursor ) || *cursor == ';' ) ) {
7813-                    ++cursor;
7814-                }
7815-                if ( cursor == m_string->end() ||
7816-                     *cursor != AnsiSkippingString::sentinel ) {
7817-                    break;
7818-                }
7819-                // if we've read an ansi sequence, set the iterator and
7820-                // return to the top of the loop
7821-                m_it = cursor + 1;
7822-            }
7823-        }
7824-
7825-        void AnsiSkippingString::const_iterator::advance() {
7826-            assert( m_it != m_string->end() );
7827-            m_it++;
7828-            tryParseAnsiEscapes();
7829-        }
7830-
7831-        void AnsiSkippingString::const_iterator::unadvance() {
7832-            assert( m_it != m_string->begin() );
7833-            m_it--;
7834-            // if *m_it is 0xff, scan back to the \033 and then m_it-- once more
7835-            // (and repeat check)
7836-            while ( *m_it == AnsiSkippingString::sentinel ) {
7837-                while ( *m_it != '\033' ) {
7838-                    assert( m_it != m_string->begin() );
7839-                    m_it--;
7840-                }
7841-                // if this happens, we must have been a begin iterator that had
7842-                // skipped over ansi sequences at the start of a string
7843-                assert( m_it != m_string->begin() );
7844-                assert( *m_it == '\033' );
7845-                m_it--;
7846-            }
7847-        }
7848-
7849-        static bool isBoundary( AnsiSkippingString const& line,
7850-                                AnsiSkippingString::const_iterator it ) {
7851-            return it == line.end() ||
7852-                   ( isWhitespace( *it ) &&
7853-                     !isWhitespace( *it.oneBefore() ) ) ||
7854-                   isBreakableBefore( *it ) ||
7855-                   isBreakableAfter( *it.oneBefore() );
7856-        }
7857-
7858-        void Column::const_iterator::calcLength() {
7859-            m_addHyphen = false;
7860-            m_parsedTo = m_lineStart;
7861-            AnsiSkippingString const& current_line = m_column.m_string;
7862-
7863-            if ( m_parsedTo == current_line.end() ) {
7864-                m_lineEnd = m_parsedTo;
7865-                return;
7866-            }
7867-
7868-            assert( m_lineStart != current_line.end() );
7869-            if ( *m_lineStart == '\n' ) { ++m_parsedTo; }
7870-
7871-            const auto maxLineLength = m_column.m_width - indentSize();
7872-            std::size_t lineLength = 0;
7873-            while ( m_parsedTo != current_line.end() &&
7874-                    lineLength < maxLineLength && *m_parsedTo != '\n' ) {
7875-                ++m_parsedTo;
7876-                ++lineLength;
7877-            }
7878-
7879-            // If we encountered a newline before the column is filled,
7880-            // then we linebreak at the newline and consider this line
7881-            // finished.
7882-            if ( lineLength < maxLineLength ) {
7883-                m_lineEnd = m_parsedTo;
7884-            } else {
7885-                // Look for a natural linebreak boundary in the column
7886-                // (We look from the end, so that the first found boundary is
7887-                // the right one)
7888-                m_lineEnd = m_parsedTo;
7889-                while ( lineLength > 0 &&
7890-                        !isBoundary( current_line, m_lineEnd ) ) {
7891-                    --lineLength;
7892-                    --m_lineEnd;
7893-                }
7894-                while ( lineLength > 0 &&
7895-                        isWhitespace( *m_lineEnd.oneBefore() ) ) {
7896-                    --lineLength;
7897-                    --m_lineEnd;
7898-                }
7899-
7900-                // If we found one, then that is where we linebreak, otherwise
7901-                // we have to split text with a hyphen
7902-                if ( lineLength == 0 ) {
7903-                    m_addHyphen = true;
7904-                    m_lineEnd = m_parsedTo.oneBefore();
7905-                }
7906-            }
7907-        }
7908-
7909-        size_t Column::const_iterator::indentSize() const {
7910-            auto initial = m_lineStart == m_column.m_string.begin()
7911-                               ? m_column.m_initialIndent
7912-                               : std::string::npos;
7913-            return initial == std::string::npos ? m_column.m_indent : initial;
7914-        }
7915-
7916-        std::string Column::const_iterator::addIndentAndSuffix(
7917-            AnsiSkippingString::const_iterator start,
7918-            AnsiSkippingString::const_iterator end ) const {
7919-            std::string ret;
7920-            const auto desired_indent = indentSize();
7921-            // ret.reserve( desired_indent + (end - start) + m_addHyphen );
7922-            ret.append( desired_indent, ' ' );
7923-            // ret.append( start, end );
7924-            ret += m_column.m_string.substring( start, end );
7925-            if ( m_addHyphen ) { ret.push_back( '-' ); }
7926-
7927-            return ret;
7928-        }
7929-
7930-        Column::const_iterator::const_iterator( Column const& column ):
7931-            m_column( column ),
7932-            m_lineStart( column.m_string.begin() ),
7933-            m_lineEnd( column.m_string.begin() ),
7934-            m_parsedTo( column.m_string.begin() ) {
7935-            assert( m_column.m_width > m_column.m_indent );
7936-            assert( m_column.m_initialIndent == std::string::npos ||
7937-                    m_column.m_width > m_column.m_initialIndent );
7938-            calcLength();
7939-            if ( m_lineStart == m_lineEnd ) {
7940-                m_lineStart = m_column.m_string.end();
7941-            }
7942-        }
7943-
7944-        std::string Column::const_iterator::operator*() const {
7945-            assert( m_lineStart <= m_parsedTo );
7946-            return addIndentAndSuffix( m_lineStart, m_lineEnd );
7947-        }
7948-
7949-        Column::const_iterator& Column::const_iterator::operator++() {
7950-            m_lineStart = m_lineEnd;
7951-            AnsiSkippingString const& current_line = m_column.m_string;
7952-            if ( m_lineStart != current_line.end() && *m_lineStart == '\n' ) {
7953-                m_lineStart++;
7954-            } else {
7955-                while ( m_lineStart != current_line.end() &&
7956-                        isWhitespace( *m_lineStart ) ) {
7957-                    ++m_lineStart;
7958-                }
7959-            }
7960-
7961-            if ( m_lineStart != current_line.end() ) { calcLength(); }
7962-            return *this;
7963-        }
7964-
7965-        Column::const_iterator Column::const_iterator::operator++( int ) {
7966-            const_iterator prev( *this );
7967-            operator++();
7968-            return prev;
7969-        }
7970-
7971-        std::ostream& operator<<( std::ostream& os, Column const& col ) {
7972-            bool first = true;
7973-            for ( auto line : col ) {
7974-                if ( first ) {
7975-                    first = false;
7976-                } else {
7977-                    os << '\n';
7978-                }
7979-                os << line;
7980-            }
7981-            return os;
7982-        }
7983-
7984-        Column Spacer( size_t spaceWidth ) {
7985-            Column ret{ "" };
7986-            ret.width( spaceWidth );
7987-            return ret;
7988-        }
7989-
7990-        Columns::iterator::iterator( Columns const& columns, EndTag ):
7991-            m_columns( columns.m_columns ), m_activeIterators( 0 ) {
7992-
7993-            m_iterators.reserve( m_columns.size() );
7994-            for ( auto const& col : m_columns ) {
7995-                m_iterators.push_back( col.end() );
7996-            }
7997-        }
7998-
7999-        Columns::iterator::iterator( Columns const& columns ):
8000-            m_columns( columns.m_columns ),
8001-            m_activeIterators( m_columns.size() ) {
8002-
8003-            m_iterators.reserve( m_columns.size() );
8004-            for ( auto const& col : m_columns ) {
8005-                m_iterators.push_back( col.begin() );
8006-            }
8007-        }
8008-
8009-        std::string Columns::iterator::operator*() const {
8010-            std::string row, padding;
8011-
8012-            for ( size_t i = 0; i < m_columns.size(); ++i ) {
8013-                const auto width = m_columns[i].width();
8014-                if ( m_iterators[i] != m_columns[i].end() ) {
8015-                    std::string col = *m_iterators[i];
8016-                    row += padding;
8017-                    row += col;
8018-
8019-                    padding.clear();
8020-                    if ( col.size() < width ) {
8021-                        padding.append( width - col.size(), ' ' );
8022-                    }
8023-                } else {
8024-                    padding.append( width, ' ' );
8025-                }
8026-            }
8027-            return row;
8028-        }
8029-
8030-        Columns::iterator& Columns::iterator::operator++() {
8031-            for ( size_t i = 0; i < m_columns.size(); ++i ) {
8032-                if ( m_iterators[i] != m_columns[i].end() ) {
8033-                    ++m_iterators[i];
8034-                }
8035-            }
8036-            return *this;
8037-        }
8038-
8039-        Columns::iterator Columns::iterator::operator++( int ) {
8040-            iterator prev( *this );
8041-            operator++();
8042-            return prev;
8043-        }
8044-
8045-        std::ostream& operator<<( std::ostream& os, Columns const& cols ) {
8046-            bool first = true;
8047-            for ( auto line : cols ) {
8048-                if ( first ) {
8049-                    first = false;
8050-                } else {
8051-                    os << '\n';
8052-                }
8053-                os << line;
8054-            }
8055-            return os;
8056-        }
8057-
8058-        Columns operator+( Column const& lhs, Column const& rhs ) {
8059-            Columns cols;
8060-            cols += lhs;
8061-            cols += rhs;
8062-            return cols;
8063-        }
8064-        Columns operator+( Column&& lhs, Column&& rhs ) {
8065-            Columns cols;
8066-            cols += CATCH_MOVE( lhs );
8067-            cols += CATCH_MOVE( rhs );
8068-            return cols;
8069-        }
8070-
8071-        Columns& operator+=( Columns& lhs, Column const& rhs ) {
8072-            lhs.m_columns.push_back( rhs );
8073-            return lhs;
8074-        }
8075-        Columns& operator+=( Columns& lhs, Column&& rhs ) {
8076-            lhs.m_columns.push_back( CATCH_MOVE( rhs ) );
8077-            return lhs;
8078-        }
8079-        Columns operator+( Columns const& lhs, Column const& rhs ) {
8080-            auto combined( lhs );
8081-            combined += rhs;
8082-            return combined;
8083-        }
8084-        Columns operator+( Columns&& lhs, Column&& rhs ) {
8085-            lhs += CATCH_MOVE( rhs );
8086-            return CATCH_MOVE( lhs );
8087-        }
8088-
8089-    } // namespace TextFlow
8090-} // namespace Catch
8091-
8092-
8093-
8094-
8095-#include <exception>
8096-
8097-namespace Catch {
8098-    bool uncaught_exceptions() {
8099-#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
8100-        return false;
8101-#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
8102-        return std::uncaught_exceptions() > 0;
8103-#else
8104-        return std::uncaught_exception();
8105-#endif
8106-  }
8107-} // end namespace Catch
8108-
8109-
8110-
8111-namespace Catch {
8112-
8113-    WildcardPattern::WildcardPattern( std::string const& pattern,
8114-                                      CaseSensitive caseSensitivity )
8115-    :   m_caseSensitivity( caseSensitivity ),
8116-        m_pattern( normaliseString( pattern ) )
8117-    {
8118-        if( startsWith( m_pattern, '*' ) ) {
8119-            m_pattern = m_pattern.substr( 1 );
8120-            m_wildcard = WildcardAtStart;
8121-        }
8122-        if( endsWith( m_pattern, '*' ) ) {
8123-            m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
8124-            m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
8125-        }
8126-    }
8127-
8128-    bool WildcardPattern::matches( std::string const& str ) const {
8129-        switch( m_wildcard ) {
8130-            case NoWildcard:
8131-                return m_pattern == normaliseString( str );
8132-            case WildcardAtStart:
8133-                return endsWith( normaliseString( str ), m_pattern );
8134-            case WildcardAtEnd:
8135-                return startsWith( normaliseString( str ), m_pattern );
8136-            case WildcardAtBothEnds:
8137-                return contains( normaliseString( str ), m_pattern );
8138-            default:
8139-                CATCH_INTERNAL_ERROR( "Unknown enum" );
8140-        }
8141-    }
8142-
8143-    std::string WildcardPattern::normaliseString( std::string const& str ) const {
8144-        return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );
8145-    }
8146-}
8147-
8148-
8149-// Note: swapping these two includes around causes MSVC to error out
8150-//       while in /permissive- mode. No, I don't know why.
8151-//       Tested on VS 2019, 18.{3, 4}.x
8152-
8153-#include <cstdint>
8154-#include <iomanip>
8155-#include <type_traits>
8156-
8157-namespace Catch {
8158-
8159-namespace {
8160-
8161-    size_t trailingBytes(unsigned char c) {
8162-        if ((c & 0xE0) == 0xC0) {
8163-            return 2;
8164-        }
8165-        if ((c & 0xF0) == 0xE0) {
8166-            return 3;
8167-        }
8168-        if ((c & 0xF8) == 0xF0) {
8169-            return 4;
8170-        }
8171-        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
8172-    }
8173-
8174-    uint32_t headerValue(unsigned char c) {
8175-        if ((c & 0xE0) == 0xC0) {
8176-            return c & 0x1F;
8177-        }
8178-        if ((c & 0xF0) == 0xE0) {
8179-            return c & 0x0F;
8180-        }
8181-        if ((c & 0xF8) == 0xF0) {
8182-            return c & 0x07;
8183-        }
8184-        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
8185-    }
8186-
8187-    void hexEscapeChar(std::ostream& os, unsigned char c) {
8188-        std::ios_base::fmtflags f(os.flags());
8189-        os << "\\x"_sr
8190-            << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
8191-            << static_cast<int>(c);
8192-        os.flags(f);
8193-    }
8194-
8195-    constexpr bool shouldNewline(XmlFormatting fmt) {
8196-        return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Newline));
8197-    }
8198-
8199-    constexpr bool shouldIndent(XmlFormatting fmt) {
8200-        return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Indent));
8201-    }
8202-
8203-} // anonymous namespace
8204-
8205-    void XmlEncode::encodeTo( std::ostream& os ) const {
8206-        // Apostrophe escaping not necessary if we always use " to write attributes
8207-        // (see: http://www.w3.org/TR/xml/#syntax)
8208-        size_t last_start = 0;
8209-        auto write_to = [&]( size_t idx ) {
8210-            if ( last_start < idx ) {
8211-                os << m_str.substr( last_start, idx - last_start );
8212-            }
8213-            last_start = idx + 1;
8214-        };
8215-
8216-        for ( std::size_t idx = 0; idx < m_str.size(); ++idx ) {
8217-            unsigned char c = static_cast<unsigned char>( m_str[idx] );
8218-            switch ( c ) {
8219-            case '<':
8220-                write_to( idx );
8221-                os << "&lt;"_sr;
8222-                break;
8223-            case '&':
8224-                write_to( idx );
8225-                os << "&amp;"_sr;
8226-                break;
8227-
8228-            case '>':
8229-                // See: http://www.w3.org/TR/xml/#syntax
8230-                if ( idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']' ) {
8231-                    write_to( idx );
8232-                    os << "&gt;"_sr;
8233-                }
8234-                break;
8235-
8236-            case '\"':
8237-                if ( m_forWhat == ForAttributes ) {
8238-                    write_to( idx );
8239-                    os << "&quot;"_sr;
8240-                }
8241-                break;
8242-
8243-            default:
8244-                // Check for control characters and invalid utf-8
8245-
8246-                // Escape control characters in standard ascii
8247-                // see
8248-                // http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
8249-                if ( c < 0x09 || ( c > 0x0D && c < 0x20 ) || c == 0x7F ) {
8250-                    write_to( idx );
8251-                    hexEscapeChar( os, c );
8252-                    break;
8253-                }
8254-
8255-                // Plain ASCII: Write it to stream
8256-                if ( c < 0x7F ) {
8257-                    break;
8258-                }
8259-
8260-                // UTF-8 territory
8261-                // Check if the encoding is valid and if it is not, hex escape
8262-                // bytes. Important: We do not check the exact decoded values for
8263-                // validity, only the encoding format First check that this bytes is
8264-                // a valid lead byte: This means that it is not encoded as 1111 1XXX
8265-                // Or as 10XX XXXX
8266-                if ( c < 0xC0 || c >= 0xF8 ) {
8267-                    write_to( idx );
8268-                    hexEscapeChar( os, c );
8269-                    break;
8270-                }
8271-
8272-                auto encBytes = trailingBytes( c );
8273-                // Are there enough bytes left to avoid accessing out-of-bounds
8274-                // memory?
8275-                if ( idx + encBytes - 1 >= m_str.size() ) {
8276-                    write_to( idx );
8277-                    hexEscapeChar( os, c );
8278-                    break;
8279-                }
8280-                // The header is valid, check data
8281-                // The next encBytes bytes must together be a valid utf-8
8282-                // This means: bitpattern 10XX XXXX and the extracted value is sane
8283-                // (ish)
8284-                bool valid = true;
8285-                uint32_t value = headerValue( c );
8286-                for ( std::size_t n = 1; n < encBytes; ++n ) {
8287-                    unsigned char nc = static_cast<unsigned char>( m_str[idx + n] );
8288-                    valid &= ( ( nc & 0xC0 ) == 0x80 );
8289-                    value = ( value << 6 ) | ( nc & 0x3F );
8290-                }
8291-
8292-                if (
8293-                    // Wrong bit pattern of following bytes
8294-                    ( !valid ) ||
8295-                    // Overlong encodings
8296-                    ( value < 0x80 ) ||
8297-                    ( 0x80 <= value && value < 0x800 && encBytes > 2 ) ||
8298-                    ( 0x800 < value && value < 0x10000 && encBytes > 3 ) ||
8299-                    // Encoded value out of range
8300-                    ( value >= 0x110000 ) ) {
8301-                    write_to( idx );
8302-                    hexEscapeChar( os, c );
8303-                    break;
8304-                }
8305-
8306-                // If we got here, this is in fact a valid(ish) utf-8 sequence
8307-                idx += encBytes - 1;
8308-                break;
8309-            }
8310-        }
8311-
8312-        write_to( m_str.size() );
8313-    }
8314-
8315-    std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
8316-        xmlEncode.encodeTo( os );
8317-        return os;
8318-    }
8319-
8320-    XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt )
8321-    :   m_writer( writer ),
8322-        m_fmt(fmt)
8323-    {}
8324-
8325-    XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
8326-    :   m_writer( other.m_writer ),
8327-        m_fmt(other.m_fmt)
8328-    {
8329-        other.m_writer = nullptr;
8330-        other.m_fmt = XmlFormatting::None;
8331-    }
8332-    XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
8333-        if ( m_writer ) {
8334-            m_writer->endElement();
8335-        }
8336-        m_writer = other.m_writer;
8337-        other.m_writer = nullptr;
8338-        m_fmt = other.m_fmt;
8339-        other.m_fmt = XmlFormatting::None;
8340-        return *this;
8341-    }
8342-
8343-
8344-    XmlWriter::ScopedElement::~ScopedElement() {
8345-        if (m_writer) {
8346-            m_writer->endElement(m_fmt);
8347-        }
8348-    }
8349-
8350-    XmlWriter::ScopedElement&
8351-    XmlWriter::ScopedElement::writeText( StringRef text, XmlFormatting fmt ) {
8352-        m_writer->writeText( text, fmt );
8353-        return *this;
8354-    }
8355-
8356-    XmlWriter::ScopedElement&
8357-    XmlWriter::ScopedElement::writeAttribute( StringRef name,
8358-                                              StringRef attribute ) {
8359-        m_writer->writeAttribute( name, attribute );
8360-        return *this;
8361-    }
8362-
8363-
8364-    XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
8365-    {
8366-        writeDeclaration();
8367-    }
8368-
8369-    XmlWriter::~XmlWriter() {
8370-        while (!m_tags.empty()) {
8371-            endElement();
8372-        }
8373-        newlineIfNecessary();
8374-    }
8375-
8376-    XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) {
8377-        ensureTagClosed();
8378-        newlineIfNecessary();
8379-        if (shouldIndent(fmt)) {
8380-            m_os << m_indent;
8381-            m_indent += "  ";
8382-        }
8383-        m_os << '<' << name;
8384-        m_tags.push_back( name );
8385-        m_tagIsOpen = true;
8386-        applyFormatting(fmt);
8387-        return *this;
8388-    }
8389-
8390-    XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) {
8391-        ScopedElement scoped( this, fmt );
8392-        startElement( name, fmt );
8393-        return scoped;
8394-    }
8395-
8396-    XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {
8397-        m_indent = m_indent.substr(0, m_indent.size() - 2);
8398-
8399-        if( m_tagIsOpen ) {
8400-            m_os << "/>";
8401-            m_tagIsOpen = false;
8402-        } else {
8403-            newlineIfNecessary();
8404-            if (shouldIndent(fmt)) {
8405-                m_os << m_indent;
8406-            }
8407-            m_os << "</" << m_tags.back() << '>';
8408-        }
8409-        m_os << std::flush;
8410-        applyFormatting(fmt);
8411-        m_tags.pop_back();
8412-        return *this;
8413-    }
8414-
8415-    XmlWriter& XmlWriter::writeAttribute( StringRef name,
8416-                                          StringRef attribute ) {
8417-        if( !name.empty() && !attribute.empty() )
8418-            m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
8419-        return *this;
8420-    }
8421-
8422-    XmlWriter& XmlWriter::writeAttribute( StringRef name, bool attribute ) {
8423-        writeAttribute(name, (attribute ? "true"_sr : "false"_sr));
8424-        return *this;
8425-    }
8426-
8427-    XmlWriter& XmlWriter::writeAttribute( StringRef name,
8428-                                          char const* attribute ) {
8429-        writeAttribute( name, StringRef( attribute ) );
8430-        return *this;
8431-    }
8432-
8433-    XmlWriter& XmlWriter::writeText( StringRef text, XmlFormatting fmt ) {
8434-        CATCH_ENFORCE(!m_tags.empty(), "Cannot write text as top level element");
8435-        if( !text.empty() ){
8436-            bool tagWasOpen = m_tagIsOpen;
8437-            ensureTagClosed();
8438-            if (tagWasOpen && shouldIndent(fmt)) {
8439-                m_os << m_indent;
8440-            }
8441-            m_os << XmlEncode( text, XmlEncode::ForTextNodes );
8442-            applyFormatting(fmt);
8443-        }
8444-        return *this;
8445-    }
8446-
8447-    XmlWriter& XmlWriter::writeComment( StringRef text, XmlFormatting fmt ) {
8448-        ensureTagClosed();
8449-        if (shouldIndent(fmt)) {
8450-            m_os << m_indent;
8451-        }
8452-        m_os << "<!-- " << text << " -->";
8453-        applyFormatting(fmt);
8454-        return *this;
8455-    }
8456-
8457-    void XmlWriter::writeStylesheetRef( StringRef url ) {
8458-        m_os << R"(<?xml-stylesheet type="text/xsl" href=")" << url << R"("?>)" << '\n';
8459-    }
8460-
8461-    void XmlWriter::ensureTagClosed() {
8462-        if( m_tagIsOpen ) {
8463-            m_os << '>' << std::flush;
8464-            newlineIfNecessary();
8465-            m_tagIsOpen = false;
8466-        }
8467-    }
8468-
8469-    void XmlWriter::applyFormatting(XmlFormatting fmt) {
8470-        m_needsNewline = shouldNewline(fmt);
8471-    }
8472-
8473-    void XmlWriter::writeDeclaration() {
8474-        m_os << R"(<?xml version="1.0" encoding="UTF-8"?>)" << '\n';
8475-    }
8476-
8477-    void XmlWriter::newlineIfNecessary() {
8478-        if( m_needsNewline ) {
8479-            m_os << '\n' << std::flush;
8480-            m_needsNewline = false;
8481-        }
8482-    }
8483-}
8484-
8485-
8486-
8487-
8488-
8489-namespace Catch {
8490-namespace Matchers {
8491-
8492-    std::string MatcherUntypedBase::toString() const {
8493-        if (m_cachedToString.empty()) {
8494-            m_cachedToString = describe();
8495-        }
8496-        return m_cachedToString;
8497-    }
8498-
8499-    MatcherUntypedBase::~MatcherUntypedBase() = default;
8500-
8501-} // namespace Matchers
8502-} // namespace Catch
8503-
8504-
8505-
8506-
8507-namespace Catch {
8508-namespace Matchers {
8509-
8510-    std::string IsEmptyMatcher::describe() const {
8511-        return "is empty";
8512-    }
8513-
8514-    std::string HasSizeMatcher::describe() const {
8515-        ReusableStringStream sstr;
8516-        sstr << "has size == " << m_target_size;
8517-        return sstr.str();
8518-    }
8519-
8520-    IsEmptyMatcher IsEmpty() {
8521-        return {};
8522-    }
8523-
8524-    HasSizeMatcher SizeIs(std::size_t sz) {
8525-        return HasSizeMatcher{ sz };
8526-    }
8527-
8528-} // end namespace Matchers
8529-} // end namespace Catch
8530-
8531-
8532-
8533-namespace Catch {
8534-namespace Matchers {
8535-
8536-bool ExceptionMessageMatcher::match(std::exception const& ex) const {
8537-    return ex.what() == m_message;
8538-}
8539-
8540-std::string ExceptionMessageMatcher::describe() const {
8541-    return "exception message matches \"" + m_message + '"';
8542-}
8543-
8544-ExceptionMessageMatcher Message(std::string const& message) {
8545-    return ExceptionMessageMatcher(message);
8546-}
8547-
8548-} // namespace Matchers
8549-} // namespace Catch
8550-
8551-
8552-
8553-#include <algorithm>
8554-#include <cmath>
8555-#include <cstdlib>
8556-#include <cstdint>
8557-#include <sstream>
8558-#include <iomanip>
8559-#include <limits>
8560-
8561-
8562-namespace Catch {
8563-namespace {
8564-
8565-    template <typename FP>
8566-    bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {
8567-        // Comparison with NaN should always be false.
8568-        // This way we can rule it out before getting into the ugly details
8569-        if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
8570-            return false;
8571-        }
8572-
8573-        // This should also handle positive and negative zeros, infinities
8574-        const auto ulpDist = ulpDistance(lhs, rhs);
8575-
8576-        return ulpDist <= maxUlpDiff;
8577-    }
8578-
8579-
8580-template <typename FP>
8581-FP step(FP start, FP direction, uint64_t steps) {
8582-    for (uint64_t i = 0; i < steps; ++i) {
8583-        start = Catch::nextafter(start, direction);
8584-    }
8585-    return start;
8586-}
8587-
8588-// Performs equivalent check of std::fabs(lhs - rhs) <= margin
8589-// But without the subtraction to allow for INFINITY in comparison
8590-bool marginComparison(double lhs, double rhs, double margin) {
8591-    return (lhs + margin >= rhs) && (rhs + margin >= lhs);
8592-}
8593-
8594-template <typename FloatingPoint>
8595-void write(std::ostream& out, FloatingPoint num) {
8596-    out << std::scientific
8597-        << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
8598-        << num;
8599-}
8600-
8601-} // end anonymous namespace
8602-
8603-namespace Matchers {
8604-namespace Detail {
8605-
8606-    enum class FloatingPointKind : uint8_t {
8607-        Float,
8608-        Double
8609-    };
8610-
8611-} // end namespace Detail
8612-
8613-
8614-    WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
8615-        :m_target{ target }, m_margin{ margin } {
8616-        CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
8617-            << " Margin has to be non-negative.");
8618-    }
8619-
8620-    // Performs equivalent check of std::fabs(lhs - rhs) <= margin
8621-    // But without the subtraction to allow for INFINITY in comparison
8622-    bool WithinAbsMatcher::match(double const& matchee) const {
8623-        return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
8624-    }
8625-
8626-    std::string WithinAbsMatcher::describe() const {
8627-        return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
8628-    }
8629-
8630-
8631-    WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType)
8632-        :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
8633-        CATCH_ENFORCE(m_type == Detail::FloatingPointKind::Double
8634-                   || m_ulps < (std::numeric_limits<uint32_t>::max)(),
8635-            "Provided ULP is impossibly large for a float comparison.");
8636-        CATCH_ENFORCE( std::numeric_limits<double>::is_iec559,
8637-                       "WithinUlp matcher only supports platforms with "
8638-                       "IEEE-754 compatible floating point representation" );
8639-    }
8640-
8641-#if defined(__clang__)
8642-#pragma clang diagnostic push
8643-// Clang <3.5 reports on the default branch in the switch below
8644-#pragma clang diagnostic ignored "-Wunreachable-code"
8645-#endif
8646-
8647-    bool WithinUlpsMatcher::match(double const& matchee) const {
8648-        switch (m_type) {
8649-        case Detail::FloatingPointKind::Float:
8650-            return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
8651-        case Detail::FloatingPointKind::Double:
8652-            return almostEqualUlps<double>(matchee, m_target, m_ulps);
8653-        default:
8654-            CATCH_INTERNAL_ERROR( "Unknown Detail::FloatingPointKind value" );
8655-        }
8656-    }
8657-
8658-#if defined(__clang__)
8659-#pragma clang diagnostic pop
8660-#endif
8661-
8662-    std::string WithinUlpsMatcher::describe() const {
8663-        std::stringstream ret;
8664-
8665-        ret << "is within " << m_ulps << " ULPs of ";
8666-
8667-        if (m_type == Detail::FloatingPointKind::Float) {
8668-            write(ret, static_cast<float>(m_target));
8669-            ret << 'f';
8670-        } else {
8671-            write(ret, m_target);
8672-        }
8673-
8674-        ret << " ([";
8675-        if (m_type == Detail::FloatingPointKind::Double) {
8676-            write( ret,
8677-                   step( m_target,
8678-                         -std::numeric_limits<double>::infinity(),
8679-                         m_ulps ) );
8680-            ret << ", ";
8681-            write( ret,
8682-                   step( m_target,
8683-                         std::numeric_limits<double>::infinity(),
8684-                         m_ulps ) );
8685-        } else {
8686-            // We have to cast INFINITY to float because of MinGW, see #1782
8687-            write( ret,
8688-                   step( static_cast<float>( m_target ),
8689-                         -std::numeric_limits<float>::infinity(),
8690-                         m_ulps ) );
8691-            ret << ", ";
8692-            write( ret,
8693-                   step( static_cast<float>( m_target ),
8694-                         std::numeric_limits<float>::infinity(),
8695-                         m_ulps ) );
8696-        }
8697-        ret << "])";
8698-
8699-        return ret.str();
8700-    }
8701-
8702-    WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
8703-        m_target(target),
8704-        m_epsilon(epsilon){
8705-        CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon <  0 does not make sense.");
8706-        CATCH_ENFORCE(m_epsilon  < 1., "Relative comparison with epsilon >= 1 does not make sense.");
8707-    }
8708-
8709-    bool WithinRelMatcher::match(double const& matchee) const {
8710-        const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
8711-        return marginComparison(matchee, m_target,
8712-                                std::isinf(relMargin)? 0 : relMargin);
8713-    }
8714-
8715-    std::string WithinRelMatcher::describe() const {
8716-        Catch::ReusableStringStream sstr;
8717-        sstr << "and " << ::Catch::Detail::stringify(m_target) << " are within " << m_epsilon * 100. << "% of each other";
8718-        return sstr.str();
8719-    }
8720-
8721-
8722-WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
8723-    return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Double);
8724-}
8725-
8726-WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
8727-    return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Float);
8728-}
8729-
8730-WithinAbsMatcher WithinAbs(double target, double margin) {
8731-    return WithinAbsMatcher(target, margin);
8732-}
8733-
8734-WithinRelMatcher WithinRel(double target, double eps) {
8735-    return WithinRelMatcher(target, eps);
8736-}
8737-
8738-WithinRelMatcher WithinRel(double target) {
8739-    return WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
8740-}
8741-
8742-WithinRelMatcher WithinRel(float target, float eps) {
8743-    return WithinRelMatcher(target, eps);
8744-}
8745-
8746-WithinRelMatcher WithinRel(float target) {
8747-    return WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
8748-}
8749-
8750-
8751-
8752-bool IsNaNMatcher::match( double const& matchee ) const {
8753-    return std::isnan( matchee );
8754-}
8755-
8756-std::string IsNaNMatcher::describe() const {
8757-    using namespace std::string_literals;
8758-    return "is NaN"s;
8759-}
8760-
8761-IsNaNMatcher IsNaN() { return IsNaNMatcher(); }
8762-
8763-    } // namespace Matchers
8764-} // namespace Catch
8765-
8766-
8767-
8768-
8769-std::string Catch::Matchers::Detail::finalizeDescription(const std::string& desc) {
8770-    if (desc.empty()) {
8771-        return "matches undescribed predicate";
8772-    } else {
8773-        return "matches predicate: \"" + desc + '"';
8774-    }
8775-}
8776-
8777-
8778-
8779-namespace Catch {
8780-    namespace Matchers {
8781-        std::string AllTrueMatcher::describe() const { return "contains only true"; }
8782-
8783-        AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
8784-
8785-        std::string NoneTrueMatcher::describe() const { return "contains no true"; }
8786-
8787-        NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
8788-
8789-        std::string AnyTrueMatcher::describe() const { return "contains at least one true"; }
8790-
8791-        AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
8792-    } // namespace Matchers
8793-} // namespace Catch
8794-
8795-
8796-
8797-#include <regex>
8798-
8799-namespace Catch {
8800-namespace Matchers {
8801-
8802-    CasedString::CasedString( std::string const& str, CaseSensitive caseSensitivity )
8803-    :   m_caseSensitivity( caseSensitivity ),
8804-        m_str( adjustString( str ) )
8805-    {}
8806-    std::string CasedString::adjustString( std::string const& str ) const {
8807-        return m_caseSensitivity == CaseSensitive::No
8808-               ? toLower( str )
8809-               : str;
8810-    }
8811-    StringRef CasedString::caseSensitivitySuffix() const {
8812-        return m_caseSensitivity == CaseSensitive::Yes
8813-                   ? StringRef()
8814-                   : " (case insensitive)"_sr;
8815-    }
8816-
8817-
8818-    StringMatcherBase::StringMatcherBase( StringRef operation, CasedString const& comparator )
8819-    : m_comparator( comparator ),
8820-      m_operation( operation ) {
8821-    }
8822-
8823-    std::string StringMatcherBase::describe() const {
8824-        std::string description;
8825-        description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
8826-                                    m_comparator.caseSensitivitySuffix().size());
8827-        description += m_operation;
8828-        description += ": \"";
8829-        description += m_comparator.m_str;
8830-        description += '"';
8831-        description += m_comparator.caseSensitivitySuffix();
8832-        return description;
8833-    }
8834-
8835-    StringEqualsMatcher::StringEqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals"_sr, comparator ) {}
8836-
8837-    bool StringEqualsMatcher::match( std::string const& source ) const {
8838-        return m_comparator.adjustString( source ) == m_comparator.m_str;
8839-    }
8840-
8841-
8842-    StringContainsMatcher::StringContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains"_sr, comparator ) {}
8843-
8844-    bool StringContainsMatcher::match( std::string const& source ) const {
8845-        return contains( m_comparator.adjustString( source ), m_comparator.m_str );
8846-    }
8847-
8848-
8849-    StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with"_sr, comparator ) {}
8850-
8851-    bool StartsWithMatcher::match( std::string const& source ) const {
8852-        return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8853-    }
8854-
8855-
8856-    EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with"_sr, comparator ) {}
8857-
8858-    bool EndsWithMatcher::match( std::string const& source ) const {
8859-        return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8860-    }
8861-
8862-
8863-
8864-    RegexMatcher::RegexMatcher(std::string regex, CaseSensitive caseSensitivity): m_regex(CATCH_MOVE(regex)), m_caseSensitivity(caseSensitivity) {}
8865-
8866-    bool RegexMatcher::match(std::string const& matchee) const {
8867-        auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
8868-        if (m_caseSensitivity == CaseSensitive::No) {
8869-            flags |= std::regex::icase;
8870-        }
8871-        auto reg = std::regex(m_regex, flags);
8872-        return std::regex_match(matchee, reg);
8873-    }
8874-
8875-    std::string RegexMatcher::describe() const {
8876-        return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Yes)? " case sensitively" : " case insensitively");
8877-    }
8878-
8879-
8880-    StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity ) {
8881-        return StringEqualsMatcher( CasedString( str, caseSensitivity) );
8882-    }
8883-    StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity ) {
8884-        return StringContainsMatcher( CasedString( str, caseSensitivity) );
8885-    }
8886-    EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity ) {
8887-        return EndsWithMatcher( CasedString( str, caseSensitivity) );
8888-    }
8889-    StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity ) {
8890-        return StartsWithMatcher( CasedString( str, caseSensitivity) );
8891-    }
8892-
8893-    RegexMatcher Matches(std::string const& regex, CaseSensitive caseSensitivity) {
8894-        return RegexMatcher(regex, caseSensitivity);
8895-    }
8896-
8897-} // namespace Matchers
8898-} // namespace Catch
8899-
8900-
8901-
8902-namespace Catch {
8903-namespace Matchers {
8904-    MatcherGenericBase::~MatcherGenericBase() = default;
8905-
8906-    namespace Detail {
8907-
8908-        std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end) {
8909-            std::string description;
8910-            std::size_t combined_size = 4;
8911-            for ( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
8912-                combined_size += desc->size();
8913-            }
8914-            combined_size += static_cast<size_t>(descriptions_end - descriptions_begin - 1) * combine.size();
8915-
8916-            description.reserve(combined_size);
8917-
8918-            description += "( ";
8919-            bool first = true;
8920-            for( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
8921-                if( first )
8922-                    first = false;
8923-                else
8924-                    description += combine;
8925-                description += *desc;
8926-            }
8927-            description += " )";
8928-            return description;
8929-        }
8930-
8931-    } // namespace Detail
8932-} // namespace Matchers
8933-} // namespace Catch
8934-
8935-
8936-
8937-
8938-namespace Catch {
8939-
8940-    // This is the general overload that takes a any string matcher
8941-    // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
8942-    // the Equals matcher (so the header does not mention matchers)
8943-    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher ) {
8944-        std::string exceptionMessage = Catch::translateActiveException();
8945-        MatchExpr<std::string, StringMatcher const&> expr( CATCH_MOVE(exceptionMessage), matcher );
8946-        handler.handleExpr( expr );
8947-    }
8948-
8949-} // namespace Catch
8950-
8951-
8952-
8953-#include <ostream>
8954-
8955-namespace Catch {
8956-
8957-    AutomakeReporter::~AutomakeReporter() = default;
8958-
8959-    void AutomakeReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
8960-        // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR.
8961-        m_stream << ":test-result: ";
8962-        if ( _testCaseStats.totals.testCases.skipped > 0 ) {
8963-            m_stream << "SKIP";
8964-        } else if (_testCaseStats.totals.assertions.allPassed()) {
8965-            m_stream << "PASS";
8966-        } else if (_testCaseStats.totals.assertions.allOk()) {
8967-            m_stream << "XFAIL";
8968-        } else {
8969-            m_stream << "FAIL";
8970-        }
8971-        m_stream << ' ' << _testCaseStats.testInfo->name << '\n';
8972-        StreamingReporterBase::testCaseEnded(_testCaseStats);
8973-    }
8974-
8975-    void AutomakeReporter::skipTest(TestCaseInfo const& testInfo) {
8976-        m_stream << ":test-result: SKIP " << testInfo.name << '\n';
8977-    }
8978-
8979-} // end namespace Catch
8980-
8981-
8982-
8983-
8984-
8985-
8986-namespace Catch {
8987-    ReporterBase::ReporterBase( ReporterConfig&& config ):
8988-        IEventListener( config.fullConfig() ),
8989-        m_wrapped_stream( CATCH_MOVE(config).takeStream() ),
8990-        m_stream( m_wrapped_stream->stream() ),
8991-        m_colour( makeColourImpl( config.colourMode(), m_wrapped_stream.get() ) ),
8992-        m_customOptions( config.customOptions() )
8993-    {}
8994-
8995-    ReporterBase::~ReporterBase() = default;
8996-
8997-    void ReporterBase::listReporters(
8998-        std::vector<ReporterDescription> const& descriptions ) {
8999-        defaultListReporters(m_stream, descriptions, m_config->verbosity());
9000-    }
9001-
9002-    void ReporterBase::listListeners(
9003-        std::vector<ListenerDescription> const& descriptions ) {
9004-        defaultListListeners( m_stream, descriptions );
9005-    }
9006-
9007-    void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
9008-        defaultListTests(m_stream,
9009-                         m_colour.get(),
9010-                         tests,
9011-                         m_config->hasTestFilters(),
9012-                         m_config->verbosity());
9013-    }
9014-
9015-    void ReporterBase::listTags(std::vector<TagInfo> const& tags) {
9016-        defaultListTags( m_stream, tags, m_config->hasTestFilters() );
9017-    }
9018-
9019-} // namespace Catch
9020-
9021-
9022-
9023-
9024-#include <ostream>
9025-
9026-namespace Catch {
9027-namespace {
9028-
9029-    // Colour::LightGrey
9030-    static constexpr Colour::Code compactDimColour = Colour::FileName;
9031-
9032-#ifdef CATCH_PLATFORM_MAC
9033-    static constexpr Catch::StringRef compactFailedString = "FAILED"_sr;
9034-    static constexpr Catch::StringRef compactPassedString = "PASSED"_sr;
9035-#else
9036-    static constexpr Catch::StringRef compactFailedString = "failed"_sr;
9037-    static constexpr Catch::StringRef compactPassedString = "passed"_sr;
9038-#endif
9039-
9040-// Implementation of CompactReporter formatting
9041-class AssertionPrinter {
9042-public:
9043-    AssertionPrinter& operator= (AssertionPrinter const&) = delete;
9044-    AssertionPrinter(AssertionPrinter const&) = delete;
9045-    AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages, ColourImpl* colourImpl_)
9046-        : stream(_stream)
9047-        , result(_stats.assertionResult)
9048-        , messages(_stats.infoMessages)
9049-        , itMessage(_stats.infoMessages.begin())
9050-        , printInfoMessages(_printInfoMessages)
9051-        , colourImpl(colourImpl_)
9052-    {}
9053-
9054-    void print() {
9055-        printSourceInfo();
9056-
9057-        itMessage = messages.begin();
9058-
9059-        switch (result.getResultType()) {
9060-        case ResultWas::Ok:
9061-            printResultType(Colour::ResultSuccess, compactPassedString);
9062-            printOriginalExpression();
9063-            printReconstructedExpression();
9064-            if (!result.hasExpression())
9065-                printRemainingMessages(Colour::None);
9066-            else
9067-                printRemainingMessages();
9068-            break;
9069-        case ResultWas::ExpressionFailed:
9070-            if (result.isOk())
9071-                printResultType(Colour::ResultSuccess, compactFailedString + " - but was ok"_sr);
9072-            else
9073-                printResultType(Colour::Error, compactFailedString);
9074-            printOriginalExpression();
9075-            printReconstructedExpression();
9076-            printRemainingMessages();
9077-            break;
9078-        case ResultWas::ThrewException:
9079-            printResultType(Colour::Error, compactFailedString);
9080-            printIssue("unexpected exception with message:");
9081-            printMessage();
9082-            printExpressionWas();
9083-            printRemainingMessages();
9084-            break;
9085-        case ResultWas::FatalErrorCondition:
9086-            printResultType(Colour::Error, compactFailedString);
9087-            printIssue("fatal error condition with message:");
9088-            printMessage();
9089-            printExpressionWas();
9090-            printRemainingMessages();
9091-            break;
9092-        case ResultWas::DidntThrowException:
9093-            printResultType(Colour::Error, compactFailedString);
9094-            printIssue("expected exception, got none");
9095-            printExpressionWas();
9096-            printRemainingMessages();
9097-            break;
9098-        case ResultWas::Info:
9099-            printResultType(Colour::None, "info"_sr);
9100-            printMessage();
9101-            printRemainingMessages();
9102-            break;
9103-        case ResultWas::Warning:
9104-            printResultType(Colour::None, "warning"_sr);
9105-            printMessage();
9106-            printRemainingMessages();
9107-            break;
9108-        case ResultWas::ExplicitFailure:
9109-            printResultType(Colour::Error, compactFailedString);
9110-            printIssue("explicitly");
9111-            printRemainingMessages(Colour::None);
9112-            break;
9113-        case ResultWas::ExplicitSkip:
9114-            printResultType(Colour::Skip, "skipped"_sr);
9115-            printMessage();
9116-            printRemainingMessages();
9117-            break;
9118-            // These cases are here to prevent compiler warnings
9119-        case ResultWas::Unknown:
9120-        case ResultWas::FailureBit:
9121-        case ResultWas::Exception:
9122-            printResultType(Colour::Error, "** internal error **");
9123-            break;
9124-        }
9125-    }
9126-
9127-private:
9128-    void printSourceInfo() const {
9129-        stream << colourImpl->guardColour( Colour::FileName )
9130-               << result.getSourceInfo() << ':';
9131-    }
9132-
9133-    void printResultType(Colour::Code colour, StringRef passOrFail) const {
9134-        if (!passOrFail.empty()) {
9135-            stream << colourImpl->guardColour(colour) << ' ' << passOrFail;
9136-            stream << ':';
9137-        }
9138-    }
9139-
9140-    void printIssue(char const* issue) const {
9141-        stream << ' ' << issue;
9142-    }
9143-
9144-    void printExpressionWas() {
9145-        if (result.hasExpression()) {
9146-            stream << ';';
9147-            {
9148-                stream << colourImpl->guardColour(compactDimColour) << " expression was:";
9149-            }
9150-            printOriginalExpression();
9151-        }
9152-    }
9153-
9154-    void printOriginalExpression() const {
9155-        if (result.hasExpression()) {
9156-            stream << ' ' << result.getExpression();
9157-        }
9158-    }
9159-
9160-    void printReconstructedExpression() const {
9161-        if (result.hasExpandedExpression()) {
9162-            stream << colourImpl->guardColour(compactDimColour) << " for: ";
9163-            stream << result.getExpandedExpression();
9164-        }
9165-    }
9166-
9167-    void printMessage() {
9168-        if (itMessage != messages.end()) {
9169-            stream << " '" << itMessage->message << '\'';
9170-            ++itMessage;
9171-        }
9172-    }
9173-
9174-    void printRemainingMessages(Colour::Code colour = compactDimColour) {
9175-        if (itMessage == messages.end())
9176-            return;
9177-
9178-        const auto itEnd = messages.cend();
9179-        const auto N = static_cast<std::size_t>(itEnd - itMessage);
9180-
9181-        stream << colourImpl->guardColour( colour ) << " with "
9182-               << pluralise( N, "message"_sr ) << ':';
9183-
9184-        while (itMessage != itEnd) {
9185-            // If this assertion is a warning ignore any INFO messages
9186-            if (printInfoMessages || itMessage->type != ResultWas::Info) {
9187-                printMessage();
9188-                if (itMessage != itEnd) {
9189-                    stream << colourImpl->guardColour(compactDimColour) << " and";
9190-                }
9191-                continue;
9192-            }
9193-            ++itMessage;
9194-        }
9195-    }
9196-
9197-private:
9198-    std::ostream& stream;
9199-    AssertionResult const& result;
9200-    std::vector<MessageInfo> const& messages;
9201-    std::vector<MessageInfo>::const_iterator itMessage;
9202-    bool printInfoMessages;
9203-    ColourImpl* colourImpl;
9204-};
9205-
9206-} // anon namespace
9207-
9208-        std::string CompactReporter::getDescription() {
9209-            return "Reports test results on a single line, suitable for IDEs";
9210-        }
9211-
9212-        void CompactReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
9213-            m_stream << "No test cases matched '" << unmatchedSpec << "'\n";
9214-        }
9215-
9216-        void CompactReporter::testRunStarting( TestRunInfo const& ) {
9217-            if ( m_config->testSpec().hasFilters() ) {
9218-                m_stream << m_colour->guardColour( Colour::BrightYellow )
9219-                         << "Filters: "
9220-                         << m_config->testSpec()
9221-                         << '\n';
9222-            }
9223-            m_stream << "RNG seed: " << getSeed() << '\n'
9224-                     << std::flush;
9225-        }
9226-
9227-        void CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
9228-            AssertionResult const& result = _assertionStats.assertionResult;
9229-
9230-            bool printInfoMessages = true;
9231-
9232-            // Drop out if result was successful and we're not printing those
9233-            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
9234-                if( result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip )
9235-                    return;
9236-                printInfoMessages = false;
9237-            }
9238-
9239-            AssertionPrinter printer( m_stream, _assertionStats, printInfoMessages, m_colour.get() );
9240-            printer.print();
9241-
9242-            m_stream << '\n' << std::flush;
9243-        }
9244-
9245-        void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
9246-            double dur = _sectionStats.durationInSeconds;
9247-            if ( shouldShowDuration( *m_config, dur ) ) {
9248-                m_stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << '\n' << std::flush;
9249-            }
9250-        }
9251-
9252-        void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {
9253-            printTestRunTotals( m_stream, *m_colour, _testRunStats.totals );
9254-            m_stream << "\n\n" << std::flush;
9255-            StreamingReporterBase::testRunEnded( _testRunStats );
9256-        }
9257-
9258-        CompactReporter::~CompactReporter() = default;
9259-
9260-} // end namespace Catch
9261-
9262-
9263-
9264-
9265-#include <cstdio>
9266-
9267-#if defined(_MSC_VER)
9268-#pragma warning(push)
9269-#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
9270- // Note that 4062 (not all labels are handled and default is missing) is enabled
9271-#endif
9272-
9273-#if defined(__clang__)
9274-#  pragma clang diagnostic push
9275-// For simplicity, benchmarking-only helpers are always enabled
9276-#  pragma clang diagnostic ignored "-Wunused-function"
9277-#endif
9278-
9279-
9280-
9281-namespace Catch {
9282-
9283-namespace {
9284-
9285-// Formatter impl for ConsoleReporter
9286-class ConsoleAssertionPrinter {
9287-public:
9288-    ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;
9289-    ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
9290-    ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, ColourImpl* colourImpl_, bool _printInfoMessages)
9291-        : stream(_stream),
9292-        stats(_stats),
9293-        result(_stats.assertionResult),
9294-        colour(Colour::None),
9295-        messages(_stats.infoMessages),
9296-        colourImpl(colourImpl_),
9297-        printInfoMessages(_printInfoMessages) {
9298-        switch (result.getResultType()) {
9299-        case ResultWas::Ok:
9300-            colour = Colour::Success;
9301-            passOrFail = "PASSED"_sr;
9302-            //if( result.hasMessage() )
9303-            if (messages.size() == 1)
9304-                messageLabel = "with message"_sr;
9305-            if (messages.size() > 1)
9306-                messageLabel = "with messages"_sr;
9307-            break;
9308-        case ResultWas::ExpressionFailed:
9309-            if (result.isOk()) {
9310-                colour = Colour::Success;
9311-                passOrFail = "FAILED - but was ok"_sr;
9312-            } else {
9313-                colour = Colour::Error;
9314-                passOrFail = "FAILED"_sr;
9315-            }
9316-            if (messages.size() == 1)
9317-                messageLabel = "with message"_sr;
9318-            if (messages.size() > 1)
9319-                messageLabel = "with messages"_sr;
9320-            break;
9321-        case ResultWas::ThrewException:
9322-            colour = Colour::Error;
9323-            passOrFail = "FAILED"_sr;
9324-            // todo switch
9325-            switch (messages.size()) { case 0:
9326-                messageLabel = "due to unexpected exception with "_sr;
9327-                break;
9328-            case 1:
9329-                messageLabel = "due to unexpected exception with message"_sr;
9330-                break;
9331-            default:
9332-                messageLabel = "due to unexpected exception with messages"_sr;
9333-                break;
9334-            }
9335-            break;
9336-        case ResultWas::FatalErrorCondition:
9337-            colour = Colour::Error;
9338-            passOrFail = "FAILED"_sr;
9339-            messageLabel = "due to a fatal error condition"_sr;
9340-            break;
9341-        case ResultWas::DidntThrowException:
9342-            colour = Colour::Error;
9343-            passOrFail = "FAILED"_sr;
9344-            messageLabel = "because no exception was thrown where one was expected"_sr;
9345-            break;
9346-        case ResultWas::Info:
9347-            messageLabel = "info"_sr;
9348-            break;
9349-        case ResultWas::Warning:
9350-            messageLabel = "warning"_sr;
9351-            break;
9352-        case ResultWas::ExplicitFailure:
9353-            passOrFail = "FAILED"_sr;
9354-            colour = Colour::Error;
9355-            if (messages.size() == 1)
9356-                messageLabel = "explicitly with message"_sr;
9357-            if (messages.size() > 1)
9358-                messageLabel = "explicitly with messages"_sr;
9359-            break;
9360-        case ResultWas::ExplicitSkip:
9361-            colour = Colour::Skip;
9362-            passOrFail = "SKIPPED"_sr;
9363-            if (messages.size() == 1)
9364-                messageLabel = "explicitly with message"_sr;
9365-            if (messages.size() > 1)
9366-                messageLabel = "explicitly with messages"_sr;
9367-            break;
9368-            // These cases are here to prevent compiler warnings
9369-        case ResultWas::Unknown:
9370-        case ResultWas::FailureBit:
9371-        case ResultWas::Exception:
9372-            passOrFail = "** internal error **"_sr;
9373-            colour = Colour::Error;
9374-            break;
9375-        }
9376-    }
9377-
9378-    void print() const {
9379-        printSourceInfo();
9380-        if (stats.totals.assertions.total() > 0) {
9381-            printResultType();
9382-            printOriginalExpression();
9383-            printReconstructedExpression();
9384-        } else {
9385-            stream << '\n';
9386-        }
9387-        printMessage();
9388-    }
9389-
9390-private:
9391-    void printResultType() const {
9392-        if (!passOrFail.empty()) {
9393-            stream << colourImpl->guardColour(colour) << passOrFail << ":\n";
9394-        }
9395-    }
9396-    void printOriginalExpression() const {
9397-        if (result.hasExpression()) {
9398-            stream << colourImpl->guardColour( Colour::OriginalExpression )
9399-                   << "  " << result.getExpressionInMacro() << '\n';
9400-        }
9401-    }
9402-    void printReconstructedExpression() const {
9403-        if (result.hasExpandedExpression()) {
9404-            stream << "with expansion:\n";
9405-            stream << colourImpl->guardColour( Colour::ReconstructedExpression )
9406-                   << TextFlow::Column( result.getExpandedExpression() )
9407-                          .indent( 2 )
9408-                   << '\n';
9409-        }
9410-    }
9411-    void printMessage() const {
9412-        if (!messageLabel.empty())
9413-            stream << messageLabel << ':' << '\n';
9414-        for (auto const& msg : messages) {
9415-            // If this assertion is a warning ignore any INFO messages
9416-            if (printInfoMessages || msg.type != ResultWas::Info)
9417-                stream << TextFlow::Column(msg.message).indent(2) << '\n';
9418-        }
9419-    }
9420-    void printSourceInfo() const {
9421-        stream << colourImpl->guardColour( Colour::FileName )
9422-               << result.getSourceInfo() << ": ";
9423-    }
9424-
9425-    std::ostream& stream;
9426-    AssertionStats const& stats;
9427-    AssertionResult const& result;
9428-    Colour::Code colour;
9429-    StringRef passOrFail;
9430-    StringRef messageLabel;
9431-    std::vector<MessageInfo> const& messages;
9432-    ColourImpl* colourImpl;
9433-    bool printInfoMessages;
9434-};
9435-
9436-std::size_t makeRatio( std::uint64_t number, std::uint64_t total ) {
9437-    const auto ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
9438-    return (ratio == 0 && number > 0) ? 1 : static_cast<std::size_t>(ratio);
9439-}
9440-
9441-std::size_t&
9442-findMax( std::size_t& i, std::size_t& j, std::size_t& k, std::size_t& l ) {
9443-    if (i > j && i > k && i > l)
9444-        return i;
9445-    else if (j > k && j > l)
9446-        return j;
9447-    else if (k > l)
9448-        return k;
9449-    else
9450-        return l;
9451-}
9452-
9453-struct ColumnBreak {};
9454-struct RowBreak {};
9455-struct OutputFlush {};
9456-
9457-class Duration {
9458-    enum class Unit : uint8_t {
9459-        Auto,
9460-        Nanoseconds,
9461-        Microseconds,
9462-        Milliseconds,
9463-        Seconds,
9464-        Minutes
9465-    };
9466-    static const uint64_t s_nanosecondsInAMicrosecond = 1000;
9467-    static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
9468-    static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
9469-    static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
9470-
9471-    double m_inNanoseconds;
9472-    Unit m_units;
9473-
9474-public:
9475-    explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
9476-        : m_inNanoseconds(inNanoseconds),
9477-        m_units(units) {
9478-        if (m_units == Unit::Auto) {
9479-            if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
9480-                m_units = Unit::Nanoseconds;
9481-            else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
9482-                m_units = Unit::Microseconds;
9483-            else if (m_inNanoseconds < s_nanosecondsInASecond)
9484-                m_units = Unit::Milliseconds;
9485-            else if (m_inNanoseconds < s_nanosecondsInAMinute)
9486-                m_units = Unit::Seconds;
9487-            else
9488-                m_units = Unit::Minutes;
9489-        }
9490-
9491-    }
9492-
9493-    auto value() const -> double {
9494-        switch (m_units) {
9495-        case Unit::Microseconds:
9496-            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
9497-        case Unit::Milliseconds:
9498-            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
9499-        case Unit::Seconds:
9500-            return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
9501-        case Unit::Minutes:
9502-            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
9503-        default:
9504-            return m_inNanoseconds;
9505-        }
9506-    }
9507-    StringRef unitsAsString() const {
9508-        switch (m_units) {
9509-        case Unit::Nanoseconds:
9510-            return "ns"_sr;
9511-        case Unit::Microseconds:
9512-            return "us"_sr;
9513-        case Unit::Milliseconds:
9514-            return "ms"_sr;
9515-        case Unit::Seconds:
9516-            return "s"_sr;
9517-        case Unit::Minutes:
9518-            return "m"_sr;
9519-        default:
9520-            return "** internal error **"_sr;
9521-        }
9522-
9523-    }
9524-    friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
9525-        return os << duration.value() << ' ' << duration.unitsAsString();
9526-    }
9527-};
9528-} // end anon namespace
9529-
9530-enum class Justification : uint8_t {
9531-    Left,
9532-    Right
9533-};
9534-
9535-struct ColumnInfo {
9536-    std::string name;
9537-    std::size_t width;
9538-    Justification justification;
9539-};
9540-
9541-class TablePrinter {
9542-    std::ostream& m_os;
9543-    std::vector<ColumnInfo> m_columnInfos;
9544-    ReusableStringStream m_oss;
9545-    int m_currentColumn = -1;
9546-    bool m_isOpen = false;
9547-
9548-public:
9549-    TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
9550-    :   m_os( os ),
9551-        m_columnInfos( CATCH_MOVE( columnInfos ) ) {}
9552-
9553-    auto columnInfos() const -> std::vector<ColumnInfo> const& {
9554-        return m_columnInfos;
9555-    }
9556-
9557-    void open() {
9558-        if (!m_isOpen) {
9559-            m_isOpen = true;
9560-            *this << RowBreak();
9561-
9562-			TextFlow::Columns headerCols;
9563-			for (auto const& info : m_columnInfos) {
9564-                assert(info.width > 2);
9565-				headerCols += TextFlow::Column(info.name).width(info.width - 2);
9566-                headerCols += TextFlow::Spacer( 2 );
9567-			}
9568-			m_os << headerCols << '\n';
9569-
9570-            m_os << lineOfChars('-') << '\n';
9571-        }
9572-    }
9573-    void close() {
9574-        if (m_isOpen) {
9575-            *this << RowBreak();
9576-            m_os << '\n' << std::flush;
9577-            m_isOpen = false;
9578-        }
9579-    }
9580-
9581-    template<typename T>
9582-    friend TablePrinter& operator<< (TablePrinter& tp, T const& value) {
9583-        tp.m_oss << value;
9584-        return tp;
9585-    }
9586-
9587-    friend TablePrinter& operator<< (TablePrinter& tp, ColumnBreak) {
9588-        auto colStr = tp.m_oss.str();
9589-        const auto strSize = colStr.size();
9590-        tp.m_oss.str("");
9591-        tp.open();
9592-        if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
9593-            tp.m_currentColumn = -1;
9594-            tp.m_os << '\n';
9595-        }
9596-        tp.m_currentColumn++;
9597-
9598-        auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
9599-        auto padding = (strSize + 1 < colInfo.width)
9600-            ? std::string(colInfo.width - (strSize + 1), ' ')
9601-            : std::string();
9602-        if (colInfo.justification == Justification::Left)
9603-            tp.m_os << colStr << padding << ' ';
9604-        else
9605-            tp.m_os << padding << colStr << ' ';
9606-        return tp;
9607-    }
9608-
9609-    friend TablePrinter& operator<< (TablePrinter& tp, RowBreak) {
9610-        if (tp.m_currentColumn > 0) {
9611-            tp.m_os << '\n';
9612-            tp.m_currentColumn = -1;
9613-        }
9614-        return tp;
9615-    }
9616-
9617-    friend TablePrinter& operator<<(TablePrinter& tp, OutputFlush) {
9618-        tp.m_os << std::flush;
9619-        return tp;
9620-    }
9621-};
9622-
9623-ConsoleReporter::ConsoleReporter(ReporterConfig&& config):
9624-    StreamingReporterBase( CATCH_MOVE( config ) ),
9625-    m_tablePrinter(Detail::make_unique<TablePrinter>(m_stream,
9626-        [&config]() -> std::vector<ColumnInfo> {
9627-        if (config.fullConfig()->benchmarkNoAnalysis())
9628-        {
9629-            return{
9630-                { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, Justification::Left },
9631-                { "     samples", 14, Justification::Right },
9632-                { "  iterations", 14, Justification::Right },
9633-                { "        mean", 14, Justification::Right }
9634-            };
9635-        }
9636-        else
9637-        {
9638-            return{
9639-                { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, Justification::Left },
9640-                { "samples      mean       std dev", 14, Justification::Right },
9641-                { "iterations   low mean   low std dev", 14, Justification::Right },
9642-                { "est run time high mean  high std dev", 14, Justification::Right }
9643-            };
9644-        }
9645-    }())) {
9646-    m_preferences.shouldReportAllAssertionStarts = false;
9647-}
9648-
9649-ConsoleReporter::~ConsoleReporter() = default;
9650-
9651-std::string ConsoleReporter::getDescription() {
9652-    return "Reports test results as plain lines of text";
9653-}
9654-
9655-void ConsoleReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
9656-    m_stream << "No test cases matched '" << unmatchedSpec << "'\n";
9657-}
9658-
9659-void ConsoleReporter::reportInvalidTestSpec( StringRef arg ) {
9660-    m_stream << "Invalid Filter: " << arg << '\n';
9661-}
9662-
9663-void ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
9664-    AssertionResult const& result = _assertionStats.assertionResult;
9665-
9666-    bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
9667-
9668-    // Drop out if result was successful but we're not printing them.
9669-    // TODO: Make configurable whether skips should be printed
9670-    if (!includeResults && result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip)
9671-        return;
9672-
9673-    lazyPrint();
9674-
9675-    ConsoleAssertionPrinter printer(m_stream, _assertionStats, m_colour.get(), includeResults);
9676-    printer.print();
9677-    m_stream << '\n' << std::flush;
9678-}
9679-
9680-void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
9681-    m_tablePrinter->close();
9682-    m_headerPrinted = false;
9683-    StreamingReporterBase::sectionStarting(_sectionInfo);
9684-}
9685-void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
9686-    m_tablePrinter->close();
9687-    if (_sectionStats.missingAssertions) {
9688-        lazyPrint();
9689-        auto guard =
9690-            m_colour->guardColour( Colour::ResultError ).engage( m_stream );
9691-        if (m_sectionStack.size() > 1)
9692-            m_stream << "\nNo assertions in section";
9693-        else
9694-            m_stream << "\nNo assertions in test case";
9695-        m_stream << " '" << _sectionStats.sectionInfo.name << "'\n\n" << std::flush;
9696-    }
9697-    double dur = _sectionStats.durationInSeconds;
9698-    if (shouldShowDuration(*m_config, dur)) {
9699-        m_stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << '\n' << std::flush;
9700-    }
9701-    if (m_headerPrinted) {
9702-        m_headerPrinted = false;
9703-    }
9704-    StreamingReporterBase::sectionEnded(_sectionStats);
9705-}
9706-
9707-void ConsoleReporter::benchmarkPreparing( StringRef name ) {
9708-	lazyPrintWithoutClosingBenchmarkTable();
9709-
9710-	auto nameCol = TextFlow::Column( static_cast<std::string>( name ) )
9711-                       .width( m_tablePrinter->columnInfos()[0].width - 2 );
9712-
9713-	bool firstLine = true;
9714-	for (auto line : nameCol) {
9715-		if (!firstLine)
9716-			(*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
9717-		else
9718-			firstLine = false;
9719-
9720-		(*m_tablePrinter) << line << ColumnBreak();
9721-	}
9722-}
9723-
9724-void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
9725-    (*m_tablePrinter) << info.samples << ColumnBreak()
9726-        << info.iterations << ColumnBreak();
9727-    if ( !m_config->benchmarkNoAnalysis() ) {
9728-        ( *m_tablePrinter )
9729-            << Duration( info.estimatedDuration ) << ColumnBreak();
9730-    }
9731-    ( *m_tablePrinter ) << OutputFlush{};
9732-}
9733-void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
9734-    if (m_config->benchmarkNoAnalysis())
9735-    {
9736-        (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
9737-    }
9738-    else
9739-    {
9740-        (*m_tablePrinter) << ColumnBreak()
9741-            << Duration(stats.mean.point.count()) << ColumnBreak()
9742-            << Duration(stats.mean.lower_bound.count()) << ColumnBreak()
9743-            << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
9744-            << Duration(stats.standardDeviation.point.count()) << ColumnBreak()
9745-            << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
9746-            << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
9747-    }
9748-}
9749-
9750-void ConsoleReporter::benchmarkFailed( StringRef error ) {
9751-    auto guard = m_colour->guardColour( Colour::Red ).engage( m_stream );
9752-    (*m_tablePrinter)
9753-        << "Benchmark failed (" << error << ')'
9754-        << ColumnBreak() << RowBreak();
9755-}
9756-
9757-void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
9758-    m_tablePrinter->close();
9759-    StreamingReporterBase::testCaseEnded(_testCaseStats);
9760-    m_headerPrinted = false;
9761-}
9762-void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
9763-    printTotalsDivider(_testRunStats.totals);
9764-    printTestRunTotals( m_stream, *m_colour, _testRunStats.totals );
9765-    m_stream << '\n' << std::flush;
9766-    StreamingReporterBase::testRunEnded(_testRunStats);
9767-}
9768-void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) {
9769-    StreamingReporterBase::testRunStarting(_testRunInfo);
9770-    if ( m_config->testSpec().hasFilters() ) {
9771-        m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
9772-                 << m_config->testSpec() << '\n';
9773-    }
9774-    m_stream << "Randomness seeded to: " << getSeed() << '\n'
9775-             << std::flush;
9776-}
9777-
9778-void ConsoleReporter::lazyPrint() {
9779-
9780-    m_tablePrinter->close();
9781-    lazyPrintWithoutClosingBenchmarkTable();
9782-}
9783-
9784-void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
9785-
9786-    if ( !m_testRunInfoPrinted ) {
9787-        lazyPrintRunInfo();
9788-    }
9789-    if (!m_headerPrinted) {
9790-        printTestCaseAndSectionHeader();
9791-        m_headerPrinted = true;
9792-    }
9793-}
9794-void ConsoleReporter::lazyPrintRunInfo() {
9795-    m_stream << '\n'
9796-             << lineOfChars( '~' ) << '\n'
9797-             << m_colour->guardColour( Colour::SecondaryText )
9798-             << currentTestRunInfo.name << " is a Catch2 v" << libraryVersion()
9799-             << " host application.\n"
9800-             << "Run with -? for options\n\n";
9801-
9802-    m_testRunInfoPrinted = true;
9803-}
9804-void ConsoleReporter::printTestCaseAndSectionHeader() {
9805-    assert(!m_sectionStack.empty());
9806-    printOpenHeader(currentTestCaseInfo->name);
9807-
9808-    if (m_sectionStack.size() > 1) {
9809-        auto guard = m_colour->guardColour( Colour::Headers ).engage( m_stream );
9810-
9811-        auto
9812-            it = m_sectionStack.begin() + 1, // Skip first section (test case)
9813-            itEnd = m_sectionStack.end();
9814-        for (; it != itEnd; ++it)
9815-            printHeaderString(it->name, 2);
9816-    }
9817-
9818-    SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
9819-
9820-
9821-    m_stream << lineOfChars( '-' ) << '\n'
9822-             << m_colour->guardColour( Colour::FileName ) << lineInfo << '\n'
9823-             << lineOfChars( '.' ) << "\n\n"
9824-             << std::flush;
9825-}
9826-
9827-void ConsoleReporter::printClosedHeader(std::string const& _name) {
9828-    printOpenHeader(_name);
9829-    m_stream << lineOfChars('.') << '\n';
9830-}
9831-void ConsoleReporter::printOpenHeader(std::string const& _name) {
9832-    m_stream << lineOfChars('-') << '\n';
9833-    {
9834-        auto guard = m_colour->guardColour( Colour::Headers ).engage( m_stream );
9835-        printHeaderString(_name);
9836-    }
9837-}
9838-
9839-void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {
9840-    // We want to get a bit fancy with line breaking here, so that subsequent
9841-    // lines start after ":" if one is present, e.g.
9842-    // ```
9843-    // blablabla: Fancy
9844-    //            linebreaking
9845-    // ```
9846-    // but we also want to avoid problems with overly long indentation causing
9847-    // the text to take up too many lines, e.g.
9848-    // ```
9849-    // blablabla: F
9850-    //            a
9851-    //            n
9852-    //            c
9853-    //            y
9854-    //            .
9855-    //            .
9856-    //            .
9857-    // ```
9858-    // So we limit the prefix indentation check to first quarter of the possible
9859-    // width
9860-    std::size_t idx = _string.find( ": " );
9861-    if ( idx != std::string::npos && idx < CATCH_CONFIG_CONSOLE_WIDTH / 4 ) {
9862-        idx += 2;
9863-    } else {
9864-        idx = 0;
9865-    }
9866-    m_stream << TextFlow::Column( _string )
9867-                  .indent( indent + idx )
9868-                  .initialIndent( indent )
9869-           << '\n';
9870-}
9871-
9872-void ConsoleReporter::printTotalsDivider(Totals const& totals) {
9873-    if (totals.testCases.total() > 0) {
9874-        std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
9875-        std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
9876-        std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
9877-        std::size_t skippedRatio = makeRatio(totals.testCases.skipped, totals.testCases.total());
9878-        while (failedRatio + failedButOkRatio + passedRatio + skippedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
9879-            findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)++;
9880-        while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
9881-            findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)--;
9882-
9883-        m_stream << m_colour->guardColour( Colour::Error )
9884-                 << std::string( failedRatio, '=' )
9885-                 << m_colour->guardColour( Colour::ResultExpectedFailure )
9886-                 << std::string( failedButOkRatio, '=' );
9887-        if ( totals.testCases.allPassed() ) {
9888-            m_stream << m_colour->guardColour( Colour::ResultSuccess )
9889-                     << std::string( passedRatio, '=' );
9890-        } else {
9891-            m_stream << m_colour->guardColour( Colour::Success )
9892-                     << std::string( passedRatio, '=' );
9893-        }
9894-        m_stream << m_colour->guardColour( Colour::Skip )
9895-                 << std::string( skippedRatio, '=' );
9896-    } else {
9897-        m_stream << m_colour->guardColour( Colour::Warning )
9898-                 << std::string( CATCH_CONFIG_CONSOLE_WIDTH - 1, '=' );
9899-    }
9900-    m_stream << '\n';
9901-}
9902-
9903-} // end namespace Catch
9904-
9905-#if defined(_MSC_VER)
9906-#pragma warning(pop)
9907-#endif
9908-
9909-#if defined(__clang__)
9910-#  pragma clang diagnostic pop
9911-#endif
9912-
9913-
9914-
9915-
9916-#include <algorithm>
9917-#include <cassert>
9918-
9919-namespace Catch {
9920-    namespace {
9921-        struct BySectionInfo {
9922-            BySectionInfo( SectionInfo const& other ): m_other( other ) {}
9923-            BySectionInfo( BySectionInfo const& other ) = default;
9924-            bool operator()(
9925-                Detail::unique_ptr<CumulativeReporterBase::SectionNode> const&
9926-                    node ) const {
9927-                return (
9928-                    ( node->stats.sectionInfo.name == m_other.name ) &&
9929-                    ( node->stats.sectionInfo.lineInfo == m_other.lineInfo ) );
9930-            }
9931-            void operator=( BySectionInfo const& ) = delete;
9932-
9933-        private:
9934-            SectionInfo const& m_other;
9935-        };
9936-
9937-    } // namespace
9938-
9939-    namespace Detail {
9940-        AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
9941-            AssertionStats const& assertion ):
9942-            m_assertion( assertion ) {}
9943-
9944-        AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
9945-            BenchmarkStats<> const& benchmark ):
9946-            m_benchmark( benchmark ) {}
9947-
9948-        bool AssertionOrBenchmarkResult::isAssertion() const {
9949-            return m_assertion.some();
9950-        }
9951-        bool AssertionOrBenchmarkResult::isBenchmark() const {
9952-            return m_benchmark.some();
9953-        }
9954-
9955-        AssertionStats const& AssertionOrBenchmarkResult::asAssertion() const {
9956-            assert(m_assertion.some());
9957-
9958-            return *m_assertion;
9959-        }
9960-        BenchmarkStats<> const& AssertionOrBenchmarkResult::asBenchmark() const {
9961-            assert(m_benchmark.some());
9962-
9963-            return *m_benchmark;
9964-        }
9965-
9966-    }
9967-
9968-    CumulativeReporterBase::~CumulativeReporterBase() = default;
9969-
9970-    void CumulativeReporterBase::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
9971-        m_sectionStack.back()->assertionsAndBenchmarks.emplace_back(benchmarkStats);
9972-    }
9973-
9974-    void
9975-    CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
9976-        // We need a copy, because SectionStats expect to take ownership
9977-        SectionStats incompleteStats( SectionInfo(sectionInfo), Counts(), 0, false );
9978-        SectionNode* node;
9979-        if ( m_sectionStack.empty() ) {
9980-            if ( !m_rootSection ) {
9981-                m_rootSection =
9982-                    Detail::make_unique<SectionNode>( incompleteStats );
9983-            }
9984-            node = m_rootSection.get();
9985-        } else {
9986-            SectionNode& parentNode = *m_sectionStack.back();
9987-            auto it = std::find_if( parentNode.childSections.begin(),
9988-                                    parentNode.childSections.end(),
9989-                                    BySectionInfo( sectionInfo ) );
9990-            if ( it == parentNode.childSections.end() ) {
9991-                auto newNode =
9992-                    Detail::make_unique<SectionNode>( incompleteStats );
9993-                node = newNode.get();
9994-                parentNode.childSections.push_back( CATCH_MOVE( newNode ) );
9995-            } else {
9996-                node = it->get();
9997-            }
9998-        }
9999-
10000-        m_deepestSection = node;
10001-        m_sectionStack.push_back( node );
10002-    }
10003-
10004-    void CumulativeReporterBase::assertionEnded(
10005-        AssertionStats const& assertionStats ) {
10006-        assert( !m_sectionStack.empty() );
10007-        // AssertionResult holds a pointer to a temporary DecomposedExpression,
10008-        // which getExpandedExpression() calls to build the expression string.
10009-        // Our section stack copy of the assertionResult will likely outlive the
10010-        // temporary, so it must be expanded or discarded now to avoid calling
10011-        // a destroyed object later.
10012-        if ( m_shouldStoreFailedAssertions &&
10013-             !assertionStats.assertionResult.isOk() ) {
10014-            static_cast<void>(
10015-                assertionStats.assertionResult.getExpandedExpression() );
10016-        }
10017-        if ( m_shouldStoreSuccesfulAssertions &&
10018-             assertionStats.assertionResult.isOk() ) {
10019-            static_cast<void>(
10020-                assertionStats.assertionResult.getExpandedExpression() );
10021-        }
10022-        SectionNode& sectionNode = *m_sectionStack.back();
10023-        sectionNode.assertionsAndBenchmarks.emplace_back( assertionStats );
10024-    }
10025-
10026-    void CumulativeReporterBase::sectionEnded( SectionStats const& sectionStats ) {
10027-        assert( !m_sectionStack.empty() );
10028-        SectionNode& node = *m_sectionStack.back();
10029-        node.stats = sectionStats;
10030-        m_sectionStack.pop_back();
10031-    }
10032-
10033-    void CumulativeReporterBase::testCaseEnded(
10034-        TestCaseStats const& testCaseStats ) {
10035-        auto node = Detail::make_unique<TestCaseNode>( testCaseStats );
10036-        assert( m_sectionStack.size() == 0 );
10037-        node->children.push_back( CATCH_MOVE(m_rootSection) );
10038-        m_testCases.push_back( CATCH_MOVE(node) );
10039-
10040-        assert( m_deepestSection );
10041-        m_deepestSection->stdOut = testCaseStats.stdOut;
10042-        m_deepestSection->stdErr = testCaseStats.stdErr;
10043-    }
10044-
10045-
10046-    void CumulativeReporterBase::testRunEnded( TestRunStats const& testRunStats ) {
10047-        assert(!m_testRun && "CumulativeReporterBase assumes there can only be one test run");
10048-        m_testRun = Detail::make_unique<TestRunNode>( testRunStats );
10049-        m_testRun->children.swap( m_testCases );
10050-        testRunEndedCumulative();
10051-    }
10052-
10053-    bool CumulativeReporterBase::SectionNode::hasAnyAssertions() const {
10054-        return std::any_of(
10055-            assertionsAndBenchmarks.begin(),
10056-            assertionsAndBenchmarks.end(),
10057-            []( Detail::AssertionOrBenchmarkResult const& res ) {
10058-                return res.isAssertion();
10059-            } );
10060-    }
10061-
10062-} // end namespace Catch
10063-
10064-
10065-
10066-
10067-namespace Catch {
10068-
10069-    void EventListenerBase::fatalErrorEncountered( StringRef ) {}
10070-
10071-    void EventListenerBase::benchmarkPreparing( StringRef ) {}
10072-    void EventListenerBase::benchmarkStarting( BenchmarkInfo const& ) {}
10073-    void EventListenerBase::benchmarkEnded( BenchmarkStats<> const& ) {}
10074-    void EventListenerBase::benchmarkFailed( StringRef ) {}
10075-
10076-    void EventListenerBase::assertionStarting( AssertionInfo const& ) {}
10077-
10078-    void EventListenerBase::assertionEnded( AssertionStats const& ) {}
10079-    void EventListenerBase::listReporters(
10080-        std::vector<ReporterDescription> const& ) {}
10081-    void EventListenerBase::listListeners(
10082-        std::vector<ListenerDescription> const& ) {}
10083-    void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {}
10084-    void EventListenerBase::listTags( std::vector<TagInfo> const& ) {}
10085-    void EventListenerBase::noMatchingTestCases( StringRef ) {}
10086-    void EventListenerBase::reportInvalidTestSpec( StringRef ) {}
10087-    void EventListenerBase::testRunStarting( TestRunInfo const& ) {}
10088-    void EventListenerBase::testCaseStarting( TestCaseInfo const& ) {}
10089-    void EventListenerBase::testCasePartialStarting(TestCaseInfo const&, uint64_t) {}
10090-    void EventListenerBase::sectionStarting( SectionInfo const& ) {}
10091-    void EventListenerBase::sectionEnded( SectionStats const& ) {}
10092-    void EventListenerBase::testCasePartialEnded(TestCaseStats const&, uint64_t) {}
10093-    void EventListenerBase::testCaseEnded( TestCaseStats const& ) {}
10094-    void EventListenerBase::testRunEnded( TestRunStats const& ) {}
10095-    void EventListenerBase::skipTest( TestCaseInfo const& ) {}
10096-} // namespace Catch
10097-
10098-
10099-
10100-
10101-#include <algorithm>
10102-#include <cfloat>
10103-#include <cmath>
10104-#include <cstdio>
10105-#include <ostream>
10106-#include <iomanip>
10107-
10108-namespace Catch {
10109-
10110-    namespace {
10111-        void listTestNamesOnly(std::ostream& out,
10112-                               std::vector<TestCaseHandle> const& tests) {
10113-            for (auto const& test : tests) {
10114-                auto const& testCaseInfo = test.getTestCaseInfo();
10115-
10116-                if (startsWith(testCaseInfo.name, '#')) {
10117-                    out << '"' << testCaseInfo.name << '"';
10118-                } else {
10119-                    out << testCaseInfo.name;
10120-                }
10121-
10122-                out << '\n';
10123-            }
10124-            out << std::flush;
10125-        }
10126-    } // end unnamed namespace
10127-
10128-
10129-    // Because formatting using c++ streams is stateful, drop down to C is
10130-    // required Alternatively we could use stringstream, but its performance
10131-    // is... not good.
10132-    std::string getFormattedDuration( double duration ) {
10133-        // Max exponent + 1 is required to represent the whole part
10134-        // + 1 for decimal point
10135-        // + 3 for the 3 decimal places
10136-        // + 1 for null terminator
10137-        const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
10138-        char buffer[maxDoubleSize];
10139-
10140-        // Save previous errno, to prevent sprintf from overwriting it
10141-        ErrnoGuard guard;
10142-#ifdef _MSC_VER
10143-        size_t printedLength = static_cast<size_t>(
10144-            sprintf_s( buffer, "%.3f", duration ) );
10145-#else
10146-        size_t printedLength = static_cast<size_t>(
10147-            std::snprintf( buffer, maxDoubleSize, "%.3f", duration ) );
10148-#endif
10149-        return std::string( buffer, printedLength );
10150-    }
10151-
10152-    bool shouldShowDuration( IConfig const& config, double duration ) {
10153-        if ( config.showDurations() == ShowDurations::Always ) {
10154-            return true;
10155-        }
10156-        if ( config.showDurations() == ShowDurations::Never ) {
10157-            return false;
10158-        }
10159-        const double min = config.minDuration();
10160-        return min >= 0 && duration >= min;
10161-    }
10162-
10163-    std::string serializeFilters( std::vector<std::string> const& filters ) {
10164-        // We add a ' ' separator between each filter
10165-        size_t serialized_size = filters.size() - 1;
10166-        for (auto const& filter : filters) {
10167-            serialized_size += filter.size();
10168-        }
10169-
10170-        std::string serialized;
10171-        serialized.reserve(serialized_size);
10172-        bool first = true;
10173-
10174-        for (auto const& filter : filters) {
10175-            if (!first) {
10176-                serialized.push_back(' ');
10177-            }
10178-            first = false;
10179-            serialized.append(filter);
10180-        }
10181-
10182-        return serialized;
10183-    }
10184-
10185-    std::ostream& operator<<( std::ostream& out, lineOfChars value ) {
10186-        for ( size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx ) {
10187-            out.put( value.c );
10188-        }
10189-        return out;
10190-    }
10191-
10192-    void
10193-    defaultListReporters( std::ostream& out,
10194-                          std::vector<ReporterDescription> const& descriptions,
10195-                          Verbosity verbosity ) {
10196-        out << "Available reporters:\n";
10197-        const auto maxNameLen =
10198-            std::max_element( descriptions.begin(),
10199-                              descriptions.end(),
10200-                              []( ReporterDescription const& lhs,
10201-                                  ReporterDescription const& rhs ) {
10202-                                  return lhs.name.size() < rhs.name.size();
10203-                              } )
10204-                ->name.size();
10205-
10206-        for ( auto const& desc : descriptions ) {
10207-            if ( verbosity == Verbosity::Quiet ) {
10208-                out << TextFlow::Column( desc.name )
10209-                           .indent( 2 )
10210-                           .width( 5 + maxNameLen )
10211-                    << '\n';
10212-            } else {
10213-                out << TextFlow::Column( desc.name + ':' )
10214-                               .indent( 2 )
10215-                               .width( 5 + maxNameLen ) +
10216-                           TextFlow::Column( desc.description )
10217-                               .initialIndent( 0 )
10218-                               .indent( 2 )
10219-                               .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
10220-                    << '\n';
10221-            }
10222-        }
10223-        out << '\n' << std::flush;
10224-    }
10225-
10226-    void defaultListListeners( std::ostream& out,
10227-                               std::vector<ListenerDescription> const& descriptions ) {
10228-        out << "Registered listeners:\n";
10229-
10230-        if(descriptions.empty()) {
10231-            return;
10232-        }
10233-
10234-        const auto maxNameLen =
10235-            std::max_element( descriptions.begin(),
10236-                              descriptions.end(),
10237-                              []( ListenerDescription const& lhs,
10238-                                  ListenerDescription const& rhs ) {
10239-                                  return lhs.name.size() < rhs.name.size();
10240-                              } )
10241-                ->name.size();
10242-
10243-        for ( auto const& desc : descriptions ) {
10244-            out << TextFlow::Column( static_cast<std::string>( desc.name ) +
10245-                                     ':' )
10246-                           .indent( 2 )
10247-                           .width( maxNameLen + 5 ) +
10248-                       TextFlow::Column( desc.description )
10249-                           .initialIndent( 0 )
10250-                           .indent( 2 )
10251-                           .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
10252-                << '\n';
10253-        }
10254-
10255-        out << '\n' << std::flush;
10256-    }
10257-
10258-    void defaultListTags( std::ostream& out,
10259-                          std::vector<TagInfo> const& tags,
10260-                          bool isFiltered ) {
10261-        if ( isFiltered ) {
10262-            out << "Tags for matching test cases:\n";
10263-        } else {
10264-            out << "All available tags:\n";
10265-        }
10266-
10267-        // minimum whitespace to pad tag counts, possibly overwritten below
10268-        size_t maxTagCountLen = 2;
10269-
10270-        // determine necessary padding for tag count column
10271-        if ( ! tags.empty() ) {
10272-            const auto maxTagCount =
10273-                std::max_element( tags.begin(),
10274-                                  tags.end(),
10275-                                  []( auto const& lhs, auto const& rhs ) {
10276-                                      return lhs.count < rhs.count;
10277-                                  } )
10278-                    ->count;
10279-            
10280-            // more padding necessary for 3+ digits
10281-            if (maxTagCount >= 100) {
10282-                auto numDigits = 1 + std::floor( std::log10( maxTagCount ) );
10283-                maxTagCountLen = static_cast<size_t>( numDigits );
10284-            }
10285-        }
10286-
10287-        for ( auto const& tagCount : tags ) {
10288-            ReusableStringStream rss;
10289-            rss << "  " << std::setw( maxTagCountLen ) << tagCount.count << "  ";
10290-            auto str = rss.str();
10291-            auto wrapper = TextFlow::Column( tagCount.all() )
10292-                               .initialIndent( 0 )
10293-                               .indent( str.size() )
10294-                               .width( CATCH_CONFIG_CONSOLE_WIDTH - 10 );
10295-            out << str << wrapper << '\n';
10296-        }
10297-        out << pluralise(tags.size(), "tag"_sr) << "\n\n" << std::flush;
10298-    }
10299-
10300-    void defaultListTests(std::ostream& out, ColourImpl* streamColour, std::vector<TestCaseHandle> const& tests, bool isFiltered, Verbosity verbosity) {
10301-        // We special case this to provide the equivalent of old
10302-        // `--list-test-names-only`, which could then be used by the
10303-        // `--input-file` option.
10304-        if (verbosity == Verbosity::Quiet) {
10305-            listTestNamesOnly(out, tests);
10306-            return;
10307-        }
10308-
10309-        if (isFiltered) {
10310-            out << "Matching test cases:\n";
10311-        } else {
10312-            out << "All available test cases:\n";
10313-        }
10314-
10315-        for (auto const& test : tests) {
10316-            auto const& testCaseInfo = test.getTestCaseInfo();
10317-            Colour::Code colour = testCaseInfo.isHidden()
10318-                ? Colour::SecondaryText
10319-                : Colour::None;
10320-            auto colourGuard = streamColour->guardColour( colour ).engage( out );
10321-
10322-            out << TextFlow::Column(testCaseInfo.name).indent(2) << '\n';
10323-            if (verbosity >= Verbosity::High) {
10324-                out << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << '\n';
10325-            }
10326-            if (!testCaseInfo.tags.empty() &&
10327-                verbosity > Verbosity::Quiet) {
10328-                out << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
10329-            }
10330-        }
10331-
10332-        if (isFiltered) {
10333-            out << pluralise(tests.size(), "matching test case"_sr);
10334-        } else {
10335-            out << pluralise(tests.size(), "test case"_sr);
10336-        }
10337-        out << "\n\n" << std::flush;
10338-    }
10339-
10340-    namespace {
10341-        class SummaryColumn {
10342-        public:
10343-            SummaryColumn( std::string suffix, Colour::Code colour ):
10344-                m_suffix( CATCH_MOVE( suffix ) ), m_colour( colour ) {}
10345-
10346-            SummaryColumn&& addRow( std::uint64_t count ) && {
10347-                std::string row = std::to_string(count);
10348-                auto const new_width = std::max( m_width, row.size() );
10349-                if ( new_width > m_width ) {
10350-                    for ( auto& oldRow : m_rows ) {
10351-                        oldRow.insert( 0, new_width - m_width, ' ' );
10352-                    }
10353-                } else {
10354-                    row.insert( 0, m_width - row.size(), ' ' );
10355-                }
10356-                m_width = new_width;
10357-                m_rows.push_back( row );
10358-                return std::move( *this );
10359-            }
10360-
10361-            std::string const& getSuffix() const { return m_suffix; }
10362-            Colour::Code getColour() const { return m_colour; }
10363-            std::string const& getRow( std::size_t index ) const {
10364-                return m_rows[index];
10365-            }
10366-
10367-        private:
10368-            std::string m_suffix;
10369-            Colour::Code m_colour;
10370-            std::size_t m_width = 0;
10371-            std::vector<std::string> m_rows;
10372-        };
10373-
10374-        void printSummaryRow( std::ostream& stream,
10375-                              ColourImpl& colour,
10376-                              StringRef label,
10377-                              std::vector<SummaryColumn> const& cols,
10378-                              std::size_t row ) {
10379-            for ( auto const& col : cols ) {
10380-                auto const& value = col.getRow( row );
10381-                auto const& suffix = col.getSuffix();
10382-                if ( suffix.empty() ) {
10383-                    stream << label << ": ";
10384-                    if ( value != "0" ) {
10385-                        stream << value;
10386-                    } else {
10387-                        stream << colour.guardColour( Colour::Warning )
10388-                               << "- none -";
10389-                    }
10390-                } else if ( value != "0" ) {
10391-                    stream << colour.guardColour( Colour::LightGrey ) << " | "
10392-                           << colour.guardColour( col.getColour() ) << value
10393-                           << ' ' << suffix;
10394-                }
10395-            }
10396-            stream << '\n';
10397-        }
10398-    } // namespace
10399-
10400-    void printTestRunTotals( std::ostream& stream,
10401-                             ColourImpl& streamColour,
10402-                             Totals const& totals ) {
10403-        if ( totals.testCases.total() == 0 ) {
10404-            stream << streamColour.guardColour( Colour::Warning )
10405-                   << "No tests ran\n";
10406-            return;
10407-        }
10408-
10409-        if ( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
10410-            stream << streamColour.guardColour( Colour::ResultSuccess )
10411-                   << "All tests passed";
10412-            stream << " ("
10413-                   << pluralise( totals.assertions.passed, "assertion"_sr )
10414-                   << " in "
10415-                   << pluralise( totals.testCases.passed, "test case"_sr )
10416-                   << ')' << '\n';
10417-            return;
10418-        }
10419-
10420-        std::vector<SummaryColumn> columns;
10421-        // Don't include "skipped assertions" in total count
10422-        const auto totalAssertionCount =
10423-            totals.assertions.total() - totals.assertions.skipped;
10424-        columns.push_back( SummaryColumn( "", Colour::None )
10425-                               .addRow( totals.testCases.total() )
10426-                               .addRow( totalAssertionCount ) );
10427-        columns.push_back( SummaryColumn( "passed", Colour::Success )
10428-                               .addRow( totals.testCases.passed )
10429-                               .addRow( totals.assertions.passed ) );
10430-        columns.push_back( SummaryColumn( "failed", Colour::ResultError )
10431-                               .addRow( totals.testCases.failed )
10432-                               .addRow( totals.assertions.failed ) );
10433-        columns.push_back( SummaryColumn( "skipped", Colour::Skip )
10434-                               .addRow( totals.testCases.skipped )
10435-                               // Don't print "skipped assertions"
10436-                               .addRow( 0 ) );
10437-        columns.push_back(
10438-            SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
10439-                .addRow( totals.testCases.failedButOk )
10440-                .addRow( totals.assertions.failedButOk ) );
10441-        printSummaryRow( stream, streamColour, "test cases"_sr, columns, 0 );
10442-        printSummaryRow( stream, streamColour, "assertions"_sr, columns, 1 );
10443-    }
10444-
10445-} // namespace Catch
10446-
10447-
10448-//
10449-
10450-namespace Catch {
10451-    namespace {
10452-        void writeSourceInfo( JsonObjectWriter& writer,
10453-                              SourceLineInfo const& sourceInfo ) {
10454-            auto source_location_writer =
10455-                writer.write( "source-location"_sr ).writeObject();
10456-            source_location_writer.write( "filename"_sr )
10457-                .write( sourceInfo.file );
10458-            source_location_writer.write( "line"_sr ).write( sourceInfo.line );
10459-        }
10460-
10461-        void writeTags( JsonArrayWriter writer, std::vector<Tag> const& tags ) {
10462-            for ( auto const& tag : tags ) {
10463-                writer.write( tag.original );
10464-            }
10465-        }
10466-
10467-        void writeProperties( JsonArrayWriter writer,
10468-                              TestCaseInfo const& info ) {
10469-            if ( info.isHidden() ) { writer.write( "is-hidden"_sr ); }
10470-            if ( info.okToFail() ) { writer.write( "ok-to-fail"_sr ); }
10471-            if ( info.expectedToFail() ) {
10472-                writer.write( "expected-to-fail"_sr );
10473-            }
10474-            if ( info.throws() ) { writer.write( "throws"_sr ); }
10475-        }
10476-
10477-    } // namespace
10478-
10479-    JsonReporter::JsonReporter( ReporterConfig&& config ):
10480-        StreamingReporterBase{ CATCH_MOVE( config ) } {
10481-
10482-        m_preferences.shouldRedirectStdOut = true;
10483-        // TBD: Do we want to report all assertions? XML reporter does
10484-        //      not, but for machine-parseable reporters I think the answer
10485-        //      should be yes.
10486-        m_preferences.shouldReportAllAssertions = true;
10487-        // We only handle assertions when they end
10488-        m_preferences.shouldReportAllAssertionStarts = false;
10489-
10490-        m_objectWriters.emplace( m_stream );
10491-        m_writers.emplace( Writer::Object );
10492-        auto& writer = m_objectWriters.top();
10493-
10494-        writer.write( "version"_sr ).write( 1 );
10495-
10496-        {
10497-            auto metadata_writer = writer.write( "metadata"_sr ).writeObject();
10498-            metadata_writer.write( "name"_sr ).write( m_config->name() );
10499-            metadata_writer.write( "rng-seed"_sr ).write( m_config->rngSeed() );
10500-            metadata_writer.write( "catch2-version"_sr )
10501-                .write( libraryVersion() );
10502-            if ( m_config->testSpec().hasFilters() ) {
10503-                metadata_writer.write( "filters"_sr )
10504-                    .write( m_config->testSpec() );
10505-            }
10506-        }
10507-    }
10508-
10509-    JsonReporter::~JsonReporter() {
10510-        endListing();
10511-        // TODO: Ensure this closes the top level object, add asserts
10512-        assert( m_writers.size() == 1 && "Only the top level object should be open" );
10513-        assert( m_writers.top() == Writer::Object );
10514-        endObject();
10515-        m_stream << '\n' << std::flush;
10516-        assert( m_writers.empty() );
10517-    }
10518-
10519-    JsonArrayWriter& JsonReporter::startArray() {
10520-        m_arrayWriters.emplace( m_arrayWriters.top().writeArray() );
10521-        m_writers.emplace( Writer::Array );
10522-        return m_arrayWriters.top();
10523-    }
10524-    JsonArrayWriter& JsonReporter::startArray( StringRef key ) {
10525-        m_arrayWriters.emplace(
10526-            m_objectWriters.top().write( key ).writeArray() );
10527-        m_writers.emplace( Writer::Array );
10528-        return m_arrayWriters.top();
10529-    }
10530-
10531-    JsonObjectWriter& JsonReporter::startObject() {
10532-        m_objectWriters.emplace( m_arrayWriters.top().writeObject() );
10533-        m_writers.emplace( Writer::Object );
10534-        return m_objectWriters.top();
10535-    }
10536-    JsonObjectWriter& JsonReporter::startObject( StringRef key ) {
10537-        m_objectWriters.emplace(
10538-            m_objectWriters.top().write( key ).writeObject() );
10539-        m_writers.emplace( Writer::Object );
10540-        return m_objectWriters.top();
10541-    }
10542-
10543-    void JsonReporter::endObject() {
10544-        assert( isInside( Writer::Object ) );
10545-        m_objectWriters.pop();
10546-        m_writers.pop();
10547-    }
10548-    void JsonReporter::endArray() {
10549-        assert( isInside( Writer::Array ) );
10550-        m_arrayWriters.pop();
10551-        m_writers.pop();
10552-    }
10553-
10554-    bool JsonReporter::isInside( Writer writer ) {
10555-        return !m_writers.empty() && m_writers.top() == writer;
10556-    }
10557-
10558-    void JsonReporter::startListing() {
10559-        if ( !m_startedListing ) { startObject( "listings"_sr ); }
10560-        m_startedListing = true;
10561-    }
10562-    void JsonReporter::endListing() {
10563-        if ( m_startedListing ) { endObject(); }
10564-        m_startedListing = false;
10565-    }
10566-
10567-    std::string JsonReporter::getDescription() {
10568-        return "Outputs listings as JSON. Test listing is Work-in-Progress!";
10569-    }
10570-
10571-    void JsonReporter::testRunStarting( TestRunInfo const& runInfo ) {
10572-        StreamingReporterBase::testRunStarting( runInfo );
10573-        endListing();
10574-
10575-        assert( isInside( Writer::Object ) );
10576-        startObject( "test-run"_sr );
10577-        startArray( "test-cases"_sr );
10578-    }
10579-
10580-     static void writeCounts( JsonObjectWriter&& writer, Counts const& counts ) {
10581-        writer.write( "passed"_sr ).write( counts.passed );
10582-        writer.write( "failed"_sr ).write( counts.failed );
10583-        writer.write( "fail-but-ok"_sr ).write( counts.failedButOk );
10584-        writer.write( "skipped"_sr ).write( counts.skipped );
10585-    }
10586-
10587-    void JsonReporter::testRunEnded(TestRunStats const& runStats) {
10588-        assert( isInside( Writer::Array ) );
10589-        // End "test-cases"
10590-        endArray();
10591-
10592-        {
10593-            auto totals =
10594-                m_objectWriters.top().write( "totals"_sr ).writeObject();
10595-            writeCounts( totals.write( "assertions"_sr ).writeObject(),
10596-                         runStats.totals.assertions );
10597-            writeCounts( totals.write( "test-cases"_sr ).writeObject(),
10598-                         runStats.totals.testCases );
10599-        }
10600-
10601-        // End the "test-run" object
10602-        endObject();
10603-    }
10604-
10605-    void JsonReporter::testCaseStarting( TestCaseInfo const& tcInfo ) {
10606-        StreamingReporterBase::testCaseStarting( tcInfo );
10607-
10608-        assert( isInside( Writer::Array ) &&
10609-                "We should be in the 'test-cases' array" );
10610-        startObject();
10611-        // "test-info" prelude
10612-        {
10613-            auto testInfo =
10614-                m_objectWriters.top().write( "test-info"_sr ).writeObject();
10615-            // TODO: handle testName vs className!!
10616-            testInfo.write( "name"_sr ).write( tcInfo.name );
10617-            writeSourceInfo(testInfo, tcInfo.lineInfo);
10618-            writeTags( testInfo.write( "tags"_sr ).writeArray(), tcInfo.tags );
10619-            writeProperties( testInfo.write( "properties"_sr ).writeArray(),
10620-                             tcInfo );
10621-        }
10622-
10623-
10624-        // Start the array for individual test runs (testCasePartial pairs)
10625-        startArray( "runs"_sr );
10626-    }
10627-
10628-    void JsonReporter::testCaseEnded( TestCaseStats const& tcStats ) {
10629-        StreamingReporterBase::testCaseEnded( tcStats );
10630-
10631-        // We need to close the 'runs' array before finishing the test case
10632-        assert( isInside( Writer::Array ) );
10633-        endArray();
10634-
10635-        {
10636-            auto totals =
10637-                m_objectWriters.top().write( "totals"_sr ).writeObject();
10638-            writeCounts( totals.write( "assertions"_sr ).writeObject(),
10639-                         tcStats.totals.assertions );
10640-            // We do not write the test case totals, because there will always be just one test case here.
10641-            // TODO: overall "result" -> success, skip, fail here? Or in partial result?
10642-        }
10643-        // We do not write out stderr/stdout, because we instead wrote those out in partial runs
10644-
10645-        // TODO: aborting?
10646-
10647-        // And we also close this test case's object
10648-        assert( isInside( Writer::Object ) );
10649-        endObject();
10650-    }
10651-
10652-    void JsonReporter::testCasePartialStarting( TestCaseInfo const& /*tcInfo*/,
10653-                                                uint64_t index ) {
10654-        startObject();
10655-        m_objectWriters.top().write( "run-idx"_sr ).write( index );
10656-        startArray( "path"_sr );
10657-        // TODO: we want to delay most of the printing to the 'root' section
10658-        // TODO: childSection key name?
10659-    }
10660-
10661-    void JsonReporter::testCasePartialEnded( TestCaseStats const& tcStats,
10662-                                             uint64_t /*index*/ ) {
10663-        // Fixme: the top level section handles this.
10664-        //// path object
10665-        endArray();
10666-        if ( !tcStats.stdOut.empty() ) {
10667-            m_objectWriters.top()
10668-                .write( "captured-stdout"_sr )
10669-                .write( tcStats.stdOut );
10670-        }
10671-        if ( !tcStats.stdErr.empty() ) {
10672-            m_objectWriters.top()
10673-                .write( "captured-stderr"_sr )
10674-                .write( tcStats.stdErr );
10675-        }
10676-        {
10677-            auto totals =
10678-                m_objectWriters.top().write( "totals"_sr ).writeObject();
10679-            writeCounts( totals.write( "assertions"_sr ).writeObject(),
10680-                         tcStats.totals.assertions );
10681-            // We do not write the test case totals, because there will
10682-            // always be just one test case here.
10683-            // TODO: overall "result" -> success, skip, fail here? Or in
10684-            // partial result?
10685-        }
10686-        // TODO: aborting?
10687-        // run object
10688-        endObject();
10689-    }
10690-
10691-    void JsonReporter::sectionStarting( SectionInfo const& sectionInfo ) {
10692-        assert( isInside( Writer::Array ) &&
10693-                "Section should always start inside an object" );
10694-        // We want to nest top level sections, even though it shares name
10695-        // and source loc with the TEST_CASE
10696-        auto& sectionObject = startObject();
10697-        sectionObject.write( "kind"_sr ).write( "section"_sr );
10698-        sectionObject.write( "name"_sr ).write( sectionInfo.name );
10699-        writeSourceInfo( m_objectWriters.top(), sectionInfo.lineInfo );
10700-
10701-
10702-        // TBD: Do we want to create this event lazily? It would become
10703-        //      rather complex, but we could do it, and it would look
10704-        //      better for empty sections. OTOH, empty sections should
10705-        //      be rare.
10706-        startArray( "path"_sr );
10707-    }
10708-    void JsonReporter::sectionEnded( SectionStats const& /*sectionStats */) {
10709-        // End the subpath array
10710-        endArray();
10711-        // TODO: metadata
10712-        // TODO: what info do we have here?
10713-
10714-        // End the section object
10715-        endObject();
10716-    }
10717-
10718-    void JsonReporter::assertionEnded( AssertionStats const& assertionStats ) {
10719-        // TODO: There is lot of different things to handle here, but
10720-        //       we can fill it in later, after we show that the basic
10721-        //       outline and streaming reporter impl works well enough.
10722-        //if ( !m_config->includeSuccessfulResults()
10723-        //    && assertionStats.assertionResult.isOk() ) {
10724-        //    return;
10725-        //}
10726-        assert( isInside( Writer::Array ) );
10727-        auto assertionObject = m_arrayWriters.top().writeObject();
10728-
10729-        assertionObject.write( "kind"_sr ).write( "assertion"_sr );
10730-        writeSourceInfo( assertionObject,
10731-                         assertionStats.assertionResult.getSourceInfo() );
10732-        assertionObject.write( "status"_sr )
10733-            .write( assertionStats.assertionResult.isOk() );
10734-        // TODO: handling of result.
10735-        // TODO: messages
10736-        // TODO: totals?
10737-    }
10738-
10739-
10740-    void JsonReporter::benchmarkPreparing( StringRef name ) { (void)name; }
10741-    void JsonReporter::benchmarkStarting( BenchmarkInfo const& ) {}
10742-    void JsonReporter::benchmarkEnded( BenchmarkStats<> const& ) {}
10743-    void JsonReporter::benchmarkFailed( StringRef error ) { (void)error; }
10744-
10745-    void JsonReporter::listReporters(
10746-        std::vector<ReporterDescription> const& descriptions ) {
10747-        startListing();
10748-
10749-        auto writer =
10750-            m_objectWriters.top().write( "reporters"_sr ).writeArray();
10751-        for ( auto const& desc : descriptions ) {
10752-            auto desc_writer = writer.writeObject();
10753-            desc_writer.write( "name"_sr ).write( desc.name );
10754-            desc_writer.write( "description"_sr ).write( desc.description );
10755-        }
10756-    }
10757-    void JsonReporter::listListeners(
10758-        std::vector<ListenerDescription> const& descriptions ) {
10759-        startListing();
10760-
10761-        auto writer =
10762-            m_objectWriters.top().write( "listeners"_sr ).writeArray();
10763-
10764-        for ( auto const& desc : descriptions ) {
10765-            auto desc_writer = writer.writeObject();
10766-            desc_writer.write( "name"_sr ).write( desc.name );
10767-            desc_writer.write( "description"_sr ).write( desc.description );
10768-        }
10769-    }
10770-    void JsonReporter::listTests( std::vector<TestCaseHandle> const& tests ) {
10771-        startListing();
10772-
10773-        auto writer = m_objectWriters.top().write( "tests"_sr ).writeArray();
10774-
10775-        for ( auto const& test : tests ) {
10776-            auto desc_writer = writer.writeObject();
10777-            auto const& info = test.getTestCaseInfo();
10778-
10779-            desc_writer.write( "name"_sr ).write( info.name );
10780-            desc_writer.write( "class-name"_sr ).write( info.className );
10781-            {
10782-                auto tag_writer = desc_writer.write( "tags"_sr ).writeArray();
10783-                for ( auto const& tag : info.tags ) {
10784-                    tag_writer.write( tag.original );
10785-                }
10786-            }
10787-            writeSourceInfo( desc_writer, info.lineInfo );
10788-        }
10789-    }
10790-    void JsonReporter::listTags( std::vector<TagInfo> const& tags ) {
10791-        startListing();
10792-
10793-        auto writer = m_objectWriters.top().write( "tags"_sr ).writeArray();
10794-        for ( auto const& tag : tags ) {
10795-            auto tag_writer = writer.writeObject();
10796-            {
10797-                auto aliases_writer =
10798-                    tag_writer.write( "aliases"_sr ).writeArray();
10799-                for ( auto alias : tag.spellings ) {
10800-                    aliases_writer.write( alias );
10801-                }
10802-            }
10803-            tag_writer.write( "count"_sr ).write( tag.count );
10804-        }
10805-    }
10806-} // namespace Catch
10807-
10808-
10809-
10810-
10811-#include <cassert>
10812-#include <ctime>
10813-#include <algorithm>
10814-#include <iomanip>
10815-
10816-namespace Catch {
10817-
10818-    namespace {
10819-        std::string getCurrentTimestamp() {
10820-            time_t rawtime;
10821-            std::time(&rawtime);
10822-
10823-            std::tm timeInfo = {};
10824-#if defined (_MSC_VER) || defined (__MINGW32__)
10825-            gmtime_s(&timeInfo, &rawtime);
10826-#elif defined (CATCH_PLATFORM_PLAYSTATION)
10827-            gmtime_s(&rawtime, &timeInfo);
10828-#elif defined (__IAR_SYSTEMS_ICC__)
10829-            timeInfo = *std::gmtime(&rawtime);
10830-#else
10831-            gmtime_r(&rawtime, &timeInfo);
10832-#endif
10833-
10834-            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
10835-            char timeStamp[timeStampSize];
10836-            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
10837-
10838-            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
10839-
10840-            return std::string(timeStamp, timeStampSize - 1);
10841-        }
10842-
10843-        std::string fileNameTag(std::vector<Tag> const& tags) {
10844-            auto it = std::find_if(begin(tags),
10845-                                   end(tags),
10846-                                   [] (Tag const& tag) {
10847-                                       return tag.original.size() > 0
10848-                                           && tag.original[0] == '#'; });
10849-            if (it != tags.end()) {
10850-                return static_cast<std::string>(
10851-                    it->original.substr(1, it->original.size() - 1)
10852-                );
10853-            }
10854-            return std::string();
10855-        }
10856-
10857-        // Formats the duration in seconds to 3 decimal places.
10858-        // This is done because some genius defined Maven Surefire schema
10859-        // in a way that only accepts 3 decimal places, and tools like
10860-        // Jenkins use that schema for validation JUnit reporter output.
10861-        std::string formatDuration( double seconds ) {
10862-            ReusableStringStream rss;
10863-            rss << std::fixed << std::setprecision( 3 ) << seconds;
10864-            return rss.str();
10865-        }
10866-
10867-        static void normalizeNamespaceMarkers(std::string& str) {
10868-            std::size_t pos = str.find( "::" );
10869-            while ( pos != std::string::npos ) {
10870-                str.replace( pos, 2, "." );
10871-                pos += 1;
10872-                pos = str.find( "::", pos );
10873-            }
10874-        }
10875-
10876-    } // anonymous namespace
10877-
10878-    JunitReporter::JunitReporter( ReporterConfig&& _config )
10879-        :   CumulativeReporterBase( CATCH_MOVE(_config) ),
10880-            xml( m_stream )
10881-        {
10882-            m_preferences.shouldRedirectStdOut = true;
10883-            m_preferences.shouldReportAllAssertions = false;
10884-            m_preferences.shouldReportAllAssertionStarts = false;
10885-            m_shouldStoreSuccesfulAssertions = false;
10886-        }
10887-
10888-    std::string JunitReporter::getDescription() {
10889-        return "Reports test results in an XML format that looks like Ant's junitreport target";
10890-    }
10891-
10892-    void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {
10893-        CumulativeReporterBase::testRunStarting( runInfo );
10894-        xml.startElement( "testsuites" );
10895-        suiteTimer.start();
10896-        stdOutForSuite.clear();
10897-        stdErrForSuite.clear();
10898-        unexpectedExceptions = 0;
10899-    }
10900-
10901-    void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
10902-        m_okToFail = testCaseInfo.okToFail();
10903-    }
10904-
10905-    void JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
10906-        if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
10907-            unexpectedExceptions++;
10908-        CumulativeReporterBase::assertionEnded( assertionStats );
10909-    }
10910-
10911-    void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
10912-        stdOutForSuite += testCaseStats.stdOut;
10913-        stdErrForSuite += testCaseStats.stdErr;
10914-        CumulativeReporterBase::testCaseEnded( testCaseStats );
10915-    }
10916-
10917-    void JunitReporter::testRunEndedCumulative() {
10918-        const auto suiteTime = suiteTimer.getElapsedSeconds();
10919-        writeRun( *m_testRun, suiteTime );
10920-        xml.endElement();
10921-    }
10922-
10923-    void JunitReporter::writeRun( TestRunNode const& testRunNode, double suiteTime ) {
10924-        XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
10925-
10926-        TestRunStats const& stats = testRunNode.value;
10927-        xml.writeAttribute( "name"_sr, stats.runInfo.name );
10928-        xml.writeAttribute( "errors"_sr, unexpectedExceptions );
10929-        xml.writeAttribute( "failures"_sr, stats.totals.assertions.failed-unexpectedExceptions );
10930-        xml.writeAttribute( "skipped"_sr, stats.totals.assertions.skipped );
10931-        xml.writeAttribute( "tests"_sr, stats.totals.assertions.total() );
10932-        xml.writeAttribute( "hostname"_sr, "tbd"_sr ); // !TBD
10933-        if( m_config->showDurations() == ShowDurations::Never )
10934-            xml.writeAttribute( "time"_sr, ""_sr );
10935-        else
10936-            xml.writeAttribute( "time"_sr, formatDuration( suiteTime ) );
10937-        xml.writeAttribute( "timestamp"_sr, getCurrentTimestamp() );
10938-
10939-        // Write properties
10940-        {
10941-            auto properties = xml.scopedElement("properties");
10942-            xml.scopedElement("property")
10943-                .writeAttribute("name"_sr, "random-seed"_sr)
10944-                .writeAttribute("value"_sr, m_config->rngSeed());
10945-            if (m_config->testSpec().hasFilters()) {
10946-                xml.scopedElement("property")
10947-                    .writeAttribute("name"_sr, "filters"_sr)
10948-                    .writeAttribute("value"_sr, m_config->testSpec());
10949-            }
10950-        }
10951-
10952-        // Write test cases
10953-        for( auto const& child : testRunNode.children )
10954-            writeTestCase( *child );
10955-
10956-        xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline );
10957-        xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline );
10958-    }
10959-
10960-    void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
10961-        TestCaseStats const& stats = testCaseNode.value;
10962-
10963-        // All test cases have exactly one section - which represents the
10964-        // test case itself. That section may have 0-n nested sections
10965-        assert( testCaseNode.children.size() == 1 );
10966-        SectionNode const& rootSection = *testCaseNode.children.front();
10967-
10968-        std::string className =
10969-            static_cast<std::string>( stats.testInfo->className );
10970-
10971-        if( className.empty() ) {
10972-            className = fileNameTag(stats.testInfo->tags);
10973-            if ( className.empty() ) {
10974-                className = "global";
10975-            }
10976-        }
10977-
10978-        if ( !m_config->name().empty() )
10979-            className = static_cast<std::string>(m_config->name()) + '.' + className;
10980-
10981-        normalizeNamespaceMarkers(className);
10982-
10983-        writeSection( className, "", rootSection, stats.testInfo->okToFail() );
10984-    }
10985-
10986-    void JunitReporter::writeSection( std::string const& className,
10987-                                      std::string const& rootName,
10988-                                      SectionNode const& sectionNode,
10989-                                      bool testOkToFail) {
10990-        std::string name = trim( sectionNode.stats.sectionInfo.name );
10991-        if( !rootName.empty() )
10992-            name = rootName + '/' + name;
10993-
10994-        if ( sectionNode.stats.assertions.total() > 0
10995-           || !sectionNode.stdOut.empty()
10996-           || !sectionNode.stdErr.empty() ) {
10997-            XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
10998-            if( className.empty() ) {
10999-                xml.writeAttribute( "classname"_sr, name );
11000-                xml.writeAttribute( "name"_sr, "root"_sr );
11001-            }
11002-            else {
11003-                xml.writeAttribute( "classname"_sr, className );
11004-                xml.writeAttribute( "name"_sr, name );
11005-            }
11006-            xml.writeAttribute( "time"_sr, formatDuration( sectionNode.stats.durationInSeconds ) );
11007-            // This is not ideal, but it should be enough to mimic gtest's
11008-            // junit output.
11009-            // Ideally the JUnit reporter would also handle `skipTest`
11010-            // events and write those out appropriately.
11011-            xml.writeAttribute( "status"_sr, "run"_sr );
11012-
11013-            if (sectionNode.stats.assertions.failedButOk) {
11014-                xml.scopedElement("skipped")
11015-                    .writeAttribute("message", "TEST_CASE tagged with !mayfail");
11016-            }
11017-
11018-            writeAssertions( sectionNode );
11019-
11020-
11021-            if( !sectionNode.stdOut.empty() )
11022-                xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
11023-            if( !sectionNode.stdErr.empty() )
11024-                xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline );
11025-        }
11026-        for( auto const& childNode : sectionNode.childSections )
11027-            if( className.empty() )
11028-                writeSection( name, "", *childNode, testOkToFail );
11029-            else
11030-                writeSection( className, name, *childNode, testOkToFail );
11031-    }
11032-
11033-    void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
11034-        for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
11035-            if (assertionOrBenchmark.isAssertion()) {
11036-                writeAssertion(assertionOrBenchmark.asAssertion());
11037-            }
11038-        }
11039-    }
11040-
11041-    void JunitReporter::writeAssertion( AssertionStats const& stats ) {
11042-        AssertionResult const& result = stats.assertionResult;
11043-        if ( !result.isOk() ||
11044-             result.getResultType() == ResultWas::ExplicitSkip ) {
11045-            std::string elementName;
11046-            switch( result.getResultType() ) {
11047-                case ResultWas::ThrewException:
11048-                case ResultWas::FatalErrorCondition:
11049-                    elementName = "error";
11050-                    break;
11051-                case ResultWas::ExplicitFailure:
11052-                case ResultWas::ExpressionFailed:
11053-                case ResultWas::DidntThrowException:
11054-                    elementName = "failure";
11055-                    break;
11056-                case ResultWas::ExplicitSkip:
11057-                    elementName = "skipped";
11058-                    break;
11059-                // We should never see these here:
11060-                case ResultWas::Info:
11061-                case ResultWas::Warning:
11062-                case ResultWas::Ok:
11063-                case ResultWas::Unknown:
11064-                case ResultWas::FailureBit:
11065-                case ResultWas::Exception:
11066-                    elementName = "internalError";
11067-                    break;
11068-            }
11069-
11070-            XmlWriter::ScopedElement e = xml.scopedElement( elementName );
11071-
11072-            xml.writeAttribute( "message"_sr, result.getExpression() );
11073-            xml.writeAttribute( "type"_sr, result.getTestMacroName() );
11074-
11075-            ReusableStringStream rss;
11076-            if ( result.getResultType() == ResultWas::ExplicitSkip ) {
11077-                rss << "SKIPPED\n";
11078-            } else {
11079-                rss << "FAILED" << ":\n";
11080-                if (result.hasExpression()) {
11081-                    rss << "  ";
11082-                    rss << result.getExpressionInMacro();
11083-                    rss << '\n';
11084-                }
11085-                if (result.hasExpandedExpression()) {
11086-                    rss << "with expansion:\n";
11087-                    rss << TextFlow::Column(result.getExpandedExpression()).indent(2) << '\n';
11088-                }
11089-            }
11090-
11091-            if( result.hasMessage() )
11092-                rss << result.getMessage() << '\n';
11093-            for( auto const& msg : stats.infoMessages )
11094-                if( msg.type == ResultWas::Info )
11095-                    rss << msg.message << '\n';
11096-
11097-            rss << "at " << result.getSourceInfo();
11098-            xml.writeText( rss.str(), XmlFormatting::Newline );
11099-        }
11100-    }
11101-
11102-} // end namespace Catch
11103-
11104-
11105-
11106-
11107-#include <ostream>
11108-
11109-namespace Catch {
11110-    void MultiReporter::updatePreferences(IEventListener const& reporterish) {
11111-        m_preferences.shouldRedirectStdOut |=
11112-            reporterish.getPreferences().shouldRedirectStdOut;
11113-        m_preferences.shouldReportAllAssertions |=
11114-            reporterish.getPreferences().shouldReportAllAssertions;
11115-        m_preferences.shouldReportAllAssertionStarts |=
11116-            reporterish.getPreferences().shouldReportAllAssertionStarts;
11117-    }
11118-
11119-    void MultiReporter::addListener( IEventListenerPtr&& listener ) {
11120-        updatePreferences(*listener);
11121-        m_reporterLikes.insert(m_reporterLikes.begin() + m_insertedListeners, CATCH_MOVE(listener) );
11122-        ++m_insertedListeners;
11123-    }
11124-
11125-    void MultiReporter::addReporter( IEventListenerPtr&& reporter ) {
11126-        updatePreferences(*reporter);
11127-
11128-        // We will need to output the captured stdout if there are reporters
11129-        // that do not want it captured.
11130-        // We do not consider listeners, because it is generally assumed that
11131-        // listeners are output-transparent, even though they can ask for stdout
11132-        // capture to do something with it.
11133-        m_haveNoncapturingReporters |= !reporter->getPreferences().shouldRedirectStdOut;
11134-
11135-        // Reporters can always be placed to the back without breaking the
11136-        // reporting order
11137-        m_reporterLikes.push_back( CATCH_MOVE( reporter ) );
11138-    }
11139-
11140-    void MultiReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
11141-        for ( auto& reporterish : m_reporterLikes ) {
11142-            reporterish->noMatchingTestCases( unmatchedSpec );
11143-        }
11144-    }
11145-
11146-    void MultiReporter::fatalErrorEncountered( StringRef error ) {
11147-        for ( auto& reporterish : m_reporterLikes ) {
11148-            reporterish->fatalErrorEncountered( error );
11149-        }
11150-    }
11151-
11152-    void MultiReporter::reportInvalidTestSpec( StringRef arg ) {
11153-        for ( auto& reporterish : m_reporterLikes ) {
11154-            reporterish->reportInvalidTestSpec( arg );
11155-        }
11156-    }
11157-
11158-    void MultiReporter::benchmarkPreparing( StringRef name ) {
11159-        for (auto& reporterish : m_reporterLikes) {
11160-            reporterish->benchmarkPreparing(name);
11161-        }
11162-    }
11163-    void MultiReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
11164-        for ( auto& reporterish : m_reporterLikes ) {
11165-            reporterish->benchmarkStarting( benchmarkInfo );
11166-        }
11167-    }
11168-    void MultiReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) {
11169-        for ( auto& reporterish : m_reporterLikes ) {
11170-            reporterish->benchmarkEnded( benchmarkStats );
11171-        }
11172-    }
11173-
11174-    void MultiReporter::benchmarkFailed( StringRef error ) {
11175-        for (auto& reporterish : m_reporterLikes) {
11176-            reporterish->benchmarkFailed(error);
11177-        }
11178-    }
11179-
11180-    void MultiReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
11181-        for ( auto& reporterish : m_reporterLikes ) {
11182-            reporterish->testRunStarting( testRunInfo );
11183-        }
11184-    }
11185-
11186-    void MultiReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
11187-        for ( auto& reporterish : m_reporterLikes ) {
11188-            reporterish->testCaseStarting( testInfo );
11189-        }
11190-    }
11191-
11192-    void
11193-    MultiReporter::testCasePartialStarting( TestCaseInfo const& testInfo,
11194-                                                uint64_t partNumber ) {
11195-        for ( auto& reporterish : m_reporterLikes ) {
11196-            reporterish->testCasePartialStarting( testInfo, partNumber );
11197-        }
11198-    }
11199-
11200-    void MultiReporter::sectionStarting( SectionInfo const& sectionInfo ) {
11201-        for ( auto& reporterish : m_reporterLikes ) {
11202-            reporterish->sectionStarting( sectionInfo );
11203-        }
11204-    }
11205-
11206-    void MultiReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
11207-        for ( auto& reporterish : m_reporterLikes ) {
11208-            reporterish->assertionStarting( assertionInfo );
11209-        }
11210-    }
11211-
11212-    void MultiReporter::assertionEnded( AssertionStats const& assertionStats ) {
11213-        const bool reportByDefault =
11214-            assertionStats.assertionResult.getResultType() != ResultWas::Ok ||
11215-            m_config->includeSuccessfulResults();
11216-
11217-        for ( auto & reporterish : m_reporterLikes ) {
11218-            if ( reportByDefault ||
11219-                 reporterish->getPreferences().shouldReportAllAssertions ) {
11220-                    reporterish->assertionEnded( assertionStats );
11221-            }
11222-        }
11223-    }
11224-
11225-    void MultiReporter::sectionEnded( SectionStats const& sectionStats ) {
11226-        for ( auto& reporterish : m_reporterLikes ) {
11227-            reporterish->sectionEnded( sectionStats );
11228-        }
11229-    }
11230-
11231-    void MultiReporter::testCasePartialEnded( TestCaseStats const& testStats,
11232-                                                  uint64_t partNumber ) {
11233-        if ( m_preferences.shouldRedirectStdOut &&
11234-             m_haveNoncapturingReporters ) {
11235-            if ( !testStats.stdOut.empty() ) {
11236-                Catch::cout() << testStats.stdOut << std::flush;
11237-            }
11238-            if ( !testStats.stdErr.empty() ) {
11239-                Catch::cerr() << testStats.stdErr << std::flush;
11240-            }
11241-        }
11242-
11243-        for ( auto& reporterish : m_reporterLikes ) {
11244-            reporterish->testCasePartialEnded( testStats, partNumber );
11245-        }
11246-    }
11247-
11248-    void MultiReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
11249-        for ( auto& reporterish : m_reporterLikes ) {
11250-            reporterish->testCaseEnded( testCaseStats );
11251-        }
11252-    }
11253-
11254-    void MultiReporter::testRunEnded( TestRunStats const& testRunStats ) {
11255-        for ( auto& reporterish : m_reporterLikes ) {
11256-            reporterish->testRunEnded( testRunStats );
11257-        }
11258-    }
11259-
11260-
11261-    void MultiReporter::skipTest( TestCaseInfo const& testInfo ) {
11262-        for ( auto& reporterish : m_reporterLikes ) {
11263-            reporterish->skipTest( testInfo );
11264-        }
11265-    }
11266-
11267-    void MultiReporter::listReporters(std::vector<ReporterDescription> const& descriptions) {
11268-        for (auto& reporterish : m_reporterLikes) {
11269-            reporterish->listReporters(descriptions);
11270-        }
11271-    }
11272-
11273-    void MultiReporter::listListeners(
11274-        std::vector<ListenerDescription> const& descriptions ) {
11275-        for ( auto& reporterish : m_reporterLikes ) {
11276-            reporterish->listListeners( descriptions );
11277-        }
11278-    }
11279-
11280-    void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) {
11281-        for (auto& reporterish : m_reporterLikes) {
11282-            reporterish->listTests(tests);
11283-        }
11284-    }
11285-
11286-    void MultiReporter::listTags(std::vector<TagInfo> const& tags) {
11287-        for (auto& reporterish : m_reporterLikes) {
11288-            reporterish->listTags(tags);
11289-        }
11290-    }
11291-
11292-} // end namespace Catch
11293-
11294-
11295-
11296-
11297-
11298-namespace Catch {
11299-    namespace Detail {
11300-
11301-        void registerReporterImpl( std::string const& name,
11302-                                   IReporterFactoryPtr reporterPtr ) {
11303-            CATCH_TRY {
11304-                getMutableRegistryHub().registerReporter(
11305-                    name, CATCH_MOVE( reporterPtr ) );
11306-            }
11307-            CATCH_CATCH_ALL {
11308-                // Do not throw when constructing global objects, instead
11309-                // register the exception to be processed later
11310-                getMutableRegistryHub().registerStartupException();
11311-            }
11312-        }
11313-
11314-        void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory ) {
11315-            getMutableRegistryHub().registerListener( CATCH_MOVE(listenerFactory) );
11316-        }
11317-
11318-
11319-    } // namespace Detail
11320-} // namespace Catch
11321-
11322-
11323-
11324-
11325-#include <map>
11326-
11327-namespace Catch {
11328-
11329-    namespace {
11330-        std::string createMetadataString(IConfig const& config) {
11331-            ReusableStringStream sstr;
11332-            if ( config.testSpec().hasFilters() ) {
11333-                sstr << "filters='"
11334-                         << config.testSpec()
11335-                         << "' ";
11336-            }
11337-            sstr << "rng-seed=" << config.rngSeed();
11338-            return sstr.str();
11339-        }
11340-    }
11341-
11342-    void SonarQubeReporter::testRunStarting(TestRunInfo const& testRunInfo) {
11343-        CumulativeReporterBase::testRunStarting(testRunInfo);
11344-
11345-        xml.writeComment( createMetadataString( *m_config ) );
11346-        xml.startElement("testExecutions");
11347-        xml.writeAttribute("version"_sr, '1');
11348-    }
11349-
11350-    void SonarQubeReporter::writeRun( TestRunNode const& runNode ) {
11351-        std::map<StringRef, std::vector<TestCaseNode const*>> testsPerFile;
11352-
11353-        for ( auto const& child : runNode.children ) {
11354-            testsPerFile[child->value.testInfo->lineInfo.file].push_back(
11355-                child.get() );
11356-        }
11357-
11358-        for ( auto const& kv : testsPerFile ) {
11359-            writeTestFile( kv.first, kv.second );
11360-        }
11361-    }
11362-
11363-    void SonarQubeReporter::writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
11364-        XmlWriter::ScopedElement e = xml.scopedElement("file");
11365-        xml.writeAttribute("path"_sr, filename);
11366-
11367-        for (auto const& child : testCaseNodes)
11368-            writeTestCase(*child);
11369-    }
11370-
11371-    void SonarQubeReporter::writeTestCase(TestCaseNode const& testCaseNode) {
11372-        // All test cases have exactly one section - which represents the
11373-        // test case itself. That section may have 0-n nested sections
11374-        assert(testCaseNode.children.size() == 1);
11375-        SectionNode const& rootSection = *testCaseNode.children.front();
11376-        writeSection("", rootSection, testCaseNode.value.testInfo->okToFail());
11377-    }
11378-
11379-    void SonarQubeReporter::writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
11380-        std::string name = trim(sectionNode.stats.sectionInfo.name);
11381-        if (!rootName.empty())
11382-            name = rootName + '/' + name;
11383-
11384-        if ( sectionNode.stats.assertions.total() > 0
11385-            || !sectionNode.stdOut.empty()
11386-            || !sectionNode.stdErr.empty() ) {
11387-            XmlWriter::ScopedElement e = xml.scopedElement("testCase");
11388-            xml.writeAttribute("name"_sr, name);
11389-            xml.writeAttribute("duration"_sr, static_cast<long>(sectionNode.stats.durationInSeconds * 1000));
11390-
11391-            writeAssertions(sectionNode, okToFail);
11392-        }
11393-
11394-        for (auto const& childNode : sectionNode.childSections)
11395-            writeSection(name, *childNode, okToFail);
11396-    }
11397-
11398-    void SonarQubeReporter::writeAssertions(SectionNode const& sectionNode, bool okToFail) {
11399-        for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
11400-            if (assertionOrBenchmark.isAssertion()) {
11401-                writeAssertion(assertionOrBenchmark.asAssertion(), okToFail);
11402-            }
11403-        }
11404-    }
11405-
11406-    void SonarQubeReporter::writeAssertion(AssertionStats const& stats, bool okToFail) {
11407-        AssertionResult const& result = stats.assertionResult;
11408-        if ( !result.isOk() ||
11409-             result.getResultType() == ResultWas::ExplicitSkip ) {
11410-            std::string elementName;
11411-            if (okToFail) {
11412-                elementName = "skipped";
11413-            } else {
11414-                switch (result.getResultType()) {
11415-                case ResultWas::ThrewException:
11416-                case ResultWas::FatalErrorCondition:
11417-                    elementName = "error";
11418-                    break;
11419-                case ResultWas::ExplicitFailure:
11420-                case ResultWas::ExpressionFailed:
11421-                case ResultWas::DidntThrowException:
11422-                    elementName = "failure";
11423-                    break;
11424-                case ResultWas::ExplicitSkip:
11425-                    elementName = "skipped";
11426-                    break;
11427-                    // We should never see these here:
11428-                case ResultWas::Info:
11429-                case ResultWas::Warning:
11430-                case ResultWas::Ok:
11431-                case ResultWas::Unknown:
11432-                case ResultWas::FailureBit:
11433-                case ResultWas::Exception:
11434-                    elementName = "internalError";
11435-                    break;
11436-                }
11437-            }
11438-
11439-            XmlWriter::ScopedElement e = xml.scopedElement(elementName);
11440-
11441-            ReusableStringStream messageRss;
11442-            messageRss << result.getTestMacroName() << '(' << result.getExpression() << ')';
11443-            xml.writeAttribute("message"_sr, messageRss.str());
11444-
11445-            ReusableStringStream textRss;
11446-            if ( result.getResultType() == ResultWas::ExplicitSkip ) {
11447-                textRss << "SKIPPED\n";
11448-            } else {
11449-                textRss << "FAILED:\n";
11450-                if (result.hasExpression()) {
11451-                    textRss << '\t' << result.getExpressionInMacro() << '\n';
11452-                }
11453-                if (result.hasExpandedExpression()) {
11454-                    textRss << "with expansion:\n\t" << result.getExpandedExpression() << '\n';
11455-                }
11456-            }
11457-
11458-            if (result.hasMessage())
11459-                textRss << result.getMessage() << '\n';
11460-
11461-            for (auto const& msg : stats.infoMessages)
11462-                if (msg.type == ResultWas::Info)
11463-                    textRss << msg.message << '\n';
11464-
11465-            textRss << "at " << result.getSourceInfo();
11466-            xml.writeText(textRss.str(), XmlFormatting::Newline);
11467-        }
11468-    }
11469-
11470-} // end namespace Catch
11471-
11472-
11473-
11474-namespace Catch {
11475-
11476-    StreamingReporterBase::~StreamingReporterBase() = default;
11477-
11478-    void
11479-    StreamingReporterBase::testRunStarting( TestRunInfo const& _testRunInfo ) {
11480-        currentTestRunInfo = _testRunInfo;
11481-    }
11482-
11483-    void StreamingReporterBase::testRunEnded( TestRunStats const& ) {
11484-        currentTestCaseInfo = nullptr;
11485-    }
11486-
11487-} // end namespace Catch
11488-
11489-
11490-
11491-#include <algorithm>
11492-#include <ostream>
11493-
11494-namespace Catch {
11495-
11496-    namespace {
11497-        // Yes, this has to be outside the class and namespaced by naming.
11498-        // Making older compiler happy is hard.
11499-        static constexpr StringRef tapFailedString = "not ok"_sr;
11500-        static constexpr StringRef tapPassedString = "ok"_sr;
11501-        static constexpr Colour::Code tapDimColour = Colour::FileName;
11502-
11503-        class TapAssertionPrinter {
11504-        public:
11505-            TapAssertionPrinter& operator= (TapAssertionPrinter const&) = delete;
11506-            TapAssertionPrinter(TapAssertionPrinter const&) = delete;
11507-            TapAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter, ColourImpl* colour_)
11508-                : stream(_stream)
11509-                , result(_stats.assertionResult)
11510-                , messages(_stats.infoMessages)
11511-                , itMessage(_stats.infoMessages.begin())
11512-                , printInfoMessages(true)
11513-                , counter(_counter)
11514-                , colourImpl( colour_ ) {}
11515-
11516-            void print() {
11517-                itMessage = messages.begin();
11518-
11519-                switch (result.getResultType()) {
11520-                case ResultWas::Ok:
11521-                    printResultType(tapPassedString);
11522-                    printOriginalExpression();
11523-                    printReconstructedExpression();
11524-                    if (!result.hasExpression())
11525-                        printRemainingMessages(Colour::None);
11526-                    else
11527-                        printRemainingMessages();
11528-                    break;
11529-                case ResultWas::ExpressionFailed:
11530-                    if (result.isOk()) {
11531-                        printResultType(tapPassedString);
11532-                    } else {
11533-                        printResultType(tapFailedString);
11534-                    }
11535-                    printOriginalExpression();
11536-                    printReconstructedExpression();
11537-                    if (result.isOk()) {
11538-                        printIssue(" # TODO");
11539-                    }
11540-                    printRemainingMessages();
11541-                    break;
11542-                case ResultWas::ThrewException:
11543-                    printResultType(tapFailedString);
11544-                    printIssue("unexpected exception with message:"_sr);
11545-                    printMessage();
11546-                    printExpressionWas();
11547-                    printRemainingMessages();
11548-                    break;
11549-                case ResultWas::FatalErrorCondition:
11550-                    printResultType(tapFailedString);
11551-                    printIssue("fatal error condition with message:"_sr);
11552-                    printMessage();
11553-                    printExpressionWas();
11554-                    printRemainingMessages();
11555-                    break;
11556-                case ResultWas::DidntThrowException:
11557-                    printResultType(tapFailedString);
11558-                    printIssue("expected exception, got none"_sr);
11559-                    printExpressionWas();
11560-                    printRemainingMessages();
11561-                    break;
11562-                case ResultWas::Info:
11563-                    printResultType("info"_sr);
11564-                    printMessage();
11565-                    printRemainingMessages();
11566-                    break;
11567-                case ResultWas::Warning:
11568-                    printResultType("warning"_sr);
11569-                    printMessage();
11570-                    printRemainingMessages();
11571-                    break;
11572-                case ResultWas::ExplicitFailure:
11573-                    printResultType(tapFailedString);
11574-                    printIssue("explicitly"_sr);
11575-                    printRemainingMessages(Colour::None);
11576-                    break;
11577-                case ResultWas::ExplicitSkip:
11578-                    printResultType(tapPassedString);
11579-                    printIssue(" # SKIP"_sr);
11580-                    printMessage();
11581-                    printRemainingMessages();
11582-                    break;
11583-                    // These cases are here to prevent compiler warnings
11584-                case ResultWas::Unknown:
11585-                case ResultWas::FailureBit:
11586-                case ResultWas::Exception:
11587-                    printResultType("** internal error **"_sr);
11588-                    break;
11589-                }
11590-            }
11591-
11592-        private:
11593-            void printResultType(StringRef passOrFail) const {
11594-                if (!passOrFail.empty()) {
11595-                    stream << passOrFail << ' ' << counter << " -";
11596-                }
11597-            }
11598-
11599-            void printIssue(StringRef issue) const {
11600-                stream << ' ' << issue;
11601-            }
11602-
11603-            void printExpressionWas() {
11604-                if (result.hasExpression()) {
11605-                    stream << ';';
11606-                    stream << colourImpl->guardColour( tapDimColour )
11607-                           << " expression was:";
11608-                    printOriginalExpression();
11609-                }
11610-            }
11611-
11612-            void printOriginalExpression() const {
11613-                if (result.hasExpression()) {
11614-                    stream << ' ' << result.getExpression();
11615-                }
11616-            }
11617-
11618-            void printReconstructedExpression() const {
11619-                if (result.hasExpandedExpression()) {
11620-                    stream << colourImpl->guardColour( tapDimColour ) << " for: ";
11621-
11622-                    std::string expr = result.getExpandedExpression();
11623-                    std::replace(expr.begin(), expr.end(), '\n', ' ');
11624-                    stream << expr;
11625-                }
11626-            }
11627-
11628-            void printMessage() {
11629-                if (itMessage != messages.end()) {
11630-                    stream << " '" << itMessage->message << '\'';
11631-                    ++itMessage;
11632-                }
11633-            }
11634-
11635-            void printRemainingMessages(Colour::Code colour = tapDimColour) {
11636-                if (itMessage == messages.end()) {
11637-                    return;
11638-                }
11639-
11640-                // using messages.end() directly (or auto) yields compilation error:
11641-                std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11642-                const std::size_t N = static_cast<std::size_t>(itEnd - itMessage);
11643-
11644-                stream << colourImpl->guardColour( colour ) << " with "
11645-                       << pluralise( N, "message"_sr ) << ':';
11646-
11647-                for (; itMessage != itEnd; ) {
11648-                    // If this assertion is a warning ignore any INFO messages
11649-                    if (printInfoMessages || itMessage->type != ResultWas::Info) {
11650-                        stream << " '" << itMessage->message << '\'';
11651-                        if (++itMessage != itEnd) {
11652-                            stream << colourImpl->guardColour(tapDimColour) << " and";
11653-                        }
11654-                    }
11655-                }
11656-            }
11657-
11658-        private:
11659-            std::ostream& stream;
11660-            AssertionResult const& result;
11661-            std::vector<MessageInfo> const& messages;
11662-            std::vector<MessageInfo>::const_iterator itMessage;
11663-            bool printInfoMessages;
11664-            std::size_t counter;
11665-            ColourImpl* colourImpl;
11666-        };
11667-
11668-    } // End anonymous namespace
11669-
11670-    void TAPReporter::testRunStarting( TestRunInfo const& ) {
11671-        if ( m_config->testSpec().hasFilters() ) {
11672-            m_stream << "# filters: " << m_config->testSpec() << '\n';
11673-        }
11674-        m_stream << "# rng-seed: " << m_config->rngSeed() << '\n'
11675-                 << std::flush;
11676-    }
11677-
11678-    void TAPReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
11679-        m_stream << "# No test cases matched '" << unmatchedSpec << "'\n";
11680-    }
11681-
11682-    void TAPReporter::assertionEnded(AssertionStats const& _assertionStats) {
11683-        ++counter;
11684-
11685-        m_stream << "# " << currentTestCaseInfo->name << '\n';
11686-        TapAssertionPrinter printer(m_stream, _assertionStats, counter, m_colour.get());
11687-        printer.print();
11688-
11689-        m_stream << '\n' << std::flush;
11690-    }
11691-
11692-    void TAPReporter::testRunEnded(TestRunStats const& _testRunStats) {
11693-        m_stream << "1.." << _testRunStats.totals.assertions.total();
11694-        if (_testRunStats.totals.testCases.total() == 0) {
11695-            m_stream << " # Skipped: No tests ran.";
11696-        }
11697-        m_stream << "\n\n" << std::flush;
11698-        StreamingReporterBase::testRunEnded(_testRunStats);
11699-    }
11700-
11701-
11702-
11703-
11704-} // end namespace Catch
11705-
11706-
11707-
11708-
11709-#include <cassert>
11710-#include <ostream>
11711-
11712-namespace Catch {
11713-
11714-    namespace {
11715-        // if string has a : in first line will set indent to follow it on
11716-        // subsequent lines
11717-        void printHeaderString(std::ostream& os, std::string const& _string, std::size_t indent = 0) {
11718-            std::size_t i = _string.find(": ");
11719-            if (i != std::string::npos)
11720-                i += 2;
11721-            else
11722-                i = 0;
11723-            os << TextFlow::Column(_string)
11724-                  .indent(indent + i)
11725-                  .initialIndent(indent) << '\n';
11726-        }
11727-
11728-        std::string escape(StringRef str) {
11729-            std::string escaped = static_cast<std::string>(str);
11730-            replaceInPlace(escaped, "|", "||");
11731-            replaceInPlace(escaped, "'", "|'");
11732-            replaceInPlace(escaped, "\n", "|n");
11733-            replaceInPlace(escaped, "\r", "|r");
11734-            replaceInPlace(escaped, "[", "|[");
11735-            replaceInPlace(escaped, "]", "|]");
11736-            return escaped;
11737-        }
11738-    } // end anonymous namespace
11739-
11740-
11741-    TeamCityReporter::~TeamCityReporter() = default;
11742-
11743-    void TeamCityReporter::testRunStarting( TestRunInfo const& runInfo ) {
11744-        m_stream << "##teamcity[testSuiteStarted name='" << escape( runInfo.name )
11745-               << "']\n";
11746-    }
11747-
11748-    void TeamCityReporter::testRunEnded( TestRunStats const& runStats ) {
11749-        m_stream << "##teamcity[testSuiteFinished name='"
11750-               << escape( runStats.runInfo.name ) << "']\n";
11751-    }
11752-
11753-    void TeamCityReporter::assertionEnded(AssertionStats const& assertionStats) {
11754-        AssertionResult const& result = assertionStats.assertionResult;
11755-        if ( !result.isOk() ||
11756-             result.getResultType() == ResultWas::ExplicitSkip ) {
11757-
11758-            ReusableStringStream msg;
11759-            if (!m_headerPrintedForThisSection)
11760-                printSectionHeader(msg.get());
11761-            m_headerPrintedForThisSection = true;
11762-
11763-            msg << result.getSourceInfo() << '\n';
11764-
11765-            switch (result.getResultType()) {
11766-            case ResultWas::ExpressionFailed:
11767-                msg << "expression failed";
11768-                break;
11769-            case ResultWas::ThrewException:
11770-                msg << "unexpected exception";
11771-                break;
11772-            case ResultWas::FatalErrorCondition:
11773-                msg << "fatal error condition";
11774-                break;
11775-            case ResultWas::DidntThrowException:
11776-                msg << "no exception was thrown where one was expected";
11777-                break;
11778-            case ResultWas::ExplicitFailure:
11779-                msg << "explicit failure";
11780-                break;
11781-            case ResultWas::ExplicitSkip:
11782-                msg << "explicit skip";
11783-                break;
11784-
11785-                // We shouldn't get here because of the isOk() test
11786-            case ResultWas::Ok:
11787-            case ResultWas::Info:
11788-            case ResultWas::Warning:
11789-                CATCH_ERROR("Internal error in TeamCity reporter");
11790-                // These cases are here to prevent compiler warnings
11791-            case ResultWas::Unknown:
11792-            case ResultWas::FailureBit:
11793-            case ResultWas::Exception:
11794-                CATCH_ERROR("Not implemented");
11795-            }
11796-            if (assertionStats.infoMessages.size() == 1)
11797-                msg << " with message:";
11798-            if (assertionStats.infoMessages.size() > 1)
11799-                msg << " with messages:";
11800-            for (auto const& messageInfo : assertionStats.infoMessages)
11801-                msg << "\n  \"" << messageInfo.message << '"';
11802-
11803-
11804-            if (result.hasExpression()) {
11805-                msg <<
11806-                    "\n  " << result.getExpressionInMacro() << "\n"
11807-                    "with expansion:\n"
11808-                    "  " << result.getExpandedExpression() << '\n';
11809-            }
11810-
11811-            if ( result.getResultType() == ResultWas::ExplicitSkip ) {
11812-                m_stream << "##teamcity[testIgnored";
11813-            } else if ( currentTestCaseInfo->okToFail() ) {
11814-                msg << "- failure ignore as test marked as 'ok to fail'\n";
11815-                m_stream << "##teamcity[testIgnored";
11816-            } else {
11817-                m_stream << "##teamcity[testFailed";
11818-            }
11819-            m_stream << " name='" << escape( currentTestCaseInfo->name ) << '\''
11820-                     << " message='" << escape( msg.str() ) << '\'' << "]\n";
11821-        }
11822-        m_stream.flush();
11823-    }
11824-
11825-    void TeamCityReporter::testCaseStarting(TestCaseInfo const& testInfo) {
11826-        m_testTimer.start();
11827-        StreamingReporterBase::testCaseStarting(testInfo);
11828-        m_stream << "##teamcity[testStarted name='"
11829-            << escape(testInfo.name) << "']\n";
11830-        m_stream.flush();
11831-    }
11832-
11833-    void TeamCityReporter::testCaseEnded(TestCaseStats const& testCaseStats) {
11834-        StreamingReporterBase::testCaseEnded(testCaseStats);
11835-        auto const& testCaseInfo = *testCaseStats.testInfo;
11836-        if (!testCaseStats.stdOut.empty())
11837-            m_stream << "##teamcity[testStdOut name='"
11838-            << escape(testCaseInfo.name)
11839-            << "' out='" << escape(testCaseStats.stdOut) << "']\n";
11840-        if (!testCaseStats.stdErr.empty())
11841-            m_stream << "##teamcity[testStdErr name='"
11842-            << escape(testCaseInfo.name)
11843-            << "' out='" << escape(testCaseStats.stdErr) << "']\n";
11844-        m_stream << "##teamcity[testFinished name='"
11845-            << escape(testCaseInfo.name) << "' duration='"
11846-            << m_testTimer.getElapsedMilliseconds() << "']\n";
11847-        m_stream.flush();
11848-    }
11849-
11850-    void TeamCityReporter::printSectionHeader(std::ostream& os) {
11851-        assert(!m_sectionStack.empty());
11852-
11853-        if (m_sectionStack.size() > 1) {
11854-            os << lineOfChars('-') << '\n';
11855-
11856-            std::vector<SectionInfo>::const_iterator
11857-                it = m_sectionStack.begin() + 1, // Skip first section (test case)
11858-                itEnd = m_sectionStack.end();
11859-            for (; it != itEnd; ++it)
11860-                printHeaderString(os, it->name);
11861-            os << lineOfChars('-') << '\n';
11862-        }
11863-
11864-        SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
11865-
11866-        os << lineInfo << '\n';
11867-        os << lineOfChars('.') << "\n\n";
11868-    }
11869-
11870-} // end namespace Catch
11871-
11872-
11873-
11874-
11875-#if defined(_MSC_VER)
11876-#pragma warning(push)
11877-#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
11878-                              // Note that 4062 (not all labels are handled
11879-                              // and default is missing) is enabled
11880-#endif
11881-
11882-namespace Catch {
11883-    XmlReporter::XmlReporter( ReporterConfig&& _config )
11884-    :   StreamingReporterBase( CATCH_MOVE(_config) ),
11885-        m_xml(m_stream)
11886-    {
11887-        m_preferences.shouldRedirectStdOut = true;
11888-        m_preferences.shouldReportAllAssertions = true;
11889-        m_preferences.shouldReportAllAssertionStarts = false;
11890-    }
11891-
11892-    XmlReporter::~XmlReporter() = default;
11893-
11894-    std::string XmlReporter::getDescription() {
11895-        return "Reports test results as an XML document";
11896-    }
11897-
11898-    std::string XmlReporter::getStylesheetRef() const {
11899-        return std::string();
11900-    }
11901-
11902-    void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {
11903-        m_xml
11904-            .writeAttribute( "filename"_sr, sourceInfo.file )
11905-            .writeAttribute( "line"_sr, sourceInfo.line );
11906-    }
11907-
11908-    void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {
11909-        StreamingReporterBase::testRunStarting( testInfo );
11910-        std::string stylesheetRef = getStylesheetRef();
11911-        if( !stylesheetRef.empty() )
11912-            m_xml.writeStylesheetRef( stylesheetRef );
11913-        m_xml.startElement("Catch2TestRun")
11914-             .writeAttribute("name"_sr, m_config->name())
11915-             .writeAttribute("rng-seed"_sr, m_config->rngSeed())
11916-             .writeAttribute("xml-format-version"_sr, 3)
11917-             .writeAttribute("catch2-version"_sr, libraryVersion());
11918-        if ( m_config->testSpec().hasFilters() ) {
11919-            m_xml.writeAttribute( "filters"_sr, m_config->testSpec() );
11920-        }
11921-    }
11922-
11923-    void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
11924-        StreamingReporterBase::testCaseStarting(testInfo);
11925-        m_xml.startElement( "TestCase" )
11926-            .writeAttribute( "name"_sr, trim( StringRef(testInfo.name) ) )
11927-            .writeAttribute( "tags"_sr, testInfo.tagsAsString() );
11928-
11929-        writeSourceInfo( testInfo.lineInfo );
11930-
11931-        if ( m_config->showDurations() == ShowDurations::Always )
11932-            m_testCaseTimer.start();
11933-        m_xml.ensureTagClosed();
11934-    }
11935-
11936-    void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {
11937-        StreamingReporterBase::sectionStarting( sectionInfo );
11938-        if( m_sectionDepth++ > 0 ) {
11939-            m_xml.startElement( "Section" )
11940-                .writeAttribute( "name"_sr, trim( StringRef(sectionInfo.name) ) );
11941-            writeSourceInfo( sectionInfo.lineInfo );
11942-            m_xml.ensureTagClosed();
11943-        }
11944-    }
11945-
11946-    void XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
11947-
11948-        AssertionResult const& result = assertionStats.assertionResult;
11949-
11950-        bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
11951-
11952-        if( includeResults || result.getResultType() == ResultWas::Warning ) {
11953-            // Print any info messages in <Info> tags.
11954-            for( auto const& msg : assertionStats.infoMessages ) {
11955-                if( msg.type == ResultWas::Info && includeResults ) {
11956-                    auto t = m_xml.scopedElement( "Info" );
11957-                    writeSourceInfo( msg.lineInfo );
11958-                    t.writeText( msg.message );
11959-                } else if ( msg.type == ResultWas::Warning ) {
11960-                    auto t = m_xml.scopedElement( "Warning" );
11961-                    writeSourceInfo( msg.lineInfo );
11962-                    t.writeText( msg.message );
11963-                }
11964-            }
11965-        }
11966-
11967-        // Drop out if result was successful but we're not printing them.
11968-        if ( !includeResults && result.getResultType() != ResultWas::Warning &&
11969-             result.getResultType() != ResultWas::ExplicitSkip ) {
11970-            return;
11971-        }
11972-
11973-        // Print the expression if there is one.
11974-        if( result.hasExpression() ) {
11975-            m_xml.startElement( "Expression" )
11976-                .writeAttribute( "success"_sr, result.succeeded() )
11977-                .writeAttribute( "type"_sr, result.getTestMacroName() );
11978-
11979-            writeSourceInfo( result.getSourceInfo() );
11980-
11981-            m_xml.scopedElement( "Original" )
11982-                .writeText( result.getExpression() );
11983-            m_xml.scopedElement( "Expanded" )
11984-                .writeText( result.getExpandedExpression() );
11985-        }
11986-
11987-        // And... Print a result applicable to each result type.
11988-        switch( result.getResultType() ) {
11989-            case ResultWas::ThrewException:
11990-                m_xml.startElement( "Exception" );
11991-                writeSourceInfo( result.getSourceInfo() );
11992-                m_xml.writeText( result.getMessage() );
11993-                m_xml.endElement();
11994-                break;
11995-            case ResultWas::FatalErrorCondition:
11996-                m_xml.startElement( "FatalErrorCondition" );
11997-                writeSourceInfo( result.getSourceInfo() );
11998-                m_xml.writeText( result.getMessage() );
11999-                m_xml.endElement();
12000-                break;
12001-            case ResultWas::Info:
12002-                m_xml.scopedElement( "Info" )
12003-                     .writeText( result.getMessage() );
12004-                break;
12005-            case ResultWas::Warning:
12006-                // Warning will already have been written
12007-                break;
12008-            case ResultWas::ExplicitFailure:
12009-                m_xml.startElement( "Failure" );
12010-                writeSourceInfo( result.getSourceInfo() );
12011-                m_xml.writeText( result.getMessage() );
12012-                m_xml.endElement();
12013-                break;
12014-            case ResultWas::ExplicitSkip:
12015-                m_xml.startElement( "Skip" );
12016-                writeSourceInfo( result.getSourceInfo() );
12017-                m_xml.writeText( result.getMessage() );
12018-                m_xml.endElement();
12019-                break;
12020-            default:
12021-                break;
12022-        }
12023-
12024-        if( result.hasExpression() )
12025-            m_xml.endElement();
12026-    }
12027-
12028-    void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
12029-        StreamingReporterBase::sectionEnded( sectionStats );
12030-        if ( --m_sectionDepth > 0 ) {
12031-            {
12032-                XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
12033-                e.writeAttribute( "successes"_sr, sectionStats.assertions.passed );
12034-                e.writeAttribute( "failures"_sr, sectionStats.assertions.failed );
12035-                e.writeAttribute( "expectedFailures"_sr, sectionStats.assertions.failedButOk );
12036-                e.writeAttribute( "skipped"_sr, sectionStats.assertions.skipped > 0 );
12037-
12038-                if ( m_config->showDurations() == ShowDurations::Always )
12039-                    e.writeAttribute( "durationInSeconds"_sr, sectionStats.durationInSeconds );
12040-            }
12041-            // Ends assertion tag
12042-            m_xml.endElement();
12043-        }
12044-    }
12045-
12046-    void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
12047-        StreamingReporterBase::testCaseEnded( testCaseStats );
12048-        XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
12049-        e.writeAttribute( "success"_sr, testCaseStats.totals.assertions.allOk() );
12050-        e.writeAttribute( "skips"_sr, testCaseStats.totals.assertions.skipped );
12051-
12052-        if ( m_config->showDurations() == ShowDurations::Always )
12053-            e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() );
12054-        if( !testCaseStats.stdOut.empty() )
12055-            m_xml.scopedElement( "StdOut" ).writeText( trim( StringRef(testCaseStats.stdOut) ), XmlFormatting::Newline );
12056-        if( !testCaseStats.stdErr.empty() )
12057-            m_xml.scopedElement( "StdErr" ).writeText( trim( StringRef(testCaseStats.stdErr) ), XmlFormatting::Newline );
12058-
12059-        m_xml.endElement();
12060-    }
12061-
12062-    void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {
12063-        StreamingReporterBase::testRunEnded( testRunStats );
12064-        m_xml.scopedElement( "OverallResults" )
12065-            .writeAttribute( "successes"_sr, testRunStats.totals.assertions.passed )
12066-            .writeAttribute( "failures"_sr, testRunStats.totals.assertions.failed )
12067-            .writeAttribute( "expectedFailures"_sr, testRunStats.totals.assertions.failedButOk )
12068-            .writeAttribute( "skips"_sr, testRunStats.totals.assertions.skipped );
12069-        m_xml.scopedElement( "OverallResultsCases")
12070-            .writeAttribute( "successes"_sr, testRunStats.totals.testCases.passed )
12071-            .writeAttribute( "failures"_sr, testRunStats.totals.testCases.failed )
12072-            .writeAttribute( "expectedFailures"_sr, testRunStats.totals.testCases.failedButOk )
12073-            .writeAttribute( "skips"_sr, testRunStats.totals.testCases.skipped );
12074-        m_xml.endElement();
12075-    }
12076-
12077-    void XmlReporter::benchmarkPreparing( StringRef name ) {
12078-        m_xml.startElement("BenchmarkResults")
12079-             .writeAttribute("name"_sr, name);
12080-    }
12081-
12082-    void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
12083-        m_xml.writeAttribute("samples"_sr, info.samples)
12084-            .writeAttribute("resamples"_sr, info.resamples)
12085-            .writeAttribute("iterations"_sr, info.iterations)
12086-            .writeAttribute("clockResolution"_sr, info.clockResolution)
12087-            .writeAttribute("estimatedDuration"_sr, info.estimatedDuration)
12088-            .writeComment("All values in nano seconds"_sr);
12089-    }
12090-
12091-    void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
12092-        m_xml.scopedElement("mean")
12093-            .writeAttribute("value"_sr, benchmarkStats.mean.point.count())
12094-            .writeAttribute("lowerBound"_sr, benchmarkStats.mean.lower_bound.count())
12095-            .writeAttribute("upperBound"_sr, benchmarkStats.mean.upper_bound.count())
12096-            .writeAttribute("ci"_sr, benchmarkStats.mean.confidence_interval);
12097-        m_xml.scopedElement("standardDeviation")
12098-            .writeAttribute("value"_sr, benchmarkStats.standardDeviation.point.count())
12099-            .writeAttribute("lowerBound"_sr, benchmarkStats.standardDeviation.lower_bound.count())
12100-            .writeAttribute("upperBound"_sr, benchmarkStats.standardDeviation.upper_bound.count())
12101-            .writeAttribute("ci"_sr, benchmarkStats.standardDeviation.confidence_interval);
12102-        m_xml.scopedElement("outliers")
12103-            .writeAttribute("variance"_sr, benchmarkStats.outlierVariance)
12104-            .writeAttribute("lowMild"_sr, benchmarkStats.outliers.low_mild)
12105-            .writeAttribute("lowSevere"_sr, benchmarkStats.outliers.low_severe)
12106-            .writeAttribute("highMild"_sr, benchmarkStats.outliers.high_mild)
12107-            .writeAttribute("highSevere"_sr, benchmarkStats.outliers.high_severe);
12108-        m_xml.endElement();
12109-    }
12110-
12111-    void XmlReporter::benchmarkFailed(StringRef error) {
12112-        m_xml.scopedElement("failed").
12113-            writeAttribute("message"_sr, error);
12114-        m_xml.endElement();
12115-    }
12116-
12117-    void XmlReporter::listReporters(std::vector<ReporterDescription> const& descriptions) {
12118-        auto outerTag = m_xml.scopedElement("AvailableReporters");
12119-        for (auto const& reporter : descriptions) {
12120-            auto inner = m_xml.scopedElement("Reporter");
12121-            m_xml.startElement("Name", XmlFormatting::Indent)
12122-                 .writeText(reporter.name, XmlFormatting::None)
12123-                 .endElement(XmlFormatting::Newline);
12124-            m_xml.startElement("Description", XmlFormatting::Indent)
12125-                 .writeText(reporter.description, XmlFormatting::None)
12126-                 .endElement(XmlFormatting::Newline);
12127-        }
12128-    }
12129-
12130-    void XmlReporter::listListeners(std::vector<ListenerDescription> const& descriptions) {
12131-        auto outerTag = m_xml.scopedElement( "RegisteredListeners" );
12132-        for ( auto const& listener : descriptions ) {
12133-            auto inner = m_xml.scopedElement( "Listener" );
12134-            m_xml.startElement( "Name", XmlFormatting::Indent )
12135-                .writeText( listener.name, XmlFormatting::None )
12136-                .endElement( XmlFormatting::Newline );
12137-            m_xml.startElement( "Description", XmlFormatting::Indent )
12138-                .writeText( listener.description, XmlFormatting::None )
12139-                .endElement( XmlFormatting::Newline );
12140-        }
12141-    }
12142-
12143-    void XmlReporter::listTests(std::vector<TestCaseHandle> const& tests) {
12144-        auto outerTag = m_xml.scopedElement("MatchingTests");
12145-        for (auto const& test : tests) {
12146-            auto innerTag = m_xml.scopedElement("TestCase");
12147-            auto const& testInfo = test.getTestCaseInfo();
12148-            m_xml.startElement("Name", XmlFormatting::Indent)
12149-                 .writeText(testInfo.name, XmlFormatting::None)
12150-                 .endElement(XmlFormatting::Newline);
12151-            m_xml.startElement("ClassName", XmlFormatting::Indent)
12152-                 .writeText(testInfo.className, XmlFormatting::None)
12153-                 .endElement(XmlFormatting::Newline);
12154-            m_xml.startElement("Tags", XmlFormatting::Indent)
12155-                 .writeText(testInfo.tagsAsString(), XmlFormatting::None)
12156-                 .endElement(XmlFormatting::Newline);
12157-
12158-            auto sourceTag = m_xml.scopedElement("SourceInfo");
12159-            m_xml.startElement("File", XmlFormatting::Indent)
12160-                 .writeText(testInfo.lineInfo.file, XmlFormatting::None)
12161-                 .endElement(XmlFormatting::Newline);
12162-            m_xml.startElement("Line", XmlFormatting::Indent)
12163-                 .writeText(std::to_string(testInfo.lineInfo.line), XmlFormatting::None)
12164-                 .endElement(XmlFormatting::Newline);
12165-        }
12166-    }
12167-
12168-    void XmlReporter::listTags(std::vector<TagInfo> const& tags) {
12169-        auto outerTag = m_xml.scopedElement("TagsFromMatchingTests");
12170-        for (auto const& tag : tags) {
12171-            auto innerTag = m_xml.scopedElement("Tag");
12172-            m_xml.startElement("Count", XmlFormatting::Indent)
12173-                 .writeText(std::to_string(tag.count), XmlFormatting::None)
12174-                 .endElement(XmlFormatting::Newline);
12175-            auto aliasTag = m_xml.scopedElement("Aliases");
12176-            for (auto const& alias : tag.spellings) {
12177-                m_xml.startElement("Alias", XmlFormatting::Indent)
12178-                     .writeText(alias, XmlFormatting::None)
12179-                     .endElement(XmlFormatting::Newline);
12180-            }
12181-        }
12182-    }
12183-
12184-} // end namespace Catch
12185-
12186-#if defined(_MSC_VER)
12187-#pragma warning(pop)
12188-#endif
12189diff --git a/include/catch_amalgamated.hpp b/include/catch_amalgamated.hpp
12190deleted file mode 100644
12191index d5eb1bb..0000000
12192--- a/include/catch_amalgamated.hpp
12193+++ /dev/null
12194@@ -1,14314 +0,0 @@
12195-
12196-//              Copyright Catch2 Authors
12197-// Distributed under the Boost Software License, Version 1.0.
12198-//   (See accompanying file LICENSE.txt or copy at
12199-//        https://www.boost.org/LICENSE_1_0.txt)
12200-
12201-// SPDX-License-Identifier: BSL-1.0
12202-
12203-//  Catch v3.11.0
12204-//  Generated: 2025-09-30 10:49:11.225746
12205-//  ----------------------------------------------------------
12206-//  This file is an amalgamation of multiple different files.
12207-//  You probably shouldn't edit it directly.
12208-//  ----------------------------------------------------------
12209-#ifndef CATCH_AMALGAMATED_HPP_INCLUDED
12210-#define CATCH_AMALGAMATED_HPP_INCLUDED
12211-
12212-
12213-/** \file
12214- * This is a convenience header for Catch2. It includes **all** of Catch2 headers.
12215- *
12216- * Generally the Catch2 users should use specific includes they need,
12217- * but this header can be used instead for ease-of-experimentation, or
12218- * just plain convenience, at the cost of (significantly) increased
12219- * compilation times.
12220- *
12221- * When a new header is added to either the top level folder, or to the
12222- * corresponding internal subfolder, it should be added here. Headers
12223- * added to the various subparts (e.g. matchers, generators, etc...),
12224- * should go their respective catch-all headers.
12225- */
12226-
12227-#ifndef CATCH_ALL_HPP_INCLUDED
12228-#define CATCH_ALL_HPP_INCLUDED
12229-
12230-
12231-
12232-/** \file
12233- * This is a convenience header for Catch2's benchmarking. It includes
12234- * **all** of Catch2 headers related to benchmarking.
12235- *
12236- * Generally the Catch2 users should use specific includes they need,
12237- * but this header can be used instead for ease-of-experimentation, or
12238- * just plain convenience, at the cost of (significantly) increased
12239- * compilation times.
12240- *
12241- * When a new header is added to either the `benchmark` folder, or to
12242- * the corresponding internal (detail) subfolder, it should be added here.
12243- */
12244-
12245-#ifndef CATCH_BENCHMARK_ALL_HPP_INCLUDED
12246-#define CATCH_BENCHMARK_ALL_HPP_INCLUDED
12247-
12248-
12249-
12250-// Adapted from donated nonius code.
12251-
12252-#ifndef CATCH_BENCHMARK_HPP_INCLUDED
12253-#define CATCH_BENCHMARK_HPP_INCLUDED
12254-
12255-
12256-
12257-#ifndef CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
12258-#define CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
12259-
12260-// Detect a number of compiler features - by compiler
12261-// The following features are defined:
12262-//
12263-// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
12264-// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
12265-// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
12266-// ****************
12267-// Note to maintainers: if new toggles are added please document them
12268-// in configuration.md, too
12269-// ****************
12270-
12271-// In general each macro has a _NO_<feature name> form
12272-// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
12273-// Many features, at point of detection, define an _INTERNAL_ macro, so they
12274-// can be combined, en-mass, with the _NO_ forms later.
12275-
12276-
12277-
12278-#ifndef CATCH_PLATFORM_HPP_INCLUDED
12279-#define CATCH_PLATFORM_HPP_INCLUDED
12280-
12281-// See e.g.:
12282-// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
12283-#ifdef __APPLE__
12284-#  ifndef __has_extension
12285-#    define __has_extension(x) 0
12286-#  endif
12287-#  include <TargetConditionals.h>
12288-#  if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
12289-      (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
12290-#    define CATCH_PLATFORM_MAC
12291-#  elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
12292-#    define CATCH_PLATFORM_IPHONE
12293-#  endif
12294-
12295-#elif defined(linux) || defined(__linux) || defined(__linux__)
12296-#  define CATCH_PLATFORM_LINUX
12297-
12298-#elif defined(__QNX__)
12299-#  define CATCH_PLATFORM_QNX
12300-
12301-#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
12302-#  define CATCH_PLATFORM_WINDOWS
12303-
12304-#  if defined( WINAPI_FAMILY ) && ( WINAPI_FAMILY == WINAPI_FAMILY_APP )
12305-#      define CATCH_PLATFORM_WINDOWS_UWP
12306-#  endif
12307-
12308-#elif defined(__ORBIS__) || defined(__PROSPERO__)
12309-#  define CATCH_PLATFORM_PLAYSTATION
12310-
12311-#endif
12312-
12313-#endif // CATCH_PLATFORM_HPP_INCLUDED
12314-
12315-#ifdef __cplusplus
12316-
12317-#  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
12318-#    define CATCH_CPP17_OR_GREATER
12319-#  endif
12320-
12321-#  if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
12322-#    define CATCH_CPP20_OR_GREATER
12323-#  endif
12324-
12325-#endif
12326-
12327-// Only GCC compiler should be used in this block, so other compilers trying to
12328-// mask themselves as GCC should be ignored.
12329-#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER)
12330-#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
12331-#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "GCC diagnostic pop" )
12332-
12333-// This only works on GCC 9+. so we have to also add a global suppression of Wparentheses
12334-// for older versions of GCC.
12335-#    define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
12336-         _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
12337-
12338-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
12339-         _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" )
12340-
12341-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
12342-         _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" )
12343-
12344-#    define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
12345-         _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" )
12346-
12347-#    define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
12348-         _Pragma( "GCC diagnostic ignored \"-Wshadow\"" )
12349-
12350-#    define CATCH_INTERNAL_CONFIG_USE_BUILTIN_CONSTANT_P
12351-
12352-#endif
12353-
12354-#if defined(__NVCOMPILER)
12355-#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" )
12356-#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "diag pop" )
12357-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" )
12358-#endif
12359-
12360-#if defined(__CUDACC__) && !defined(__clang__)
12361-#  ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
12362-// New pragmas introduced in CUDA 11.5+
12363-#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" )
12364-#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "nv_diagnostic pop" )
12365-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" )
12366-#  else
12367-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" )
12368-#  endif
12369-#endif
12370-
12371-// clang-cl defines _MSC_VER as well as __clang__, which could cause the
12372-// start/stop internal suppression macros to be double defined.
12373-#if defined(__clang__) && !defined(_MSC_VER)
12374-#    define CATCH_INTERNAL_CONFIG_USE_BUILTIN_CONSTANT_P
12375-#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
12376-#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "clang diagnostic pop" )
12377-#endif // __clang__ && !_MSC_VER
12378-
12379-#if defined(__clang__)
12380-
12381-#    define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
12382-         _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
12383-         _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
12384-
12385-#    define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
12386-         _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
12387-
12388-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
12389-         _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
12390-
12391-#    if (__clang_major__ >= 20)
12392-#        define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
12393-             _Pragma( "clang diagnostic ignored \"-Wvariadic-macro-arguments-omitted\"" )
12394-#    elif (__clang_major__ == 19)
12395-#        define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
12396-	         _Pragma( "clang diagnostic ignored \"-Wc++20-extensions\"" )
12397-#    else
12398-#        define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
12399-             _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
12400-#    endif
12401-
12402-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
12403-         _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
12404-
12405-#    define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
12406-        _Pragma( "clang diagnostic ignored \"-Wcomma\"" )
12407-
12408-#    define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
12409-        _Pragma( "clang diagnostic ignored \"-Wshadow\"" )
12410-
12411-#endif // __clang__
12412-
12413-// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
12414-// which results in calls to destructors being emitted for each temporary,
12415-// without a matching initialization. In practice, this can result in something
12416-// like `std::string::~string` being called on an uninitialized value.
12417-//
12418-// For example, this code will likely segfault under IBM XL:
12419-// ```
12420-// REQUIRE(std::string("12") + "34" == "1234")
12421-// ```
12422-//
12423-// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which
12424-// results in calls to the immediately evaluated lambda expressions to be
12425-// reported as unevaluated lambdas.
12426-// https://developer.nvidia.com/nvidia_bug/3321845.
12427-//
12428-// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
12429-#if defined( __ibmxl__ ) || defined( __CUDACC__ ) || defined( __NVCOMPILER )
12430-#    define CATCH_INTERNAL_CONFIG_NO_USE_BUILTIN_CONSTANT_P
12431-#endif
12432-
12433-
12434-
12435-////////////////////////////////////////////////////////////////////////////////
12436-// We know some environments not to support full POSIX signals
12437-#if defined( CATCH_PLATFORM_WINDOWS ) ||                                       \
12438-    defined( CATCH_PLATFORM_PLAYSTATION ) ||                                   \
12439-    defined( __CYGWIN__ ) ||                                                   \
12440-    defined( __QNX__ ) ||                                                      \
12441-    defined( __EMSCRIPTEN__ ) ||                                               \
12442-    defined( __DJGPP__ ) ||                                                    \
12443-    defined( __OS400__ )
12444-#    define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
12445-#else
12446-#    define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
12447-#endif
12448-
12449-////////////////////////////////////////////////////////////////////////////////
12450-// Assume that some platforms do not support getenv.
12451-#if defined( CATCH_PLATFORM_WINDOWS_UWP ) ||                                   \
12452-    defined( CATCH_PLATFORM_PLAYSTATION ) ||                                   \
12453-    defined( _GAMING_XBOX )
12454-#    define CATCH_INTERNAL_CONFIG_NO_GETENV
12455-#else
12456-#    define CATCH_INTERNAL_CONFIG_GETENV
12457-#endif
12458-
12459-////////////////////////////////////////////////////////////////////////////////
12460-// Android somehow still does not support std::to_string
12461-#if defined(__ANDROID__)
12462-#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
12463-#endif
12464-
12465-////////////////////////////////////////////////////////////////////////////////
12466-// Not all Windows environments support SEH properly
12467-#if defined(__MINGW32__)
12468-#    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
12469-#endif
12470-
12471-////////////////////////////////////////////////////////////////////////////////
12472-// PS4
12473-#if defined(__ORBIS__)
12474-#    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
12475-#endif
12476-
12477-////////////////////////////////////////////////////////////////////////////////
12478-// Cygwin
12479-#ifdef __CYGWIN__
12480-
12481-// Required for some versions of Cygwin to declare gettimeofday
12482-// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
12483-#   define _BSD_SOURCE
12484-// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
12485-// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
12486-# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
12487-           && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
12488-
12489-#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
12490-
12491-# endif
12492-#endif // __CYGWIN__
12493-
12494-////////////////////////////////////////////////////////////////////////////////
12495-// Visual C++
12496-#if defined(_MSC_VER)
12497-
12498-// We want to defer to nvcc-specific warning suppression if we are compiled
12499-// with nvcc masquerading for MSVC.
12500-#    if !defined( __CUDACC__ )
12501-#        define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
12502-            __pragma( warning( push ) )
12503-#        define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
12504-            __pragma( warning( pop ) )
12505-#    endif
12506-
12507-// Universal Windows platform does not support SEH
12508-#  if !defined(CATCH_PLATFORM_WINDOWS_UWP)
12509-#    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
12510-#  endif
12511-
12512-// Only some Windows platform families support the console
12513-#  if defined(WINAPI_FAMILY_PARTITION)
12514-#    if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
12515-#      define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
12516-#    endif
12517-#  endif
12518-
12519-// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
12520-// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
12521-// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
12522-#  if !defined(__clang__) // Handle Clang masquerading for msvc
12523-#    if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
12524-#      define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
12525-#    endif // MSVC_TRADITIONAL
12526-#  endif // __clang__
12527-
12528-#endif // _MSC_VER
12529-
12530-#if defined(_REENTRANT) || defined(_MSC_VER)
12531-// Enable async processing, as -pthread is specified or no additional linking is required
12532-# define CATCH_INTERNAL_CONFIG_USE_ASYNC
12533-#endif // _MSC_VER
12534-
12535-////////////////////////////////////////////////////////////////////////////////
12536-// Check if we are compiled with -fno-exceptions or equivalent
12537-#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
12538-#  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
12539-#endif
12540-
12541-
12542-////////////////////////////////////////////////////////////////////////////////
12543-// Embarcadero C++Build
12544-#if defined(__BORLANDC__)
12545-    #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
12546-#endif
12547-
12548-////////////////////////////////////////////////////////////////////////////////
12549-
12550-// RTX is a special version of Windows that is real time.
12551-// This means that it is detected as Windows, but does not provide
12552-// the same set of capabilities as real Windows does.
12553-#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
12554-    #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
12555-    #define CATCH_INTERNAL_CONFIG_NO_ASYNC
12556-    #define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
12557-#endif
12558-
12559-#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
12560-#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
12561-#endif
12562-
12563-// Various stdlib support checks that require __has_include
12564-#if defined(__has_include)
12565-  // Check if string_view is available and usable
12566-  #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
12567-  #    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
12568-  #endif
12569-
12570-  // Check if optional is available and usable
12571-  #  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
12572-  #    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
12573-  #  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
12574-
12575-  // Check if byte is available and usable
12576-  #  if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
12577-  #    include <cstddef>
12578-  #    if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
12579-  #      define CATCH_INTERNAL_CONFIG_CPP17_BYTE
12580-  #    endif
12581-  #  endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
12582-
12583-  // Check if variant is available and usable
12584-  #  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
12585-  #    if defined(__clang__) && (__clang_major__ < 8)
12586-         // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
12587-         // fix should be in clang 8, workaround in libstdc++ 8.2
12588-  #      include <ciso646>
12589-  #      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
12590-  #        define CATCH_CONFIG_NO_CPP17_VARIANT
12591-  #      else
12592-  #        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
12593-  #      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
12594-  #    else
12595-  #      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
12596-  #    endif // defined(__clang__) && (__clang_major__ < 8)
12597-  #  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
12598-#endif // defined(__has_include)
12599-
12600-
12601-#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)
12602-#   define CATCH_CONFIG_WINDOWS_SEH
12603-#endif
12604-// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
12605-#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)
12606-#   define CATCH_CONFIG_POSIX_SIGNALS
12607-#endif
12608-
12609-#if defined(CATCH_INTERNAL_CONFIG_GETENV) && !defined(CATCH_INTERNAL_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_GETENV)
12610-#   define CATCH_CONFIG_GETENV
12611-#endif
12612-
12613-#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
12614-#    define CATCH_CONFIG_CPP11_TO_STRING
12615-#endif
12616-
12617-#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
12618-#  define CATCH_CONFIG_CPP17_OPTIONAL
12619-#endif
12620-
12621-#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
12622-#  define CATCH_CONFIG_CPP17_STRING_VIEW
12623-#endif
12624-
12625-#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
12626-#  define CATCH_CONFIG_CPP17_VARIANT
12627-#endif
12628-
12629-#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
12630-#  define CATCH_CONFIG_CPP17_BYTE
12631-#endif
12632-
12633-
12634-#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
12635-#  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
12636-#endif
12637-
12638-#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)
12639-#  define CATCH_CONFIG_NEW_CAPTURE
12640-#endif
12641-
12642-#if !defined( CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED ) && \
12643-    !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) &&          \
12644-    !defined( CATCH_CONFIG_NO_DISABLE_EXCEPTIONS )
12645-#  define CATCH_CONFIG_DISABLE_EXCEPTIONS
12646-#endif
12647-
12648-#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
12649-#  define CATCH_CONFIG_POLYFILL_ISNAN
12650-#endif
12651-
12652-#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC)  && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
12653-#  define CATCH_CONFIG_USE_ASYNC
12654-#endif
12655-
12656-#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
12657-#  define CATCH_CONFIG_GLOBAL_NEXTAFTER
12658-#endif
12659-
12660-
12661-// The goal of this macro is to avoid evaluation of the arguments, but
12662-// still have the compiler warn on problems inside...
12663-#if defined( CATCH_INTERNAL_CONFIG_USE_BUILTIN_CONSTANT_P ) && \
12664-    !defined( CATCH_INTERNAL_CONFIG_NO_USE_BUILTIN_CONSTANT_P ) && !defined(CATCH_CONFIG_USE_BUILTIN_CONSTANT_P)
12665-#define CATCH_CONFIG_USE_BUILTIN_CONSTANT_P
12666-#endif
12667-
12668-#if defined( CATCH_CONFIG_USE_BUILTIN_CONSTANT_P ) && \
12669-    !defined( CATCH_CONFIG_NO_USE_BUILTIN_CONSTANT_P )
12670-#    define CATCH_INTERNAL_IGNORE_BUT_WARN( ... )                                              \
12671-        (void)__builtin_constant_p( __VA_ARGS__ ) /* NOLINT(cppcoreguidelines-pro-type-vararg, \
12672-                                                     hicpp-vararg) */
12673-#else
12674-#    define CATCH_INTERNAL_IGNORE_BUT_WARN( ... )
12675-#endif
12676-
12677-// Even if we do not think the compiler has that warning, we still have
12678-// to provide a macro that can be used by the code.
12679-#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
12680-#   define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
12681-#endif
12682-#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
12683-#   define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
12684-#endif
12685-#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
12686-#   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
12687-#endif
12688-#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
12689-#   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
12690-#endif
12691-#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT)
12692-#   define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT
12693-#endif
12694-#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS)
12695-#   define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS
12696-#endif
12697-#if !defined(CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS)
12698-#   define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS
12699-#endif
12700-#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
12701-#   define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
12702-#endif
12703-#if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS )
12704-#    define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
12705-#endif
12706-#if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS )
12707-#    define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS
12708-#endif
12709-#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS )
12710-#    define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS
12711-#endif
12712-
12713-#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
12714-#   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
12715-#elif defined(__clang__) && (__clang_major__ < 5)
12716-#   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
12717-#endif
12718-
12719-
12720-#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
12721-#define CATCH_TRY if ((true))
12722-#define CATCH_CATCH_ALL if ((false))
12723-#define CATCH_CATCH_ANON(type) if ((false))
12724-#else
12725-#define CATCH_TRY try
12726-#define CATCH_CATCH_ALL catch (...)
12727-#define CATCH_CATCH_ANON(type) catch (type)
12728-#endif
12729-
12730-#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
12731-#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
12732-#endif
12733-
12734-#if defined( CATCH_PLATFORM_WINDOWS ) &&       \
12735-    !defined( CATCH_CONFIG_COLOUR_WIN32 ) && \
12736-    !defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \
12737-    !defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 )
12738-#    define CATCH_CONFIG_COLOUR_WIN32
12739-#endif
12740-
12741-#if defined( CATCH_CONFIG_SHARED_LIBRARY ) && defined( _MSC_VER ) && \
12742-    !defined( CATCH_CONFIG_STATIC )
12743-#    ifdef Catch2_EXPORTS
12744-#        define CATCH_EXPORT //__declspec( dllexport ) // not needed
12745-#    else
12746-#        define CATCH_EXPORT __declspec( dllimport )
12747-#    endif
12748-#else
12749-#    define CATCH_EXPORT
12750-#endif
12751-
12752-#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
12753-
12754-
12755-#ifndef CATCH_CONTEXT_HPP_INCLUDED
12756-#define CATCH_CONTEXT_HPP_INCLUDED
12757-
12758-
12759-namespace Catch {
12760-
12761-    class IResultCapture;
12762-    class IConfig;
12763-
12764-    class Context {
12765-        IConfig const* m_config = nullptr;
12766-        IResultCapture* m_resultCapture = nullptr;
12767-
12768-        CATCH_EXPORT static Context currentContext;
12769-        friend Context& getCurrentMutableContext();
12770-        friend Context const& getCurrentContext();
12771-
12772-    public:
12773-        constexpr IResultCapture* getResultCapture() const {
12774-            return m_resultCapture;
12775-        }
12776-        constexpr IConfig const* getConfig() const { return m_config; }
12777-        constexpr void setResultCapture( IResultCapture* resultCapture ) {
12778-            m_resultCapture = resultCapture;
12779-        }
12780-        constexpr void setConfig( IConfig const* config ) { m_config = config; }
12781-    };
12782-
12783-    Context& getCurrentMutableContext();
12784-
12785-    inline Context const& getCurrentContext() {
12786-        return Context::currentContext;
12787-    }
12788-
12789-    class SimplePcg32;
12790-    SimplePcg32& sharedRng();
12791-}
12792-
12793-#endif // CATCH_CONTEXT_HPP_INCLUDED
12794-
12795-
12796-#ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
12797-#define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
12798-
12799-#include <type_traits>
12800-
12801-//! Replacement for std::move with better compile time performance
12802-#define CATCH_MOVE(...) static_cast<std::remove_reference_t<decltype(__VA_ARGS__)>&&>(__VA_ARGS__)
12803-
12804-//! Replacement for std::forward with better compile time performance
12805-#define CATCH_FORWARD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
12806-
12807-#endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
12808-
12809-
12810-#ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
12811-#define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
12812-
12813-namespace Catch {
12814-
12815-    //! Used to signal that an assertion macro failed
12816-    struct TestFailureException{};
12817-    //! Used to signal that the remainder of a test should be skipped
12818-    struct TestSkipException {};
12819-
12820-    /**
12821-     * Outlines throwing of `TestFailureException` into a single TU
12822-     *
12823-     * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
12824-     */
12825-    [[noreturn]] void throw_test_failure_exception();
12826-
12827-    /**
12828-     * Outlines throwing of `TestSkipException` into a single TU
12829-     *
12830-     * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
12831-     */
12832-    [[noreturn]] void throw_test_skip_exception();
12833-
12834-} // namespace Catch
12835-
12836-#endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
12837-
12838-
12839-#ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED
12840-#define CATCH_UNIQUE_NAME_HPP_INCLUDED
12841-
12842-
12843-
12844-
12845-/** \file
12846- * Wrapper for the CONFIG configuration option
12847- *
12848- * When generating internal unique names, there are two options. Either
12849- * we mix in the current line number, or mix in an incrementing number.
12850- * We prefer the latter, using `__COUNTER__`, but users might want to
12851- * use the former.
12852- */
12853-
12854-#ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED
12855-#define CATCH_CONFIG_COUNTER_HPP_INCLUDED
12856-
12857-
12858-#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
12859-    #define CATCH_INTERNAL_CONFIG_COUNTER
12860-#endif
12861-
12862-#if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \
12863-    !defined( CATCH_CONFIG_NO_COUNTER ) && \
12864-    !defined( CATCH_CONFIG_COUNTER )
12865-#    define CATCH_CONFIG_COUNTER
12866-#endif
12867-
12868-
12869-#endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED
12870-#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
12871-#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
12872-#ifdef CATCH_CONFIG_COUNTER
12873-#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
12874-#else
12875-#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
12876-#endif
12877-
12878-#endif // CATCH_UNIQUE_NAME_HPP_INCLUDED
12879-
12880-
12881-#ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
12882-#define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
12883-
12884-#include <string>
12885-
12886-
12887-
12888-#ifndef CATCH_STRINGREF_HPP_INCLUDED
12889-#define CATCH_STRINGREF_HPP_INCLUDED
12890-
12891-#include <cstddef>
12892-#include <string>
12893-#include <iosfwd>
12894-#include <cassert>
12895-
12896-#include <cstring>
12897-
12898-namespace Catch {
12899-
12900-    /// A non-owning string class (similar to the forthcoming std::string_view)
12901-    /// Note that, because a StringRef may be a substring of another string,
12902-    /// it may not be null terminated.
12903-    class StringRef {
12904-    public:
12905-        using size_type = std::size_t;
12906-        using const_iterator = const char*;
12907-
12908-        static constexpr size_type npos{ static_cast<size_type>( -1 ) };
12909-
12910-    private:
12911-        static constexpr char const* const s_empty = "";
12912-
12913-        char const* m_start = s_empty;
12914-        size_type m_size = 0;
12915-
12916-    public: // construction
12917-        constexpr StringRef() noexcept = default;
12918-
12919-        StringRef( char const* rawChars ) noexcept;
12920-
12921-        constexpr StringRef( char const* rawChars, size_type size ) noexcept
12922-        :   m_start( rawChars ),
12923-            m_size( size )
12924-        {}
12925-
12926-        StringRef( std::string const& stdString ) noexcept
12927-        :   m_start( stdString.c_str() ),
12928-            m_size( stdString.size() )
12929-        {}
12930-
12931-        explicit operator std::string() const {
12932-            return std::string(m_start, m_size);
12933-        }
12934-
12935-    public: // operators
12936-        auto operator == ( StringRef other ) const noexcept -> bool {
12937-            return m_size == other.m_size
12938-                && (std::memcmp( m_start, other.m_start, m_size ) == 0);
12939-        }
12940-        auto operator != (StringRef other) const noexcept -> bool {
12941-            return !(*this == other);
12942-        }
12943-
12944-        constexpr auto operator[] ( size_type index ) const noexcept -> char {
12945-            assert(index < m_size);
12946-            return m_start[index];
12947-        }
12948-
12949-        bool operator<(StringRef rhs) const noexcept;
12950-
12951-    public: // named queries
12952-        constexpr auto empty() const noexcept -> bool {
12953-            return m_size == 0;
12954-        }
12955-        constexpr auto size() const noexcept -> size_type {
12956-            return m_size;
12957-        }
12958-
12959-        // Returns a substring of [start, start + length).
12960-        // If start + length > size(), then the substring is [start, size()).
12961-        // If start > size(), then the substring is empty.
12962-        constexpr StringRef substr(size_type start, size_type length) const noexcept {
12963-            if (start < m_size) {
12964-                const auto shortened_size = m_size - start;
12965-                return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length);
12966-            } else {
12967-                return StringRef();
12968-            }
12969-        }
12970-
12971-        // Returns the current start pointer. May not be null-terminated.
12972-        constexpr char const* data() const noexcept {
12973-            return m_start;
12974-        }
12975-
12976-        constexpr const_iterator begin() const { return m_start; }
12977-        constexpr const_iterator end() const { return m_start + m_size; }
12978-
12979-
12980-        friend std::string& operator += (std::string& lhs, StringRef rhs);
12981-        friend std::ostream& operator << (std::ostream& os, StringRef str);
12982-        friend std::string operator+(StringRef lhs, StringRef rhs);
12983-
12984-        /**
12985-         * Provides a three-way comparison with rhs
12986-         *
12987-         * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive
12988-         * number if lhs > rhs
12989-         */
12990-        int compare( StringRef rhs ) const;
12991-    };
12992-
12993-
12994-    constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
12995-        return StringRef( rawChars, size );
12996-    }
12997-} // namespace Catch
12998-
12999-constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
13000-    return Catch::StringRef( rawChars, size );
13001-}
13002-
13003-#endif // CATCH_STRINGREF_HPP_INCLUDED
13004-
13005-
13006-#ifndef CATCH_RESULT_TYPE_HPP_INCLUDED
13007-#define CATCH_RESULT_TYPE_HPP_INCLUDED
13008-
13009-namespace Catch {
13010-
13011-    // ResultWas::OfType enum
13012-    struct ResultWas { enum OfType {
13013-        Unknown = -1,
13014-        Ok = 0,
13015-        Info = 1,
13016-        Warning = 2,
13017-        // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit?
13018-        ExplicitSkip = 4,
13019-
13020-        FailureBit = 0x10,
13021-
13022-        ExpressionFailed = FailureBit | 1,
13023-        ExplicitFailure = FailureBit | 2,
13024-
13025-        Exception = 0x100 | FailureBit,
13026-
13027-        ThrewException = Exception | 1,
13028-        DidntThrowException = Exception | 2,
13029-
13030-        FatalErrorCondition = 0x200 | FailureBit
13031-
13032-    }; };
13033-
13034-    constexpr bool isOk( ResultWas::OfType resultType ) {
13035-        return ( resultType & ResultWas::FailureBit ) == 0;
13036-    }
13037-    constexpr bool isJustInfo( int flags ) { return flags == ResultWas::Info; }
13038-
13039-
13040-    // ResultDisposition::Flags enum
13041-    struct ResultDisposition { enum Flags {
13042-        Normal = 0x01,
13043-
13044-        ContinueOnFailure = 0x02,   // Failures fail test, but execution continues
13045-        FalseTest = 0x04,           // Prefix expression with !
13046-        SuppressFail = 0x08         // Failures are reported but do not fail the test
13047-    }; };
13048-
13049-    constexpr ResultDisposition::Flags operator|( ResultDisposition::Flags lhs,
13050-                                        ResultDisposition::Flags rhs ) {
13051-        return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) |
13052-                                                      static_cast<int>( rhs ) );
13053-    }
13054-
13055-    constexpr bool isFalseTest( int flags ) {
13056-        return ( flags & ResultDisposition::FalseTest ) != 0;
13057-    }
13058-    constexpr bool shouldSuppressFailure( int flags ) {
13059-        return ( flags & ResultDisposition::SuppressFail ) != 0;
13060-    }
13061-
13062-} // end namespace Catch
13063-
13064-#endif // CATCH_RESULT_TYPE_HPP_INCLUDED
13065-
13066-
13067-#ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED
13068-#define CATCH_UNIQUE_PTR_HPP_INCLUDED
13069-
13070-#include <cassert>
13071-#include <type_traits>
13072-
13073-
13074-namespace Catch {
13075-namespace Detail {
13076-    /**
13077-     * A reimplementation of `std::unique_ptr` for improved compilation performance
13078-     *
13079-     * Does not support arrays nor custom deleters.
13080-     */
13081-    template <typename T>
13082-    class unique_ptr {
13083-        T* m_ptr;
13084-    public:
13085-        constexpr unique_ptr(std::nullptr_t = nullptr):
13086-            m_ptr{}
13087-        {}
13088-        explicit constexpr unique_ptr(T* ptr):
13089-            m_ptr(ptr)
13090-        {}
13091-
13092-        template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
13093-        unique_ptr(unique_ptr<U>&& from):
13094-            m_ptr(from.release())
13095-        {}
13096-
13097-        template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
13098-        unique_ptr& operator=(unique_ptr<U>&& from) {
13099-            reset(from.release());
13100-
13101-            return *this;
13102-        }
13103-
13104-        unique_ptr(unique_ptr const&) = delete;
13105-        unique_ptr& operator=(unique_ptr const&) = delete;
13106-
13107-        unique_ptr(unique_ptr&& rhs) noexcept:
13108-            m_ptr(rhs.m_ptr) {
13109-            rhs.m_ptr = nullptr;
13110-        }
13111-        unique_ptr& operator=(unique_ptr&& rhs) noexcept {
13112-            reset(rhs.release());
13113-
13114-            return *this;
13115-        }
13116-
13117-        ~unique_ptr() {
13118-            delete m_ptr;
13119-        }
13120-
13121-        T& operator*() {
13122-            assert(m_ptr);
13123-            return *m_ptr;
13124-        }
13125-        T const& operator*() const {
13126-            assert(m_ptr);
13127-            return *m_ptr;
13128-        }
13129-        T* operator->() noexcept {
13130-            assert(m_ptr);
13131-            return m_ptr;
13132-        }
13133-        T const* operator->() const noexcept {
13134-            assert(m_ptr);
13135-            return m_ptr;
13136-        }
13137-
13138-        T* get() { return m_ptr; }
13139-        T const* get() const { return m_ptr; }
13140-
13141-        void reset(T* ptr = nullptr) {
13142-            delete m_ptr;
13143-            m_ptr = ptr;
13144-        }
13145-
13146-        T* release() {
13147-            auto temp = m_ptr;
13148-            m_ptr = nullptr;
13149-            return temp;
13150-        }
13151-
13152-        explicit operator bool() const {
13153-            return m_ptr != nullptr;
13154-        }
13155-
13156-        friend void swap(unique_ptr& lhs, unique_ptr& rhs) {
13157-            auto temp = lhs.m_ptr;
13158-            lhs.m_ptr = rhs.m_ptr;
13159-            rhs.m_ptr = temp;
13160-        }
13161-    };
13162-
13163-    //! Specialization to cause compile-time error for arrays
13164-    template <typename T>
13165-    class unique_ptr<T[]>;
13166-
13167-    template <typename T, typename... Args>
13168-    unique_ptr<T> make_unique(Args&&... args) {
13169-        return unique_ptr<T>(new T(CATCH_FORWARD(args)...));
13170-    }
13171-
13172-
13173-} // end namespace Detail
13174-} // end namespace Catch
13175-
13176-#endif // CATCH_UNIQUE_PTR_HPP_INCLUDED
13177-
13178-
13179-#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
13180-#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
13181-
13182-
13183-
13184-// Adapted from donated nonius code.
13185-
13186-#ifndef CATCH_CLOCK_HPP_INCLUDED
13187-#define CATCH_CLOCK_HPP_INCLUDED
13188-
13189-#include <chrono>
13190-
13191-namespace Catch {
13192-    namespace Benchmark {
13193-        using IDuration = std::chrono::nanoseconds;
13194-        using FDuration = std::chrono::duration<double, std::nano>;
13195-
13196-        template <typename Clock>
13197-        using TimePoint = typename Clock::time_point;
13198-
13199-        using default_clock = std::chrono::steady_clock;
13200-    } // namespace Benchmark
13201-} // namespace Catch
13202-
13203-#endif // CATCH_CLOCK_HPP_INCLUDED
13204-
13205-namespace Catch {
13206-
13207-    // We cannot forward declare the type with default template argument
13208-    // multiple times, so it is split out into a separate header so that
13209-    // we can prevent multiple declarations in dependees
13210-    template <typename Duration = Benchmark::FDuration>
13211-    struct BenchmarkStats;
13212-
13213-} // end namespace Catch
13214-
13215-#endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
13216-
13217-namespace Catch {
13218-
13219-    class AssertionResult;
13220-    struct AssertionInfo;
13221-    struct SectionInfo;
13222-    struct SectionEndInfo;
13223-    struct MessageInfo;
13224-    struct MessageBuilder;
13225-    struct Counts;
13226-    struct AssertionReaction;
13227-    struct SourceLineInfo;
13228-
13229-    class ITransientExpression;
13230-    class IGeneratorTracker;
13231-
13232-    struct BenchmarkInfo;
13233-
13234-    namespace Generators {
13235-        class GeneratorUntypedBase;
13236-        using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
13237-    }
13238-
13239-
13240-    class IResultCapture {
13241-    public:
13242-        virtual ~IResultCapture();
13243-
13244-        virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0;
13245-        virtual bool sectionStarted( StringRef sectionName,
13246-                                     SourceLineInfo const& sectionLineInfo,
13247-                                     Counts& assertions ) = 0;
13248-        virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
13249-        virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
13250-
13251-        virtual IGeneratorTracker*
13252-        acquireGeneratorTracker( StringRef generatorName,
13253-                                 SourceLineInfo const& lineInfo ) = 0;
13254-        virtual IGeneratorTracker*
13255-        createGeneratorTracker( StringRef generatorName,
13256-                                SourceLineInfo lineInfo,
13257-                                Generators::GeneratorBasePtr&& generator ) = 0;
13258-
13259-        virtual void benchmarkPreparing( StringRef name ) = 0;
13260-        virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
13261-        virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
13262-        virtual void benchmarkFailed( StringRef error ) = 0;
13263-
13264-        static void pushScopedMessage( MessageInfo&& message );
13265-        static void popScopedMessage( unsigned int messageId );
13266-        static void emplaceUnscopedMessage( MessageBuilder&& builder );
13267-
13268-        virtual void handleFatalErrorCondition( StringRef message ) = 0;
13269-
13270-        virtual void handleExpr
13271-                (   AssertionInfo const& info,
13272-                    ITransientExpression const& expr,
13273-                    AssertionReaction& reaction ) = 0;
13274-        virtual void handleMessage
13275-                (   AssertionInfo const& info,
13276-                    ResultWas::OfType resultType,
13277-                    std::string&& message,
13278-                    AssertionReaction& reaction ) = 0;
13279-        virtual void handleUnexpectedExceptionNotThrown
13280-                (   AssertionInfo const& info,
13281-                    AssertionReaction& reaction ) = 0;
13282-        virtual void handleUnexpectedInflightException
13283-                (   AssertionInfo const& info,
13284-                    std::string&& message,
13285-                    AssertionReaction& reaction ) = 0;
13286-        virtual void handleIncomplete
13287-                (   AssertionInfo const& info ) = 0;
13288-        virtual void handleNonExpr
13289-                (   AssertionInfo const &info,
13290-                    ResultWas::OfType resultType,
13291-                    AssertionReaction &reaction ) = 0;
13292-
13293-
13294-        virtual bool lastAssertionPassed() = 0;
13295-
13296-        // Deprecated, do not use:
13297-        virtual std::string getCurrentTestName() const = 0;
13298-        virtual const AssertionResult* getLastResult() const = 0;
13299-        virtual void exceptionEarlyReported() = 0;
13300-    };
13301-
13302-    namespace Detail {
13303-        [[noreturn]]
13304-        void missingCaptureInstance();
13305-    }
13306-    inline IResultCapture& getResultCapture() {
13307-        if (auto* capture = getCurrentContext().getResultCapture()) {
13308-            return *capture;
13309-        } else {
13310-            Detail::missingCaptureInstance();
13311-        }
13312-    }
13313-
13314-}
13315-
13316-#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
13317-
13318-
13319-#ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED
13320-#define CATCH_INTERFACES_CONFIG_HPP_INCLUDED
13321-
13322-
13323-
13324-#ifndef CATCH_NONCOPYABLE_HPP_INCLUDED
13325-#define CATCH_NONCOPYABLE_HPP_INCLUDED
13326-
13327-namespace Catch {
13328-    namespace Detail {
13329-
13330-        //! Deriving classes become noncopyable and nonmovable
13331-        class NonCopyable {
13332-        public:
13333-            NonCopyable( NonCopyable const& ) = delete;
13334-            NonCopyable( NonCopyable&& ) = delete;
13335-            NonCopyable& operator=( NonCopyable const& ) = delete;
13336-            NonCopyable& operator=( NonCopyable&& ) = delete;
13337-
13338-        protected:
13339-            NonCopyable() noexcept = default;
13340-        };
13341-
13342-    } // namespace Detail
13343-} // namespace Catch
13344-
13345-#endif // CATCH_NONCOPYABLE_HPP_INCLUDED
13346-
13347-#include <chrono>
13348-#include <string>
13349-#include <vector>
13350-
13351-namespace Catch {
13352-
13353-    enum class Verbosity {
13354-        Quiet = 0,
13355-        Normal,
13356-        High
13357-    };
13358-
13359-    struct WarnAbout { enum What {
13360-        Nothing = 0x00,
13361-        //! A test case or leaf section did not run any assertions
13362-        NoAssertions = 0x01,
13363-        //! A command line test spec matched no test cases
13364-        UnmatchedTestSpec = 0x02,
13365-    }; };
13366-
13367-    enum class ShowDurations {
13368-        DefaultForReporter,
13369-        Always,
13370-        Never
13371-    };
13372-    enum class TestRunOrder {
13373-        Declared,
13374-        LexicographicallySorted,
13375-        Randomized
13376-    };
13377-    enum class ColourMode : std::uint8_t {
13378-        //! Let Catch2 pick implementation based on platform detection
13379-        PlatformDefault,
13380-        //! Use ANSI colour code escapes
13381-        ANSI,
13382-        //! Use Win32 console colour API
13383-        Win32,
13384-        //! Don't use any colour
13385-        None
13386-    };
13387-    struct WaitForKeypress { enum When {
13388-        Never,
13389-        BeforeStart = 1,
13390-        BeforeExit = 2,
13391-        BeforeStartAndExit = BeforeStart | BeforeExit
13392-    }; };
13393-
13394-    class TestSpec;
13395-    class IStream;
13396-
13397-    class IConfig : public Detail::NonCopyable {
13398-    public:
13399-        virtual ~IConfig();
13400-
13401-        virtual bool allowThrows() const = 0;
13402-        virtual StringRef name() const = 0;
13403-        virtual bool includeSuccessfulResults() const = 0;
13404-        virtual bool shouldDebugBreak() const = 0;
13405-        virtual bool warnAboutMissingAssertions() const = 0;
13406-        virtual bool warnAboutUnmatchedTestSpecs() const = 0;
13407-        virtual bool zeroTestsCountAsSuccess() const = 0;
13408-        virtual int abortAfter() const = 0;
13409-        virtual bool showInvisibles() const = 0;
13410-        virtual ShowDurations showDurations() const = 0;
13411-        virtual double minDuration() const = 0;
13412-        virtual TestSpec const& testSpec() const = 0;
13413-        virtual bool hasTestFilters() const = 0;
13414-        virtual std::vector<std::string> const& getTestsOrTags() const = 0;
13415-        virtual TestRunOrder runOrder() const = 0;
13416-        virtual uint32_t rngSeed() const = 0;
13417-        virtual unsigned int shardCount() const = 0;
13418-        virtual unsigned int shardIndex() const = 0;
13419-        virtual ColourMode defaultColourMode() const = 0;
13420-        virtual std::vector<std::string> const& getSectionsToRun() const = 0;
13421-        virtual Verbosity verbosity() const = 0;
13422-
13423-        virtual bool skipBenchmarks() const = 0;
13424-        virtual bool benchmarkNoAnalysis() const = 0;
13425-        virtual unsigned int benchmarkSamples() const = 0;
13426-        virtual double benchmarkConfidenceInterval() const = 0;
13427-        virtual unsigned int benchmarkResamples() const = 0;
13428-        virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
13429-    };
13430-}
13431-
13432-#endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED
13433-
13434-
13435-#ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
13436-#define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
13437-
13438-
13439-#include <string>
13440-
13441-namespace Catch {
13442-
13443-    class TestCaseHandle;
13444-    struct TestCaseInfo;
13445-    class ITestCaseRegistry;
13446-    class IExceptionTranslatorRegistry;
13447-    class IExceptionTranslator;
13448-    class ReporterRegistry;
13449-    class IReporterFactory;
13450-    class ITagAliasRegistry;
13451-    class ITestInvoker;
13452-    class IMutableEnumValuesRegistry;
13453-    struct SourceLineInfo;
13454-
13455-    class StartupExceptionRegistry;
13456-    class EventListenerFactory;
13457-
13458-    using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
13459-
13460-    class IRegistryHub {
13461-    public:
13462-        virtual ~IRegistryHub(); // = default
13463-
13464-        virtual ReporterRegistry const& getReporterRegistry() const = 0;
13465-        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
13466-        virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
13467-        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
13468-
13469-
13470-        virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
13471-    };
13472-
13473-    class IMutableRegistryHub {
13474-    public:
13475-        virtual ~IMutableRegistryHub(); // = default
13476-        virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0;
13477-        virtual void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) = 0;
13478-        virtual void registerTest(Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker) = 0;
13479-        virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
13480-        virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
13481-        virtual void registerStartupException() noexcept = 0;
13482-        virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
13483-    };
13484-
13485-    IRegistryHub const& getRegistryHub();
13486-    IMutableRegistryHub& getMutableRegistryHub();
13487-    void cleanUp();
13488-    std::string translateActiveException();
13489-
13490-}
13491-
13492-#endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
13493-
13494-
13495-#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED
13496-#define CATCH_BENCHMARK_STATS_HPP_INCLUDED
13497-
13498-
13499-
13500-// Adapted from donated nonius code.
13501-
13502-#ifndef CATCH_ESTIMATE_HPP_INCLUDED
13503-#define CATCH_ESTIMATE_HPP_INCLUDED
13504-
13505-namespace Catch {
13506-    namespace Benchmark {
13507-        template <typename Type>
13508-        struct Estimate {
13509-            Type point;
13510-            Type lower_bound;
13511-            Type upper_bound;
13512-            double confidence_interval;
13513-        };
13514-    } // namespace Benchmark
13515-} // namespace Catch
13516-
13517-#endif // CATCH_ESTIMATE_HPP_INCLUDED
13518-
13519-
13520-// Adapted from donated nonius code.
13521-
13522-#ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
13523-#define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
13524-
13525-namespace Catch {
13526-    namespace Benchmark {
13527-        struct OutlierClassification {
13528-            int samples_seen = 0;
13529-            int low_severe = 0;     // more than 3 times IQR below Q1
13530-            int low_mild = 0;       // 1.5 to 3 times IQR below Q1
13531-            int high_mild = 0;      // 1.5 to 3 times IQR above Q3
13532-            int high_severe = 0;    // more than 3 times IQR above Q3
13533-
13534-            constexpr int total() const {
13535-                return low_severe + low_mild + high_mild + high_severe;
13536-            }
13537-        };
13538-    } // namespace Benchmark
13539-} // namespace Catch
13540-
13541-#endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED
13542-// The fwd decl & default specialization needs to be seen by VS2017 before
13543-// BenchmarkStats itself, or VS2017 will report compilation error.
13544-
13545-#include <string>
13546-#include <vector>
13547-
13548-namespace Catch {
13549-
13550-    struct BenchmarkInfo {
13551-        std::string name;
13552-        double estimatedDuration;
13553-        int iterations;
13554-        unsigned int samples;
13555-        unsigned int resamples;
13556-        double clockResolution;
13557-        double clockCost;
13558-    };
13559-
13560-    // We need to keep template parameter for backwards compatibility,
13561-    // but we also do not want to use the template paraneter.
13562-    template <class Dummy>
13563-    struct BenchmarkStats {
13564-        BenchmarkInfo info;
13565-
13566-        std::vector<Benchmark::FDuration> samples;
13567-        Benchmark::Estimate<Benchmark::FDuration> mean;
13568-        Benchmark::Estimate<Benchmark::FDuration> standardDeviation;
13569-        Benchmark::OutlierClassification outliers;
13570-        double outlierVariance;
13571-    };
13572-
13573-
13574-} // end namespace Catch
13575-
13576-#endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED
13577-
13578-
13579-// Adapted from donated nonius code.
13580-
13581-#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED
13582-#define CATCH_ENVIRONMENT_HPP_INCLUDED
13583-
13584-
13585-namespace Catch {
13586-    namespace Benchmark {
13587-        struct EnvironmentEstimate {
13588-            FDuration mean;
13589-            OutlierClassification outliers;
13590-        };
13591-        struct Environment {
13592-            EnvironmentEstimate clock_resolution;
13593-            EnvironmentEstimate clock_cost;
13594-        };
13595-    } // namespace Benchmark
13596-} // namespace Catch
13597-
13598-#endif // CATCH_ENVIRONMENT_HPP_INCLUDED
13599-
13600-
13601-// Adapted from donated nonius code.
13602-
13603-#ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED
13604-#define CATCH_EXECUTION_PLAN_HPP_INCLUDED
13605-
13606-
13607-
13608-// Adapted from donated nonius code.
13609-
13610-#ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
13611-#define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
13612-
13613-
13614-
13615-// Adapted from donated nonius code.
13616-
13617-#ifndef CATCH_CHRONOMETER_HPP_INCLUDED
13618-#define CATCH_CHRONOMETER_HPP_INCLUDED
13619-
13620-
13621-
13622-// Adapted from donated nonius code.
13623-
13624-#ifndef CATCH_OPTIMIZER_HPP_INCLUDED
13625-#define CATCH_OPTIMIZER_HPP_INCLUDED
13626-
13627-#if defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
13628-#   include <atomic> // atomic_thread_fence
13629-#endif
13630-
13631-
13632-#include <type_traits>
13633-
13634-namespace Catch {
13635-    namespace Benchmark {
13636-#if defined(__GNUC__) || defined(__clang__)
13637-        template <typename T>
13638-        inline void keep_memory(T* p) {
13639-            asm volatile("" : : "g"(p) : "memory");
13640-        }
13641-        inline void keep_memory() {
13642-            asm volatile("" : : : "memory");
13643-        }
13644-
13645-        namespace Detail {
13646-            inline void optimizer_barrier() { keep_memory(); }
13647-        } // namespace Detail
13648-#elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
13649-
13650-#if defined(_MSVC_VER)
13651-#pragma optimize("", off)
13652-#elif defined(__IAR_SYSTEMS_ICC__)
13653-// For IAR the pragma only affects the following function
13654-#pragma optimize=disable
13655-#endif
13656-        template <typename T>
13657-        inline void keep_memory(T* p) {
13658-            // thanks @milleniumbug
13659-            *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
13660-        }
13661-        // TODO equivalent keep_memory()
13662-#if defined(_MSVC_VER)
13663-#pragma optimize("", on)
13664-#endif
13665-
13666-        namespace Detail {
13667-            inline void optimizer_barrier() {
13668-                std::atomic_thread_fence(std::memory_order_seq_cst);
13669-            }
13670-        } // namespace Detail
13671-
13672-#endif
13673-
13674-        template <typename T>
13675-        inline void deoptimize_value(T&& x) {
13676-            keep_memory(&x);
13677-        }
13678-
13679-        template <typename Fn, typename... Args>
13680-        inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same<void, decltype(fn(args...))>::value> {
13681-            deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...));
13682-        }
13683-
13684-        template <typename Fn, typename... Args>
13685-        inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> {
13686-            CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...);
13687-        }
13688-    } // namespace Benchmark
13689-} // namespace Catch
13690-
13691-#endif // CATCH_OPTIMIZER_HPP_INCLUDED
13692-
13693-
13694-#ifndef CATCH_META_HPP_INCLUDED
13695-#define CATCH_META_HPP_INCLUDED
13696-
13697-#include <type_traits>
13698-
13699-namespace Catch {
13700-    template <typename>
13701-    struct true_given : std::true_type {};
13702-
13703-    struct is_callable_tester {
13704-        template <typename Fun, typename... Args>
13705-        static true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int);
13706-        template <typename...>
13707-        static std::false_type test(...);
13708-    };
13709-
13710-    template <typename T>
13711-    struct is_callable;
13712-
13713-    template <typename Fun, typename... Args>
13714-    struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
13715-
13716-
13717-#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
13718-    // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
13719-    // replaced with std::invoke_result here.
13720-    template <typename Func, typename... U>
13721-    using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
13722-#else
13723-    template <typename Func, typename... U>
13724-    using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::result_of_t<Func(U...)>>>;
13725-#endif
13726-
13727-} // namespace Catch
13728-
13729-namespace mpl_{
13730-    struct na;
13731-}
13732-
13733-#endif // CATCH_META_HPP_INCLUDED
13734-
13735-namespace Catch {
13736-    namespace Benchmark {
13737-        namespace Detail {
13738-            struct ChronometerConcept {
13739-                virtual void start() = 0;
13740-                virtual void finish() = 0;
13741-                virtual ~ChronometerConcept(); // = default;
13742-
13743-                ChronometerConcept() = default;
13744-                ChronometerConcept(ChronometerConcept const&) = default;
13745-                ChronometerConcept& operator=(ChronometerConcept const&) = default;
13746-            };
13747-            template <typename Clock>
13748-            struct ChronometerModel final : public ChronometerConcept {
13749-                void start() override { started = Clock::now(); }
13750-                void finish() override { finished = Clock::now(); }
13751-
13752-                IDuration elapsed() const {
13753-                    return std::chrono::duration_cast<std::chrono::nanoseconds>(
13754-                        finished - started );
13755-                }
13756-
13757-                TimePoint<Clock> started;
13758-                TimePoint<Clock> finished;
13759-            };
13760-        } // namespace Detail
13761-
13762-        struct Chronometer {
13763-        public:
13764-            template <typename Fun>
13765-            void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable<Fun(int)>()); }
13766-
13767-            int runs() const { return repeats; }
13768-
13769-            Chronometer(Detail::ChronometerConcept& meter, int repeats_)
13770-                : impl(&meter)
13771-                , repeats(repeats_) {}
13772-
13773-        private:
13774-            template <typename Fun>
13775-            void measure(Fun&& fun, std::false_type) {
13776-                measure([&fun](int) { return fun(); }, std::true_type());
13777-            }
13778-
13779-            template <typename Fun>
13780-            void measure(Fun&& fun, std::true_type) {
13781-                Detail::optimizer_barrier();
13782-                impl->start();
13783-                for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i);
13784-                impl->finish();
13785-                Detail::optimizer_barrier();
13786-            }
13787-
13788-            Detail::ChronometerConcept* impl;
13789-            int repeats;
13790-        };
13791-    } // namespace Benchmark
13792-} // namespace Catch
13793-
13794-#endif // CATCH_CHRONOMETER_HPP_INCLUDED
13795-
13796-#include <type_traits>
13797-
13798-namespace Catch {
13799-    namespace Benchmark {
13800-        namespace Detail {
13801-            template <typename T, typename U>
13802-            static constexpr bool is_related_v = std::is_same<std::decay_t<T>, std::decay_t<U>>::value;
13803-
13804-            /// We need to reinvent std::function because every piece of code that might add overhead
13805-            /// in a measurement context needs to have consistent performance characteristics so that we
13806-            /// can account for it in the measurement.
13807-            /// Implementations of std::function with optimizations that aren't always applicable, like
13808-            /// small buffer optimizations, are not uncommon.
13809-            /// This is effectively an implementation of std::function without any such optimizations;
13810-            /// it may be slow, but it is consistently slow.
13811-            struct BenchmarkFunction {
13812-            private:
13813-                struct callable {
13814-                    virtual void call(Chronometer meter) const = 0;
13815-                    virtual ~callable(); // = default;
13816-
13817-                    callable() = default;
13818-                    callable(callable&&) = default;
13819-                    callable& operator=(callable&&) = default;
13820-                };
13821-                template <typename Fun>
13822-                struct model : public callable {
13823-                    model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
13824-                    model(Fun const& fun_) : fun(fun_) {}
13825-
13826-                    void call(Chronometer meter) const override {
13827-                        call(meter, is_callable<Fun(Chronometer)>());
13828-                    }
13829-                    void call(Chronometer meter, std::true_type) const {
13830-                        fun(meter);
13831-                    }
13832-                    void call(Chronometer meter, std::false_type) const {
13833-                        meter.measure(fun);
13834-                    }
13835-
13836-                    Fun fun;
13837-                };
13838-
13839-            public:
13840-                BenchmarkFunction();
13841-
13842-                template <typename Fun,
13843-                    std::enable_if_t<!is_related_v<Fun, BenchmarkFunction>, int> = 0>
13844-                    BenchmarkFunction(Fun&& fun)
13845-                    : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
13846-
13847-                BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
13848-                    f( CATCH_MOVE( that.f ) ) {}
13849-
13850-                BenchmarkFunction&
13851-                operator=( BenchmarkFunction&& that ) noexcept {
13852-                    f = CATCH_MOVE( that.f );
13853-                    return *this;
13854-                }
13855-
13856-                void operator()(Chronometer meter) const { f->call(meter); }
13857-
13858-            private:
13859-                Catch::Detail::unique_ptr<callable> f;
13860-            };
13861-        } // namespace Detail
13862-    } // namespace Benchmark
13863-} // namespace Catch
13864-
13865-#endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
13866-
13867-
13868-// Adapted from donated nonius code.
13869-
13870-#ifndef CATCH_REPEAT_HPP_INCLUDED
13871-#define CATCH_REPEAT_HPP_INCLUDED
13872-
13873-#include <type_traits>
13874-
13875-namespace Catch {
13876-    namespace Benchmark {
13877-        namespace Detail {
13878-            template <typename Fun>
13879-            struct repeater {
13880-                void operator()(int k) const {
13881-                    for (int i = 0; i < k; ++i) {
13882-                        fun();
13883-                    }
13884-                }
13885-                Fun fun;
13886-            };
13887-            template <typename Fun>
13888-            repeater<std::decay_t<Fun>> repeat(Fun&& fun) {
13889-                return { CATCH_FORWARD(fun) };
13890-            }
13891-        } // namespace Detail
13892-    } // namespace Benchmark
13893-} // namespace Catch
13894-
13895-#endif // CATCH_REPEAT_HPP_INCLUDED
13896-
13897-
13898-// Adapted from donated nonius code.
13899-
13900-#ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
13901-#define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
13902-
13903-
13904-
13905-// Adapted from donated nonius code.
13906-
13907-#ifndef CATCH_MEASURE_HPP_INCLUDED
13908-#define CATCH_MEASURE_HPP_INCLUDED
13909-
13910-
13911-
13912-// Adapted from donated nonius code.
13913-
13914-#ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED
13915-#define CATCH_COMPLETE_INVOKE_HPP_INCLUDED
13916-
13917-
13918-namespace Catch {
13919-    namespace Benchmark {
13920-        namespace Detail {
13921-            template <typename T>
13922-            struct CompleteType { using type = T; };
13923-            template <>
13924-            struct CompleteType<void> { struct type {}; };
13925-
13926-            template <typename T>
13927-            using CompleteType_t = typename CompleteType<T>::type;
13928-
13929-            template <typename Result>
13930-            struct CompleteInvoker {
13931-                template <typename Fun, typename... Args>
13932-                static Result invoke(Fun&& fun, Args&&... args) {
13933-                    return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
13934-                }
13935-            };
13936-            template <>
13937-            struct CompleteInvoker<void> {
13938-                template <typename Fun, typename... Args>
13939-                static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {
13940-                    CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
13941-                    return {};
13942-                }
13943-            };
13944-
13945-            // invoke and not return void :(
13946-            template <typename Fun, typename... Args>
13947-            CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {
13948-                return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
13949-            }
13950-
13951-        } // namespace Detail
13952-
13953-        template <typename Fun>
13954-        Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {
13955-            return Detail::complete_invoke(CATCH_FORWARD(fun));
13956-        }
13957-    } // namespace Benchmark
13958-} // namespace Catch
13959-
13960-#endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED
13961-
13962-
13963-// Adapted from donated nonius code.
13964-
13965-#ifndef CATCH_TIMING_HPP_INCLUDED
13966-#define CATCH_TIMING_HPP_INCLUDED
13967-
13968-
13969-namespace Catch {
13970-    namespace Benchmark {
13971-        template <typename Result>
13972-        struct Timing {
13973-            IDuration elapsed;
13974-            Result result;
13975-            int iterations;
13976-        };
13977-        template <typename Func, typename... Args>
13978-        using TimingOf = Timing<Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
13979-    } // namespace Benchmark
13980-} // namespace Catch
13981-
13982-#endif // CATCH_TIMING_HPP_INCLUDED
13983-
13984-namespace Catch {
13985-    namespace Benchmark {
13986-        namespace Detail {
13987-            template <typename Clock, typename Fun, typename... Args>
13988-            TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) {
13989-                auto start = Clock::now();
13990-                auto&& r = Detail::complete_invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
13991-                auto end = Clock::now();
13992-                auto delta = end - start;
13993-                return { delta, CATCH_FORWARD(r), 1 };
13994-            }
13995-        } // namespace Detail
13996-    } // namespace Benchmark
13997-} // namespace Catch
13998-
13999-#endif // CATCH_MEASURE_HPP_INCLUDED
14000-
14001-#include <type_traits>
14002-
14003-namespace Catch {
14004-    namespace Benchmark {
14005-        namespace Detail {
14006-            template <typename Clock, typename Fun>
14007-            TimingOf<Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
14008-                return Detail::measure<Clock>(fun, iters);
14009-            }
14010-            template <typename Clock, typename Fun>
14011-            TimingOf<Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
14012-                Detail::ChronometerModel<Clock> meter;
14013-                auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
14014-
14015-                return { meter.elapsed(), CATCH_MOVE(result), iters };
14016-            }
14017-
14018-            template <typename Clock, typename Fun>
14019-            using run_for_at_least_argument_t = std::conditional_t<is_callable<Fun(Chronometer)>::value, Chronometer, int>;
14020-
14021-
14022-            [[noreturn]]
14023-            void throw_optimized_away_error();
14024-
14025-            template <typename Clock, typename Fun>
14026-            TimingOf<Fun, run_for_at_least_argument_t<Clock, Fun>>
14027-                run_for_at_least(IDuration how_long,
14028-                                 const int initial_iterations,
14029-                                 Fun&& fun) {
14030-                auto iters = initial_iterations;
14031-                while (iters < (1 << 30)) {
14032-                    auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
14033-
14034-                    if (Timing.elapsed >= how_long) {
14035-                        return { Timing.elapsed, CATCH_MOVE(Timing.result), iters };
14036-                    }
14037-                    iters *= 2;
14038-                }
14039-                throw_optimized_away_error();
14040-            }
14041-        } // namespace Detail
14042-    } // namespace Benchmark
14043-} // namespace Catch
14044-
14045-#endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
14046-
14047-#include <vector>
14048-
14049-namespace Catch {
14050-    namespace Benchmark {
14051-        struct ExecutionPlan {
14052-            int iterations_per_sample;
14053-            FDuration estimated_duration;
14054-            Detail::BenchmarkFunction benchmark;
14055-            FDuration warmup_time;
14056-            int warmup_iterations;
14057-
14058-            template <typename Clock>
14059-            std::vector<FDuration> run(const IConfig &cfg, Environment env) const {
14060-                // warmup a bit
14061-                Detail::run_for_at_least<Clock>(
14062-                    std::chrono::duration_cast<IDuration>( warmup_time ),
14063-                    warmup_iterations,
14064-                    Detail::repeat( []() { return Clock::now(); } )
14065-                );
14066-
14067-                std::vector<FDuration> times;
14068-                const auto num_samples = cfg.benchmarkSamples();
14069-                times.reserve( num_samples );
14070-                for ( size_t i = 0; i < num_samples; ++i ) {
14071-                    Detail::ChronometerModel<Clock> model;
14072-                    this->benchmark( Chronometer( model, iterations_per_sample ) );
14073-                    auto sample_time = model.elapsed() - env.clock_cost.mean;
14074-                    if ( sample_time < FDuration::zero() ) {
14075-                        sample_time = FDuration::zero();
14076-                    }
14077-                    times.push_back(sample_time / iterations_per_sample);
14078-                }
14079-                return times;
14080-            }
14081-        };
14082-    } // namespace Benchmark
14083-} // namespace Catch
14084-
14085-#endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED
14086-
14087-
14088-// Adapted from donated nonius code.
14089-
14090-#ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
14091-#define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
14092-
14093-
14094-
14095-// Adapted from donated nonius code.
14096-
14097-#ifndef CATCH_STATS_HPP_INCLUDED
14098-#define CATCH_STATS_HPP_INCLUDED
14099-
14100-
14101-#include <vector>
14102-
14103-namespace Catch {
14104-    namespace Benchmark {
14105-        namespace Detail {
14106-            using sample = std::vector<double>;
14107-
14108-            double weighted_average_quantile( int k,
14109-                                              int q,
14110-                                              double* first,
14111-                                              double* last );
14112-
14113-            OutlierClassification
14114-            classify_outliers( double const* first, double const* last );
14115-
14116-            double mean( double const* first, double const* last );
14117-
14118-            double normal_cdf( double x );
14119-
14120-            double erfc_inv(double x);
14121-
14122-            double normal_quantile(double p);
14123-
14124-            Estimate<double>
14125-            bootstrap( double confidence_level,
14126-                       double* first,
14127-                       double* last,
14128-                       sample const& resample,
14129-                       double ( *estimator )( double const*, double const* ) );
14130-
14131-            struct bootstrap_analysis {
14132-                Estimate<double> mean;
14133-                Estimate<double> standard_deviation;
14134-                double outlier_variance;
14135-            };
14136-
14137-            bootstrap_analysis analyse_samples(double confidence_level,
14138-                                               unsigned int n_resamples,
14139-                                               double* first,
14140-                                               double* last);
14141-        } // namespace Detail
14142-    } // namespace Benchmark
14143-} // namespace Catch
14144-
14145-#endif // CATCH_STATS_HPP_INCLUDED
14146-
14147-#include <algorithm>
14148-#include <vector>
14149-#include <cmath>
14150-
14151-namespace Catch {
14152-    namespace Benchmark {
14153-        namespace Detail {
14154-            template <typename Clock>
14155-            std::vector<double> resolution(int k) {
14156-                const size_t points = static_cast<size_t>( k + 1 );
14157-                // To avoid overhead from the branch inside vector::push_back,
14158-                // we allocate them all and then overwrite.
14159-                std::vector<TimePoint<Clock>> times(points);
14160-                for ( auto& time : times ) {
14161-                    time = Clock::now();
14162-                }
14163-
14164-                std::vector<double> deltas;
14165-                deltas.reserve(static_cast<size_t>(k));
14166-                for ( size_t idx = 1; idx < points; ++idx ) {
14167-                    deltas.push_back( static_cast<double>(
14168-                        ( times[idx] - times[idx - 1] ).count() ) );
14169-                }
14170-
14171-                return deltas;
14172-            }
14173-
14174-            constexpr auto warmup_iterations = 10000;
14175-            constexpr auto warmup_time = std::chrono::milliseconds(100);
14176-            constexpr auto minimum_ticks = 1000;
14177-            constexpr auto warmup_seed = 10000;
14178-            constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
14179-            constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
14180-            constexpr auto clock_cost_estimation_tick_limit = 100000;
14181-            constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10);
14182-            constexpr auto clock_cost_estimation_iterations = 10000;
14183-
14184-            template <typename Clock>
14185-            int warmup() {
14186-                return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>)
14187-                    .iterations;
14188-            }
14189-            template <typename Clock>
14190-            EnvironmentEstimate estimate_clock_resolution(int iterations) {
14191-                auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>)
14192-                    .result;
14193-                return {
14194-                    FDuration(mean(r.data(), r.data() + r.size())),
14195-                    classify_outliers(r.data(), r.data() + r.size()),
14196-                };
14197-            }
14198-            template <typename Clock>
14199-            EnvironmentEstimate estimate_clock_cost(FDuration resolution) {
14200-                auto time_limit = (std::min)(
14201-                    resolution * clock_cost_estimation_tick_limit,
14202-                    FDuration(clock_cost_estimation_time_limit));
14203-                auto time_clock = [](int k) {
14204-                    return Detail::measure<Clock>([k] {
14205-                        for (int i = 0; i < k; ++i) {
14206-                            volatile auto ignored = Clock::now();
14207-                            (void)ignored;
14208-                        }
14209-                    }).elapsed;
14210-                };
14211-                time_clock(1);
14212-                int iters = clock_cost_estimation_iterations;
14213-                auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock);
14214-                std::vector<double> times;
14215-                int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
14216-                times.reserve(static_cast<size_t>(nsamples));
14217-                for ( int s = 0; s < nsamples; ++s ) {
14218-                    times.push_back( static_cast<double>(
14219-                        ( time_clock( r.iterations ) / r.iterations )
14220-                            .count() ) );
14221-                }
14222-                return {
14223-                    FDuration(mean(times.data(), times.data() + times.size())),
14224-                    classify_outliers(times.data(), times.data() + times.size()),
14225-                };
14226-            }
14227-
14228-            template <typename Clock>
14229-            Environment measure_environment() {
14230-#if defined(__clang__)
14231-#    pragma clang diagnostic push
14232-#    pragma clang diagnostic ignored "-Wexit-time-destructors"
14233-#endif
14234-                static Catch::Detail::unique_ptr<Environment> env;
14235-#if defined(__clang__)
14236-#    pragma clang diagnostic pop
14237-#endif
14238-                if (env) {
14239-                    return *env;
14240-                }
14241-
14242-                auto iters = Detail::warmup<Clock>();
14243-                auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
14244-                auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
14245-
14246-                env = Catch::Detail::make_unique<Environment>( Environment{resolution, cost} );
14247-                return *env;
14248-            }
14249-        } // namespace Detail
14250-    } // namespace Benchmark
14251-} // namespace Catch
14252-
14253-#endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
14254-
14255-
14256-// Adapted from donated nonius code.
14257-
14258-#ifndef CATCH_ANALYSE_HPP_INCLUDED
14259-#define CATCH_ANALYSE_HPP_INCLUDED
14260-
14261-
14262-
14263-// Adapted from donated nonius code.
14264-
14265-#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
14266-#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
14267-
14268-
14269-#include <vector>
14270-
14271-namespace Catch {
14272-    namespace Benchmark {
14273-        struct SampleAnalysis {
14274-            std::vector<FDuration> samples;
14275-            Estimate<FDuration> mean;
14276-            Estimate<FDuration> standard_deviation;
14277-            OutlierClassification outliers;
14278-            double outlier_variance;
14279-        };
14280-    } // namespace Benchmark
14281-} // namespace Catch
14282-
14283-#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
14284-
14285-
14286-namespace Catch {
14287-    class IConfig;
14288-
14289-    namespace Benchmark {
14290-        namespace Detail {
14291-            SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last);
14292-        } // namespace Detail
14293-    } // namespace Benchmark
14294-} // namespace Catch
14295-
14296-#endif // CATCH_ANALYSE_HPP_INCLUDED
14297-
14298-#include <algorithm>
14299-#include <chrono>
14300-#include <exception>
14301-#include <string>
14302-#include <cmath>
14303-
14304-namespace Catch {
14305-    namespace Benchmark {
14306-        struct Benchmark {
14307-            Benchmark(std::string&& benchmarkName)
14308-                : name(CATCH_MOVE(benchmarkName)) {}
14309-
14310-            template <class FUN>
14311-            Benchmark(std::string&& benchmarkName , FUN &&func)
14312-                : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}
14313-
14314-            template <typename Clock>
14315-            ExecutionPlan prepare(const IConfig &cfg, Environment env) {
14316-                auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
14317-                auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
14318-                auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun);
14319-                int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
14320-                return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), CATCH_MOVE(fun), std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
14321-            }
14322-
14323-            template <typename Clock = default_clock>
14324-            void run() {
14325-                static_assert( Clock::is_steady,
14326-                               "Benchmarking clock should be steady" );
14327-                auto const* cfg = getCurrentContext().getConfig();
14328-
14329-                auto env = Detail::measure_environment<Clock>();
14330-
14331-                getResultCapture().benchmarkPreparing(name);
14332-                CATCH_TRY{
14333-                    auto plan = user_code([&] {
14334-                        return prepare<Clock>(*cfg, env);
14335-                    });
14336-
14337-                    BenchmarkInfo info {
14338-                        CATCH_MOVE(name),
14339-                        plan.estimated_duration.count(),
14340-                        plan.iterations_per_sample,
14341-                        cfg->benchmarkSamples(),
14342-                        cfg->benchmarkResamples(),
14343-                        env.clock_resolution.mean.count(),
14344-                        env.clock_cost.mean.count()
14345-                    };
14346-
14347-                    getResultCapture().benchmarkStarting(info);
14348-
14349-                    auto samples = user_code([&] {
14350-                        return plan.template run<Clock>(*cfg, env);
14351-                    });
14352-
14353-                    auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size());
14354-                    BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
14355-                    getResultCapture().benchmarkEnded(stats);
14356-                } CATCH_CATCH_ALL {
14357-                    getResultCapture().benchmarkFailed(translateActiveException());
14358-                    // We let the exception go further up so that the
14359-                    // test case is marked as failed.
14360-                    std::rethrow_exception(std::current_exception());
14361-                }
14362-            }
14363-
14364-            // sets lambda to be used in fun *and* executes benchmark!
14365-            template <typename Fun, std::enable_if_t<!Detail::is_related_v<Fun, Benchmark>, int> = 0>
14366-                Benchmark & operator=(Fun func) {
14367-                auto const* cfg = getCurrentContext().getConfig();
14368-                if (!cfg->skipBenchmarks()) {
14369-                    fun = Detail::BenchmarkFunction(func);
14370-                    run();
14371-                }
14372-                return *this;
14373-            }
14374-
14375-            explicit operator bool() {
14376-                return true;
14377-            }
14378-
14379-        private:
14380-            Detail::BenchmarkFunction fun;
14381-            std::string name;
14382-        };
14383-    }
14384-} // namespace Catch
14385-
14386-#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
14387-#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
14388-
14389-#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
14390-    if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
14391-        BenchmarkName = [&](int benchmarkIndex)
14392-
14393-#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
14394-    if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
14395-        BenchmarkName = [&]
14396-
14397-#if defined(CATCH_CONFIG_PREFIX_ALL)
14398-
14399-#define CATCH_BENCHMARK(...) \
14400-    INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
14401-#define CATCH_BENCHMARK_ADVANCED(name) \
14402-    INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
14403-
14404-#else
14405-
14406-#define BENCHMARK(...) \
14407-    INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
14408-#define BENCHMARK_ADVANCED(name) \
14409-    INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
14410-
14411-#endif
14412-
14413-#endif // CATCH_BENCHMARK_HPP_INCLUDED
14414-
14415-
14416-// Adapted from donated nonius code.
14417-
14418-#ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED
14419-#define CATCH_CONSTRUCTOR_HPP_INCLUDED
14420-
14421-
14422-#include <type_traits>
14423-
14424-namespace Catch {
14425-    namespace Benchmark {
14426-        namespace Detail {
14427-            template <typename T, bool Destruct>
14428-            struct ObjectStorage
14429-            {
14430-                ObjectStorage() = default;
14431-
14432-                ObjectStorage(const ObjectStorage& other)
14433-                {
14434-                    new(&data) T(other.stored_object());
14435-                }
14436-
14437-                ObjectStorage(ObjectStorage&& other)
14438-                {
14439-                    new(data) T(CATCH_MOVE(other.stored_object()));
14440-                }
14441-
14442-                ~ObjectStorage() { destruct_on_exit<T>(); }
14443-
14444-                template <typename... Args>
14445-                void construct(Args&&... args)
14446-                {
14447-                    new (data) T(CATCH_FORWARD(args)...);
14448-                }
14449-
14450-                template <bool AllowManualDestruction = !Destruct>
14451-                std::enable_if_t<AllowManualDestruction> destruct()
14452-                {
14453-                    stored_object().~T();
14454-                }
14455-
14456-            private:
14457-                // If this is a constructor benchmark, destruct the underlying object
14458-                template <typename U>
14459-                void destruct_on_exit(std::enable_if_t<Destruct, U>* = nullptr) { destruct<true>(); }
14460-                // Otherwise, don't
14461-                template <typename U>
14462-                void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { }
14463-
14464-#if defined( __GNUC__ ) && __GNUC__ <= 6
14465-#    pragma GCC diagnostic push
14466-#    pragma GCC diagnostic ignored "-Wstrict-aliasing"
14467-#endif
14468-                T& stored_object() { return *reinterpret_cast<T*>( data ); }
14469-
14470-                T const& stored_object() const {
14471-                    return *reinterpret_cast<T const*>( data );
14472-                }
14473-#if defined( __GNUC__ ) && __GNUC__ <= 6
14474-#    pragma GCC diagnostic pop
14475-#endif
14476-
14477-                alignas( T ) unsigned char data[sizeof( T )]{};
14478-            };
14479-        } // namespace Detail
14480-
14481-        template <typename T>
14482-        using storage_for = Detail::ObjectStorage<T, true>;
14483-
14484-        template <typename T>
14485-        using destructable_object = Detail::ObjectStorage<T, false>;
14486-    } // namespace Benchmark
14487-} // namespace Catch
14488-
14489-#endif // CATCH_CONSTRUCTOR_HPP_INCLUDED
14490-
14491-#endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED
14492-
14493-
14494-#ifndef CATCH_APPROX_HPP_INCLUDED
14495-#define CATCH_APPROX_HPP_INCLUDED
14496-
14497-
14498-
14499-#ifndef CATCH_TOSTRING_HPP_INCLUDED
14500-#define CATCH_TOSTRING_HPP_INCLUDED
14501-
14502-
14503-#include <vector>
14504-#include <cstddef>
14505-#include <type_traits>
14506-#include <string>
14507-
14508-
14509-
14510-
14511-/** \file
14512- * Wrapper for the WCHAR configuration option
14513- *
14514- * We want to support platforms that do not provide `wchar_t`, so we
14515- * sometimes have to disable providing wchar_t overloads through Catch2,
14516- * e.g. the StringMaker specialization for `std::wstring`.
14517- */
14518-
14519-#ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED
14520-#define CATCH_CONFIG_WCHAR_HPP_INCLUDED
14521-
14522-
14523-// We assume that WCHAR should be enabled by default, and only disabled
14524-// for a shortlist (so far only DJGPP) of compilers.
14525-
14526-#if defined(__DJGPP__)
14527-#  define CATCH_INTERNAL_CONFIG_NO_WCHAR
14528-#endif // __DJGPP__
14529-
14530-#if !defined( CATCH_INTERNAL_CONFIG_NO_WCHAR ) && \
14531-    !defined( CATCH_CONFIG_NO_WCHAR ) && \
14532-    !defined( CATCH_CONFIG_WCHAR )
14533-#    define CATCH_CONFIG_WCHAR
14534-#endif
14535-
14536-#endif // CATCH_CONFIG_WCHAR_HPP_INCLUDED
14537-
14538-
14539-#ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
14540-#define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
14541-
14542-
14543-#include <iosfwd>
14544-#include <cstddef>
14545-#include <ostream>
14546-#include <string>
14547-
14548-namespace Catch {
14549-
14550-    class ReusableStringStream : Detail::NonCopyable {
14551-        std::size_t m_index;
14552-        std::ostream* m_oss;
14553-    public:
14554-        ReusableStringStream();
14555-        ~ReusableStringStream();
14556-
14557-        //! Returns the serialized state
14558-        std::string str() const;
14559-        //! Sets internal state to `str`
14560-        void str(std::string const& str);
14561-
14562-#if defined(__GNUC__) && !defined(__clang__)
14563-#pragma GCC diagnostic push
14564-// Old versions of GCC do not understand -Wnonnull-compare
14565-#pragma GCC diagnostic ignored "-Wpragmas"
14566-// Streaming a function pointer triggers Waddress and Wnonnull-compare
14567-// on GCC, because it implicitly converts it to bool and then decides
14568-// that the check it uses (a? true : false) is tautological and cannot
14569-// be null...
14570-#pragma GCC diagnostic ignored "-Waddress"
14571-#pragma GCC diagnostic ignored "-Wnonnull-compare"
14572-#endif
14573-
14574-        template<typename T>
14575-        auto operator << ( T const& value ) -> ReusableStringStream& {
14576-            *m_oss << value;
14577-            return *this;
14578-        }
14579-
14580-#if defined(__GNUC__) && !defined(__clang__)
14581-#pragma GCC diagnostic pop
14582-#endif
14583-        auto get() -> std::ostream& { return *m_oss; }
14584-    };
14585-}
14586-
14587-#endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
14588-
14589-
14590-#ifndef CATCH_VOID_TYPE_HPP_INCLUDED
14591-#define CATCH_VOID_TYPE_HPP_INCLUDED
14592-
14593-
14594-namespace Catch {
14595-    namespace Detail {
14596-
14597-        template <typename...>
14598-        struct make_void { using type = void; };
14599-
14600-        template <typename... Ts>
14601-        using void_t = typename make_void<Ts...>::type;
14602-
14603-    } // namespace Detail
14604-} // namespace Catch
14605-
14606-
14607-#endif // CATCH_VOID_TYPE_HPP_INCLUDED
14608-
14609-
14610-#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
14611-#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
14612-
14613-
14614-#include <vector>
14615-
14616-namespace Catch {
14617-
14618-    namespace Detail {
14619-        struct EnumInfo {
14620-            StringRef m_name;
14621-            std::vector<std::pair<int, StringRef>> m_values;
14622-
14623-            ~EnumInfo();
14624-
14625-            StringRef lookup( int value ) const;
14626-        };
14627-    } // namespace Detail
14628-
14629-    class IMutableEnumValuesRegistry {
14630-    public:
14631-        virtual ~IMutableEnumValuesRegistry(); // = default;
14632-
14633-        virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
14634-
14635-        template<typename E>
14636-        Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
14637-            static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
14638-            std::vector<int> intValues;
14639-            intValues.reserve( values.size() );
14640-            for( auto enumValue : values )
14641-                intValues.push_back( static_cast<int>( enumValue ) );
14642-            return registerEnum( enumName, allEnums, intValues );
14643-        }
14644-    };
14645-
14646-} // Catch
14647-
14648-#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
14649-
14650-#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
14651-#include <string_view>
14652-#endif
14653-
14654-#ifdef _MSC_VER
14655-#pragma warning(push)
14656-#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
14657-#endif
14658-
14659-// We need a dummy global operator<< so we can bring it into Catch namespace later
14660-struct Catch_global_namespace_dummy{};
14661-std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
14662-
14663-namespace Catch {
14664-    // Bring in global namespace operator<< for ADL lookup in
14665-    // `IsStreamInsertable` below.
14666-    using ::operator<<;
14667-
14668-    namespace Detail {
14669-
14670-        inline std::size_t catch_strnlen(const char *str, std::size_t n) {
14671-            auto ret = std::char_traits<char>::find(str, n, '\0');
14672-            if (ret != nullptr) {
14673-                return static_cast<std::size_t>(ret - str);
14674-            }
14675-            return n;
14676-        }
14677-
14678-        constexpr StringRef unprintableString = "{?}"_sr;
14679-
14680-        //! Encases `string in quotes, and optionally escapes invisibles
14681-        std::string convertIntoString( StringRef string, bool escapeInvisibles );
14682-
14683-        //! Encases `string` in quotes, and escapes invisibles if user requested
14684-        //! it via CLI
14685-        std::string convertIntoString( StringRef string );
14686-
14687-        std::string rawMemoryToString( const void *object, std::size_t size );
14688-
14689-        template<typename T>
14690-        std::string rawMemoryToString( const T& object ) {
14691-          return rawMemoryToString( &object, sizeof(object) );
14692-        }
14693-
14694-        template<typename T,typename = void>
14695-        static constexpr bool IsStreamInsertable_v = false;
14696-
14697-        template <typename T>
14698-        static constexpr bool IsStreamInsertable_v<
14699-            T,
14700-            decltype( void( std::declval<std::ostream&>() << std::declval<T>() ) )> =
14701-            true;
14702-
14703-        template<typename E>
14704-        std::string convertUnknownEnumToString( E e );
14705-
14706-        template<typename T>
14707-        std::enable_if_t<
14708-            !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
14709-        std::string> convertUnstreamable( T const& ) {
14710-            return std::string(Detail::unprintableString);
14711-        }
14712-        template<typename T>
14713-        std::enable_if_t<
14714-            !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
14715-         std::string> convertUnstreamable(T const& ex) {
14716-            return ex.what();
14717-        }
14718-
14719-
14720-        template<typename T>
14721-        std::enable_if_t<
14722-            std::is_enum<T>::value,
14723-        std::string> convertUnstreamable( T const& value ) {
14724-            return convertUnknownEnumToString( value );
14725-        }
14726-
14727-#if defined(_MANAGED)
14728-        //! Convert a CLR string to a utf8 std::string
14729-        template<typename T>
14730-        std::string clrReferenceToString( T^ ref ) {
14731-            if (ref == nullptr)
14732-                return std::string("null");
14733-            auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
14734-            cli::pin_ptr<System::Byte> p = &bytes[0];
14735-            return std::string(reinterpret_cast<char const *>(p), bytes->Length);
14736-        }
14737-#endif
14738-
14739-    } // namespace Detail
14740-
14741-
14742-    template <typename T, typename = void>
14743-    struct StringMaker {
14744-        template <typename Fake = T>
14745-        static
14746-        std::enable_if_t<::Catch::Detail::IsStreamInsertable_v<Fake>, std::string>
14747-            convert(const Fake& value) {
14748-                ReusableStringStream rss;
14749-                // NB: call using the function-like syntax to avoid ambiguity with
14750-                // user-defined templated operator<< under clang.
14751-                rss.operator<<(value);
14752-                return rss.str();
14753-        }
14754-
14755-        template <typename Fake = T>
14756-        static
14757-        std::enable_if_t<!::Catch::Detail::IsStreamInsertable_v<Fake>, std::string>
14758-            convert( const Fake& value ) {
14759-#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
14760-            return Detail::convertUnstreamable(value);
14761-#else
14762-            return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
14763-#endif
14764-        }
14765-    };
14766-
14767-    namespace Detail {
14768-
14769-        std::string makeExceptionHappenedString();
14770-
14771-        // This function dispatches all stringification requests inside of Catch.
14772-        // Should be preferably called fully qualified, like ::Catch::Detail::stringify
14773-        template <typename T>
14774-        std::string stringify( const T& e ) {
14775-            CATCH_TRY {
14776-                return ::Catch::StringMaker<
14777-                    std::remove_cv_t<std::remove_reference_t<T>>>::convert( e );
14778-            }
14779-            CATCH_CATCH_ALL { return makeExceptionHappenedString(); }
14780-        }
14781-
14782-        template<typename E>
14783-        std::string convertUnknownEnumToString( E e ) {
14784-            return ::Catch::Detail::stringify(static_cast<std::underlying_type_t<E>>(e));
14785-        }
14786-
14787-#if defined(_MANAGED)
14788-        template <typename T>
14789-        std::string stringify( T^ e ) {
14790-            return ::Catch::StringMaker<T^>::convert(e);
14791-        }
14792-#endif
14793-
14794-    } // namespace Detail
14795-
14796-    // Some predefined specializations
14797-
14798-    template<>
14799-    struct StringMaker<std::string> {
14800-        static std::string convert(const std::string& str);
14801-    };
14802-
14803-#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
14804-    template<>
14805-    struct StringMaker<std::string_view> {
14806-        static std::string convert(std::string_view str);
14807-    };
14808-#endif
14809-
14810-    template<>
14811-    struct StringMaker<char const *> {
14812-        static std::string convert(char const * str);
14813-    };
14814-    template<>
14815-    struct StringMaker<char *> {
14816-        static std::string convert(char * str);
14817-    };
14818-
14819-#if defined(CATCH_CONFIG_WCHAR)
14820-    template<>
14821-    struct StringMaker<std::wstring> {
14822-        static std::string convert(const std::wstring& wstr);
14823-    };
14824-
14825-# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
14826-    template<>
14827-    struct StringMaker<std::wstring_view> {
14828-        static std::string convert(std::wstring_view str);
14829-    };
14830-# endif
14831-
14832-    template<>
14833-    struct StringMaker<wchar_t const *> {
14834-        static std::string convert(wchar_t const * str);
14835-    };
14836-    template<>
14837-    struct StringMaker<wchar_t *> {
14838-        static std::string convert(wchar_t * str);
14839-    };
14840-#endif // CATCH_CONFIG_WCHAR
14841-
14842-    template<size_t SZ>
14843-    struct StringMaker<char[SZ]> {
14844-        static std::string convert(char const* str) {
14845-            return Detail::convertIntoString(
14846-                StringRef( str, Detail::catch_strnlen( str, SZ ) ) );
14847-        }
14848-    };
14849-    template<size_t SZ>
14850-    struct StringMaker<signed char[SZ]> {
14851-        static std::string convert(signed char const* str) {
14852-            auto reinterpreted = reinterpret_cast<char const*>(str);
14853-            return Detail::convertIntoString(
14854-                StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
14855-        }
14856-    };
14857-    template<size_t SZ>
14858-    struct StringMaker<unsigned char[SZ]> {
14859-        static std::string convert(unsigned char const* str) {
14860-            auto reinterpreted = reinterpret_cast<char const*>(str);
14861-            return Detail::convertIntoString(
14862-                StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
14863-        }
14864-    };
14865-
14866-#if defined(CATCH_CONFIG_CPP17_BYTE)
14867-    template<>
14868-    struct StringMaker<std::byte> {
14869-        static std::string convert(std::byte value);
14870-    };
14871-#endif // defined(CATCH_CONFIG_CPP17_BYTE)
14872-    template<>
14873-    struct StringMaker<int> {
14874-        static std::string convert(int value);
14875-    };
14876-    template<>
14877-    struct StringMaker<long> {
14878-        static std::string convert(long value);
14879-    };
14880-    template<>
14881-    struct StringMaker<long long> {
14882-        static std::string convert(long long value);
14883-    };
14884-    template<>
14885-    struct StringMaker<unsigned int> {
14886-        static std::string convert(unsigned int value);
14887-    };
14888-    template<>
14889-    struct StringMaker<unsigned long> {
14890-        static std::string convert(unsigned long value);
14891-    };
14892-    template<>
14893-    struct StringMaker<unsigned long long> {
14894-        static std::string convert(unsigned long long value);
14895-    };
14896-
14897-    template<>
14898-    struct StringMaker<bool> {
14899-        static std::string convert(bool b) {
14900-            using namespace std::string_literals;
14901-            return b ? "true"s : "false"s;
14902-        }
14903-    };
14904-
14905-    template<>
14906-    struct StringMaker<char> {
14907-        static std::string convert(char c);
14908-    };
14909-    template<>
14910-    struct StringMaker<signed char> {
14911-        static std::string convert(signed char value);
14912-    };
14913-    template<>
14914-    struct StringMaker<unsigned char> {
14915-        static std::string convert(unsigned char value);
14916-    };
14917-
14918-    template<>
14919-    struct StringMaker<std::nullptr_t> {
14920-        static std::string convert(std::nullptr_t) {
14921-            using namespace std::string_literals;
14922-            return "nullptr"s;
14923-        }
14924-    };
14925-
14926-    template<>
14927-    struct StringMaker<float> {
14928-        static std::string convert(float value);
14929-        CATCH_EXPORT static int precision;
14930-    };
14931-
14932-    template<>
14933-    struct StringMaker<double> {
14934-        static std::string convert(double value);
14935-        CATCH_EXPORT static int precision;
14936-    };
14937-
14938-    template <typename T>
14939-    struct StringMaker<T*> {
14940-        template <typename U>
14941-        static std::string convert(U* p) {
14942-            if (p) {
14943-                return ::Catch::Detail::rawMemoryToString(p);
14944-            } else {
14945-                return "nullptr";
14946-            }
14947-        }
14948-    };
14949-
14950-    template <typename R, typename C>
14951-    struct StringMaker<R C::*> {
14952-        static std::string convert(R C::* p) {
14953-            if (p) {
14954-                return ::Catch::Detail::rawMemoryToString(p);
14955-            } else {
14956-                return "nullptr";
14957-            }
14958-        }
14959-    };
14960-
14961-#if defined(_MANAGED)
14962-    template <typename T>
14963-    struct StringMaker<T^> {
14964-        static std::string convert( T^ ref ) {
14965-            return ::Catch::Detail::clrReferenceToString(ref);
14966-        }
14967-    };
14968-#endif
14969-
14970-    namespace Detail {
14971-        template<typename InputIterator, typename Sentinel = InputIterator>
14972-        std::string rangeToString(InputIterator first, Sentinel last) {
14973-            ReusableStringStream rss;
14974-            rss << "{ ";
14975-            if (first != last) {
14976-                rss << ::Catch::Detail::stringify(*first);
14977-                for (++first; first != last; ++first)
14978-                    rss << ", " << ::Catch::Detail::stringify(*first);
14979-            }
14980-            rss << " }";
14981-            return rss.str();
14982-        }
14983-    }
14984-
14985-} // namespace Catch
14986-
14987-//////////////////////////////////////////////////////
14988-// Separate std-lib types stringification, so it can be selectively enabled
14989-// This means that we do not bring in their headers
14990-
14991-#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
14992-#  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
14993-#  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
14994-#  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
14995-#  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
14996-#endif
14997-
14998-// Separate std::pair specialization
14999-#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
15000-#include <utility>
15001-namespace Catch {
15002-    template<typename T1, typename T2>
15003-    struct StringMaker<std::pair<T1, T2> > {
15004-        static std::string convert(const std::pair<T1, T2>& pair) {
15005-            ReusableStringStream rss;
15006-            rss << "{ "
15007-                << ::Catch::Detail::stringify(pair.first)
15008-                << ", "
15009-                << ::Catch::Detail::stringify(pair.second)
15010-                << " }";
15011-            return rss.str();
15012-        }
15013-    };
15014-}
15015-#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
15016-
15017-#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
15018-#include <optional>
15019-namespace Catch {
15020-    template<typename T>
15021-    struct StringMaker<std::optional<T> > {
15022-        static std::string convert(const std::optional<T>& optional) {
15023-            if (optional.has_value()) {
15024-                return ::Catch::Detail::stringify(*optional);
15025-            } else {
15026-                return "{ }";
15027-            }
15028-        }
15029-    };
15030-    template <>
15031-    struct StringMaker<std::nullopt_t> {
15032-        static std::string convert(const std::nullopt_t&) {
15033-            return "{ }";
15034-        }
15035-    };
15036-}
15037-#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
15038-
15039-// Separate std::tuple specialization
15040-#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
15041-#include <tuple>
15042-namespace Catch {
15043-    namespace Detail {
15044-        template<
15045-            typename Tuple,
15046-            std::size_t N = 0,
15047-            bool = (N < std::tuple_size<Tuple>::value)
15048-            >
15049-            struct TupleElementPrinter {
15050-            static void print(const Tuple& tuple, std::ostream& os) {
15051-                os << (N ? ", " : " ")
15052-                    << ::Catch::Detail::stringify(std::get<N>(tuple));
15053-                TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
15054-            }
15055-        };
15056-
15057-        template<
15058-            typename Tuple,
15059-            std::size_t N
15060-        >
15061-            struct TupleElementPrinter<Tuple, N, false> {
15062-            static void print(const Tuple&, std::ostream&) {}
15063-        };
15064-
15065-    }
15066-
15067-
15068-    template<typename ...Types>
15069-    struct StringMaker<std::tuple<Types...>> {
15070-        static std::string convert(const std::tuple<Types...>& tuple) {
15071-            ReusableStringStream rss;
15072-            rss << '{';
15073-            Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
15074-            rss << " }";
15075-            return rss.str();
15076-        }
15077-    };
15078-}
15079-#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
15080-
15081-#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
15082-#include <variant>
15083-namespace Catch {
15084-    template<>
15085-    struct StringMaker<std::monostate> {
15086-        static std::string convert(const std::monostate&) {
15087-            return "{ }";
15088-        }
15089-    };
15090-
15091-    template<typename... Elements>
15092-    struct StringMaker<std::variant<Elements...>> {
15093-        static std::string convert(const std::variant<Elements...>& variant) {
15094-            if (variant.valueless_by_exception()) {
15095-                return "{valueless variant}";
15096-            } else {
15097-                return std::visit(
15098-                    [](const auto& value) {
15099-                        return ::Catch::Detail::stringify(value);
15100-                    },
15101-                    variant
15102-                );
15103-            }
15104-        }
15105-    };
15106-}
15107-#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
15108-
15109-namespace Catch {
15110-    // Import begin/ end from std here
15111-    using std::begin;
15112-    using std::end;
15113-
15114-    namespace Detail {
15115-        template <typename T, typename = void>
15116-        struct is_range_impl : std::false_type {};
15117-
15118-        template <typename T>
15119-        struct is_range_impl<T, void_t<decltype(begin(std::declval<T>()))>> : std::true_type {};
15120-    } // namespace Detail
15121-
15122-    template <typename T>
15123-    struct is_range : Detail::is_range_impl<T> {};
15124-
15125-#if defined(_MANAGED) // Managed types are never ranges
15126-    template <typename T>
15127-    struct is_range<T^> {
15128-        static const bool value = false;
15129-    };
15130-#endif
15131-
15132-    template<typename Range>
15133-    std::string rangeToString( Range const& range ) {
15134-        return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
15135-    }
15136-
15137-    // Handle vector<bool> specially
15138-    template<typename Allocator>
15139-    std::string rangeToString( std::vector<bool, Allocator> const& v ) {
15140-        ReusableStringStream rss;
15141-        rss << "{ ";
15142-        bool first = true;
15143-        for( bool b : v ) {
15144-            if( first )
15145-                first = false;
15146-            else
15147-                rss << ", ";
15148-            rss << ::Catch::Detail::stringify( b );
15149-        }
15150-        rss << " }";
15151-        return rss.str();
15152-    }
15153-
15154-    template<typename R>
15155-    struct StringMaker<R, std::enable_if_t<is_range<R>::value && !::Catch::Detail::IsStreamInsertable_v<R>>> {
15156-        static std::string convert( R const& range ) {
15157-            return rangeToString( range );
15158-        }
15159-    };
15160-
15161-    template <typename T, size_t SZ>
15162-    struct StringMaker<T[SZ]> {
15163-        static std::string convert(T const(&arr)[SZ]) {
15164-            return rangeToString(arr);
15165-        }
15166-    };
15167-
15168-
15169-} // namespace Catch
15170-
15171-// Separate std::chrono::duration specialization
15172-#include <ctime>
15173-#include <ratio>
15174-#include <chrono>
15175-
15176-
15177-namespace Catch {
15178-
15179-template <class Ratio>
15180-struct ratio_string {
15181-    static std::string symbol() {
15182-        Catch::ReusableStringStream rss;
15183-        rss << '[' << Ratio::num << '/'
15184-            << Ratio::den << ']';
15185-        return rss.str();
15186-    }
15187-};
15188-
15189-template <>
15190-struct ratio_string<std::atto> {
15191-    static char symbol() { return 'a'; }
15192-};
15193-template <>
15194-struct ratio_string<std::femto> {
15195-    static char symbol() { return 'f'; }
15196-};
15197-template <>
15198-struct ratio_string<std::pico> {
15199-    static char symbol() { return 'p'; }
15200-};
15201-template <>
15202-struct ratio_string<std::nano> {
15203-    static char symbol() { return 'n'; }
15204-};
15205-template <>
15206-struct ratio_string<std::micro> {
15207-    static char symbol() { return 'u'; }
15208-};
15209-template <>
15210-struct ratio_string<std::milli> {
15211-    static char symbol() { return 'm'; }
15212-};
15213-
15214-    ////////////
15215-    // std::chrono::duration specializations
15216-    template<typename Value, typename Ratio>
15217-    struct StringMaker<std::chrono::duration<Value, Ratio>> {
15218-        static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
15219-            ReusableStringStream rss;
15220-            rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
15221-            return rss.str();
15222-        }
15223-    };
15224-    template<typename Value>
15225-    struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
15226-        static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
15227-            ReusableStringStream rss;
15228-            rss << duration.count() << " s";
15229-            return rss.str();
15230-        }
15231-    };
15232-    template<typename Value>
15233-    struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
15234-        static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
15235-            ReusableStringStream rss;
15236-            rss << duration.count() << " m";
15237-            return rss.str();
15238-        }
15239-    };
15240-    template<typename Value>
15241-    struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
15242-        static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
15243-            ReusableStringStream rss;
15244-            rss << duration.count() << " h";
15245-            return rss.str();
15246-        }
15247-    };
15248-
15249-    ////////////
15250-    // std::chrono::time_point specialization
15251-    // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
15252-    template<typename Clock, typename Duration>
15253-    struct StringMaker<std::chrono::time_point<Clock, Duration>> {
15254-        static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
15255-            return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
15256-        }
15257-    };
15258-    // std::chrono::time_point<system_clock> specialization
15259-    template<typename Duration>
15260-    struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
15261-        static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
15262-            const auto systemish = std::chrono::time_point_cast<
15263-                std::chrono::system_clock::duration>( time_point );
15264-            const auto as_time_t = std::chrono::system_clock::to_time_t( systemish );
15265-
15266-#ifdef _MSC_VER
15267-            std::tm timeInfo = {};
15268-            const auto err = gmtime_s( &timeInfo, &as_time_t );
15269-            if ( err ) {
15270-                return "gmtime from provided timepoint has failed. This "
15271-                       "happens e.g. with pre-1970 dates using Microsoft libc";
15272-            }
15273-#else
15274-            std::tm* timeInfo = std::gmtime( &as_time_t );
15275-#endif
15276-
15277-            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
15278-            char timeStamp[timeStampSize];
15279-            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
15280-
15281-#ifdef _MSC_VER
15282-            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
15283-#else
15284-            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
15285-#endif
15286-            return std::string(timeStamp, timeStampSize - 1);
15287-        }
15288-    };
15289-}
15290-
15291-
15292-#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
15293-namespace Catch { \
15294-    template<> struct StringMaker<enumName> { \
15295-        static std::string convert( enumName value ) { \
15296-            static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
15297-            return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
15298-        } \
15299-    }; \
15300-}
15301-
15302-#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
15303-
15304-#ifdef _MSC_VER
15305-#pragma warning(pop)
15306-#endif
15307-
15308-#endif // CATCH_TOSTRING_HPP_INCLUDED
15309-
15310-#include <type_traits>
15311-
15312-namespace Catch {
15313-
15314-    class Approx {
15315-    private:
15316-        bool equalityComparisonImpl(double other) const;
15317-        // Sets and validates the new margin (margin >= 0)
15318-        void setMargin(double margin);
15319-        // Sets and validates the new epsilon (0 < epsilon < 1)
15320-        void setEpsilon(double epsilon);
15321-
15322-    public:
15323-        explicit Approx ( double value );
15324-
15325-        static Approx custom();
15326-
15327-        Approx operator-() const;
15328-
15329-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15330-        Approx operator()( T const& value ) const {
15331-            Approx approx( static_cast<double>(value) );
15332-            approx.m_epsilon = m_epsilon;
15333-            approx.m_margin = m_margin;
15334-            approx.m_scale = m_scale;
15335-            return approx;
15336-        }
15337-
15338-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15339-        explicit Approx( T const& value ): Approx(static_cast<double>(value))
15340-        {}
15341-
15342-
15343-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15344-        friend bool operator == ( const T& lhs, Approx const& rhs ) {
15345-            auto lhs_v = static_cast<double>(lhs);
15346-            return rhs.equalityComparisonImpl(lhs_v);
15347-        }
15348-
15349-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15350-        friend bool operator == ( Approx const& lhs, const T& rhs ) {
15351-            return operator==( rhs, lhs );
15352-        }
15353-
15354-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15355-        friend bool operator != ( T const& lhs, Approx const& rhs ) {
15356-            return !operator==( lhs, rhs );
15357-        }
15358-
15359-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15360-        friend bool operator != ( Approx const& lhs, T const& rhs ) {
15361-            return !operator==( rhs, lhs );
15362-        }
15363-
15364-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15365-        friend bool operator <= ( T const& lhs, Approx const& rhs ) {
15366-            return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
15367-        }
15368-
15369-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15370-        friend bool operator <= ( Approx const& lhs, T const& rhs ) {
15371-            return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
15372-        }
15373-
15374-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15375-        friend bool operator >= ( T const& lhs, Approx const& rhs ) {
15376-            return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
15377-        }
15378-
15379-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15380-        friend bool operator >= ( Approx const& lhs, T const& rhs ) {
15381-            return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
15382-        }
15383-
15384-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15385-        Approx& epsilon( T const& newEpsilon ) {
15386-            const auto epsilonAsDouble = static_cast<double>(newEpsilon);
15387-            setEpsilon(epsilonAsDouble);
15388-            return *this;
15389-        }
15390-
15391-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15392-        Approx& margin( T const& newMargin ) {
15393-            const auto marginAsDouble = static_cast<double>(newMargin);
15394-            setMargin(marginAsDouble);
15395-            return *this;
15396-        }
15397-
15398-        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
15399-        Approx& scale( T const& newScale ) {
15400-            m_scale = static_cast<double>(newScale);
15401-            return *this;
15402-        }
15403-
15404-        std::string toString() const;
15405-
15406-    private:
15407-        double m_epsilon;
15408-        double m_margin;
15409-        double m_scale;
15410-        double m_value;
15411-    };
15412-
15413-namespace literals {
15414-    Approx operator ""_a(long double val);
15415-    Approx operator ""_a(unsigned long long val);
15416-} // end namespace literals
15417-
15418-template<>
15419-struct StringMaker<Catch::Approx> {
15420-    static std::string convert(Catch::Approx const& value);
15421-};
15422-
15423-} // end namespace Catch
15424-
15425-#endif // CATCH_APPROX_HPP_INCLUDED
15426-
15427-
15428-#ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED
15429-#define CATCH_ASSERTION_INFO_HPP_INCLUDED
15430-
15431-
15432-
15433-#ifndef CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
15434-#define CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
15435-
15436-#include <cstddef>
15437-#include <iosfwd>
15438-
15439-namespace Catch {
15440-
15441-    struct SourceLineInfo {
15442-
15443-        SourceLineInfo() = delete;
15444-        constexpr SourceLineInfo( char const* _file, std::size_t _line ) noexcept:
15445-            file( _file ),
15446-            line( _line )
15447-        {}
15448-
15449-        bool operator == ( SourceLineInfo const& other ) const noexcept;
15450-        bool operator < ( SourceLineInfo const& other ) const noexcept;
15451-
15452-        char const* file;
15453-        std::size_t line;
15454-
15455-        friend std::ostream& operator << (std::ostream& os, SourceLineInfo const& info);
15456-    };
15457-}
15458-
15459-#define CATCH_INTERNAL_LINEINFO \
15460-    ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
15461-
15462-#endif // CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
15463-
15464-namespace Catch {
15465-
15466-    struct AssertionInfo {
15467-        // AssertionInfo() = delete;
15468-
15469-        StringRef macroName;
15470-        SourceLineInfo lineInfo;
15471-        StringRef capturedExpression;
15472-        ResultDisposition::Flags resultDisposition;
15473-    };
15474-
15475-} // end namespace Catch
15476-
15477-#endif // CATCH_ASSERTION_INFO_HPP_INCLUDED
15478-
15479-
15480-#ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED
15481-#define CATCH_ASSERTION_RESULT_HPP_INCLUDED
15482-
15483-
15484-
15485-#ifndef CATCH_LAZY_EXPR_HPP_INCLUDED
15486-#define CATCH_LAZY_EXPR_HPP_INCLUDED
15487-
15488-#include <iosfwd>
15489-
15490-namespace Catch {
15491-
15492-    class ITransientExpression;
15493-
15494-    class LazyExpression {
15495-        friend class AssertionHandler;
15496-        friend struct AssertionStats;
15497-        friend class RunContext;
15498-
15499-        ITransientExpression const* m_transientExpression = nullptr;
15500-        bool m_isNegated;
15501-    public:
15502-        constexpr LazyExpression( bool isNegated ):
15503-            m_isNegated(isNegated)
15504-        {}
15505-        constexpr LazyExpression(LazyExpression const& other) = default;
15506-        LazyExpression& operator = ( LazyExpression const& ) = delete;
15507-
15508-        constexpr explicit operator bool() const {
15509-            return m_transientExpression != nullptr;
15510-        }
15511-
15512-        friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
15513-    };
15514-
15515-} // namespace Catch
15516-
15517-#endif // CATCH_LAZY_EXPR_HPP_INCLUDED
15518-
15519-#include <string>
15520-
15521-namespace Catch {
15522-
15523-    struct AssertionResultData
15524-    {
15525-        AssertionResultData() = delete;
15526-
15527-        AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
15528-
15529-        std::string message;
15530-        mutable std::string reconstructedExpression;
15531-        LazyExpression lazyExpression;
15532-        ResultWas::OfType resultType;
15533-
15534-        std::string reconstructExpression() const;
15535-    };
15536-
15537-    class AssertionResult {
15538-    public:
15539-        AssertionResult() = delete;
15540-        AssertionResult( AssertionInfo const& info, AssertionResultData&& data );
15541-
15542-        bool isOk() const;
15543-        bool succeeded() const;
15544-        ResultWas::OfType getResultType() const;
15545-        bool hasExpression() const;
15546-        bool hasMessage() const;
15547-        std::string getExpression() const;
15548-        std::string getExpressionInMacro() const;
15549-        bool hasExpandedExpression() const;
15550-        std::string getExpandedExpression() const;
15551-        StringRef getMessage() const;
15552-        SourceLineInfo getSourceInfo() const;
15553-        StringRef getTestMacroName() const;
15554-
15555-    //protected:
15556-        AssertionInfo m_info;
15557-        AssertionResultData m_resultData;
15558-    };
15559-
15560-} // end namespace Catch
15561-
15562-#endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED
15563-
15564-
15565-#ifndef CATCH_CASE_SENSITIVE_HPP_INCLUDED
15566-#define CATCH_CASE_SENSITIVE_HPP_INCLUDED
15567-
15568-namespace Catch {
15569-
15570-    enum class CaseSensitive { Yes, No };
15571-
15572-} // namespace Catch
15573-
15574-#endif // CATCH_CASE_SENSITIVE_HPP_INCLUDED
15575-
15576-
15577-#ifndef CATCH_CONFIG_HPP_INCLUDED
15578-#define CATCH_CONFIG_HPP_INCLUDED
15579-
15580-
15581-
15582-#ifndef CATCH_TEST_SPEC_HPP_INCLUDED
15583-#define CATCH_TEST_SPEC_HPP_INCLUDED
15584-
15585-#ifdef __clang__
15586-#pragma clang diagnostic push
15587-#pragma clang diagnostic ignored "-Wpadded"
15588-#endif
15589-
15590-
15591-
15592-#ifndef CATCH_WILDCARD_PATTERN_HPP_INCLUDED
15593-#define CATCH_WILDCARD_PATTERN_HPP_INCLUDED
15594-
15595-
15596-#include <string>
15597-
15598-namespace Catch
15599-{
15600-    class WildcardPattern {
15601-        enum WildcardPosition {
15602-            NoWildcard = 0,
15603-            WildcardAtStart = 1,
15604-            WildcardAtEnd = 2,
15605-            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
15606-        };
15607-
15608-    public:
15609-
15610-        WildcardPattern( std::string const& pattern, CaseSensitive caseSensitivity );
15611-        bool matches( std::string const& str ) const;
15612-
15613-    private:
15614-        std::string normaliseString( std::string const& str ) const;
15615-        CaseSensitive m_caseSensitivity;
15616-        WildcardPosition m_wildcard = NoWildcard;
15617-        std::string m_pattern;
15618-    };
15619-}
15620-
15621-#endif // CATCH_WILDCARD_PATTERN_HPP_INCLUDED
15622-
15623-#include <iosfwd>
15624-#include <string>
15625-#include <vector>
15626-
15627-namespace Catch {
15628-
15629-    class IConfig;
15630-    struct TestCaseInfo;
15631-    class TestCaseHandle;
15632-
15633-    class TestSpec {
15634-
15635-        class Pattern {
15636-        public:
15637-            explicit Pattern( std::string const& name );
15638-            virtual ~Pattern();
15639-            virtual bool matches( TestCaseInfo const& testCase ) const = 0;
15640-            std::string const& name() const;
15641-        private:
15642-            virtual void serializeTo( std::ostream& out ) const = 0;
15643-            // Writes string that would be reparsed into the pattern
15644-            friend std::ostream& operator<<(std::ostream& out,
15645-                                            Pattern const& pattern) {
15646-                pattern.serializeTo( out );
15647-                return out;
15648-            }
15649-
15650-            std::string const m_name;
15651-        };
15652-
15653-        class NamePattern : public Pattern {
15654-        public:
15655-            explicit NamePattern( std::string const& name, std::string const& filterString );
15656-            bool matches( TestCaseInfo const& testCase ) const override;
15657-        private:
15658-            void serializeTo( std::ostream& out ) const override;
15659-
15660-            WildcardPattern m_wildcardPattern;
15661-        };
15662-
15663-        class TagPattern : public Pattern {
15664-        public:
15665-            explicit TagPattern( std::string const& tag, std::string const& filterString );
15666-            bool matches( TestCaseInfo const& testCase ) const override;
15667-        private:
15668-            void serializeTo( std::ostream& out ) const override;
15669-
15670-            std::string m_tag;
15671-        };
15672-
15673-        struct Filter {
15674-            std::vector<Detail::unique_ptr<Pattern>> m_required;
15675-            std::vector<Detail::unique_ptr<Pattern>> m_forbidden;
15676-
15677-            //! Serializes this filter into a string that would be parsed into
15678-            //! an equivalent filter
15679-            void serializeTo( std::ostream& out ) const;
15680-            friend std::ostream& operator<<(std::ostream& out, Filter const& f) {
15681-                f.serializeTo( out );
15682-                return out;
15683-            }
15684-
15685-            bool matches( TestCaseInfo const& testCase ) const;
15686-        };
15687-
15688-        static std::string extractFilterName( Filter const& filter );
15689-
15690-    public:
15691-        struct FilterMatch {
15692-            std::string name;
15693-            std::vector<TestCaseHandle const*> tests;
15694-        };
15695-        using Matches = std::vector<FilterMatch>;
15696-        using vectorStrings = std::vector<std::string>;
15697-
15698-        bool hasFilters() const;
15699-        bool matches( TestCaseInfo const& testCase ) const;
15700-        Matches matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const;
15701-        const vectorStrings & getInvalidSpecs() const;
15702-
15703-    private:
15704-        std::vector<Filter> m_filters;
15705-        std::vector<std::string> m_invalidSpecs;
15706-
15707-        friend class TestSpecParser;
15708-        //! Serializes this test spec into a string that would be parsed into
15709-        //! equivalent test spec
15710-        void serializeTo( std::ostream& out ) const;
15711-        friend std::ostream& operator<<(std::ostream& out,
15712-                                        TestSpec const& spec) {
15713-            spec.serializeTo( out );
15714-            return out;
15715-        }
15716-    };
15717-}
15718-
15719-#ifdef __clang__
15720-#pragma clang diagnostic pop
15721-#endif
15722-
15723-#endif // CATCH_TEST_SPEC_HPP_INCLUDED
15724-
15725-
15726-#ifndef CATCH_OPTIONAL_HPP_INCLUDED
15727-#define CATCH_OPTIONAL_HPP_INCLUDED
15728-
15729-
15730-#include <cassert>
15731-
15732-namespace Catch {
15733-
15734-    // An optional type
15735-    template<typename T>
15736-    class Optional {
15737-    public:
15738-        Optional(): nullableValue( nullptr ) {}
15739-        ~Optional() { reset(); }
15740-
15741-        Optional( T const& _value ):
15742-            nullableValue( new ( storage ) T( _value ) ) {}
15743-        Optional( T&& _value ):
15744-            nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {}
15745-
15746-        Optional& operator=( T const& _value ) {
15747-            reset();
15748-            nullableValue = new ( storage ) T( _value );
15749-            return *this;
15750-        }
15751-        Optional& operator=( T&& _value ) {
15752-            reset();
15753-            nullableValue = new ( storage ) T( CATCH_MOVE( _value ) );
15754-            return *this;
15755-        }
15756-
15757-        Optional( Optional const& _other ):
15758-            nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {}
15759-        Optional( Optional&& _other ):
15760-            nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) )
15761-                                  : nullptr ) {}
15762-
15763-        Optional& operator=( Optional const& _other ) {
15764-            if ( &_other != this ) {
15765-                reset();
15766-                if ( _other ) { nullableValue = new ( storage ) T( *_other ); }
15767-            }
15768-            return *this;
15769-        }
15770-        Optional& operator=( Optional&& _other ) {
15771-            if ( &_other != this ) {
15772-                reset();
15773-                if ( _other ) {
15774-                    nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) );
15775-                }
15776-            }
15777-            return *this;
15778-        }
15779-
15780-        void reset() {
15781-            if ( nullableValue ) { nullableValue->~T(); }
15782-            nullableValue = nullptr;
15783-        }
15784-
15785-        T& operator*() {
15786-            assert(nullableValue);
15787-            return *nullableValue;
15788-        }
15789-        T const& operator*() const {
15790-            assert(nullableValue);
15791-            return *nullableValue;
15792-        }
15793-        T* operator->() {
15794-            assert(nullableValue);
15795-            return nullableValue;
15796-        }
15797-        const T* operator->() const {
15798-            assert(nullableValue);
15799-            return nullableValue;
15800-        }
15801-
15802-        T valueOr( T const& defaultValue ) const {
15803-            return nullableValue ? *nullableValue : defaultValue;
15804-        }
15805-
15806-        bool some() const { return nullableValue != nullptr; }
15807-        bool none() const { return nullableValue == nullptr; }
15808-
15809-        bool operator !() const { return nullableValue == nullptr; }
15810-        explicit operator bool() const {
15811-            return some();
15812-        }
15813-
15814-        friend bool operator==(Optional const& a, Optional const& b) {
15815-            if (a.none() && b.none()) {
15816-                return true;
15817-            } else if (a.some() && b.some()) {
15818-                return *a == *b;
15819-            } else {
15820-                return false;
15821-            }
15822-        }
15823-        friend bool operator!=(Optional const& a, Optional const& b) {
15824-            return !( a == b );
15825-        }
15826-
15827-    private:
15828-        T* nullableValue;
15829-        alignas(alignof(T)) char storage[sizeof(T)];
15830-    };
15831-
15832-} // end namespace Catch
15833-
15834-#endif // CATCH_OPTIONAL_HPP_INCLUDED
15835-
15836-
15837-#ifndef CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
15838-#define CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
15839-
15840-#include <cstdint>
15841-
15842-namespace Catch {
15843-
15844-    enum class GenerateFrom {
15845-        Time,
15846-        RandomDevice,
15847-        //! Currently equivalent to RandomDevice, but can change at any point
15848-        Default
15849-    };
15850-
15851-    std::uint32_t generateRandomSeed(GenerateFrom from);
15852-
15853-} // end namespace Catch
15854-
15855-#endif // CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
15856-
15857-
15858-#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
15859-#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
15860-
15861-
15862-#include <map>
15863-#include <string>
15864-#include <vector>
15865-
15866-namespace Catch {
15867-
15868-    enum class ColourMode : std::uint8_t;
15869-
15870-    namespace Detail {
15871-        //! Splits the reporter spec into reporter name and kv-pair options
15872-        std::vector<std::string> splitReporterSpec( StringRef reporterSpec );
15873-
15874-        Optional<ColourMode> stringToColourMode( StringRef colourMode );
15875-    }
15876-
15877-    /**
15878-     * Structured reporter spec that a reporter can be created from
15879-     *
15880-     * Parsing has been validated, but semantics have not. This means e.g.
15881-     * that the colour mode is known to Catch2, but it might not be
15882-     * compiled into the binary, and the output filename might not be
15883-     * openable.
15884-     */
15885-    class ReporterSpec {
15886-        std::string m_name;
15887-        Optional<std::string> m_outputFileName;
15888-        Optional<ColourMode> m_colourMode;
15889-        std::map<std::string, std::string> m_customOptions;
15890-
15891-        friend bool operator==( ReporterSpec const& lhs,
15892-                                ReporterSpec const& rhs );
15893-        friend bool operator!=( ReporterSpec const& lhs,
15894-                                ReporterSpec const& rhs ) {
15895-            return !( lhs == rhs );
15896-        }
15897-
15898-    public:
15899-        ReporterSpec(
15900-            std::string name,
15901-            Optional<std::string> outputFileName,
15902-            Optional<ColourMode> colourMode,
15903-            std::map<std::string, std::string> customOptions );
15904-
15905-        std::string const& name() const { return m_name; }
15906-
15907-        Optional<std::string> const& outputFile() const {
15908-            return m_outputFileName;
15909-        }
15910-
15911-        Optional<ColourMode> const& colourMode() const { return m_colourMode; }
15912-
15913-        std::map<std::string, std::string> const& customOptions() const {
15914-            return m_customOptions;
15915-        }
15916-    };
15917-
15918-    /**
15919-     * Parses provided reporter spec string into
15920-     *
15921-     * Returns empty optional on errors, e.g.
15922-     *  * field that is not first and not a key+value pair
15923-     *  * duplicated keys in kv pair
15924-     *  * unknown catch reporter option
15925-     *  * empty key/value in an custom kv pair
15926-     *  * ...
15927-     */
15928-    Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec );
15929-
15930-}
15931-
15932-#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
15933-
15934-#include <chrono>
15935-#include <map>
15936-#include <string>
15937-#include <vector>
15938-
15939-namespace Catch {
15940-
15941-    class IStream;
15942-
15943-    /**
15944-     * `ReporterSpec` but with the defaults filled in.
15945-     *
15946-     * Like `ReporterSpec`, the semantics are unchecked.
15947-     */
15948-    struct ProcessedReporterSpec {
15949-        std::string name;
15950-        std::string outputFilename;
15951-        ColourMode colourMode;
15952-        std::map<std::string, std::string> customOptions;
15953-        friend bool operator==( ProcessedReporterSpec const& lhs,
15954-                                ProcessedReporterSpec const& rhs );
15955-        friend bool operator!=( ProcessedReporterSpec const& lhs,
15956-                                ProcessedReporterSpec const& rhs ) {
15957-            return !( lhs == rhs );
15958-        }
15959-    };
15960-
15961-    struct ConfigData {
15962-
15963-        bool listTests = false;
15964-        bool listTags = false;
15965-        bool listReporters = false;
15966-        bool listListeners = false;
15967-
15968-        bool showSuccessfulTests = false;
15969-        bool shouldDebugBreak = false;
15970-        bool noThrow = false;
15971-        bool showHelp = false;
15972-        bool showInvisibles = false;
15973-        bool filenamesAsTags = false;
15974-        bool libIdentify = false;
15975-        bool allowZeroTests = false;
15976-
15977-        int abortAfter = -1;
15978-        uint32_t rngSeed = generateRandomSeed(GenerateFrom::Default);
15979-
15980-        unsigned int shardCount = 1;
15981-        unsigned int shardIndex = 0;
15982-
15983-        bool skipBenchmarks = false;
15984-        bool benchmarkNoAnalysis = false;
15985-        unsigned int benchmarkSamples = 100;
15986-        double benchmarkConfidenceInterval = 0.95;
15987-        unsigned int benchmarkResamples = 100'000;
15988-        std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
15989-
15990-        Verbosity verbosity = Verbosity::Normal;
15991-        WarnAbout::What warnings = WarnAbout::Nothing;
15992-        ShowDurations showDurations = ShowDurations::DefaultForReporter;
15993-        double minDuration = -1;
15994-        TestRunOrder runOrder = TestRunOrder::Randomized;
15995-        ColourMode defaultColourMode = ColourMode::PlatformDefault;
15996-        WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
15997-
15998-        std::string defaultOutputFilename;
15999-        std::string name;
16000-        std::string processName;
16001-        std::vector<ReporterSpec> reporterSpecifications;
16002-
16003-        std::vector<std::string> testsOrTags;
16004-        std::vector<std::string> sectionsToRun;
16005-
16006-        std::string prematureExitGuardFilePath;
16007-    };
16008-
16009-
16010-    class Config : public IConfig {
16011-    public:
16012-
16013-        Config() = default;
16014-        Config( ConfigData const& data );
16015-        ~Config() override; // = default in the cpp file
16016-
16017-        bool listTests() const;
16018-        bool listTags() const;
16019-        bool listReporters() const;
16020-        bool listListeners() const;
16021-
16022-        std::vector<ReporterSpec> const& getReporterSpecs() const;
16023-        std::vector<ProcessedReporterSpec> const&
16024-        getProcessedReporterSpecs() const;
16025-
16026-        std::vector<std::string> const& getTestsOrTags() const override;
16027-        std::vector<std::string> const& getSectionsToRun() const override;
16028-
16029-        TestSpec const& testSpec() const override;
16030-        bool hasTestFilters() const override;
16031-
16032-        bool showHelp() const;
16033-
16034-        std::string const& getExitGuardFilePath() const;
16035-
16036-        // IConfig interface
16037-        bool allowThrows() const override;
16038-        StringRef name() const override;
16039-        bool includeSuccessfulResults() const override;
16040-        bool warnAboutMissingAssertions() const override;
16041-        bool warnAboutUnmatchedTestSpecs() const override;
16042-        bool zeroTestsCountAsSuccess() const override;
16043-        ShowDurations showDurations() const override;
16044-        double minDuration() const override;
16045-        TestRunOrder runOrder() const override;
16046-        uint32_t rngSeed() const override;
16047-        unsigned int shardCount() const override;
16048-        unsigned int shardIndex() const override;
16049-        ColourMode defaultColourMode() const override;
16050-        bool shouldDebugBreak() const override;
16051-        int abortAfter() const override;
16052-        bool showInvisibles() const override;
16053-        Verbosity verbosity() const override;
16054-        bool skipBenchmarks() const override;
16055-        bool benchmarkNoAnalysis() const override;
16056-        unsigned int benchmarkSamples() const override;
16057-        double benchmarkConfidenceInterval() const override;
16058-        unsigned int benchmarkResamples() const override;
16059-        std::chrono::milliseconds benchmarkWarmupTime() const override;
16060-
16061-    private:
16062-        // Reads Bazel env vars and applies them to the config
16063-        void readBazelEnvVars();
16064-
16065-        ConfigData m_data;
16066-        std::vector<ProcessedReporterSpec> m_processedReporterSpecs;
16067-        TestSpec m_testSpec;
16068-        bool m_hasTestFilters = false;
16069-    };
16070-} // end namespace Catch
16071-
16072-#endif // CATCH_CONFIG_HPP_INCLUDED
16073-
16074-
16075-#ifndef CATCH_GET_RANDOM_SEED_HPP_INCLUDED
16076-#define CATCH_GET_RANDOM_SEED_HPP_INCLUDED
16077-
16078-#include <cstdint>
16079-
16080-namespace Catch {
16081-    //! Returns Catch2's current RNG seed.
16082-    std::uint32_t getSeed();
16083-}
16084-
16085-#endif // CATCH_GET_RANDOM_SEED_HPP_INCLUDED
16086-
16087-
16088-#ifndef CATCH_MESSAGE_HPP_INCLUDED
16089-#define CATCH_MESSAGE_HPP_INCLUDED
16090-
16091-
16092-
16093-
16094-/** \file
16095- * Wrapper for the CATCH_CONFIG_PREFIX_MESSAGES configuration option
16096- *
16097- * CATCH_CONFIG_PREFIX_ALL can be used to avoid clashes with other macros
16098- * by prepending CATCH_. This may not be desirable if the only clashes are with
16099- * logger macros such as INFO and WARN. In this cases
16100- * CATCH_CONFIG_PREFIX_MESSAGES can be used to only prefix a small subset
16101- * of relevant macros.
16102- *
16103- */
16104-
16105-#ifndef CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
16106-#define CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
16107-
16108-
16109-#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_PREFIX_MESSAGES)
16110-    #define CATCH_CONFIG_PREFIX_MESSAGES
16111-#endif
16112-
16113-#endif // CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
16114-
16115-
16116-#ifndef CATCH_STREAM_END_STOP_HPP_INCLUDED
16117-#define CATCH_STREAM_END_STOP_HPP_INCLUDED
16118-
16119-
16120-namespace Catch {
16121-
16122-    // Use this in variadic streaming macros to allow
16123-    //    << +StreamEndStop
16124-    // as well as
16125-    //    << stuff +StreamEndStop
16126-    struct StreamEndStop {
16127-        constexpr StringRef operator+() const { return StringRef(); }
16128-
16129-        template <typename T>
16130-        constexpr friend T const& operator+( T const& value, StreamEndStop ) {
16131-            return value;
16132-        }
16133-    };
16134-
16135-} // namespace Catch
16136-
16137-#endif // CATCH_STREAM_END_STOP_HPP_INCLUDED
16138-
16139-
16140-#ifndef CATCH_MESSAGE_INFO_HPP_INCLUDED
16141-#define CATCH_MESSAGE_INFO_HPP_INCLUDED
16142-
16143-
16144-
16145-#ifndef CATCH_DEPRECATION_MACRO_HPP_INCLUDED
16146-#define CATCH_DEPRECATION_MACRO_HPP_INCLUDED
16147-
16148-
16149-#if !defined( CATCH_CONFIG_NO_DEPRECATION_ANNOTATIONS )
16150-#    define DEPRECATED( msg ) [[deprecated( msg )]]
16151-#else
16152-#    define DEPRECATED( msg )
16153-#endif
16154-
16155-#endif // CATCH_DEPRECATION_MACRO_HPP_INCLUDED
16156-
16157-#include <string>
16158-
16159-namespace Catch {
16160-
16161-    struct MessageInfo {
16162-        MessageInfo(    StringRef _macroName,
16163-                        SourceLineInfo const& _lineInfo,
16164-                        ResultWas::OfType _type );
16165-
16166-        StringRef macroName;
16167-        std::string message;
16168-        SourceLineInfo lineInfo;
16169-        ResultWas::OfType type;
16170-        // The "ID" of the message, used to know when to remove it from reporter context.
16171-        unsigned int sequence;
16172-
16173-        DEPRECATED( "Explicitly use the 'sequence' member instead" )
16174-        bool operator == (MessageInfo const& other) const {
16175-            return sequence == other.sequence;
16176-        }
16177-        DEPRECATED( "Explicitly use the 'sequence' member instead" )
16178-        bool operator < (MessageInfo const& other) const {
16179-            return sequence < other.sequence;
16180-        }
16181-    private:
16182-        static thread_local unsigned int globalCount;
16183-    };
16184-
16185-} // end namespace Catch
16186-
16187-#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED
16188-
16189-#include <string>
16190-#include <vector>
16191-
16192-namespace Catch {
16193-
16194-    struct SourceLineInfo;
16195-    class IResultCapture;
16196-
16197-    struct MessageStream {
16198-
16199-        template<typename T>
16200-        MessageStream& operator << ( T const& value ) {
16201-            m_stream << value;
16202-            return *this;
16203-        }
16204-
16205-        ReusableStringStream m_stream;
16206-    };
16207-
16208-    struct MessageBuilder : MessageStream {
16209-        MessageBuilder( StringRef macroName,
16210-                        SourceLineInfo const& lineInfo,
16211-                        ResultWas::OfType type ):
16212-            m_info(macroName, lineInfo, type) {}
16213-
16214-        template<typename T>
16215-        MessageBuilder&& operator << ( T const& value ) && {
16216-            m_stream << value;
16217-            return CATCH_MOVE(*this);
16218-        }
16219-
16220-        MessageInfo m_info;
16221-    };
16222-
16223-    class ScopedMessage {
16224-    public:
16225-        explicit ScopedMessage( MessageBuilder&& builder );
16226-        ScopedMessage( ScopedMessage& duplicate ) = delete;
16227-        ScopedMessage( ScopedMessage&& old ) noexcept;
16228-        ~ScopedMessage();
16229-
16230-        unsigned int m_messageId;
16231-        bool m_moved = false;
16232-    };
16233-
16234-    class Capturer {
16235-        std::vector<MessageInfo> m_messages;
16236-        size_t m_captured = 0;
16237-    public:
16238-        Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
16239-
16240-        Capturer(Capturer const&) = delete;
16241-        Capturer& operator=(Capturer const&) = delete;
16242-
16243-        ~Capturer();
16244-
16245-        void captureValue( size_t index, std::string const& value );
16246-
16247-        template<typename T>
16248-        void captureValues( size_t index, T const& value ) {
16249-            captureValue( index, Catch::Detail::stringify( value ) );
16250-        }
16251-
16252-        template<typename T, typename... Ts>
16253-        void captureValues( size_t index, T const& value, Ts const&... values ) {
16254-            captureValue( index, Catch::Detail::stringify(value) );
16255-            captureValues( index+1, values... );
16256-        }
16257-    };
16258-
16259-} // end namespace Catch
16260-
16261-///////////////////////////////////////////////////////////////////////////////
16262-#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
16263-    do { \
16264-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
16265-        catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
16266-        catchAssertionHandler.complete(); \
16267-    } while( false )
16268-
16269-///////////////////////////////////////////////////////////////////////////////
16270-#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
16271-    Catch::Capturer varName( macroName##_catch_sr,        \
16272-                             CATCH_INTERNAL_LINEINFO,     \
16273-                             Catch::ResultWas::Info,      \
16274-                             #__VA_ARGS__##_catch_sr );   \
16275-    varName.captureValues( 0, __VA_ARGS__ )
16276-
16277-///////////////////////////////////////////////////////////////////////////////
16278-#define INTERNAL_CATCH_INFO( macroName, log ) \
16279-    const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
16280-
16281-///////////////////////////////////////////////////////////////////////////////
16282-#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
16283-    Catch::IResultCapture::emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
16284-
16285-
16286-#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
16287-
16288-  #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
16289-  #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
16290-  #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
16291-  #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ )
16292-
16293-#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
16294-
16295-  #define CATCH_INFO( msg )          (void)(0)
16296-  #define CATCH_UNSCOPED_INFO( msg ) (void)(0)
16297-  #define CATCH_WARN( msg )          (void)(0)
16298-  #define CATCH_CAPTURE( ... )       (void)(0)
16299-
16300-#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
16301-
16302-  #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
16303-  #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
16304-  #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
16305-  #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ )
16306-
16307-#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
16308-
16309-  #define INFO( msg )          (void)(0)
16310-  #define UNSCOPED_INFO( msg ) (void)(0)
16311-  #define WARN( msg )          (void)(0)
16312-  #define CAPTURE( ... )       (void)(0)
16313-
16314-#endif // end of user facing macro declarations
16315-
16316-
16317-
16318-
16319-#endif // CATCH_MESSAGE_HPP_INCLUDED
16320-
16321-
16322-#ifndef CATCH_SECTION_INFO_HPP_INCLUDED
16323-#define CATCH_SECTION_INFO_HPP_INCLUDED
16324-
16325-
16326-
16327-#ifndef CATCH_TOTALS_HPP_INCLUDED
16328-#define CATCH_TOTALS_HPP_INCLUDED
16329-
16330-#include <cstdint>
16331-
16332-namespace Catch {
16333-
16334-    struct Counts {
16335-        Counts operator - ( Counts const& other ) const;
16336-        Counts& operator += ( Counts const& other );
16337-
16338-        std::uint64_t total() const;
16339-        bool allPassed() const;
16340-        bool allOk() const;
16341-
16342-        std::uint64_t passed = 0;
16343-        std::uint64_t failed = 0;
16344-        std::uint64_t failedButOk = 0;
16345-        std::uint64_t skipped = 0;
16346-    };
16347-
16348-    struct Totals {
16349-
16350-        Totals operator - ( Totals const& other ) const;
16351-        Totals& operator += ( Totals const& other );
16352-
16353-        Totals delta( Totals const& prevTotals ) const;
16354-
16355-        Counts assertions;
16356-        Counts testCases;
16357-    };
16358-}
16359-
16360-#endif // CATCH_TOTALS_HPP_INCLUDED
16361-
16362-#include <string>
16363-
16364-namespace Catch {
16365-
16366-    struct SectionInfo {
16367-        // The last argument is ignored, so that people can write
16368-        // SECTION("ShortName", "Proper description that is long") and
16369-        // still use the `-c` flag comfortably.
16370-        SectionInfo( SourceLineInfo const& _lineInfo, std::string _name,
16371-                    const char* const = nullptr ):
16372-            name(CATCH_MOVE(_name)),
16373-            lineInfo(_lineInfo)
16374-            {}
16375-
16376-        std::string name;
16377-        SourceLineInfo lineInfo;
16378-    };
16379-
16380-    struct SectionEndInfo {
16381-        SectionInfo sectionInfo;
16382-        Counts prevAssertions;
16383-        double durationInSeconds;
16384-    };
16385-
16386-} // end namespace Catch
16387-
16388-#endif // CATCH_SECTION_INFO_HPP_INCLUDED
16389-
16390-
16391-#ifndef CATCH_SESSION_HPP_INCLUDED
16392-#define CATCH_SESSION_HPP_INCLUDED
16393-
16394-
16395-
16396-#ifndef CATCH_COMMANDLINE_HPP_INCLUDED
16397-#define CATCH_COMMANDLINE_HPP_INCLUDED
16398-
16399-
16400-
16401-#ifndef CATCH_CLARA_HPP_INCLUDED
16402-#define CATCH_CLARA_HPP_INCLUDED
16403-
16404-#if defined( __clang__ )
16405-#    pragma clang diagnostic push
16406-#    pragma clang diagnostic ignored "-Wweak-vtables"
16407-#    pragma clang diagnostic ignored "-Wshadow"
16408-#    pragma clang diagnostic ignored "-Wdeprecated"
16409-#endif
16410-
16411-#if defined( __GNUC__ )
16412-#    pragma GCC diagnostic push
16413-#    pragma GCC diagnostic ignored "-Wsign-conversion"
16414-#endif
16415-
16416-#ifndef CLARA_CONFIG_OPTIONAL_TYPE
16417-#    ifdef __has_include
16418-#        if __has_include( <optional>) && __cplusplus >= 201703L
16419-#            include <optional>
16420-#            define CLARA_CONFIG_OPTIONAL_TYPE std::optional
16421-#        endif
16422-#    endif
16423-#endif
16424-
16425-
16426-#include <cassert>
16427-#include <memory>
16428-#include <ostream>
16429-#include <sstream>
16430-#include <string>
16431-#include <type_traits>
16432-#include <vector>
16433-
16434-namespace Catch {
16435-    namespace Clara {
16436-
16437-        class Args;
16438-        class Parser;
16439-
16440-        // enum of result types from a parse
16441-        enum class ParseResultType {
16442-            Matched,
16443-            NoMatch,
16444-            ShortCircuitAll,
16445-            ShortCircuitSame
16446-        };
16447-
16448-        struct accept_many_t {};
16449-        constexpr accept_many_t accept_many {};
16450-
16451-        namespace Detail {
16452-            struct fake_arg {
16453-                template <typename T>
16454-                operator T();
16455-            };
16456-
16457-            template <typename F, typename = void>
16458-            static constexpr bool is_unary_function_v = false;
16459-
16460-            template <typename F>
16461-            static constexpr bool is_unary_function_v<
16462-                F,
16463-                Catch::Detail::void_t<decltype( std::declval<F>()(
16464-                    fake_arg() ) )>> = true;
16465-
16466-            // Traits for extracting arg and return type of lambdas (for single
16467-            // argument lambdas)
16468-            template <typename L>
16469-            struct UnaryLambdaTraits
16470-                : UnaryLambdaTraits<decltype( &L::operator() )> {};
16471-
16472-            template <typename ClassT, typename ReturnT, typename... Args>
16473-            struct UnaryLambdaTraits<ReturnT ( ClassT::* )( Args... ) const> {
16474-                static const bool isValid = false;
16475-            };
16476-
16477-            template <typename ClassT, typename ReturnT, typename ArgT>
16478-            struct UnaryLambdaTraits<ReturnT ( ClassT::* )( ArgT ) const> {
16479-                static const bool isValid = true;
16480-                using ArgType = std::remove_const_t<std::remove_reference_t<ArgT>>;
16481-                using ReturnType = ReturnT;
16482-            };
16483-
16484-            class TokenStream;
16485-
16486-            // Wraps a token coming from a token stream. These may not directly
16487-            // correspond to strings as a single string may encode an option +
16488-            // its argument if the : or = form is used
16489-            enum class TokenType { Option, Argument };
16490-            struct Token {
16491-                TokenType type;
16492-                StringRef token;
16493-            };
16494-
16495-            // Abstracts iterators into args as a stream of tokens, with option
16496-            // arguments uniformly handled
16497-            class TokenStream {
16498-                using Iterator = std::vector<StringRef>::const_iterator;
16499-                Iterator it;
16500-                Iterator itEnd;
16501-                std::vector<Token> m_tokenBuffer;
16502-                void loadBuffer();
16503-
16504-            public:
16505-                explicit TokenStream( Args const& args );
16506-                TokenStream( Iterator it, Iterator itEnd );
16507-
16508-                explicit operator bool() const {
16509-                    return !m_tokenBuffer.empty() || it != itEnd;
16510-                }
16511-
16512-                size_t count() const {
16513-                    return m_tokenBuffer.size() + ( itEnd - it );
16514-                }
16515-
16516-                Token operator*() const {
16517-                    assert( !m_tokenBuffer.empty() );
16518-                    return m_tokenBuffer.front();
16519-                }
16520-
16521-                Token const* operator->() const {
16522-                    assert( !m_tokenBuffer.empty() );
16523-                    return &m_tokenBuffer.front();
16524-                }
16525-
16526-                TokenStream& operator++();
16527-            };
16528-
16529-            //! Denotes type of a parsing result
16530-            enum class ResultType {
16531-                Ok,          ///< No errors
16532-                LogicError,  ///< Error in user-specified arguments for
16533-                             ///< construction
16534-                RuntimeError ///< Error in parsing inputs
16535-            };
16536-
16537-            class ResultBase {
16538-            protected:
16539-                ResultBase( ResultType type ): m_type( type ) {}
16540-                virtual ~ResultBase(); // = default;
16541-
16542-
16543-                ResultBase(ResultBase const&) = default;
16544-                ResultBase& operator=(ResultBase const&) = default;
16545-                ResultBase(ResultBase&&) = default;
16546-                ResultBase& operator=(ResultBase&&) = default;
16547-
16548-                virtual void enforceOk() const = 0;
16549-
16550-                ResultType m_type;
16551-            };
16552-
16553-            template <typename T>
16554-            class ResultValueBase : public ResultBase {
16555-            public:
16556-                T const& value() const& {
16557-                    enforceOk();
16558-                    return m_value;
16559-                }
16560-                T&& value() && {
16561-                    enforceOk();
16562-                    return CATCH_MOVE( m_value );
16563-                }
16564-
16565-            protected:
16566-                ResultValueBase( ResultType type ): ResultBase( type ) {}
16567-
16568-                ResultValueBase( ResultValueBase const& other ):
16569-                    ResultBase( other ) {
16570-                    if ( m_type == ResultType::Ok )
16571-                        new ( &m_value ) T( other.m_value );
16572-                }
16573-                ResultValueBase( ResultValueBase&& other ):
16574-                    ResultBase( other ) {
16575-                    if ( m_type == ResultType::Ok )
16576-                        new ( &m_value ) T( CATCH_MOVE(other.m_value) );
16577-                }
16578-
16579-
16580-                ResultValueBase( ResultType, T const& value ):
16581-                    ResultBase( ResultType::Ok ) {
16582-                    new ( &m_value ) T( value );
16583-                }
16584-                ResultValueBase( ResultType, T&& value ):
16585-                    ResultBase( ResultType::Ok ) {
16586-                    new ( &m_value ) T( CATCH_MOVE(value) );
16587-                }
16588-
16589-                ResultValueBase& operator=( ResultValueBase const& other ) {
16590-                    if ( m_type == ResultType::Ok )
16591-                        m_value.~T();
16592-                    ResultBase::operator=( other );
16593-                    if ( m_type == ResultType::Ok )
16594-                        new ( &m_value ) T( other.m_value );
16595-                    return *this;
16596-                }
16597-                ResultValueBase& operator=( ResultValueBase&& other ) {
16598-                    if ( m_type == ResultType::Ok ) m_value.~T();
16599-                    ResultBase::operator=( other );
16600-                    if ( m_type == ResultType::Ok )
16601-                        new ( &m_value ) T( CATCH_MOVE(other.m_value) );
16602-                    return *this;
16603-                }
16604-
16605-
16606-                ~ResultValueBase() override {
16607-                    if ( m_type == ResultType::Ok )
16608-                        m_value.~T();
16609-                }
16610-
16611-                union {
16612-                    T m_value;
16613-                };
16614-            };
16615-
16616-            template <> class ResultValueBase<void> : public ResultBase {
16617-            protected:
16618-                using ResultBase::ResultBase;
16619-            };
16620-
16621-            template <typename T = void>
16622-            class BasicResult : public ResultValueBase<T> {
16623-            public:
16624-                template <typename U>
16625-                explicit BasicResult( BasicResult<U> const& other ):
16626-                    ResultValueBase<T>( other.type() ),
16627-                    m_errorMessage( other.errorMessage() ) {
16628-                    assert( type() != ResultType::Ok );
16629-                }
16630-
16631-                template <typename U>
16632-                static auto ok( U&& value ) -> BasicResult {
16633-                    return { ResultType::Ok, CATCH_FORWARD(value) };
16634-                }
16635-                static auto ok() -> BasicResult { return { ResultType::Ok }; }
16636-                static auto logicError( std::string&& message )
16637-                    -> BasicResult {
16638-                    return { ResultType::LogicError, CATCH_MOVE(message) };
16639-                }
16640-                static auto runtimeError( std::string&& message )
16641-                    -> BasicResult {
16642-                    return { ResultType::RuntimeError, CATCH_MOVE(message) };
16643-                }
16644-
16645-                explicit operator bool() const {
16646-                    return m_type == ResultType::Ok;
16647-                }
16648-                auto type() const -> ResultType { return m_type; }
16649-                auto errorMessage() const -> std::string const& {
16650-                    return m_errorMessage;
16651-                }
16652-
16653-            protected:
16654-                void enforceOk() const override {
16655-
16656-                    // Errors shouldn't reach this point, but if they do
16657-                    // the actual error message will be in m_errorMessage
16658-                    assert( m_type != ResultType::LogicError );
16659-                    assert( m_type != ResultType::RuntimeError );
16660-                    if ( m_type != ResultType::Ok )
16661-                        std::abort();
16662-                }
16663-
16664-                std::string
16665-                    m_errorMessage; // Only populated if resultType is an error
16666-
16667-                BasicResult( ResultType type,
16668-                             std::string&& message ):
16669-                    ResultValueBase<T>( type ), m_errorMessage( CATCH_MOVE(message) ) {
16670-                    assert( m_type != ResultType::Ok );
16671-                }
16672-
16673-                using ResultValueBase<T>::ResultValueBase;
16674-                using ResultBase::m_type;
16675-            };
16676-
16677-            class ParseState {
16678-            public:
16679-                ParseState( ParseResultType type,
16680-                            TokenStream remainingTokens );
16681-
16682-                ParseResultType type() const { return m_type; }
16683-                TokenStream const& remainingTokens() const& {
16684-                    return m_remainingTokens;
16685-                }
16686-                TokenStream&& remainingTokens() && {
16687-                    return CATCH_MOVE( m_remainingTokens );
16688-                }
16689-
16690-            private:
16691-                ParseResultType m_type;
16692-                TokenStream m_remainingTokens;
16693-            };
16694-
16695-            using Result = BasicResult<void>;
16696-            using ParserResult = BasicResult<ParseResultType>;
16697-            using InternalParseResult = BasicResult<ParseState>;
16698-
16699-            struct HelpColumns {
16700-                std::string left;
16701-                StringRef descriptions;
16702-            };
16703-
16704-            template <typename T>
16705-            ParserResult convertInto( std::string const& source, T& target ) {
16706-                std::stringstream ss( source );
16707-                ss >> target;
16708-                if ( ss.fail() ) {
16709-                    return ParserResult::runtimeError(
16710-                        "Unable to convert '" + source +
16711-                        "' to destination type" );
16712-                } else {
16713-                    return ParserResult::ok( ParseResultType::Matched );
16714-                }
16715-            }
16716-            ParserResult convertInto( std::string const& source,
16717-                                      std::string& target );
16718-            ParserResult convertInto( std::string const& source, bool& target );
16719-
16720-#ifdef CLARA_CONFIG_OPTIONAL_TYPE
16721-            template <typename T>
16722-            auto convertInto( std::string const& source,
16723-                              CLARA_CONFIG_OPTIONAL_TYPE<T>& target )
16724-                -> ParserResult {
16725-                T temp;
16726-                auto result = convertInto( source, temp );
16727-                if ( result )
16728-                    target = CATCH_MOVE( temp );
16729-                return result;
16730-            }
16731-#endif // CLARA_CONFIG_OPTIONAL_TYPE
16732-
16733-            struct BoundRef : Catch::Detail::NonCopyable {
16734-                virtual ~BoundRef() = default;
16735-                virtual bool isContainer() const;
16736-                virtual bool isFlag() const;
16737-            };
16738-            struct BoundValueRefBase : BoundRef {
16739-                virtual auto setValue( std::string const& arg )
16740-                    -> ParserResult = 0;
16741-            };
16742-            struct BoundFlagRefBase : BoundRef {
16743-                virtual auto setFlag( bool flag ) -> ParserResult = 0;
16744-                bool isFlag() const override;
16745-            };
16746-
16747-            template <typename T> struct BoundValueRef : BoundValueRefBase {
16748-                T& m_ref;
16749-
16750-                explicit BoundValueRef( T& ref ): m_ref( ref ) {}
16751-
16752-                ParserResult setValue( std::string const& arg ) override {
16753-                    return convertInto( arg, m_ref );
16754-                }
16755-            };
16756-
16757-            template <typename T>
16758-            struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
16759-                std::vector<T>& m_ref;
16760-
16761-                explicit BoundValueRef( std::vector<T>& ref ): m_ref( ref ) {}
16762-
16763-                auto isContainer() const -> bool override { return true; }
16764-
16765-                auto setValue( std::string const& arg )
16766-                    -> ParserResult override {
16767-                    T temp;
16768-                    auto result = convertInto( arg, temp );
16769-                    if ( result )
16770-                        m_ref.push_back( temp );
16771-                    return result;
16772-                }
16773-            };
16774-
16775-            struct BoundFlagRef : BoundFlagRefBase {
16776-                bool& m_ref;
16777-
16778-                explicit BoundFlagRef( bool& ref ): m_ref( ref ) {}
16779-
16780-                ParserResult setFlag( bool flag ) override;
16781-            };
16782-
16783-            template <typename ReturnType> struct LambdaInvoker {
16784-                static_assert(
16785-                    std::is_same<ReturnType, ParserResult>::value,
16786-                    "Lambda must return void or clara::ParserResult" );
16787-
16788-                template <typename L, typename ArgType>
16789-                static auto invoke( L const& lambda, ArgType const& arg )
16790-                    -> ParserResult {
16791-                    return lambda( arg );
16792-                }
16793-            };
16794-
16795-            template <> struct LambdaInvoker<void> {
16796-                template <typename L, typename ArgType>
16797-                static auto invoke( L const& lambda, ArgType const& arg )
16798-                    -> ParserResult {
16799-                    lambda( arg );
16800-                    return ParserResult::ok( ParseResultType::Matched );
16801-                }
16802-            };
16803-
16804-            template <typename ArgType, typename L>
16805-            auto invokeLambda( L const& lambda, std::string const& arg )
16806-                -> ParserResult {
16807-                ArgType temp{};
16808-                auto result = convertInto( arg, temp );
16809-                return !result ? result
16810-                               : LambdaInvoker<typename UnaryLambdaTraits<
16811-                                     L>::ReturnType>::invoke( lambda, temp );
16812-            }
16813-
16814-            template <typename L> struct BoundLambda : BoundValueRefBase {
16815-                L m_lambda;
16816-
16817-                static_assert(
16818-                    UnaryLambdaTraits<L>::isValid,
16819-                    "Supplied lambda must take exactly one argument" );
16820-                explicit BoundLambda( L const& lambda ): m_lambda( lambda ) {}
16821-
16822-                auto setValue( std::string const& arg )
16823-                    -> ParserResult override {
16824-                    return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(
16825-                        m_lambda, arg );
16826-                }
16827-            };
16828-
16829-            template <typename L> struct BoundManyLambda : BoundLambda<L> {
16830-                explicit BoundManyLambda( L const& lambda ): BoundLambda<L>( lambda ) {}
16831-                bool isContainer() const override { return true; }
16832-            };
16833-
16834-            template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
16835-                L m_lambda;
16836-
16837-                static_assert(
16838-                    UnaryLambdaTraits<L>::isValid,
16839-                    "Supplied lambda must take exactly one argument" );
16840-                static_assert(
16841-                    std::is_same<typename UnaryLambdaTraits<L>::ArgType,
16842-                                 bool>::value,
16843-                    "flags must be boolean" );
16844-
16845-                explicit BoundFlagLambda( L const& lambda ):
16846-                    m_lambda( lambda ) {}
16847-
16848-                auto setFlag( bool flag ) -> ParserResult override {
16849-                    return LambdaInvoker<typename UnaryLambdaTraits<
16850-                        L>::ReturnType>::invoke( m_lambda, flag );
16851-                }
16852-            };
16853-
16854-            enum class Optionality { Optional, Required };
16855-
16856-            class ParserBase {
16857-            public:
16858-                virtual ~ParserBase() = default;
16859-                virtual auto validate() const -> Result { return Result::ok(); }
16860-                virtual auto parse( std::string const& exeName,
16861-                                    TokenStream tokens ) const
16862-                    -> InternalParseResult = 0;
16863-                virtual size_t cardinality() const;
16864-
16865-                InternalParseResult parse( Args const& args ) const;
16866-            };
16867-
16868-            template <typename DerivedT>
16869-            class ComposableParserImpl : public ParserBase {
16870-            public:
16871-                template <typename T>
16872-                auto operator|( T const& other ) const -> Parser;
16873-            };
16874-
16875-            // Common code and state for Args and Opts
16876-            template <typename DerivedT>
16877-            class ParserRefImpl : public ComposableParserImpl<DerivedT> {
16878-            protected:
16879-                Optionality m_optionality = Optionality::Optional;
16880-                std::shared_ptr<BoundRef> m_ref;
16881-                StringRef m_hint;
16882-                StringRef m_description;
16883-
16884-                explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ):
16885-                    m_ref( ref ) {}
16886-
16887-            public:
16888-                template <typename LambdaT>
16889-                ParserRefImpl( accept_many_t,
16890-                               LambdaT const& ref,
16891-                               StringRef hint ):
16892-                    m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ),
16893-                    m_hint( hint ) {}
16894-
16895-                template <typename T,
16896-                          typename = typename std::enable_if_t<
16897-                              !Detail::is_unary_function_v<T>>>
16898-                ParserRefImpl( T& ref, StringRef hint ):
16899-                    m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
16900-                    m_hint( hint ) {}
16901-
16902-                template <typename LambdaT,
16903-                          typename = typename std::enable_if_t<
16904-                              Detail::is_unary_function_v<LambdaT>>>
16905-                ParserRefImpl( LambdaT const& ref, StringRef hint ):
16906-                    m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
16907-                    m_hint( hint ) {}
16908-
16909-                DerivedT& operator()( StringRef description ) & {
16910-                    m_description = description;
16911-                    return static_cast<DerivedT&>( *this );
16912-                }
16913-                DerivedT&& operator()( StringRef description ) && {
16914-                    m_description = description;
16915-                    return static_cast<DerivedT&&>( *this );
16916-                }
16917-
16918-                auto optional() -> DerivedT& {
16919-                    m_optionality = Optionality::Optional;
16920-                    return static_cast<DerivedT&>( *this );
16921-                }
16922-
16923-                auto required() -> DerivedT& {
16924-                    m_optionality = Optionality::Required;
16925-                    return static_cast<DerivedT&>( *this );
16926-                }
16927-
16928-                auto isOptional() const -> bool {
16929-                    return m_optionality == Optionality::Optional;
16930-                }
16931-
16932-                auto cardinality() const -> size_t override {
16933-                    if ( m_ref->isContainer() )
16934-                        return 0;
16935-                    else
16936-                        return 1;
16937-                }
16938-
16939-                StringRef hint() const { return m_hint; }
16940-            };
16941-
16942-        } // namespace detail
16943-
16944-
16945-        // A parser for arguments
16946-        class Arg : public Detail::ParserRefImpl<Arg> {
16947-        public:
16948-            using ParserRefImpl::ParserRefImpl;
16949-            using ParserBase::parse;
16950-
16951-            Detail::InternalParseResult
16952-                parse(std::string const&,
16953-                      Detail::TokenStream tokens) const override;
16954-        };
16955-
16956-        // A parser for options
16957-        class Opt : public Detail::ParserRefImpl<Opt> {
16958-        protected:
16959-            std::vector<StringRef> m_optNames;
16960-
16961-        public:
16962-            template <typename LambdaT>
16963-            explicit Opt(LambdaT const& ref) :
16964-                ParserRefImpl(
16965-                    std::make_shared<Detail::BoundFlagLambda<LambdaT>>(ref)) {}
16966-
16967-            explicit Opt(bool& ref);
16968-
16969-            template <typename LambdaT,
16970-                      typename = typename std::enable_if_t<
16971-                          Detail::is_unary_function_v<LambdaT>>>
16972-            Opt( LambdaT const& ref, StringRef hint ):
16973-                ParserRefImpl( ref, hint ) {}
16974-
16975-            template <typename LambdaT>
16976-            Opt( accept_many_t, LambdaT const& ref, StringRef hint ):
16977-                ParserRefImpl( accept_many, ref, hint ) {}
16978-
16979-            template <typename T,
16980-                      typename = typename std::enable_if_t<
16981-                          !Detail::is_unary_function_v<T>>>
16982-            Opt( T& ref, StringRef hint ):
16983-                ParserRefImpl( ref, hint ) {}
16984-
16985-            Opt& operator[]( StringRef optName ) & {
16986-                m_optNames.push_back(optName);
16987-                return *this;
16988-            }
16989-            Opt&& operator[]( StringRef optName ) && {
16990-                m_optNames.push_back( optName );
16991-                return CATCH_MOVE(*this);
16992-            }
16993-
16994-            Detail::HelpColumns getHelpColumns() const;
16995-
16996-            bool isMatch(StringRef optToken) const;
16997-
16998-            using ParserBase::parse;
16999-
17000-            Detail::InternalParseResult
17001-                parse(std::string const&,
17002-                      Detail::TokenStream tokens) const override;
17003-
17004-            Detail::Result validate() const override;
17005-        };
17006-
17007-        // Specifies the name of the executable
17008-        class ExeName : public Detail::ComposableParserImpl<ExeName> {
17009-            std::shared_ptr<std::string> m_name;
17010-            std::shared_ptr<Detail::BoundValueRefBase> m_ref;
17011-
17012-        public:
17013-            ExeName();
17014-            explicit ExeName(std::string& ref);
17015-
17016-            template <typename LambdaT>
17017-            explicit ExeName(LambdaT const& lambda) : ExeName() {
17018-                m_ref = std::make_shared<Detail::BoundLambda<LambdaT>>(lambda);
17019-            }
17020-
17021-            // The exe name is not parsed out of the normal tokens, but is
17022-            // handled specially
17023-            Detail::InternalParseResult
17024-                parse(std::string const&,
17025-                      Detail::TokenStream tokens) const override;
17026-
17027-            std::string const& name() const { return *m_name; }
17028-            Detail::ParserResult set(std::string const& newName);
17029-        };
17030-
17031-
17032-        // A Combined parser
17033-        class Parser : Detail::ParserBase {
17034-            mutable ExeName m_exeName;
17035-            std::vector<Opt> m_options;
17036-            std::vector<Arg> m_args;
17037-
17038-        public:
17039-
17040-            auto operator|=(ExeName const& exeName) -> Parser& {
17041-                m_exeName = exeName;
17042-                return *this;
17043-            }
17044-
17045-            auto operator|=(Arg const& arg) -> Parser& {
17046-                m_args.push_back(arg);
17047-                return *this;
17048-            }
17049-
17050-            friend Parser& operator|=( Parser& p, Opt const& opt ) {
17051-                p.m_options.push_back( opt );
17052-                return p;
17053-            }
17054-            friend Parser& operator|=( Parser& p, Opt&& opt ) {
17055-                p.m_options.push_back( CATCH_MOVE(opt) );
17056-                return p;
17057-            }
17058-
17059-            Parser& operator|=(Parser const& other);
17060-
17061-            template <typename T>
17062-            friend Parser operator|( Parser const& p, T&& rhs ) {
17063-                Parser temp( p );
17064-                temp |= rhs;
17065-                return temp;
17066-            }
17067-
17068-            template <typename T>
17069-            friend Parser operator|( Parser&& p, T&& rhs ) {
17070-                p |= CATCH_FORWARD(rhs);
17071-                return CATCH_MOVE(p);
17072-            }
17073-
17074-            std::vector<Detail::HelpColumns> getHelpColumns() const;
17075-
17076-            void writeToStream(std::ostream& os) const;
17077-
17078-            friend auto operator<<(std::ostream& os, Parser const& parser)
17079-                -> std::ostream& {
17080-                parser.writeToStream(os);
17081-                return os;
17082-            }
17083-
17084-            Detail::Result validate() const override;
17085-
17086-            using ParserBase::parse;
17087-            Detail::InternalParseResult
17088-                parse(std::string const& exeName,
17089-                      Detail::TokenStream tokens) const override;
17090-        };
17091-
17092-        /**
17093-         * Wrapper over argc + argv, assumes that the inputs outlive it
17094-         */
17095-        class Args {
17096-            friend Detail::TokenStream;
17097-            StringRef m_exeName;
17098-            std::vector<StringRef> m_args;
17099-
17100-        public:
17101-            Args(int argc, char const* const* argv);
17102-            // Helper constructor for testing
17103-            Args(std::initializer_list<StringRef> args);
17104-
17105-            StringRef exeName() const { return m_exeName; }
17106-        };
17107-
17108-
17109-        // Convenience wrapper for option parser that specifies the help option
17110-        struct Help : Opt {
17111-            Help(bool& showHelpFlag);
17112-        };
17113-
17114-        // Result type for parser operation
17115-        using Detail::ParserResult;
17116-
17117-        namespace Detail {
17118-            template <typename DerivedT>
17119-            template <typename T>
17120-            Parser
17121-                ComposableParserImpl<DerivedT>::operator|(T const& other) const {
17122-                return Parser() | static_cast<DerivedT const&>(*this) | other;
17123-            }
17124-        }
17125-
17126-    } // namespace Clara
17127-} // namespace Catch
17128-
17129-#if defined( __clang__ )
17130-#    pragma clang diagnostic pop
17131-#endif
17132-
17133-#if defined( __GNUC__ )
17134-#    pragma GCC diagnostic pop
17135-#endif
17136-
17137-#endif // CATCH_CLARA_HPP_INCLUDED
17138-
17139-namespace Catch {
17140-
17141-    struct ConfigData;
17142-
17143-    Clara::Parser makeCommandLineParser( ConfigData& config );
17144-
17145-} // end namespace Catch
17146-
17147-#endif // CATCH_COMMANDLINE_HPP_INCLUDED
17148-
17149-namespace Catch {
17150-
17151-    // TODO: Use C++17 `inline` variables
17152-    constexpr int UnspecifiedErrorExitCode = 1;
17153-    constexpr int NoTestsRunExitCode = 2;
17154-    constexpr int UnmatchedTestSpecExitCode = 3;
17155-    constexpr int AllTestsSkippedExitCode = 4;
17156-    constexpr int InvalidTestSpecExitCode = 5;
17157-    constexpr int TestFailureExitCode = 42;
17158-
17159-    class Session : Detail::NonCopyable {
17160-    public:
17161-
17162-        Session();
17163-        ~Session();
17164-
17165-        void showHelp() const;
17166-        void libIdentify();
17167-
17168-        int applyCommandLine( int argc, char const * const * argv );
17169-    #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
17170-        int applyCommandLine( int argc, wchar_t const * const * argv );
17171-    #endif
17172-
17173-        void useConfigData( ConfigData const& configData );
17174-
17175-        template<typename CharT>
17176-        int run(int argc, CharT const * const argv[]) {
17177-            if (m_startupExceptions)
17178-                return 1;
17179-            int returnCode = applyCommandLine(argc, argv);
17180-            if (returnCode == 0)
17181-                returnCode = run();
17182-            return returnCode;
17183-        }
17184-
17185-        int run();
17186-
17187-        Clara::Parser const& cli() const;
17188-        void cli( Clara::Parser const& newParser );
17189-        ConfigData& configData();
17190-        Config& config();
17191-    private:
17192-        int runInternal();
17193-
17194-        Clara::Parser m_cli;
17195-        ConfigData m_configData;
17196-        Detail::unique_ptr<Config> m_config;
17197-        bool m_startupExceptions = false;
17198-    };
17199-
17200-} // end namespace Catch
17201-
17202-#endif // CATCH_SESSION_HPP_INCLUDED
17203-
17204-
17205-#ifndef CATCH_TAG_ALIAS_HPP_INCLUDED
17206-#define CATCH_TAG_ALIAS_HPP_INCLUDED
17207-
17208-
17209-#include <string>
17210-
17211-namespace Catch {
17212-
17213-    struct TagAlias {
17214-        TagAlias(std::string const& _tag, SourceLineInfo _lineInfo):
17215-            tag(_tag),
17216-            lineInfo(_lineInfo)
17217-        {}
17218-
17219-        std::string tag;
17220-        SourceLineInfo lineInfo;
17221-    };
17222-
17223-} // end namespace Catch
17224-
17225-#endif // CATCH_TAG_ALIAS_HPP_INCLUDED
17226-
17227-
17228-#ifndef CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
17229-#define CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
17230-
17231-
17232-namespace Catch {
17233-
17234-    struct RegistrarForTagAliases {
17235-        RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
17236-    };
17237-
17238-} // end namespace Catch
17239-
17240-#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
17241-    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17242-    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
17243-    namespace{ const Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
17244-    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
17245-
17246-#endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
17247-
17248-
17249-#ifndef CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
17250-#define CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
17251-
17252-// We need this suppression to leak, because it took until GCC 10
17253-// for the front end to handle local suppression via _Pragma properly
17254-// inside templates (so `TEMPLATE_TEST_CASE` and co).
17255-// **THIS IS DIFFERENT FOR STANDARD TESTS, WHERE GCC 9 IS SUFFICIENT**
17256-#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ < 10
17257-#pragma GCC diagnostic ignored "-Wparentheses"
17258-#endif
17259-
17260-
17261-
17262-
17263-#ifndef CATCH_TEST_MACROS_HPP_INCLUDED
17264-#define CATCH_TEST_MACROS_HPP_INCLUDED
17265-
17266-
17267-
17268-#ifndef CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
17269-#define CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
17270-
17271-
17272-
17273-#ifndef CATCH_ASSERTION_HANDLER_HPP_INCLUDED
17274-#define CATCH_ASSERTION_HANDLER_HPP_INCLUDED
17275-
17276-
17277-
17278-#ifndef CATCH_DECOMPOSER_HPP_INCLUDED
17279-#define CATCH_DECOMPOSER_HPP_INCLUDED
17280-
17281-
17282-
17283-#ifndef CATCH_COMPARE_TRAITS_HPP_INCLUDED
17284-#define CATCH_COMPARE_TRAITS_HPP_INCLUDED
17285-
17286-
17287-#include <type_traits>
17288-
17289-namespace Catch {
17290-    namespace Detail {
17291-
17292-#if defined( __GNUC__ ) && !defined( __clang__ )
17293-#    pragma GCC diagnostic push
17294-    // GCC likes to complain about comparing bool with 0, in the decltype()
17295-    // that defines the comparable traits below.
17296-#    pragma GCC diagnostic ignored "-Wbool-compare"
17297-    // "ordered comparison of pointer with integer zero" same as above,
17298-    // but it does not have a separate warning flag to suppress
17299-#    pragma GCC diagnostic ignored "-Wextra"
17300-    // Did you know that comparing floats with `0` directly
17301-    // is super-duper dangerous in unevaluated context?
17302-#    pragma GCC diagnostic ignored "-Wfloat-equal"
17303-#endif
17304-
17305-#if defined( __clang__ )
17306-#    pragma clang diagnostic push
17307-    // Did you know that comparing floats with `0` directly
17308-    // is super-duper dangerous in unevaluated context?
17309-#    pragma clang diagnostic ignored "-Wfloat-equal"
17310-#endif
17311-
17312-#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op )                               \
17313-    template <typename, typename, typename = void>                            \
17314-    struct is_##id##_comparable : std::false_type {};                         \
17315-    template <typename T, typename U>                                         \
17316-    struct is_##id##_comparable<                                              \
17317-        T,                                                                    \
17318-        U,                                                                    \
17319-        void_t<decltype( std::declval<T>() op std::declval<U>() )>>           \
17320-        : std::true_type {};                                                  \
17321-    template <typename, typename = void>                                      \
17322-    struct is_##id##_0_comparable : std::false_type {};                       \
17323-    template <typename T>                                                     \
17324-    struct is_##id##_0_comparable<T,                                          \
17325-                                  void_t<decltype( std::declval<T>() op 0 )>> \
17326-        : std::true_type {};
17327-
17328-        // We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, !=
17329-        CATCH_DEFINE_COMPARABLE_TRAIT( lt, < )
17330-        CATCH_DEFINE_COMPARABLE_TRAIT( le, <= )
17331-        CATCH_DEFINE_COMPARABLE_TRAIT( gt, > )
17332-        CATCH_DEFINE_COMPARABLE_TRAIT( ge, >= )
17333-        CATCH_DEFINE_COMPARABLE_TRAIT( eq, == )
17334-        CATCH_DEFINE_COMPARABLE_TRAIT( ne, != )
17335-
17336-#undef CATCH_DEFINE_COMPARABLE_TRAIT
17337-
17338-#if defined( __GNUC__ ) && !defined( __clang__ )
17339-#    pragma GCC diagnostic pop
17340-#endif
17341-#if defined( __clang__ )
17342-#    pragma clang diagnostic pop
17343-#endif
17344-
17345-
17346-    } // namespace Detail
17347-} // namespace Catch
17348-
17349-#endif // CATCH_COMPARE_TRAITS_HPP_INCLUDED
17350-
17351-
17352-#ifndef CATCH_LOGICAL_TRAITS_HPP_INCLUDED
17353-#define CATCH_LOGICAL_TRAITS_HPP_INCLUDED
17354-
17355-#include <type_traits>
17356-
17357-namespace Catch {
17358-namespace Detail {
17359-
17360-#if defined( __cpp_lib_logical_traits ) && __cpp_lib_logical_traits >= 201510
17361-
17362-    using std::conjunction;
17363-    using std::disjunction;
17364-    using std::negation;
17365-
17366-#else
17367-
17368-    template <class...> struct conjunction : std::true_type {};
17369-    template <class B1> struct conjunction<B1> : B1 {};
17370-    template <class B1, class... Bn>
17371-    struct conjunction<B1, Bn...>
17372-        : std::conditional_t<bool( B1::value ), conjunction<Bn...>, B1> {};
17373-
17374-    template <class...> struct disjunction : std::false_type {};
17375-    template <class B1> struct disjunction<B1> : B1 {};
17376-    template <class B1, class... Bn>
17377-    struct disjunction<B1, Bn...>
17378-        : std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {};
17379-
17380-    template <class B>
17381-    struct negation : std::integral_constant<bool, !bool(B::value)> {};
17382-
17383-#endif
17384-
17385-} // namespace Detail
17386-} // namespace Catch
17387-
17388-#endif // CATCH_LOGICAL_TRAITS_HPP_INCLUDED
17389-
17390-#include <type_traits>
17391-#include <iosfwd>
17392-
17393-/** \file
17394- * Why does decomposing look the way it does:
17395- *
17396- * Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into
17397- * `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first,
17398- * and our custom operator is used for `a == b`, because `a` is transformed
17399- * into `ExprLhs<T&>` and then into `BinaryExpr<T&, U&>`.
17400- *
17401- * In practice, decomposing ends up a mess, because we have to support
17402- * various fun things.
17403- *
17404- * 1) Types that are only comparable with literal 0, and they do this by
17405- *    comparing against a magic type with pointer constructor and deleted
17406- *    other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++
17407- *
17408- * 2) Types that are only comparable with literal 0, and they do this by
17409- *    comparing against a magic type with consteval integer constructor.
17410- *    Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL.
17411- *
17412- * 3) Types that have no linkage, and so we cannot form a reference to
17413- *    them. Example: some implementations of traits.
17414- *
17415- * 4) Starting with C++20, when the compiler sees `a == b`, it also uses
17416- *    `b == a` when constructing the overload set. For us this means that
17417- *    when the compiler handles `ExprLhs<T> == b`, it also tries to resolve
17418- *    the overload set for `b == ExprLhs<T>`.
17419- *
17420- * To accommodate these use cases, decomposer ended up rather complex.
17421- *
17422- * 1) These types are handled by adding SFINAE overloads to our comparison
17423- *    operators, checking whether `T == U` are comparable with the given
17424- *    operator, and if not, whether T (or U) are comparable with literal 0.
17425- *    If yes, the overload compares T (or U) with 0 literal inline in the
17426- *    definition.
17427- *
17428- *    Note that for extra correctness, we check  that the other type is
17429- *    either an `int` (literal 0 is captured as `int` by templates), or
17430- *    a `long` (some platforms use 0L for `NULL` and we want to support
17431- *    that for pointer comparisons).
17432- *
17433- * 2) For these types, `is_foo_comparable<T, int>` is true, but letting
17434- *    them fall into the overload that actually does `T == int` causes
17435- *    compilation error. Handling them requires that the decomposition
17436- *    is `constexpr`, so that P2564R3 applies and the `consteval` from
17437- *    their accompanying magic type is propagated through the `constexpr`
17438- *    call stack.
17439- *
17440- *    However this is not enough to handle these types automatically,
17441- *    because our default is to capture types by reference, to avoid
17442- *    runtime copies. While these references cannot become dangling,
17443- *    they outlive the constexpr context and thus the default capture
17444- *    path cannot be actually constexpr.
17445- *
17446- *    The solution is to capture these types by value, by explicitly
17447- *    specializing `Catch::capture_by_value` for them. Catch2 provides
17448- *    specialization for `std::foo_ordering`s, but users can specialize
17449- *    the trait for their own types as well.
17450- *
17451- * 3) If a type has no linkage, we also cannot capture it by reference.
17452- *    The solution is once again to capture them by value. We handle
17453- *    the common cases by using `std::is_arithmetic` and `std::is_enum`
17454- *    as the default for `Catch::capture_by_value`, but that is only a
17455- *    some-effort heuristic. These combine to capture all possible bitfield
17456- *    bases, and also some trait-like types. As with 2), users can
17457- *    specialize `capture_by_value` for their own types as needed.
17458- *
17459- * 4) To support C++20 and make the SFINAE on our decomposing operators
17460- *    work, the SFINAE has to happen in return type, rather than in
17461- *    a template type. This is due to our use of logical type traits
17462- *    (`conjunction`/`disjunction`/`negation`), that we use to workaround
17463- *    an issue in older (9-) versions of GCC. I still blame C++20 for
17464- *    this, because without the comparison order switching, the logical
17465- *    traits could still be used in template type.
17466- *
17467- * There are also other side concerns, e.g. supporting both `REQUIRE(a)`
17468- * and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot
17469- * nicely into the same expression handling logic, but these are rather
17470- * straightforward and add only a bit of complexity (e.g. common base
17471- * class for decomposed expressions).
17472- */
17473-
17474-#ifdef _MSC_VER
17475-#pragma warning(push)
17476-#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
17477-#pragma warning(disable:4018) // more "signed/unsigned mismatch"
17478-#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
17479-#pragma warning(disable:4180) // qualifier applied to function type has no meaning
17480-#pragma warning(disable:4800) // Forcing result to true or false
17481-#endif
17482-
17483-#ifdef __clang__
17484-#  pragma clang diagnostic push
17485-#  pragma clang diagnostic ignored "-Wsign-compare"
17486-#  pragma clang diagnostic ignored "-Wnon-virtual-dtor"
17487-#elif defined __GNUC__
17488-#  pragma GCC diagnostic push
17489-#  pragma GCC diagnostic ignored "-Wsign-compare"
17490-#  pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
17491-#endif
17492-
17493-#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>)
17494-#  include <compare>
17495-#    if defined( __cpp_lib_three_way_comparison ) && \
17496-            __cpp_lib_three_way_comparison >= 201907L
17497-#      define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS
17498-#    endif
17499-#endif
17500-
17501-namespace Catch {
17502-
17503-    namespace Detail {
17504-        // This was added in C++20, but we require only C++14 for now.
17505-        template <typename T>
17506-        using RemoveCVRef_t = std::remove_cv_t<std::remove_reference_t<T>>;
17507-    }
17508-
17509-    // Note: This is about as much as we can currently reasonably support.
17510-    //       In an ideal world, we could capture by value small trivially
17511-    //       copyable types, but the actual `std::is_trivially_copyable`
17512-    //       trait is a huge mess with standard-violating results on
17513-    //       GCC and Clang, which are unlikely to be fixed soon due to ABI
17514-    //       concerns.
17515-    //       `std::is_scalar` also causes issues due to the `is_pointer`
17516-    //       component, which causes ambiguity issues with (references-to)
17517-    //       function pointer. If those are resolved, we still need to
17518-    //       disambiguate the overload set for arrays, through explicit
17519-    //       overload for references to sized arrays.
17520-    template <typename T>
17521-    struct capture_by_value
17522-        : std::integral_constant<bool,
17523-                                 std::is_arithmetic<T>::value ||
17524-                                     std::is_enum<T>::value> {};
17525-
17526-#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS )
17527-    template <>
17528-    struct capture_by_value<std::strong_ordering> : std::true_type {};
17529-    template <>
17530-    struct capture_by_value<std::weak_ordering> : std::true_type {};
17531-    template <>
17532-    struct capture_by_value<std::partial_ordering> : std::true_type {};
17533-#endif
17534-
17535-    template <typename T>
17536-    struct always_false : std::false_type {};
17537-
17538-    class ITransientExpression {
17539-        bool m_isBinaryExpression;
17540-        bool m_result;
17541-
17542-    protected:
17543-        ~ITransientExpression() = default;
17544-
17545-    public:
17546-        constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
17547-        constexpr auto getResult() const -> bool { return m_result; }
17548-        //! This function **has** to be overridden by the derived class.
17549-        virtual void streamReconstructedExpression( std::ostream& os ) const;
17550-
17551-        constexpr ITransientExpression( bool isBinaryExpression, bool result )
17552-        :   m_isBinaryExpression( isBinaryExpression ),
17553-            m_result( result )
17554-        {}
17555-
17556-        constexpr ITransientExpression( ITransientExpression const& ) = default;
17557-        constexpr ITransientExpression& operator=( ITransientExpression const& ) = default;
17558-
17559-        friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
17560-            expr.streamReconstructedExpression(out);
17561-            return out;
17562-        }
17563-    };
17564-
17565-    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
17566-
17567-    template<typename LhsT, typename RhsT>
17568-    class BinaryExpr  : public ITransientExpression {
17569-        LhsT m_lhs;
17570-        StringRef m_op;
17571-        RhsT m_rhs;
17572-
17573-        void streamReconstructedExpression( std::ostream &os ) const override {
17574-            formatReconstructedExpression
17575-                    ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
17576-        }
17577-
17578-    public:
17579-        constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
17580-        :   ITransientExpression{ true, comparisonResult },
17581-            m_lhs( lhs ),
17582-            m_op( op ),
17583-            m_rhs( rhs )
17584-        {}
17585-
17586-        template<typename T>
17587-        auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17588-            static_assert(always_false<T>::value,
17589-            "chained comparisons are not supported inside assertions, "
17590-            "wrap the expression inside parentheses, or decompose it");
17591-        }
17592-
17593-        template<typename T>
17594-        auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17595-            static_assert(always_false<T>::value,
17596-            "chained comparisons are not supported inside assertions, "
17597-            "wrap the expression inside parentheses, or decompose it");
17598-        }
17599-
17600-        template<typename T>
17601-        auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17602-            static_assert(always_false<T>::value,
17603-            "chained comparisons are not supported inside assertions, "
17604-            "wrap the expression inside parentheses, or decompose it");
17605-        }
17606-
17607-        template<typename T>
17608-        auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17609-            static_assert(always_false<T>::value,
17610-            "chained comparisons are not supported inside assertions, "
17611-            "wrap the expression inside parentheses, or decompose it");
17612-        }
17613-
17614-        template<typename T>
17615-        auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17616-            static_assert(always_false<T>::value,
17617-            "chained comparisons are not supported inside assertions, "
17618-            "wrap the expression inside parentheses, or decompose it");
17619-        }
17620-
17621-        template<typename T>
17622-        auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17623-            static_assert(always_false<T>::value,
17624-            "chained comparisons are not supported inside assertions, "
17625-            "wrap the expression inside parentheses, or decompose it");
17626-        }
17627-
17628-        template<typename T>
17629-        auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17630-            static_assert(always_false<T>::value,
17631-            "chained comparisons are not supported inside assertions, "
17632-            "wrap the expression inside parentheses, or decompose it");
17633-        }
17634-
17635-        template<typename T>
17636-        auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
17637-            static_assert(always_false<T>::value,
17638-            "chained comparisons are not supported inside assertions, "
17639-            "wrap the expression inside parentheses, or decompose it");
17640-        }
17641-    };
17642-
17643-    template<typename LhsT>
17644-    class UnaryExpr : public ITransientExpression {
17645-        LhsT m_lhs;
17646-
17647-        void streamReconstructedExpression( std::ostream &os ) const override {
17648-            os << Catch::Detail::stringify( m_lhs );
17649-        }
17650-
17651-    public:
17652-        explicit constexpr UnaryExpr( LhsT lhs )
17653-        :   ITransientExpression{ false, static_cast<bool>(lhs) },
17654-            m_lhs( lhs )
17655-        {}
17656-    };
17657-
17658-
17659-    template<typename LhsT>
17660-    class ExprLhs {
17661-        LhsT m_lhs;
17662-    public:
17663-        explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
17664-
17665-#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op )           \
17666-    template <typename RhsT>                                                   \
17667-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \
17668-        -> std::enable_if_t<                                                   \
17669-            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17670-                                Detail::negation<capture_by_value<             \
17671-                                    Detail::RemoveCVRef_t<RhsT>>>>::value,     \
17672-            BinaryExpr<LhsT, RhsT const&>> {                                   \
17673-        return {                                                               \
17674-            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17675-    }                                                                          \
17676-    template <typename RhsT>                                                   \
17677-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17678-        -> std::enable_if_t<                                                   \
17679-            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17680-                                capture_by_value<RhsT>>::value,                \
17681-            BinaryExpr<LhsT, RhsT>> {                                          \
17682-        return {                                                               \
17683-            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17684-    }                                                                          \
17685-    template <typename RhsT>                                                   \
17686-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17687-        -> std::enable_if_t<                                                   \
17688-            Detail::conjunction<                                               \
17689-                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17690-                Detail::is_eq_0_comparable<LhsT>,                              \
17691-              /* We allow long because we want `ptr op NULL` to be accepted */ \
17692-                Detail::disjunction<std::is_same<RhsT, int>,                   \
17693-                                    std::is_same<RhsT, long>>>::value,         \
17694-            BinaryExpr<LhsT, RhsT>> {                                          \
17695-        if ( rhs != 0 ) { throw_test_failure_exception(); }                    \
17696-        return {                                                               \
17697-            static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \
17698-    }                                                                          \
17699-    template <typename RhsT>                                                   \
17700-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17701-        -> std::enable_if_t<                                                   \
17702-            Detail::conjunction<                                               \
17703-                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17704-                Detail::is_eq_0_comparable<RhsT>,                              \
17705-              /* We allow long because we want `ptr op NULL` to be accepted */ \
17706-                Detail::disjunction<std::is_same<LhsT, int>,                   \
17707-                                    std::is_same<LhsT, long>>>::value,         \
17708-            BinaryExpr<LhsT, RhsT>> {                                          \
17709-        if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); }              \
17710-        return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs };    \
17711-    }
17712-
17713-        CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
17714-        CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != )
17715-
17716-    #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
17717-
17718-
17719-#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op )         \
17720-    template <typename RhsT>                                                   \
17721-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \
17722-        -> std::enable_if_t<                                                   \
17723-            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17724-                                Detail::negation<capture_by_value<             \
17725-                                    Detail::RemoveCVRef_t<RhsT>>>>::value,     \
17726-            BinaryExpr<LhsT, RhsT const&>> {                                   \
17727-        return {                                                               \
17728-            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17729-    }                                                                          \
17730-    template <typename RhsT>                                                   \
17731-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17732-        -> std::enable_if_t<                                                   \
17733-            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17734-                                capture_by_value<RhsT>>::value,                \
17735-            BinaryExpr<LhsT, RhsT>> {                                          \
17736-        return {                                                               \
17737-            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17738-    }                                                                          \
17739-    template <typename RhsT>                                                   \
17740-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17741-        -> std::enable_if_t<                                                   \
17742-            Detail::conjunction<                                               \
17743-                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17744-                Detail::is_##id##_0_comparable<LhsT>,                          \
17745-                std::is_same<RhsT, int>>::value,                               \
17746-            BinaryExpr<LhsT, RhsT>> {                                          \
17747-        if ( rhs != 0 ) { throw_test_failure_exception(); }                    \
17748-        return {                                                               \
17749-            static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \
17750-    }                                                                          \
17751-    template <typename RhsT>                                                   \
17752-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17753-        -> std::enable_if_t<                                                   \
17754-            Detail::conjunction<                                               \
17755-                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17756-                Detail::is_##id##_0_comparable<RhsT>,                          \
17757-                std::is_same<LhsT, int>>::value,                               \
17758-            BinaryExpr<LhsT, RhsT>> {                                          \
17759-        if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); }              \
17760-        return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs };    \
17761-    }
17762-
17763-        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < )
17764-        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= )
17765-        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > )
17766-        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= )
17767-
17768-    #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR
17769-
17770-
17771-#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op )                        \
17772-    template <typename RhsT>                                                   \
17773-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \
17774-        -> std::enable_if_t<                                                   \
17775-            !capture_by_value<Detail::RemoveCVRef_t<RhsT>>::value,             \
17776-            BinaryExpr<LhsT, RhsT const&>> {                                   \
17777-        return {                                                               \
17778-            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17779-    }                                                                          \
17780-    template <typename RhsT>                                                   \
17781-    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17782-        -> std::enable_if_t<capture_by_value<RhsT>::value,                     \
17783-                            BinaryExpr<LhsT, RhsT>> {                          \
17784-        return {                                                               \
17785-            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17786-    }
17787-
17788-        CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|)
17789-        CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&)
17790-        CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^)
17791-
17792-    #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR
17793-
17794-        template<typename RhsT>
17795-        friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
17796-            static_assert(always_false<RhsT>::value,
17797-            "operator&& is not supported inside assertions, "
17798-            "wrap the expression inside parentheses, or decompose it");
17799-        }
17800-
17801-        template<typename RhsT>
17802-        friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
17803-            static_assert(always_false<RhsT>::value,
17804-            "operator|| is not supported inside assertions, "
17805-            "wrap the expression inside parentheses, or decompose it");
17806-        }
17807-
17808-        constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
17809-            return UnaryExpr<LhsT>{ m_lhs };
17810-        }
17811-    };
17812-
17813-    struct Decomposer {
17814-        template <typename T,
17815-                  std::enable_if_t<!capture_by_value<Detail::RemoveCVRef_t<T>>::value,
17816-                      int> = 0>
17817-        constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
17818-            return ExprLhs<const T&>{ lhs };
17819-        }
17820-
17821-        template <typename T,
17822-                  std::enable_if_t<capture_by_value<T>::value, int> = 0>
17823-        constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
17824-            return ExprLhs<T>{ value };
17825-        }
17826-    };
17827-
17828-} // end namespace Catch
17829-
17830-#ifdef _MSC_VER
17831-#pragma warning(pop)
17832-#endif
17833-#ifdef __clang__
17834-#  pragma clang diagnostic pop
17835-#elif defined __GNUC__
17836-#  pragma GCC diagnostic pop
17837-#endif
17838-
17839-#endif // CATCH_DECOMPOSER_HPP_INCLUDED
17840-
17841-#include <string>
17842-
17843-namespace Catch {
17844-
17845-    struct AssertionReaction {
17846-        bool shouldDebugBreak = false;
17847-        bool shouldThrow = false;
17848-        bool shouldSkip = false;
17849-    };
17850-
17851-    class AssertionHandler {
17852-        AssertionInfo m_assertionInfo;
17853-        AssertionReaction m_reaction;
17854-        bool m_completed = false;
17855-        IResultCapture& m_resultCapture;
17856-
17857-    public:
17858-        AssertionHandler
17859-            (   StringRef macroName,
17860-                SourceLineInfo const& lineInfo,
17861-                StringRef capturedExpression,
17862-                ResultDisposition::Flags resultDisposition );
17863-        ~AssertionHandler() {
17864-            if ( !m_completed ) {
17865-                m_resultCapture.handleIncomplete( m_assertionInfo );
17866-            }
17867-        }
17868-
17869-
17870-        template<typename T>
17871-        constexpr void handleExpr( ExprLhs<T> const& expr ) {
17872-            handleExpr( expr.makeUnaryExpr() );
17873-        }
17874-        void handleExpr( ITransientExpression const& expr );
17875-
17876-        void handleMessage(ResultWas::OfType resultType, std::string&& message);
17877-
17878-        void handleExceptionThrownAsExpected();
17879-        void handleUnexpectedExceptionNotThrown();
17880-        void handleExceptionNotThrownAsExpected();
17881-        void handleThrowingCallSkipped();
17882-        void handleUnexpectedInflightException();
17883-
17884-        void complete();
17885-
17886-        // query
17887-        auto allowThrows() const -> bool;
17888-    };
17889-
17890-    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str );
17891-
17892-} // namespace Catch
17893-
17894-#endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED
17895-
17896-
17897-#ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
17898-#define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
17899-
17900-
17901-#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
17902-  #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
17903-#else
17904-  #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
17905-#endif
17906-
17907-#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
17908-
17909-// We need this suppression to leak, because it took until GCC 10
17910-// for the front end to handle local suppression via _Pragma properly
17911-#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9
17912-  #pragma GCC diagnostic ignored "-Wparentheses"
17913-#endif
17914-
17915-#if !defined(CATCH_CONFIG_DISABLE)
17916-
17917-#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
17918-
17919-///////////////////////////////////////////////////////////////////////////////
17920-// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
17921-// macros.
17922-#define INTERNAL_CATCH_TRY
17923-#define INTERNAL_CATCH_CATCH( capturer )
17924-
17925-#else // CATCH_CONFIG_FAST_COMPILE
17926-
17927-#define INTERNAL_CATCH_TRY try
17928-#define INTERNAL_CATCH_CATCH( handler ) catch(...) { (handler).handleUnexpectedInflightException(); }
17929-
17930-#endif
17931-
17932-///////////////////////////////////////////////////////////////////////////////
17933-#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
17934-    do { /* NOLINT(bugprone-infinite-loop) */ \
17935-        /* The expression should not be evaluated, but warnings should hopefully be checked */ \
17936-        CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
17937-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
17938-        INTERNAL_CATCH_TRY { \
17939-            CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17940-            CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
17941-            catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \
17942-            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17943-        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
17944-        catchAssertionHandler.complete(); \
17945-    } while( (void)0, (false) && static_cast<const bool&>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
17946-    // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
17947-
17948-///////////////////////////////////////////////////////////////////////////////
17949-#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
17950-    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
17951-    if( Catch::getResultCapture().lastAssertionPassed() )
17952-
17953-///////////////////////////////////////////////////////////////////////////////
17954-#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
17955-    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
17956-    if( !Catch::getResultCapture().lastAssertionPassed() )
17957-
17958-///////////////////////////////////////////////////////////////////////////////
17959-#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
17960-    do { \
17961-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
17962-        try { \
17963-            CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17964-            CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
17965-            static_cast<void>(__VA_ARGS__); \
17966-            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17967-            catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
17968-        } \
17969-        catch( ... ) { \
17970-            catchAssertionHandler.handleUnexpectedInflightException(); \
17971-        } \
17972-        catchAssertionHandler.complete(); \
17973-    } while( false )
17974-
17975-///////////////////////////////////////////////////////////////////////////////
17976-#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
17977-    do { \
17978-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
17979-        if( catchAssertionHandler.allowThrows() ) \
17980-            try { \
17981-                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17982-                CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
17983-                CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
17984-                static_cast<void>(__VA_ARGS__); \
17985-                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17986-                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
17987-            } \
17988-            catch( ... ) { \
17989-                catchAssertionHandler.handleExceptionThrownAsExpected(); \
17990-            } \
17991-        else \
17992-            catchAssertionHandler.handleThrowingCallSkipped(); \
17993-        catchAssertionHandler.complete(); \
17994-    } while( false )
17995-
17996-///////////////////////////////////////////////////////////////////////////////
17997-#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
17998-    do { \
17999-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
18000-        if( catchAssertionHandler.allowThrows() ) \
18001-            try { \
18002-                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18003-                CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
18004-                CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
18005-                static_cast<void>(expr); \
18006-                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18007-                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
18008-            } \
18009-            catch( exceptionType const& ) { \
18010-                catchAssertionHandler.handleExceptionThrownAsExpected(); \
18011-            } \
18012-            catch( ... ) { \
18013-                catchAssertionHandler.handleUnexpectedInflightException(); \
18014-            } \
18015-        else \
18016-            catchAssertionHandler.handleThrowingCallSkipped(); \
18017-        catchAssertionHandler.complete(); \
18018-    } while( false )
18019-
18020-
18021-
18022-///////////////////////////////////////////////////////////////////////////////
18023-// Although this is matcher-based, it can be used with just a string
18024-#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
18025-    do { \
18026-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
18027-        if( catchAssertionHandler.allowThrows() ) \
18028-            try { \
18029-                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18030-                CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
18031-                CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
18032-                static_cast<void>(__VA_ARGS__); \
18033-                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18034-                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
18035-            } \
18036-            catch( ... ) { \
18037-                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher ); \
18038-            } \
18039-        else \
18040-            catchAssertionHandler.handleThrowingCallSkipped(); \
18041-        catchAssertionHandler.complete(); \
18042-    } while( false )
18043-
18044-#endif // CATCH_CONFIG_DISABLE
18045-
18046-#endif // CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
18047-
18048-
18049-#ifndef CATCH_SECTION_HPP_INCLUDED
18050-#define CATCH_SECTION_HPP_INCLUDED
18051-
18052-
18053-
18054-
18055-/** \file
18056- * Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option
18057- *
18058- * Some of Catch2's macros can be defined differently to work better with
18059- * static analysis tools, like clang-tidy or coverity.
18060- * Currently the main use case is to show that `SECTION`s are executed
18061- * exclusively, and not all in one run of a `TEST_CASE`.
18062- */
18063-
18064-#ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
18065-#define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
18066-
18067-
18068-#if defined(__clang_analyzer__) || defined(__COVERITY__)
18069-    #define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT
18070-#endif
18071-
18072-#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \
18073-    !defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \
18074-    !defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT )
18075-#    define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
18076-#endif
18077-
18078-
18079-#endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
18080-
18081-
18082-#ifndef CATCH_TIMER_HPP_INCLUDED
18083-#define CATCH_TIMER_HPP_INCLUDED
18084-
18085-#include <cstdint>
18086-
18087-namespace Catch {
18088-
18089-    class Timer {
18090-        uint64_t m_nanoseconds = 0;
18091-    public:
18092-        void start();
18093-        auto getElapsedNanoseconds() const -> uint64_t;
18094-        auto getElapsedMicroseconds() const -> uint64_t;
18095-        auto getElapsedMilliseconds() const -> unsigned int;
18096-        auto getElapsedSeconds() const -> double;
18097-    };
18098-
18099-} // namespace Catch
18100-
18101-#endif // CATCH_TIMER_HPP_INCLUDED
18102-
18103-namespace Catch {
18104-
18105-    class Section : Detail::NonCopyable {
18106-    public:
18107-        Section( SectionInfo&& info );
18108-        Section( SourceLineInfo const& _lineInfo,
18109-                 StringRef _name,
18110-                 const char* const = nullptr );
18111-        ~Section();
18112-
18113-        // This indicates whether the section should be executed or not
18114-        explicit operator bool() const;
18115-
18116-    private:
18117-        SectionInfo m_info;
18118-
18119-        Counts m_assertions;
18120-        bool m_sectionIncluded;
18121-        Timer m_timer;
18122-    };
18123-
18124-} // end namespace Catch
18125-
18126-#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
18127-#    define INTERNAL_CATCH_SECTION( ... )                                 \
18128-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                         \
18129-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                  \
18130-        if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(            \
18131-                 catch_internal_Section ) =                               \
18132-                 Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
18133-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
18134-
18135-#    define INTERNAL_CATCH_DYNAMIC_SECTION( ... )                     \
18136-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                     \
18137-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS              \
18138-        if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(        \
18139-                 catch_internal_Section ) =                           \
18140-                 Catch::SectionInfo(                                  \
18141-                     CATCH_INTERNAL_LINEINFO,                         \
18142-                     ( Catch::ReusableStringStream() << __VA_ARGS__ ) \
18143-                         .str() ) )                                   \
18144-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
18145-
18146-#else
18147-
18148-// These section definitions imply that at most one section at one level
18149-// will be entered (because only one section's __LINE__ can be equal to
18150-// the dummy `catchInternalSectionHint` variable from `TEST_CASE`).
18151-
18152-namespace Catch {
18153-    namespace Detail {
18154-        // Intentionally without linkage, as it should only be used as a dummy
18155-        // symbol for static analysis.
18156-        // The arguments are used as a dummy for checking warnings in the passed
18157-        // expressions.
18158-        int GetNewSectionHint( StringRef, const char* const = nullptr );
18159-    } // namespace Detail
18160-} // namespace Catch
18161-
18162-
18163-#    define INTERNAL_CATCH_SECTION( ... )                                   \
18164-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                           \
18165-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                    \
18166-        CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \
18167-        if ( [[maybe_unused]] const int catchInternalPreviousSectionHint =  \
18168-                 catchInternalSectionHint,                                  \
18169-             catchInternalSectionHint =                                     \
18170-                 Catch::Detail::GetNewSectionHint(__VA_ARGS__);             \
18171-             catchInternalPreviousSectionHint == __LINE__ )                 \
18172-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
18173-
18174-#    define INTERNAL_CATCH_DYNAMIC_SECTION( ... )                           \
18175-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                           \
18176-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                    \
18177-        CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \
18178-        if ( [[maybe_unused]] const int catchInternalPreviousSectionHint =  \
18179-                 catchInternalSectionHint,                                  \
18180-             catchInternalSectionHint = Catch::Detail::GetNewSectionHint(   \
18181-                ( Catch::ReusableStringStream() << __VA_ARGS__ ).str());    \
18182-             catchInternalPreviousSectionHint == __LINE__ )                 \
18183-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
18184-
18185-#endif
18186-
18187-
18188-#endif // CATCH_SECTION_HPP_INCLUDED
18189-
18190-
18191-#ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED
18192-#define CATCH_TEST_REGISTRY_HPP_INCLUDED
18193-
18194-
18195-
18196-#ifndef CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
18197-#define CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
18198-
18199-namespace Catch {
18200-
18201-    class ITestInvoker {
18202-    public:
18203-        virtual void prepareTestCase();
18204-        virtual void tearDownTestCase();
18205-        virtual void invoke() const = 0;
18206-        virtual ~ITestInvoker(); // = default
18207-    };
18208-
18209-} // namespace Catch
18210-
18211-#endif // CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
18212-
18213-
18214-#ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
18215-#define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
18216-
18217-#define INTERNAL_CATCH_EXPAND1( param ) INTERNAL_CATCH_EXPAND2( param )
18218-#define INTERNAL_CATCH_EXPAND2( ... ) INTERNAL_CATCH_NO##__VA_ARGS__
18219-#define INTERNAL_CATCH_DEF( ... ) INTERNAL_CATCH_DEF __VA_ARGS__
18220-#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
18221-
18222-#define INTERNAL_CATCH_REMOVE_PARENS( ... ) \
18223-    INTERNAL_CATCH_EXPAND1( INTERNAL_CATCH_DEF __VA_ARGS__ )
18224-
18225-#endif // CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
18226-
18227-// GCC 5 and older do not properly handle disabling unused-variable warning
18228-// with a _Pragma. This means that we have to leak the suppression to the
18229-// user code as well :-(
18230-#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
18231-#pragma GCC diagnostic ignored "-Wunused-variable"
18232-#endif
18233-
18234-
18235-
18236-namespace Catch {
18237-
18238-template<typename C>
18239-class TestInvokerAsMethod : public ITestInvoker {
18240-    void (C::*m_testAsMethod)();
18241-public:
18242-    constexpr TestInvokerAsMethod( void ( C::*testAsMethod )() ) noexcept:
18243-        m_testAsMethod( testAsMethod ) {}
18244-
18245-    void invoke() const override {
18246-        C obj;
18247-        (obj.*m_testAsMethod)();
18248-    }
18249-};
18250-
18251-Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() );
18252-
18253-template<typename C>
18254-Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
18255-    return Detail::make_unique<TestInvokerAsMethod<C>>( testAsMethod );
18256-}
18257-
18258-template <typename C>
18259-class TestInvokerFixture : public ITestInvoker {
18260-    void ( C::*m_testAsMethod )() const;
18261-    Detail::unique_ptr<C> m_fixture = nullptr;
18262-
18263-public:
18264-    constexpr TestInvokerFixture( void ( C::*testAsMethod )() const ) noexcept:
18265-        m_testAsMethod( testAsMethod ) {}
18266-
18267-    void prepareTestCase() override {
18268-        m_fixture = Detail::make_unique<C>();
18269-    }
18270-
18271-    void tearDownTestCase() override {
18272-        m_fixture.reset();
18273-    }
18274-
18275-    void invoke() const override {
18276-        auto* f = m_fixture.get();
18277-        ( f->*m_testAsMethod )();
18278-    }
18279-};
18280-
18281-template<typename C>
18282-Detail::unique_ptr<ITestInvoker> makeTestInvokerFixture( void ( C::*testAsMethod )() const ) {
18283-    return Detail::make_unique<TestInvokerFixture<C>>( testAsMethod );
18284-}
18285-
18286-struct NameAndTags {
18287-    constexpr NameAndTags( StringRef name_ = StringRef(),
18288-                           StringRef tags_ = StringRef() ) noexcept:
18289-        name( name_ ), tags( tags_ ) {}
18290-    StringRef name;
18291-    StringRef tags;
18292-};
18293-
18294-struct AutoReg : Detail::NonCopyable {
18295-    AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
18296-};
18297-
18298-} // end namespace Catch
18299-
18300-#if defined(CATCH_CONFIG_DISABLE)
18301-    #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
18302-        static inline void TestName()
18303-    #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
18304-        namespace{                        \
18305-            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
18306-                void test();              \
18307-            };                            \
18308-        }                                 \
18309-        void TestName::test()
18310-#endif
18311-
18312-
18313-#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
18314-
18315-    ///////////////////////////////////////////////////////////////////////////////
18316-    #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
18317-        static void TestName(); \
18318-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18319-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18320-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18321-        namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
18322-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18323-        static void TestName()
18324-    #define INTERNAL_CATCH_TESTCASE( ... ) \
18325-        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ )
18326-
18327-#else  // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
18328-
18329-
18330-// Dummy registrator for the dumy test case macros
18331-namespace Catch {
18332-    namespace Detail {
18333-        struct DummyUse {
18334-            DummyUse( void ( * )( int ), Catch::NameAndTags const& );
18335-        };
18336-    } // namespace Detail
18337-} // namespace Catch
18338-
18339-// Note that both the presence of the argument and its exact name are
18340-// necessary for the section support.
18341-
18342-// We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE`
18343-// tests can compile. The redefined `TEST_CASE` shadows this with param.
18344-static int catchInternalSectionHint = 0;
18345-
18346-#    define INTERNAL_CATCH_TESTCASE2( fname, ... )                         \
18347-        static void fname( int );                                          \
18348-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                          \
18349-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                           \
18350-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                   \
18351-        static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME(   \
18352-            dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } );    \
18353-        CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                            \
18354-        static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
18355-            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
18356-#    define INTERNAL_CATCH_TESTCASE( ... ) \
18357-        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ )
18358-
18359-
18360-#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
18361-
18362-    ///////////////////////////////////////////////////////////////////////////////
18363-    #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
18364-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18365-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18366-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18367-        namespace{ \
18368-            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
18369-                void test(); \
18370-            }; \
18371-            const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
18372-            Catch::makeTestInvoker( &TestName::test ),                    \
18373-            CATCH_INTERNAL_LINEINFO,                                      \
18374-            #ClassName##_catch_sr,                                        \
18375-            Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
18376-        } \
18377-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18378-        void TestName::test()
18379-    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
18380-        INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
18381-
18382-    ///////////////////////////////////////////////////////////////////////////////
18383-    #define INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE2( TestName, ClassName, ... )      \
18384-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                             \
18385-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                              \
18386-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                      \
18387-        namespace {                                                           \
18388-            struct TestName : INTERNAL_CATCH_REMOVE_PARENS( ClassName ) {     \
18389-                void test() const;                                            \
18390-            };                                                                \
18391-            const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
18392-                Catch::makeTestInvokerFixture( &TestName::test ),                    \
18393-                CATCH_INTERNAL_LINEINFO,                                      \
18394-                #ClassName##_catch_sr,                                        \
18395-                Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */             \
18396-        }                                                                     \
18397-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                              \
18398-        void TestName::test() const
18399-    #define INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( ClassName, ... )    \
18400-        INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
18401-
18402-
18403-    ///////////////////////////////////////////////////////////////////////////////
18404-    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
18405-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18406-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18407-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18408-        namespace {                                                           \
18409-        const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
18410-            Catch::makeTestInvoker( &QualifiedMethod ),                   \
18411-            CATCH_INTERNAL_LINEINFO,                                      \
18412-            "&" #QualifiedMethod##_catch_sr,                              \
18413-            Catch::NameAndTags{ __VA_ARGS__ } );                          \
18414-    } /* NOLINT */ \
18415-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
18416-
18417-
18418-    ///////////////////////////////////////////////////////////////////////////////
18419-    #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
18420-        do { \
18421-            CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18422-            CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18423-            CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18424-            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
18425-            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18426-        } while(false)
18427-
18428-
18429-#endif // CATCH_TEST_REGISTRY_HPP_INCLUDED
18430-
18431-
18432-#ifndef CATCH_UNREACHABLE_HPP_INCLUDED
18433-#define CATCH_UNREACHABLE_HPP_INCLUDED
18434-
18435-/**\file
18436- * Polyfill `std::unreachable`
18437- *
18438- * We need something like `std::unreachable` to tell the compiler that
18439- * some macros, e.g. `FAIL` or `SKIP`, do not continue execution in normal
18440- * manner, and should handle it as such, e.g. not warn if there is no return
18441- * from non-void function after a `FAIL` or `SKIP`.
18442- */
18443-
18444-#include <exception>
18445-
18446-#if defined( __cpp_lib_unreachable ) && __cpp_lib_unreachable > 202202L
18447-#    include <utility>
18448-namespace Catch {
18449-    namespace Detail {
18450-        using Unreachable = std::unreachable;
18451-    }
18452-} // namespace Catch
18453-
18454-#else // vv If we do not have std::unreachable, we implement something similar
18455-
18456-namespace Catch {
18457-    namespace Detail {
18458-
18459-        [[noreturn]]
18460-        inline void Unreachable() noexcept {
18461-#    if defined( NDEBUG )
18462-#        if defined( _MSC_VER ) && !defined( __clang__ )
18463-            __assume( false );
18464-#        elif defined( __GNUC__ )
18465-            __builtin_unreachable();
18466-#        else // vv platform without known optimization hint
18467-            std::terminate();
18468-#        endif
18469-#    else  // ^^ NDEBUG
18470-            // For non-release builds, we prefer termination on bug over UB
18471-            std::terminate();
18472-#    endif //
18473-        }
18474-
18475-    } // namespace Detail
18476-} // end namespace Catch
18477-
18478-#endif
18479-
18480-#endif // CATCH_UNREACHABLE_HPP_INCLUDED
18481-
18482-
18483-// All of our user-facing macros support configuration toggle, that
18484-// forces them to be defined prefixed with CATCH_. We also like to
18485-// support another toggle that can minimize (disable) their implementation.
18486-// Given this, we have 4 different configuration options below
18487-
18488-#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
18489-
18490-  #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
18491-  #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
18492-
18493-  #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
18494-  #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
18495-  #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
18496-
18497-  #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18498-  #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
18499-  #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
18500-  #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
18501-  #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
18502-
18503-  #define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18504-  #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
18505-  #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18506-
18507-  #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
18508-  #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
18509-  #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
18510-  #define CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, __VA_ARGS__ )
18511-  #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
18512-  #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
18513-  #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
18514-  #define CATCH_FAIL( ... ) do { \
18515-           INTERNAL_CATCH_MSG("CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ );  \
18516-           Catch::Detail::Unreachable(); \
18517-         } while ( false )
18518-  #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18519-  #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18520-  #define CATCH_SKIP( ... ) do { \
18521-           INTERNAL_CATCH_MSG( "CATCH_SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \
18522-           Catch::Detail::Unreachable(); \
18523-         } while (false)
18524-
18525-
18526-  #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
18527-    #define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
18528-    #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
18529-    #define CATCH_STATIC_CHECK( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
18530-    #define CATCH_STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
18531-  #else
18532-    #define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )
18533-    #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
18534-    #define CATCH_STATIC_CHECK( ... )       CATCH_CHECK( __VA_ARGS__ )
18535-    #define CATCH_STATIC_CHECK_FALSE( ... ) CATCH_CHECK_FALSE( __VA_ARGS__ )
18536-  #endif
18537-
18538-
18539-  // "BDD-style" convenience wrappers
18540-  #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
18541-  #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
18542-  #define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
18543-  #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
18544-  #define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
18545-  #define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
18546-  #define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
18547-  #define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
18548-
18549-#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, implemented | vv prefixed, disabled
18550-
18551-  #define CATCH_REQUIRE( ... )        (void)(0)
18552-  #define CATCH_REQUIRE_FALSE( ... )  (void)(0)
18553-
18554-  #define CATCH_REQUIRE_THROWS( ... ) (void)(0)
18555-  #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
18556-  #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
18557-
18558-  #define CATCH_CHECK( ... )         (void)(0)
18559-  #define CATCH_CHECK_FALSE( ... )   (void)(0)
18560-  #define CATCH_CHECKED_IF( ... )    if (__VA_ARGS__)
18561-  #define CATCH_CHECKED_ELSE( ... )  if (!(__VA_ARGS__))
18562-  #define CATCH_CHECK_NOFAIL( ... )  (void)(0)
18563-
18564-  #define CATCH_CHECK_THROWS( ... )  (void)(0)
18565-  #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
18566-  #define CATCH_CHECK_NOTHROW( ... ) (void)(0)
18567-
18568-  #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
18569-  #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
18570-  #define CATCH_METHOD_AS_TEST_CASE( method, ... )
18571-  #define CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
18572-  #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
18573-  #define CATCH_SECTION( ... )
18574-  #define CATCH_DYNAMIC_SECTION( ... )
18575-  #define CATCH_FAIL( ... ) (void)(0)
18576-  #define CATCH_FAIL_CHECK( ... ) (void)(0)
18577-  #define CATCH_SUCCEED( ... ) (void)(0)
18578-  #define CATCH_SKIP( ... ) (void)(0)
18579-
18580-  #define CATCH_STATIC_REQUIRE( ... )       (void)(0)
18581-  #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
18582-  #define CATCH_STATIC_CHECK( ... )       (void)(0)
18583-  #define CATCH_STATIC_CHECK_FALSE( ... ) (void)(0)
18584-
18585-  // "BDD-style" convenience wrappers
18586-  #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
18587-  #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
18588-  #define CATCH_GIVEN( desc )
18589-  #define CATCH_AND_GIVEN( desc )
18590-  #define CATCH_WHEN( desc )
18591-  #define CATCH_AND_WHEN( desc )
18592-  #define CATCH_THEN( desc )
18593-  #define CATCH_AND_THEN( desc )
18594-
18595-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, disabled | vv unprefixed, implemented
18596-
18597-  #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__  )
18598-  #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
18599-
18600-  #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
18601-  #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
18602-  #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
18603-
18604-  #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18605-  #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
18606-  #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
18607-  #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
18608-  #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
18609-
18610-  #define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18611-  #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
18612-  #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18613-
18614-  #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
18615-  #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
18616-  #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
18617-  #define TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, __VA_ARGS__ )
18618-  #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
18619-  #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
18620-  #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
18621-  #define FAIL( ... ) do { \
18622-           INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \
18623-           Catch::Detail::Unreachable(); \
18624-         } while (false)
18625-  #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18626-  #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
18627-  #define SKIP( ... ) do { \
18628-           INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \
18629-           Catch::Detail::Unreachable(); \
18630-         } while (false)
18631-
18632-
18633-  #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
18634-    #define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
18635-    #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
18636-    #define STATIC_CHECK( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
18637-    #define STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
18638-  #else
18639-    #define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )
18640-    #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
18641-    #define STATIC_CHECK( ... )       CHECK( __VA_ARGS__ )
18642-    #define STATIC_CHECK_FALSE( ... ) CHECK_FALSE( __VA_ARGS__ )
18643-  #endif
18644-
18645-  // "BDD-style" convenience wrappers
18646-  #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
18647-  #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
18648-  #define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
18649-  #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
18650-  #define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
18651-  #define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
18652-  #define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
18653-  #define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
18654-
18655-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ unprefixed, implemented | vv unprefixed, disabled
18656-
18657-  #define REQUIRE( ... )       (void)(0)
18658-  #define REQUIRE_FALSE( ... ) (void)(0)
18659-
18660-  #define REQUIRE_THROWS( ... ) (void)(0)
18661-  #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
18662-  #define REQUIRE_NOTHROW( ... ) (void)(0)
18663-
18664-  #define CHECK( ... ) (void)(0)
18665-  #define CHECK_FALSE( ... ) (void)(0)
18666-  #define CHECKED_IF( ... ) if (__VA_ARGS__)
18667-  #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
18668-  #define CHECK_NOFAIL( ... ) (void)(0)
18669-
18670-  #define CHECK_THROWS( ... )  (void)(0)
18671-  #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
18672-  #define CHECK_NOTHROW( ... ) (void)(0)
18673-
18674-  #define TEST_CASE( ... )  INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
18675-  #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
18676-  #define METHOD_AS_TEST_CASE( method, ... )
18677-  #define TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
18678-  #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
18679-  #define SECTION( ... )
18680-  #define DYNAMIC_SECTION( ... )
18681-  #define FAIL( ... ) (void)(0)
18682-  #define FAIL_CHECK( ... ) (void)(0)
18683-  #define SUCCEED( ... ) (void)(0)
18684-  #define SKIP( ... ) (void)(0)
18685-
18686-  #define STATIC_REQUIRE( ... )       (void)(0)
18687-  #define STATIC_REQUIRE_FALSE( ... ) (void)(0)
18688-  #define STATIC_CHECK( ... )       (void)(0)
18689-  #define STATIC_CHECK_FALSE( ... ) (void)(0)
18690-
18691-  // "BDD-style" convenience wrappers
18692-  #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ) )
18693-  #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
18694-
18695-  #define GIVEN( desc )
18696-  #define AND_GIVEN( desc )
18697-  #define WHEN( desc )
18698-  #define AND_WHEN( desc )
18699-  #define THEN( desc )
18700-  #define AND_THEN( desc )
18701-
18702-#endif // ^^ unprefixed, disabled
18703-
18704-// end of user facing macros
18705-
18706-#endif // CATCH_TEST_MACROS_HPP_INCLUDED
18707-
18708-
18709-#ifndef CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
18710-#define CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
18711-
18712-
18713-
18714-#ifndef CATCH_PREPROCESSOR_HPP_INCLUDED
18715-#define CATCH_PREPROCESSOR_HPP_INCLUDED
18716-
18717-
18718-#if defined(__GNUC__)
18719-// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work
18720-#pragma GCC system_header
18721-#endif
18722-
18723-
18724-namespace Catch {
18725-    namespace Detail {
18726-        template <int N>
18727-        struct priority_tag : priority_tag<N - 1> {};
18728-        template <>
18729-        struct priority_tag<0> {};
18730-    }
18731-}
18732-
18733-#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
18734-#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
18735-#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
18736-#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
18737-#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
18738-#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
18739-
18740-#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18741-#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
18742-// MSVC needs more evaluations
18743-#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
18744-#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
18745-#else
18746-#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)
18747-#endif
18748-
18749-#define CATCH_REC_END(...)
18750-#define CATCH_REC_OUT
18751-
18752-#define CATCH_EMPTY()
18753-#define CATCH_DEFER(id) id CATCH_EMPTY()
18754-
18755-#define CATCH_REC_GET_END2() 0, CATCH_REC_END
18756-#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
18757-#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
18758-#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
18759-#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
18760-#define CATCH_REC_NEXT(test, next)  CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
18761-
18762-#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
18763-#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
18764-#define CATCH_REC_LIST2(f, x, peek, ...)   f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
18765-
18766-#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__ )
18767-#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__ )
18768-#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__ )
18769-
18770-// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
18771-// and passes userdata as the first parameter to each invocation,
18772-// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
18773-#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
18774-
18775-#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
18776-
18777-#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
18778-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18779-#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
18780-#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
18781-#else
18782-// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
18783-#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
18784-#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
18785-#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
18786-#endif
18787-
18788-#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
18789-#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
18790-
18791-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18792-#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>(Catch::Detail::priority_tag<1>{}))
18793-#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
18794-#else
18795-#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>(Catch::Detail::priority_tag<1>{})))
18796-#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
18797-#endif
18798-
18799-#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
18800-    CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
18801-
18802-#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
18803-#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
18804-#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
18805-#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)
18806-#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)
18807-#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)
18808-#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)
18809-#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)
18810-#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)
18811-#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)
18812-#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)
18813-
18814-#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
18815-
18816-#define INTERNAL_CATCH_TYPE_GEN\
18817-    template<typename...> struct TypeList {};\
18818-    template<typename... Ts>\
18819-    constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TypeList<Ts...> { return {}; }\
18820-    template<template<typename...> class...> struct TemplateTypeList{};\
18821-    template<template<typename...> class...Cs>\
18822-    constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TemplateTypeList<Cs...> { return {}; }\
18823-    template<typename...>\
18824-    struct append;\
18825-    template<typename...>\
18826-    struct rewrap;\
18827-    template<template<typename...> class, typename...>\
18828-    struct create;\
18829-    template<template<typename...> class, typename>\
18830-    struct convert;\
18831-    \
18832-    template<typename T> \
18833-    struct append<T> { using type = T; };\
18834-    template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
18835-    struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
18836-    template< template<typename...> class L1, typename...E1, typename...Rest>\
18837-    struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
18838-    \
18839-    template< template<typename...> class Container, template<typename...> class List, typename...elems>\
18840-    struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
18841-    template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
18842-    struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
18843-    \
18844-    template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
18845-    struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
18846-    template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
18847-    struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
18848-
18849-#define INTERNAL_CATCH_NTTP_1(signature, ...)\
18850-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
18851-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18852-    constexpr auto get_wrapper(Catch::Detail::priority_tag<0>) noexcept -> Nttp<__VA_ARGS__> { return {}; } \
18853-    template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
18854-    template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
18855-    constexpr auto get_wrapper(Catch::Detail::priority_tag<0>) noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
18856-    \
18857-    template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18858-    struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
18859-    template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
18860-    struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
18861-    template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
18862-    struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
18863-
18864-#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
18865-#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
18866-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18867-    static void TestName()
18868-#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
18869-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18870-    static void TestName()
18871-
18872-#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
18873-#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
18874-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18875-    static void TestName()
18876-#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
18877-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18878-    static void TestName()
18879-
18880-#define INTERNAL_CATCH_TYPES_REGISTER(TestFunc)\
18881-    template<typename... Ts>\
18882-    void reg_test(TypeList<Ts...>, Catch::NameAndTags nameAndTags)\
18883-    {\
18884-        Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Ts...>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
18885-    }
18886-
18887-#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature, ...)
18888-#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
18889-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18890-    void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
18891-    {\
18892-        Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
18893-    }
18894-
18895-#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
18896-    template<typename Type>\
18897-    void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
18898-    {\
18899-        Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
18900-    }
18901-
18902-#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
18903-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18904-    void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
18905-    {\
18906-        Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
18907-    }
18908-
18909-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
18910-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
18911-    template<typename TestType> \
18912-    struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
18913-        void test();\
18914-    }
18915-
18916-#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
18917-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
18918-    struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
18919-        void test();\
18920-    }
18921-
18922-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
18923-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
18924-    template<typename TestType> \
18925-    void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
18926-#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
18927-    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
18928-    void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
18929-
18930-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18931-#define INTERNAL_CATCH_NTTP_0
18932-#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)
18933-#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__)
18934-#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__)
18935-#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__)
18936-#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_TYPES_REGISTER(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__)
18937-#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__)
18938-#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__)
18939-#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__)
18940-#else
18941-#define INTERNAL_CATCH_NTTP_0(signature)
18942-#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__))
18943-#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__))
18944-#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__))
18945-#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__))
18946-#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_TYPES_REGISTER(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__))
18947-#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__))
18948-#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__))
18949-#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__))
18950-#endif
18951-
18952-#endif // CATCH_PREPROCESSOR_HPP_INCLUDED
18953-
18954-
18955-// GCC 5 and older do not properly handle disabling unused-variable warning
18956-// with a _Pragma. This means that we have to leak the suppression to the
18957-// user code as well :-(
18958-#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
18959-#pragma GCC diagnostic ignored "-Wunused-variable"
18960-#endif
18961-
18962-#if defined(CATCH_CONFIG_DISABLE)
18963-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... )  \
18964-        INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
18965-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... )    \
18966-        namespace{                                                                                  \
18967-            namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                      \
18968-            INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
18969-        }                                                                                           \
18970-        }                                                                                           \
18971-        INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
18972-
18973-    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18974-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
18975-            INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ )
18976-    #else
18977-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
18978-            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
18979-    #endif
18980-
18981-    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18982-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
18983-            INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ )
18984-    #else
18985-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
18986-            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
18987-    #endif
18988-
18989-    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18990-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
18991-            INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
18992-    #else
18993-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
18994-            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
18995-    #endif
18996-
18997-    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18998-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
18999-            INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
19000-    #else
19001-        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
19002-            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
19003-    #endif
19004-#endif
19005-
19006-
19007-    ///////////////////////////////////////////////////////////////////////////////
19008-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
19009-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
19010-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
19011-        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
19012-        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
19013-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
19014-        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
19015-        INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
19016-        namespace {\
19017-        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
19018-            INTERNAL_CATCH_TYPE_GEN\
19019-            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
19020-            INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
19021-            template<typename...Types> \
19022-            struct TestName{\
19023-                TestName(){\
19024-                    size_t index = 0;                                    \
19025-                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
19026-                    using expander = size_t[]; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
19027-                    (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
19028-                }\
19029-            };\
19030-            static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
19031-            TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
19032-            return 0;\
19033-        }();\
19034-        }\
19035-        }\
19036-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
19037-        INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
19038-
19039-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19040-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
19041-        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ )
19042-#else
19043-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
19044-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
19045-#endif
19046-
19047-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19048-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
19049-        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ )
19050-#else
19051-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
19052-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
19053-#endif
19054-
19055-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
19056-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                      \
19057-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \
19058-        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS                \
19059-        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS       \
19060-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
19061-        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
19062-        template<typename TestType> static void TestFuncName();       \
19063-        namespace {\
19064-        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                     \
19065-            INTERNAL_CATCH_TYPE_GEN                                                  \
19066-            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))         \
19067-            template<typename... Types>                               \
19068-            struct TestName {                                         \
19069-                void reg_tests() {                                          \
19070-                    size_t index = 0;                                    \
19071-                    using expander = size_t[];                           \
19072-                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
19073-                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
19074-                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
19075-                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + types_list[index % num_types] + '>', Tags } ), index++)... };/* NOLINT */\
19076-                }                                                     \
19077-            };                                                        \
19078-            static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
19079-                using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(Catch::Detail::priority_tag<1>{})), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
19080-                TestInit t;                                           \
19081-                t.reg_tests();                                        \
19082-                return 0;                                             \
19083-            }();                                                      \
19084-        }                                                             \
19085-        }                                                             \
19086-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
19087-        template<typename TestType>                                   \
19088-        static void TestFuncName()
19089-
19090-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19091-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
19092-        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T,__VA_ARGS__)
19093-#else
19094-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
19095-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T, __VA_ARGS__ ) )
19096-#endif
19097-
19098-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19099-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
19100-        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__)
19101-#else
19102-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
19103-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
19104-#endif
19105-
19106-    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
19107-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
19108-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
19109-        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
19110-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
19111-        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
19112-        template<typename TestType> static void TestFunc();       \
19113-        namespace {\
19114-        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
19115-        INTERNAL_CATCH_TYPE_GEN\
19116-        template<typename... Types>                               \
19117-        struct TestName {                                         \
19118-            void reg_tests() {                                          \
19119-                size_t index = 0;                                    \
19120-                using expander = size_t[];                           \
19121-                (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
19122-            }                                                     \
19123-        };\
19124-        static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
19125-                using TestInit = typename convert<TestName, TmplList>::type; \
19126-                TestInit t;                                           \
19127-                t.reg_tests();                                        \
19128-                return 0;                                             \
19129-            }();                                                      \
19130-        }}\
19131-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
19132-        template<typename TestType>                                   \
19133-        static void TestFunc()
19134-
19135-    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
19136-        INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, TmplList )
19137-
19138-
19139-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
19140-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
19141-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
19142-        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
19143-        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
19144-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
19145-        namespace {\
19146-        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
19147-            INTERNAL_CATCH_TYPE_GEN\
19148-            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
19149-            INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
19150-            INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
19151-            template<typename...Types> \
19152-            struct TestNameClass{\
19153-                TestNameClass(){\
19154-                    size_t index = 0;                                    \
19155-                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
19156-                    using expander = size_t[];\
19157-                    (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
19158-                }\
19159-            };\
19160-            static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
19161-                TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
19162-                return 0;\
19163-        }();\
19164-        }\
19165-        }\
19166-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
19167-        INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
19168-
19169-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19170-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
19171-        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
19172-#else
19173-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
19174-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
19175-#endif
19176-
19177-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19178-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
19179-        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
19180-#else
19181-    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
19182-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
19183-#endif
19184-
19185-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
19186-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
19187-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
19188-        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
19189-        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
19190-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
19191-        template<typename TestType> \
19192-            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
19193-                void test();\
19194-            };\
19195-        namespace {\
19196-        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
19197-            INTERNAL_CATCH_TYPE_GEN                  \
19198-            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
19199-            template<typename...Types>\
19200-            struct TestNameClass{\
19201-                void reg_tests(){\
19202-                    std::size_t index = 0;\
19203-                    using expander = std::size_t[];\
19204-                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
19205-                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
19206-                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
19207-                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + types_list[index % num_types] + '>', Tags } ), index++)... };/* NOLINT */ \
19208-                }\
19209-            };\
19210-            static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
19211-                using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>(Catch::Detail::priority_tag<1>{})), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
19212-                TestInit t;\
19213-                t.reg_tests();\
19214-                return 0;\
19215-            }(); \
19216-        }\
19217-        }\
19218-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
19219-        template<typename TestType> \
19220-        void TestName<TestType>::test()
19221-
19222-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19223-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
19224-        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
19225-#else
19226-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
19227-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
19228-#endif
19229-
19230-#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19231-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
19232-        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
19233-#else
19234-    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
19235-        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
19236-#endif
19237-
19238-    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
19239-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
19240-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
19241-        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
19242-        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
19243-        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
19244-        template<typename TestType> \
19245-        struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
19246-            void test();\
19247-        };\
19248-        namespace {\
19249-        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
19250-            INTERNAL_CATCH_TYPE_GEN\
19251-            template<typename...Types>\
19252-            struct TestNameClass{\
19253-                void reg_tests(){\
19254-                    size_t index = 0;\
19255-                    using expander = size_t[];\
19256-                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
19257-                }\
19258-            };\
19259-            static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
19260-                using TestInit = typename convert<TestNameClass, TmplList>::type;\
19261-                TestInit t;\
19262-                t.reg_tests();\
19263-                return 0;\
19264-            }(); \
19265-        }}\
19266-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
19267-        template<typename TestType> \
19268-        void TestName<TestType>::test()
19269-
19270-#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
19271-        INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, TmplList )
19272-
19273-
19274-#endif // CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
19275-
19276-
19277-#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
19278-
19279-  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19280-    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
19281-    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
19282-    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19283-    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
19284-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
19285-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
19286-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
19287-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
19288-    #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
19289-    #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
19290-  #else
19291-    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
19292-    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
19293-    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
19294-    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
19295-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
19296-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
19297-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
19298-    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
19299-    #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
19300-    #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
19301-  #endif
19302-
19303-#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
19304-
19305-  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19306-    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
19307-    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
19308-    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
19309-    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
19310-  #else
19311-    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
19312-    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
19313-    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
19314-    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
19315-  #endif
19316-
19317-  // When disabled, these can be shared between proper preprocessor and MSVC preprocessor
19318-  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
19319-  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
19320-  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19321-  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19322-  #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
19323-  #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19324-
19325-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
19326-
19327-  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19328-    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
19329-    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
19330-    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19331-    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
19332-    #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
19333-    #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
19334-    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
19335-    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
19336-    #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
19337-    #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
19338-  #else
19339-    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
19340-    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
19341-    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
19342-    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
19343-    #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
19344-    #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
19345-    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
19346-    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
19347-    #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
19348-    #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
19349-  #endif
19350-
19351-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
19352-
19353-  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
19354-    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
19355-    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
19356-    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
19357-    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
19358-  #else
19359-    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
19360-    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
19361-    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
19362-    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
19363-  #endif
19364-
19365-  // When disabled, these can be shared between proper preprocessor and MSVC preprocessor
19366-  #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
19367-  #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
19368-  #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19369-  #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19370-  #define TEMPLATE_LIST_TEST_CASE( ... ) TEMPLATE_TEST_CASE(__VA_ARGS__)
19371-  #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
19372-
19373-#endif // end of user facing macro declarations
19374-
19375-
19376-#endif // CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
19377-
19378-
19379-#ifndef CATCH_TEST_CASE_INFO_HPP_INCLUDED
19380-#define CATCH_TEST_CASE_INFO_HPP_INCLUDED
19381-
19382-
19383-
19384-#include <cstdint>
19385-#include <string>
19386-#include <vector>
19387-
19388-#ifdef __clang__
19389-#pragma clang diagnostic push
19390-#pragma clang diagnostic ignored "-Wpadded"
19391-#endif
19392-
19393-namespace Catch {
19394-
19395-    /**
19396-     * A **view** of a tag string that provides case insensitive comparisons
19397-     *
19398-     * Note that in Catch2 internals, the square brackets around tags are
19399-     * not a part of tag's representation, so e.g. "[cool-tag]" is represented
19400-     * as "cool-tag" internally.
19401-     */
19402-    struct Tag {
19403-        constexpr Tag(StringRef original_):
19404-            original(original_)
19405-        {}
19406-        StringRef original;
19407-
19408-        friend bool operator< ( Tag const& lhs, Tag const& rhs );
19409-        friend bool operator==( Tag const& lhs, Tag const& rhs );
19410-    };
19411-
19412-    class ITestInvoker;
19413-    struct NameAndTags;
19414-
19415-    enum class TestCaseProperties : uint8_t {
19416-        None = 0,
19417-        IsHidden = 1 << 1,
19418-        ShouldFail = 1 << 2,
19419-        MayFail = 1 << 3,
19420-        Throws = 1 << 4,
19421-        NonPortable = 1 << 5,
19422-        Benchmark = 1 << 6
19423-    };
19424-
19425-    /**
19426-     * Various metadata about the test case.
19427-     *
19428-     * A test case is uniquely identified by its (class)name and tags
19429-     * combination, with source location being ignored, and other properties
19430-     * being determined from tags.
19431-     *
19432-     * Tags are kept sorted.
19433-     */
19434-    struct TestCaseInfo : Detail::NonCopyable {
19435-
19436-        TestCaseInfo(StringRef _className,
19437-                     NameAndTags const& _nameAndTags,
19438-                     SourceLineInfo const& _lineInfo);
19439-
19440-        bool isHidden() const;
19441-        bool throws() const;
19442-        bool okToFail() const;
19443-        bool expectedToFail() const;
19444-
19445-        // Adds the tag(s) with test's filename (for the -# flag)
19446-        void addFilenameTag();
19447-
19448-        //! Orders by name, classname and tags
19449-        friend bool operator<( TestCaseInfo const& lhs,
19450-                               TestCaseInfo const& rhs );
19451-
19452-
19453-        std::string tagsAsString() const;
19454-
19455-        std::string name;
19456-        StringRef className;
19457-    private:
19458-        std::string backingTags;
19459-        // Internally we copy tags to the backing storage and then add
19460-        // refs to this storage to the tags vector.
19461-        void internalAppendTag(StringRef tagString);
19462-    public:
19463-        std::vector<Tag> tags;
19464-        SourceLineInfo lineInfo;
19465-        TestCaseProperties properties = TestCaseProperties::None;
19466-    };
19467-
19468-    /**
19469-     * Wrapper over the test case information and the test case invoker
19470-     *
19471-     * Does not own either, and is specifically made to be cheap
19472-     * to copy around.
19473-     */
19474-    class TestCaseHandle {
19475-        TestCaseInfo* m_info;
19476-        ITestInvoker* m_invoker;
19477-    public:
19478-        constexpr TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) :
19479-            m_info(info), m_invoker(invoker) {}
19480-
19481-        void prepareTestCase() const {
19482-            m_invoker->prepareTestCase();
19483-        }
19484-
19485-        void tearDownTestCase() const {
19486-            m_invoker->tearDownTestCase();
19487-        }
19488-
19489-        void invoke() const {
19490-            m_invoker->invoke();
19491-        }
19492-
19493-        constexpr TestCaseInfo const& getTestCaseInfo() const {
19494-            return *m_info;
19495-        }
19496-    };
19497-
19498-    Detail::unique_ptr<TestCaseInfo>
19499-    makeTestCaseInfo( StringRef className,
19500-                      NameAndTags const& nameAndTags,
19501-                      SourceLineInfo const& lineInfo );
19502-}
19503-
19504-#ifdef __clang__
19505-#pragma clang diagnostic pop
19506-#endif
19507-
19508-#endif // CATCH_TEST_CASE_INFO_HPP_INCLUDED
19509-
19510-
19511-#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
19512-#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
19513-
19514-
19515-namespace Catch {
19516-
19517-    struct TestRunInfo {
19518-        constexpr TestRunInfo(StringRef _name) : name(_name) {}
19519-        StringRef name;
19520-    };
19521-
19522-} // end namespace Catch
19523-
19524-#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED
19525-
19526-
19527-#ifndef CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
19528-#define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
19529-
19530-
19531-
19532-#ifndef CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
19533-#define CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
19534-
19535-
19536-#include <string>
19537-#include <vector>
19538-
19539-namespace Catch {
19540-    using exceptionTranslateFunction = std::string(*)();
19541-
19542-    class IExceptionTranslator;
19543-    using ExceptionTranslators = std::vector<Detail::unique_ptr<IExceptionTranslator const>>;
19544-
19545-    class IExceptionTranslator {
19546-    public:
19547-        virtual ~IExceptionTranslator(); // = default
19548-        virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
19549-    };
19550-
19551-    class IExceptionTranslatorRegistry {
19552-    public:
19553-        virtual ~IExceptionTranslatorRegistry(); // = default
19554-        virtual std::string translateActiveException() const = 0;
19555-    };
19556-
19557-} // namespace Catch
19558-
19559-#endif // CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
19560-
19561-#include <exception>
19562-
19563-namespace Catch {
19564-    namespace Detail {
19565-        void registerTranslatorImpl(
19566-            Detail::unique_ptr<IExceptionTranslator>&& translator );
19567-    }
19568-
19569-    class ExceptionTranslatorRegistrar {
19570-        template<typename T>
19571-        class ExceptionTranslator : public IExceptionTranslator {
19572-        public:
19573-
19574-            constexpr ExceptionTranslator( std::string(*translateFunction)( T const& ) )
19575-            : m_translateFunction( translateFunction )
19576-            {}
19577-
19578-            std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
19579-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
19580-                try {
19581-                    if( it == itEnd )
19582-                        std::rethrow_exception(std::current_exception());
19583-                    else
19584-                        return (*it)->translate( it+1, itEnd );
19585-                }
19586-                catch( T const& ex ) {
19587-                    return m_translateFunction( ex );
19588-                }
19589-#else
19590-                return "You should never get here!";
19591-#endif
19592-            }
19593-
19594-        protected:
19595-            std::string(*m_translateFunction)( T const& );
19596-        };
19597-
19598-    public:
19599-        template<typename T>
19600-        ExceptionTranslatorRegistrar( std::string(*translateFunction)( T const& ) ) {
19601-            Detail::registerTranslatorImpl(
19602-                Detail::make_unique<ExceptionTranslator<T>>(
19603-                    translateFunction ) );
19604-        }
19605-    };
19606-
19607-} // namespace Catch
19608-
19609-///////////////////////////////////////////////////////////////////////////////
19610-#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
19611-    static std::string translatorName( signature ); \
19612-    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
19613-    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
19614-    namespace{ const Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
19615-    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
19616-    static std::string translatorName( signature )
19617-
19618-#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
19619-
19620-#if defined(CATCH_CONFIG_DISABLE)
19621-    #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
19622-            static std::string translatorName( signature )
19623-#endif
19624-
19625-
19626-// This macro is always prefixed
19627-#if !defined(CATCH_CONFIG_DISABLE)
19628-#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
19629-#else
19630-#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
19631-#endif
19632-
19633-
19634-#endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
19635-
19636-
19637-#ifndef CATCH_VERSION_HPP_INCLUDED
19638-#define CATCH_VERSION_HPP_INCLUDED
19639-
19640-#include <iosfwd>
19641-
19642-namespace Catch {
19643-
19644-    // Versioning information
19645-    struct Version {
19646-        Version( Version const& ) = delete;
19647-        Version& operator=( Version const& ) = delete;
19648-        Version(    unsigned int _majorVersion,
19649-                    unsigned int _minorVersion,
19650-                    unsigned int _patchNumber,
19651-                    char const * const _branchName,
19652-                    unsigned int _buildNumber );
19653-
19654-        unsigned int const majorVersion;
19655-        unsigned int const minorVersion;
19656-        unsigned int const patchNumber;
19657-
19658-        // buildNumber is only used if branchName is not null
19659-        char const * const branchName;
19660-        unsigned int const buildNumber;
19661-
19662-        friend std::ostream& operator << ( std::ostream& os, Version const& version );
19663-    };
19664-
19665-    Version const& libraryVersion();
19666-}
19667-
19668-#endif // CATCH_VERSION_HPP_INCLUDED
19669-
19670-
19671-#ifndef CATCH_VERSION_MACROS_HPP_INCLUDED
19672-#define CATCH_VERSION_MACROS_HPP_INCLUDED
19673-
19674-#define CATCH_VERSION_MAJOR 3
19675-#define CATCH_VERSION_MINOR 11
19676-#define CATCH_VERSION_PATCH 0
19677-
19678-#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
19679-
19680-
19681-/** \file
19682- * This is a convenience header for Catch2's Generator support. It includes
19683- * **all** of Catch2 headers related to generators.
19684- *
19685- * Generally the Catch2 users should use specific includes they need,
19686- * but this header can be used instead for ease-of-experimentation, or
19687- * just plain convenience, at the cost of (significantly) increased
19688- * compilation times.
19689- *
19690- * When a new header is added to either the `generators` folder,
19691- * or to the corresponding internal subfolder, it should be added here.
19692- */
19693-
19694-#ifndef CATCH_GENERATORS_ALL_HPP_INCLUDED
19695-#define CATCH_GENERATORS_ALL_HPP_INCLUDED
19696-
19697-
19698-
19699-#ifndef CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
19700-#define CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
19701-
19702-#include <exception>
19703-
19704-namespace Catch {
19705-
19706-    // Exception type to be thrown when a Generator runs into an error,
19707-    // e.g. it cannot initialize the first return value based on
19708-    // runtime information
19709-    class GeneratorException : public std::exception {
19710-        const char* const m_msg = "";
19711-
19712-    public:
19713-        GeneratorException(const char* msg):
19714-            m_msg(msg)
19715-        {}
19716-
19717-        const char* what() const noexcept final;
19718-    };
19719-
19720-} // end namespace Catch
19721-
19722-#endif // CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
19723-
19724-
19725-#ifndef CATCH_GENERATORS_HPP_INCLUDED
19726-#define CATCH_GENERATORS_HPP_INCLUDED
19727-
19728-
19729-
19730-#ifndef CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
19731-#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
19732-
19733-
19734-#include <string>
19735-
19736-namespace Catch {
19737-
19738-    namespace Generators {
19739-        class GeneratorUntypedBase {
19740-            // Caches result from `toStringImpl`, assume that when it is an
19741-            // empty string, the cache is invalidated.
19742-            mutable std::string m_stringReprCache;
19743-
19744-            // Counts based on `next` returning true
19745-            std::size_t m_currentElementIndex = 0;
19746-
19747-            /**
19748-             * Attempts to move the generator to the next element
19749-             *
19750-             * Returns true iff the move succeeded (and a valid element
19751-             * can be retrieved).
19752-             */
19753-            virtual bool next() = 0;
19754-
19755-            //! Customization point for `currentElementAsString`
19756-            virtual std::string stringifyImpl() const = 0;
19757-
19758-        public:
19759-            GeneratorUntypedBase() = default;
19760-            // Generation of copy ops is deprecated (and Clang will complain)
19761-            // if there is a user destructor defined
19762-            GeneratorUntypedBase(GeneratorUntypedBase const&) = default;
19763-            GeneratorUntypedBase& operator=(GeneratorUntypedBase const&) = default;
19764-
19765-            virtual ~GeneratorUntypedBase(); // = default;
19766-
19767-            /**
19768-             * Attempts to move the generator to the next element
19769-             *
19770-             * Serves as a non-virtual interface to `next`, so that the
19771-             * top level interface can provide sanity checking and shared
19772-             * features.
19773-             *
19774-             * As with `next`, returns true iff the move succeeded and
19775-             * the generator has new valid element to provide.
19776-             */
19777-            bool countedNext();
19778-
19779-            std::size_t currentElementIndex() const { return m_currentElementIndex; }
19780-
19781-            /**
19782-             * Returns generator's current element as user-friendly string.
19783-             *
19784-             * By default returns string equivalent to calling
19785-             * `Catch::Detail::stringify` on the current element, but generators
19786-             * can customize their implementation as needed.
19787-             *
19788-             * Not thread-safe due to internal caching.
19789-             *
19790-             * The returned ref is valid only until the generator instance
19791-             * is destructed, or it moves onto the next element, whichever
19792-             * comes first.
19793-             */
19794-            StringRef currentElementAsString() const;
19795-        };
19796-        using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
19797-
19798-    } // namespace Generators
19799-
19800-    class IGeneratorTracker {
19801-    public:
19802-        virtual ~IGeneratorTracker(); // = default;
19803-        virtual auto hasGenerator() const -> bool = 0;
19804-        virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
19805-        virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
19806-    };
19807-
19808-} // namespace Catch
19809-
19810-#endif // CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
19811-
19812-#include <vector>
19813-#include <tuple>
19814-
19815-namespace Catch {
19816-
19817-namespace Generators {
19818-
19819-namespace Detail {
19820-
19821-    //! Throws GeneratorException with the provided message
19822-    [[noreturn]]
19823-    void throw_generator_exception(char const * msg);
19824-
19825-} // end namespace detail
19826-
19827-    template<typename T>
19828-    class IGenerator : public GeneratorUntypedBase {
19829-        std::string stringifyImpl() const override {
19830-            return ::Catch::Detail::stringify( get() );
19831-        }
19832-
19833-    public:
19834-        // Returns the current element of the generator
19835-        //
19836-        // \Precondition The generator is either freshly constructed,
19837-        // or the last call to `next()` returned true
19838-        virtual T const& get() const = 0;
19839-        using type = T;
19840-    };
19841-
19842-    template <typename T>
19843-    using GeneratorPtr = Catch::Detail::unique_ptr<IGenerator<T>>;
19844-
19845-    template <typename T>
19846-    class GeneratorWrapper final {
19847-        GeneratorPtr<T> m_generator;
19848-    public:
19849-        //! Takes ownership of the passed pointer.
19850-        GeneratorWrapper(IGenerator<T>* generator):
19851-            m_generator(generator) {}
19852-        GeneratorWrapper(GeneratorPtr<T> generator):
19853-            m_generator(CATCH_MOVE(generator)) {}
19854-
19855-        T const& get() const {
19856-            return m_generator->get();
19857-        }
19858-        bool next() {
19859-            return m_generator->countedNext();
19860-        }
19861-    };
19862-
19863-
19864-    template<typename T>
19865-    class SingleValueGenerator final : public IGenerator<T> {
19866-        T m_value;
19867-    public:
19868-        SingleValueGenerator(T const& value) :
19869-            m_value(value)
19870-        {}
19871-        SingleValueGenerator(T&& value):
19872-            m_value(CATCH_MOVE(value))
19873-        {}
19874-
19875-        T const& get() const override {
19876-            return m_value;
19877-        }
19878-        bool next() override {
19879-            return false;
19880-        }
19881-    };
19882-
19883-    template<typename T>
19884-    class FixedValuesGenerator final : public IGenerator<T> {
19885-        static_assert(!std::is_same<T, bool>::value,
19886-            "FixedValuesGenerator does not support bools because of std::vector<bool>"
19887-            "specialization, use SingleValue Generator instead.");
19888-        std::vector<T> m_values;
19889-        size_t m_idx = 0;
19890-    public:
19891-        FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
19892-
19893-        T const& get() const override {
19894-            return m_values[m_idx];
19895-        }
19896-        bool next() override {
19897-            ++m_idx;
19898-            return m_idx < m_values.size();
19899-        }
19900-    };
19901-
19902-    template <typename T, typename DecayedT = std::decay_t<T>>
19903-    GeneratorWrapper<DecayedT> value( T&& value ) {
19904-        return GeneratorWrapper<DecayedT>(
19905-            Catch::Detail::make_unique<SingleValueGenerator<DecayedT>>(
19906-                CATCH_FORWARD( value ) ) );
19907-    }
19908-    template <typename T>
19909-    GeneratorWrapper<T> values(std::initializer_list<T> values) {
19910-        return GeneratorWrapper<T>(Catch::Detail::make_unique<FixedValuesGenerator<T>>(values));
19911-    }
19912-
19913-    template<typename T>
19914-    class Generators : public IGenerator<T> {
19915-        std::vector<GeneratorWrapper<T>> m_generators;
19916-        size_t m_current = 0;
19917-
19918-        void add_generator( GeneratorWrapper<T>&& generator ) {
19919-            m_generators.emplace_back( CATCH_MOVE( generator ) );
19920-        }
19921-        void add_generator( T const& val ) {
19922-            m_generators.emplace_back( value( val ) );
19923-        }
19924-        void add_generator( T&& val ) {
19925-            m_generators.emplace_back( value( CATCH_MOVE( val ) ) );
19926-        }
19927-        template <typename U>
19928-        std::enable_if_t<!std::is_same<std::decay_t<U>, T>::value>
19929-        add_generator( U&& val ) {
19930-            add_generator( T( CATCH_FORWARD( val ) ) );
19931-        }
19932-
19933-        template <typename U> void add_generators( U&& valueOrGenerator ) {
19934-            add_generator( CATCH_FORWARD( valueOrGenerator ) );
19935-        }
19936-
19937-        template <typename U, typename... Gs>
19938-        void add_generators( U&& valueOrGenerator, Gs&&... moreGenerators ) {
19939-            add_generator( CATCH_FORWARD( valueOrGenerator ) );
19940-            add_generators( CATCH_FORWARD( moreGenerators )... );
19941-        }
19942-
19943-    public:
19944-        template <typename... Gs>
19945-        Generators(Gs &&... moreGenerators) {
19946-            m_generators.reserve(sizeof...(Gs));
19947-            add_generators(CATCH_FORWARD(moreGenerators)...);
19948-        }
19949-
19950-        T const& get() const override {
19951-            return m_generators[m_current].get();
19952-        }
19953-
19954-        bool next() override {
19955-            if (m_current >= m_generators.size()) {
19956-                return false;
19957-            }
19958-            const bool current_status = m_generators[m_current].next();
19959-            if (!current_status) {
19960-                ++m_current;
19961-            }
19962-            return m_current < m_generators.size();
19963-        }
19964-    };
19965-
19966-
19967-    template <typename... Ts>
19968-    GeneratorWrapper<std::tuple<std::decay_t<Ts>...>>
19969-    table( std::initializer_list<std::tuple<std::decay_t<Ts>...>> tuples ) {
19970-        return values<std::tuple<Ts...>>( tuples );
19971-    }
19972-
19973-    // Tag type to signal that a generator sequence should convert arguments to a specific type
19974-    template <typename T>
19975-    struct as {};
19976-
19977-    template<typename T, typename... Gs>
19978-    auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
19979-        return Generators<T>(CATCH_MOVE(generator), CATCH_FORWARD(moreGenerators)...);
19980-    }
19981-    template<typename T>
19982-    auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
19983-        return Generators<T>(CATCH_MOVE(generator));
19984-    }
19985-    template<typename T, typename... Gs>
19986-    auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<std::decay_t<T>> {
19987-        return makeGenerators( value( CATCH_FORWARD( val ) ), CATCH_FORWARD( moreGenerators )... );
19988-    }
19989-    template<typename T, typename U, typename... Gs>
19990-    auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
19991-        return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... );
19992-    }
19993-
19994-    IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName,
19995-                                                SourceLineInfo const& lineInfo );
19996-    IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
19997-                                               SourceLineInfo lineInfo,
19998-                                               GeneratorBasePtr&& generator );
19999-
20000-    template<typename L>
20001-    auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
20002-        using UnderlyingType = typename decltype(generatorExpression())::type;
20003-
20004-        IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo );
20005-        // Creation of tracker is delayed after generator creation, so
20006-        // that constructing generator can fail without breaking everything.
20007-        if (!tracker) {
20008-            tracker = createGeneratorTracker(
20009-                generatorName,
20010-                lineInfo,
20011-                Catch::Detail::make_unique<Generators<UnderlyingType>>(
20012-                    generatorExpression() ) );
20013-        }
20014-
20015-        auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker->getGenerator() );
20016-        return generator.get();
20017-    }
20018-
20019-} // namespace Generators
20020-} // namespace Catch
20021-
20022-#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
20023-#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
20024-
20025-#define GENERATE( ... ) \
20026-    Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
20027-                                 CATCH_INTERNAL_LINEINFO, \
20028-                                 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
20029-#define GENERATE_COPY( ... ) \
20030-    Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
20031-                                 CATCH_INTERNAL_LINEINFO, \
20032-                                 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
20033-#define GENERATE_REF( ... ) \
20034-    Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
20035-                                 CATCH_INTERNAL_LINEINFO, \
20036-                                 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
20037-
20038-#endif // CATCH_GENERATORS_HPP_INCLUDED
20039-
20040-
20041-#ifndef CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
20042-#define CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
20043-
20044-
20045-#include <cassert>
20046-
20047-namespace Catch {
20048-namespace Generators {
20049-
20050-    template <typename T>
20051-    class TakeGenerator final : public IGenerator<T> {
20052-        GeneratorWrapper<T> m_generator;
20053-        size_t m_returned = 0;
20054-        size_t m_target;
20055-    public:
20056-        TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
20057-            m_generator(CATCH_MOVE(generator)),
20058-            m_target(target)
20059-        {
20060-            assert(target != 0 && "Empty generators are not allowed");
20061-        }
20062-        T const& get() const override {
20063-            return m_generator.get();
20064-        }
20065-        bool next() override {
20066-            ++m_returned;
20067-            if (m_returned >= m_target) {
20068-                return false;
20069-            }
20070-
20071-            const auto success = m_generator.next();
20072-            // If the underlying generator does not contain enough values
20073-            // then we cut short as well
20074-            if (!success) {
20075-                m_returned = m_target;
20076-            }
20077-            return success;
20078-        }
20079-    };
20080-
20081-    template <typename T>
20082-    GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
20083-        return GeneratorWrapper<T>(Catch::Detail::make_unique<TakeGenerator<T>>(target, CATCH_MOVE(generator)));
20084-    }
20085-
20086-
20087-    template <typename T, typename Predicate>
20088-    class FilterGenerator final : public IGenerator<T> {
20089-        GeneratorWrapper<T> m_generator;
20090-        Predicate m_predicate;
20091-        static_assert(!std::is_reference<Predicate>::value, "This would most likely result in a dangling reference");
20092-    public:
20093-        template <typename P>
20094-        FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
20095-            m_generator(CATCH_MOVE(generator)),
20096-            m_predicate(CATCH_FORWARD(pred))
20097-        {
20098-            if (!m_predicate(m_generator.get())) {
20099-                // It might happen that there are no values that pass the
20100-                // filter. In that case we throw an exception.
20101-                auto has_initial_value = next();
20102-                if (!has_initial_value) {
20103-                    Detail::throw_generator_exception("No valid value found in filtered generator");
20104-                }
20105-            }
20106-        }
20107-
20108-        T const& get() const override {
20109-            return m_generator.get();
20110-        }
20111-
20112-        bool next() override {
20113-            bool success = m_generator.next();
20114-            if (!success) {
20115-                return false;
20116-            }
20117-            while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
20118-            return success;
20119-        }
20120-    };
20121-
20122-
20123-    template <typename T, typename Predicate>
20124-    GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
20125-        return GeneratorWrapper<T>(Catch::Detail::make_unique<FilterGenerator<T, typename std::remove_reference<Predicate>::type>>(CATCH_FORWARD(pred), CATCH_MOVE(generator)));
20126-    }
20127-
20128-    template <typename T>
20129-    class RepeatGenerator final : public IGenerator<T> {
20130-        static_assert(!std::is_same<T, bool>::value,
20131-            "RepeatGenerator currently does not support bools"
20132-            "because of std::vector<bool> specialization");
20133-        GeneratorWrapper<T> m_generator;
20134-        mutable std::vector<T> m_returned;
20135-        size_t m_target_repeats;
20136-        size_t m_current_repeat = 0;
20137-        size_t m_repeat_index = 0;
20138-    public:
20139-        RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
20140-            m_generator(CATCH_MOVE(generator)),
20141-            m_target_repeats(repeats)
20142-        {
20143-            assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
20144-        }
20145-
20146-        T const& get() const override {
20147-            if (m_current_repeat == 0) {
20148-                m_returned.push_back(m_generator.get());
20149-                return m_returned.back();
20150-            }
20151-            return m_returned[m_repeat_index];
20152-        }
20153-
20154-        bool next() override {
20155-            // There are 2 basic cases:
20156-            // 1) We are still reading the generator
20157-            // 2) We are reading our own cache
20158-
20159-            // In the first case, we need to poke the underlying generator.
20160-            // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
20161-            if (m_current_repeat == 0) {
20162-                const auto success = m_generator.next();
20163-                if (!success) {
20164-                    ++m_current_repeat;
20165-                }
20166-                return m_current_repeat < m_target_repeats;
20167-            }
20168-
20169-            // In the second case, we need to move indices forward and check that we haven't run up against the end
20170-            ++m_repeat_index;
20171-            if (m_repeat_index == m_returned.size()) {
20172-                m_repeat_index = 0;
20173-                ++m_current_repeat;
20174-            }
20175-            return m_current_repeat < m_target_repeats;
20176-        }
20177-    };
20178-
20179-    template <typename T>
20180-    GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
20181-        return GeneratorWrapper<T>(Catch::Detail::make_unique<RepeatGenerator<T>>(repeats, CATCH_MOVE(generator)));
20182-    }
20183-
20184-    template <typename T, typename U, typename Func>
20185-    class MapGenerator final : public IGenerator<T> {
20186-        // TBD: provide static assert for mapping function, for friendly error message
20187-        GeneratorWrapper<U> m_generator;
20188-        Func m_function;
20189-        // To avoid returning dangling reference, we have to save the values
20190-        T m_cache;
20191-    public:
20192-        template <typename F2 = Func>
20193-        MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
20194-            m_generator(CATCH_MOVE(generator)),
20195-            m_function(CATCH_FORWARD(function)),
20196-            m_cache(m_function(m_generator.get()))
20197-        {}
20198-
20199-        T const& get() const override {
20200-            return m_cache;
20201-        }
20202-        bool next() override {
20203-            const auto success = m_generator.next();
20204-            if (success) {
20205-                m_cache = m_function(m_generator.get());
20206-            }
20207-            return success;
20208-        }
20209-    };
20210-
20211-    template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
20212-    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
20213-        return GeneratorWrapper<T>(
20214-            Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
20215-        );
20216-    }
20217-
20218-    template <typename T, typename U, typename Func>
20219-    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
20220-        return GeneratorWrapper<T>(
20221-            Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
20222-        );
20223-    }
20224-
20225-    template <typename T>
20226-    class ChunkGenerator final : public IGenerator<std::vector<T>> {
20227-        std::vector<T> m_chunk;
20228-        size_t m_chunk_size;
20229-        GeneratorWrapper<T> m_generator;
20230-        bool m_used_up = false;
20231-    public:
20232-        ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
20233-            m_chunk_size(size), m_generator(CATCH_MOVE(generator))
20234-        {
20235-            m_chunk.reserve(m_chunk_size);
20236-            if (m_chunk_size != 0) {
20237-                m_chunk.push_back(m_generator.get());
20238-                for (size_t i = 1; i < m_chunk_size; ++i) {
20239-                    if (!m_generator.next()) {
20240-                        Detail::throw_generator_exception("Not enough values to initialize the first chunk");
20241-                    }
20242-                    m_chunk.push_back(m_generator.get());
20243-                }
20244-            }
20245-        }
20246-        std::vector<T> const& get() const override {
20247-            return m_chunk;
20248-        }
20249-        bool next() override {
20250-            m_chunk.clear();
20251-            for (size_t idx = 0; idx < m_chunk_size; ++idx) {
20252-                if (!m_generator.next()) {
20253-                    return false;
20254-                }
20255-                m_chunk.push_back(m_generator.get());
20256-            }
20257-            return true;
20258-        }
20259-    };
20260-
20261-    template <typename T>
20262-    GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
20263-        return GeneratorWrapper<std::vector<T>>(
20264-            Catch::Detail::make_unique<ChunkGenerator<T>>(size, CATCH_MOVE(generator))
20265-        );
20266-    }
20267-
20268-} // namespace Generators
20269-} // namespace Catch
20270-
20271-
20272-#endif // CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
20273-
20274-
20275-#ifndef CATCH_GENERATORS_RANDOM_HPP_INCLUDED
20276-#define CATCH_GENERATORS_RANDOM_HPP_INCLUDED
20277-
20278-
20279-
20280-#ifndef CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
20281-#define CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
20282-
20283-#include <cstdint>
20284-
20285-namespace Catch {
20286-
20287-    // This is a simple implementation of C++11 Uniform Random Number
20288-    // Generator. It does not provide all operators, because Catch2
20289-    // does not use it, but it should behave as expected inside stdlib's
20290-    // distributions.
20291-    // The implementation is based on the PCG family (http://pcg-random.org)
20292-    class SimplePcg32 {
20293-        using state_type = std::uint64_t;
20294-    public:
20295-        using result_type = std::uint32_t;
20296-        static constexpr result_type (min)() {
20297-            return 0;
20298-        }
20299-        static constexpr result_type (max)() {
20300-            return static_cast<result_type>(-1);
20301-        }
20302-
20303-        // Provide some default initial state for the default constructor
20304-        SimplePcg32():SimplePcg32(0xed743cc4U) {}
20305-
20306-        explicit SimplePcg32(result_type seed_);
20307-
20308-        void seed(result_type seed_);
20309-        void discard(uint64_t skip);
20310-
20311-        result_type operator()();
20312-
20313-    private:
20314-        friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
20315-        friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
20316-
20317-        // In theory we also need operator<< and operator>>
20318-        // In practice we do not use them, so we will skip them for now
20319-
20320-
20321-        std::uint64_t m_state;
20322-        // This part of the state determines which "stream" of the numbers
20323-        // is chosen -- we take it as a constant for Catch2, so we only
20324-        // need to deal with seeding the main state.
20325-        // Picked by reading 8 bytes from `/dev/random` :-)
20326-        static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
20327-    };
20328-
20329-} // end namespace Catch
20330-
20331-#endif // CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
20332-
20333-
20334-
20335-#ifndef CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
20336-#define CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
20337-
20338-
20339-
20340-
20341-#ifndef CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
20342-#define CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
20343-
20344-#include <climits>
20345-#include <cstddef>
20346-#include <cstdint>
20347-#include <type_traits>
20348-
20349-// Note: We use the usual enable-disable-autodetect dance here even though
20350-//       we do not support these in CMake configuration options (yet?).
20351-//       It is highly unlikely that we will need to make these actually
20352-//       user-configurable, but this will make it simpler if weend up needing
20353-//       it, and it provides an escape hatch to the users who need it.
20354-#if defined( __SIZEOF_INT128__ )
20355-#    define CATCH_CONFIG_INTERNAL_UINT128
20356-// Unlike GCC, MSVC does not polyfill umul as mulh + mul pair on ARM machines.
20357-// Currently we do not bother doing this ourselves, but we could if it became
20358-// important for perf.
20359-#elif defined( _MSC_VER ) && defined( _M_X64 )
20360-#    define CATCH_CONFIG_INTERNAL_MSVC_UMUL128
20361-#endif
20362-
20363-#if defined( CATCH_CONFIG_INTERNAL_UINT128 ) && \
20364-    !defined( CATCH_CONFIG_NO_UINT128 ) &&      \
20365-    !defined( CATCH_CONFIG_UINT128 )
20366-#define CATCH_CONFIG_UINT128
20367-#endif
20368-
20369-#if defined( CATCH_CONFIG_INTERNAL_MSVC_UMUL128 ) && \
20370-    !defined( CATCH_CONFIG_NO_MSVC_UMUL128 ) &&      \
20371-    !defined( CATCH_CONFIG_MSVC_UMUL128 )
20372-#    define CATCH_CONFIG_MSVC_UMUL128
20373-#    include <intrin.h>
20374-#endif
20375-
20376-
20377-namespace Catch {
20378-    namespace Detail {
20379-
20380-        template <std::size_t>
20381-        struct SizedUnsignedType;
20382-#define SizedUnsignedTypeHelper( TYPE )        \
20383-    template <>                                \
20384-    struct SizedUnsignedType<sizeof( TYPE )> { \
20385-        using type = TYPE;                     \
20386-    }
20387-
20388-        SizedUnsignedTypeHelper( std::uint8_t );
20389-        SizedUnsignedTypeHelper( std::uint16_t );
20390-        SizedUnsignedTypeHelper( std::uint32_t );
20391-        SizedUnsignedTypeHelper( std::uint64_t );
20392-#undef SizedUnsignedTypeHelper
20393-
20394-        template <std::size_t sz>
20395-        using SizedUnsignedType_t = typename SizedUnsignedType<sz>::type;
20396-
20397-        template <typename T>
20398-        using DoubleWidthUnsignedType_t = SizedUnsignedType_t<2 * sizeof( T )>;
20399-
20400-        template <typename T>
20401-        struct ExtendedMultResult {
20402-            T upper;
20403-            T lower;
20404-            constexpr bool operator==( ExtendedMultResult const& rhs ) const {
20405-                return upper == rhs.upper && lower == rhs.lower;
20406-            }
20407-        };
20408-
20409-        /**
20410-         * Returns 128 bit result of lhs * rhs using portable C++ code
20411-         *
20412-         * This implementation is almost twice as fast as naive long multiplication,
20413-         * and unlike intrinsic-based approach, it supports constexpr evaluation.
20414-         */
20415-        constexpr ExtendedMultResult<std::uint64_t>
20416-        extendedMultPortable(std::uint64_t lhs, std::uint64_t rhs) {
20417-#define CarryBits( x ) ( x >> 32 )
20418-#define Digits( x ) ( x & 0xFF'FF'FF'FF )
20419-            std::uint64_t lhs_low = Digits( lhs );
20420-            std::uint64_t rhs_low = Digits( rhs );
20421-            std::uint64_t low_low = ( lhs_low * rhs_low );
20422-            std::uint64_t high_high = CarryBits( lhs ) * CarryBits( rhs );
20423-
20424-            // We add in carry bits from low-low already
20425-            std::uint64_t high_low =
20426-                ( CarryBits( lhs ) * rhs_low ) + CarryBits( low_low );
20427-            // Note that we can add only low bits from high_low, to avoid
20428-            // overflow with large inputs
20429-            std::uint64_t low_high =
20430-                ( lhs_low * CarryBits( rhs ) ) + Digits( high_low );
20431-
20432-            return { high_high + CarryBits( high_low ) + CarryBits( low_high ),
20433-                     ( low_high << 32 ) | Digits( low_low ) };
20434-#undef CarryBits
20435-#undef Digits
20436-        }
20437-
20438-        //! Returns 128 bit result of lhs * rhs
20439-        inline ExtendedMultResult<std::uint64_t>
20440-        extendedMult( std::uint64_t lhs, std::uint64_t rhs ) {
20441-#if defined( CATCH_CONFIG_UINT128 )
20442-            auto result = __uint128_t( lhs ) * __uint128_t( rhs );
20443-            return { static_cast<std::uint64_t>( result >> 64 ),
20444-                     static_cast<std::uint64_t>( result ) };
20445-#elif defined( CATCH_CONFIG_MSVC_UMUL128 )
20446-            std::uint64_t high;
20447-            std::uint64_t low = _umul128( lhs, rhs, &high );
20448-            return { high, low };
20449-#else
20450-            return extendedMultPortable( lhs, rhs );
20451-#endif
20452-        }
20453-
20454-
20455-        template <typename UInt>
20456-        constexpr ExtendedMultResult<UInt> extendedMult( UInt lhs, UInt rhs ) {
20457-            static_assert( std::is_unsigned<UInt>::value,
20458-                           "extendedMult can only handle unsigned integers" );
20459-            static_assert( sizeof( UInt ) < sizeof( std::uint64_t ),
20460-                           "Generic extendedMult can only handle types smaller "
20461-                           "than uint64_t" );
20462-            using WideType = DoubleWidthUnsignedType_t<UInt>;
20463-
20464-            auto result = WideType( lhs ) * WideType( rhs );
20465-            return {
20466-                static_cast<UInt>( result >> ( CHAR_BIT * sizeof( UInt ) ) ),
20467-                static_cast<UInt>( result & UInt( -1 ) ) };
20468-        }
20469-
20470-
20471-        template <typename TargetType,
20472-                  typename Generator>
20473-            std::enable_if_t<sizeof(typename Generator::result_type) >= sizeof(TargetType),
20474-            TargetType> fillBitsFrom(Generator& gen) {
20475-            using gresult_type = typename Generator::result_type;
20476-            static_assert( std::is_unsigned<TargetType>::value, "Only unsigned integers are supported" );
20477-            static_assert( Generator::min() == 0 &&
20478-                           Generator::max() == static_cast<gresult_type>( -1 ),
20479-                           "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
20480-
20481-            // We want to return the top bits from a generator, as they are
20482-            // usually considered higher quality.
20483-            constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
20484-            constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
20485-
20486-            return static_cast<TargetType>( gen() >>
20487-                                            ( generated_bits - return_bits) );
20488-        }
20489-
20490-        template <typename TargetType,
20491-                  typename Generator>
20492-            std::enable_if_t<sizeof(typename Generator::result_type) < sizeof(TargetType),
20493-            TargetType> fillBitsFrom(Generator& gen) {
20494-            using gresult_type = typename Generator::result_type;
20495-            static_assert( std::is_unsigned<TargetType>::value,
20496-                           "Only unsigned integers are supported" );
20497-            static_assert( Generator::min() == 0 &&
20498-                           Generator::max() == static_cast<gresult_type>( -1 ),
20499-                           "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
20500-
20501-            constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
20502-            constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
20503-            std::size_t filled_bits = 0;
20504-            TargetType ret = 0;
20505-            do {
20506-                ret <<= generated_bits;
20507-                ret |= gen();
20508-                filled_bits += generated_bits;
20509-            } while ( filled_bits < return_bits );
20510-
20511-            return ret;
20512-        }
20513-
20514-        /*
20515-         * Transposes numbers into unsigned type while keeping their ordering
20516-         *
20517-         * This means that signed types are changed so that the ordering is
20518-         * [INT_MIN, ..., -1, 0, ..., INT_MAX], rather than order we would
20519-         * get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1])
20520-         */
20521-        template <typename OriginalType, typename UnsignedType>
20522-        constexpr
20523-        std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType>
20524-        transposeToNaturalOrder( UnsignedType in ) {
20525-            static_assert(
20526-                sizeof( OriginalType ) == sizeof( UnsignedType ),
20527-                "reordering requires the same sized types on both sides" );
20528-            static_assert( std::is_unsigned<UnsignedType>::value,
20529-                           "Input type must be unsigned" );
20530-            // Assuming 2s complement (standardized in current C++), the
20531-            // positive and negative numbers are already internally ordered,
20532-            // and their difference is in the top bit. Swapping it orders
20533-            // them the desired way.
20534-            constexpr auto highest_bit =
20535-                UnsignedType( 1 ) << ( sizeof( UnsignedType ) * CHAR_BIT - 1 );
20536-            return static_cast<UnsignedType>( in ^ highest_bit );
20537-        }
20538-
20539-
20540-
20541-        template <typename OriginalType,
20542-                  typename UnsignedType>
20543-        constexpr
20544-        std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType>
20545-            transposeToNaturalOrder(UnsignedType in) {
20546-            static_assert(
20547-                sizeof( OriginalType ) == sizeof( UnsignedType ),
20548-                "reordering requires the same sized types on both sides" );
20549-            static_assert( std::is_unsigned<UnsignedType>::value, "Input type must be unsigned" );
20550-            // No reordering is needed for unsigned -> unsigned
20551-            return in;
20552-        }
20553-    } // namespace Detail
20554-} // namespace Catch
20555-
20556-#endif // CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
20557-
20558-namespace Catch {
20559-
20560-/**
20561- * Implementation of uniform distribution on integers.
20562- *
20563- * Unlike `std::uniform_int_distribution`, this implementation supports
20564- * various 1 byte integral types, including bool (but you should not
20565- * actually use it for bools).
20566- *
20567- * The underlying algorithm is based on the one described in "Fast Random
20568- * Integer Generation in an Interval" by Daniel Lemire, but has been
20569- * optimized under the assumption of reuse of the same distribution object.
20570- */
20571-template <typename IntegerType>
20572-class uniform_integer_distribution {
20573-    static_assert(std::is_integral<IntegerType>::value, "...");
20574-
20575-    using UnsignedIntegerType = Detail::SizedUnsignedType_t<sizeof(IntegerType)>;
20576-
20577-    // Only the left bound is stored, and we store it converted to its
20578-    // unsigned image. This avoids having to do the conversions inside
20579-    // the operator(), at the cost of having to do the conversion in
20580-    // the a() getter. The right bound is only needed in the b() getter,
20581-    // so we recompute it there from other stored data.
20582-    UnsignedIntegerType m_a;
20583-
20584-    // How many different values are there in [a, b]. a == b => 1, can be 0 for distribution over all values in the type.
20585-    UnsignedIntegerType m_ab_distance;
20586-
20587-    // We hoisted this out of the main generation function. Technically,
20588-    // this means that using this distribution will be slower than Lemire's
20589-    // algorithm if this distribution instance will be used only few times,
20590-    // but it will be faster if it is used many times. Since Catch2 uses
20591-    // distributions only to implement random generators, we assume that each
20592-    // distribution will be reused many times and this is an optimization.
20593-    UnsignedIntegerType m_rejection_threshold = 0;
20594-
20595-    static constexpr UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) {
20596-        // This overflows and returns 0 if a == 0 and b == TYPE_MAX.
20597-        // We handle that later when generating the number.
20598-        return transposeTo(b) - transposeTo(a) + 1;
20599-    }
20600-
20601-    static constexpr UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) {
20602-        // distance == 0 means that we will return all possible values from
20603-        // the type's range, and that we shouldn't reject anything.
20604-        if ( ab_distance == 0 ) { return 0; }
20605-        return ( ~ab_distance + 1 ) % ab_distance;
20606-    }
20607-
20608-    static constexpr UnsignedIntegerType transposeTo(IntegerType in) {
20609-        return Detail::transposeToNaturalOrder<IntegerType>(
20610-            static_cast<UnsignedIntegerType>( in ) );
20611-    }
20612-    static constexpr IntegerType transposeBack(UnsignedIntegerType in) {
20613-        return static_cast<IntegerType>(
20614-            Detail::transposeToNaturalOrder<IntegerType>(in) );
20615-    }
20616-
20617-public:
20618-    using result_type = IntegerType;
20619-
20620-    constexpr uniform_integer_distribution( IntegerType a, IntegerType b ):
20621-        m_a( transposeTo(a) ),
20622-        m_ab_distance( computeDistance(a, b) ),
20623-        m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) {
20624-        assert( a <= b );
20625-    }
20626-
20627-    template <typename Generator>
20628-    constexpr result_type operator()( Generator& g ) {
20629-        // All possible values of result_type are valid.
20630-        if ( m_ab_distance == 0 ) {
20631-            return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) );
20632-        }
20633-
20634-        auto random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
20635-        auto emul = Detail::extendedMult( random_number, m_ab_distance );
20636-        // Unlike Lemire's algorithm we skip the ab_distance check, since
20637-        // we precomputed the rejection threshold, which is always tighter.
20638-        while (emul.lower < m_rejection_threshold) {
20639-            random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
20640-            emul = Detail::extendedMult( random_number, m_ab_distance );
20641-        }
20642-
20643-        return transposeBack(m_a + emul.upper);
20644-    }
20645-
20646-    constexpr result_type a() const { return transposeBack(m_a); }
20647-    constexpr result_type b() const { return transposeBack(m_ab_distance + m_a - 1); }
20648-};
20649-
20650-} // end namespace Catch
20651-
20652-#endif // CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
20653-
20654-
20655-
20656-#ifndef CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
20657-#define CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
20658-
20659-
20660-
20661-
20662-#ifndef CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
20663-#define CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
20664-
20665-
20666-
20667-#ifndef CATCH_POLYFILLS_HPP_INCLUDED
20668-#define CATCH_POLYFILLS_HPP_INCLUDED
20669-
20670-namespace Catch {
20671-
20672-    bool isnan(float f);
20673-    bool isnan(double d);
20674-
20675-    float nextafter(float x, float y);
20676-    double nextafter(double x, double y);
20677-
20678-}
20679-
20680-#endif // CATCH_POLYFILLS_HPP_INCLUDED
20681-
20682-#include <cassert>
20683-#include <cmath>
20684-#include <cstdint>
20685-#include <limits>
20686-#include <type_traits>
20687-
20688-namespace Catch {
20689-
20690-    namespace Detail {
20691-        /**
20692-         * Returns the largest magnitude of 1-ULP distance inside the [a, b] range.
20693-         *
20694-         * Assumes `a < b`.
20695-         */
20696-        template <typename FloatType>
20697-        FloatType gamma(FloatType a, FloatType b) {
20698-            static_assert( std::is_floating_point<FloatType>::value,
20699-                           "gamma returns the largest ULP magnitude within "
20700-                           "floating point range [a, b]. This only makes sense "
20701-                           "for floating point types" );
20702-            assert( a <= b );
20703-
20704-            const auto gamma_up = Catch::nextafter( a, std::numeric_limits<FloatType>::infinity() ) - a;
20705-            const auto gamma_down = b - Catch::nextafter( b, -std::numeric_limits<FloatType>::infinity() );
20706-
20707-            return gamma_up < gamma_down ? gamma_down : gamma_up;
20708-        }
20709-
20710-        template <typename FloatingPoint>
20711-        struct DistanceTypePicker;
20712-        template <>
20713-        struct DistanceTypePicker<float> {
20714-            using type = std::uint32_t;
20715-        };
20716-        template <>
20717-        struct DistanceTypePicker<double> {
20718-            using type = std::uint64_t;
20719-        };
20720-
20721-        template <typename T>
20722-        using DistanceType = typename DistanceTypePicker<T>::type;
20723-
20724-#if defined( __GNUC__ ) || defined( __clang__ )
20725-#    pragma GCC diagnostic push
20726-#    pragma GCC diagnostic ignored "-Wfloat-equal"
20727-#endif
20728-        /**
20729-         * Computes the number of equi-distant floats in [a, b]
20730-         *
20731-         * Since not every range can be split into equidistant floats
20732-         * exactly, we actually compute ceil(b/distance - a/distance),
20733-         * because in those cases we want to overcount.
20734-         *
20735-         * Uses modified Dekker's FastTwoSum algorithm to handle rounding.
20736-         */
20737-        template <typename FloatType>
20738-        DistanceType<FloatType>
20739-        count_equidistant_floats( FloatType a, FloatType b, FloatType distance ) {
20740-            assert( a <= b );
20741-            // We get distance as gamma for our uniform float distribution,
20742-            // so this will round perfectly.
20743-            const auto ag = a / distance;
20744-            const auto bg = b / distance;
20745-
20746-            const auto s = bg - ag;
20747-            const auto err = ( std::fabs( a ) <= std::fabs( b ) )
20748-                                 ? -ag - ( s - bg )
20749-                                 : bg - ( s + ag );
20750-            const auto ceil_s = static_cast<DistanceType<FloatType>>( std::ceil( s ) );
20751-
20752-            return ( ceil_s != s ) ? ceil_s : ceil_s + ( err > 0 );
20753-        }
20754-#if defined( __GNUC__ ) || defined( __clang__ )
20755-#    pragma GCC diagnostic pop
20756-#endif
20757-
20758-    }
20759-
20760-} // end namespace Catch
20761-
20762-#endif // CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
20763-
20764-#include <cmath>
20765-#include <type_traits>
20766-
20767-namespace Catch {
20768-
20769-    namespace Detail {
20770-#if defined( __GNUC__ ) || defined( __clang__ )
20771-#    pragma GCC diagnostic push
20772-#    pragma GCC diagnostic ignored "-Wfloat-equal"
20773-#endif
20774-        // The issue with overflow only happens with maximal ULP and HUGE
20775-        // distance, e.g. when generating numbers in [-inf, inf] for given
20776-        // type. So we only check for the largest possible ULP in the
20777-        // type, and return something that does not overflow to inf in 1 mult.
20778-        constexpr std::uint64_t calculate_max_steps_in_one_go(double gamma) {
20779-            if ( gamma == 1.99584030953472e+292 ) { return 9007199254740991; }
20780-            return static_cast<std::uint64_t>( -1 );
20781-        }
20782-        constexpr std::uint32_t calculate_max_steps_in_one_go(float gamma) {
20783-            if ( gamma == 2.028241e+31f ) { return 16777215; }
20784-            return static_cast<std::uint32_t>( -1 );
20785-        }
20786-#if defined( __GNUC__ ) || defined( __clang__ )
20787-#    pragma GCC diagnostic pop
20788-#endif
20789-    }
20790-
20791-/**
20792- * Implementation of uniform distribution on floating point numbers.
20793- *
20794- * Note that we support only `float` and `double` types, because these
20795- * usually mean the same thing across different platform. `long double`
20796- * varies wildly by platform and thus we cannot provide reproducible
20797- * implementation. Also note that we don't implement all parts of
20798- * distribution per standard: this distribution is not serializable, nor
20799- * can the range be arbitrarily reset.
20800- *
20801- * The implementation also uses different approach than the one taken by
20802- * `std::uniform_real_distribution`, where instead of generating a number
20803- * between [0, 1) and then multiplying the range bounds with it, we first
20804- * split the [a, b] range into a set of equidistributed floating point
20805- * numbers, and then use uniform int distribution to pick which one to
20806- * return.
20807- *
20808- * This has the advantage of guaranteeing uniformity (the multiplication
20809- * method loses uniformity due to rounding when multiplying floats), except
20810- * for small non-uniformity at one side of the interval, where we have
20811- * to deal with the fact that not every interval is splittable into
20812- * equidistributed floats.
20813- *
20814- * Based on "Drawing random floating-point numbers from an interval" by
20815- * Frederic Goualard.
20816- */
20817-template <typename FloatType>
20818-class uniform_floating_point_distribution {
20819-    static_assert(std::is_floating_point<FloatType>::value, "...");
20820-    static_assert(!std::is_same<FloatType, long double>::value,
20821-                  "We do not support long double due to inconsistent behaviour between platforms");
20822-
20823-    using WidthType = Detail::DistanceType<FloatType>;
20824-
20825-    FloatType m_a, m_b;
20826-    FloatType m_ulp_magnitude;
20827-    WidthType m_floats_in_range;
20828-    uniform_integer_distribution<WidthType> m_int_dist;
20829-
20830-    // In specific cases, we can overflow into `inf` when computing the
20831-    // `steps * g` offset. To avoid this, we don't offset by more than this
20832-    // in one multiply + addition.
20833-    WidthType m_max_steps_in_one_go;
20834-    // We don't want to do the magnitude check every call to `operator()`
20835-    bool m_a_has_leq_magnitude;
20836-
20837-public:
20838-    using result_type = FloatType;
20839-
20840-    uniform_floating_point_distribution( FloatType a, FloatType b ):
20841-        m_a( a ),
20842-        m_b( b ),
20843-        m_ulp_magnitude( Detail::gamma( m_a, m_b ) ),
20844-        m_floats_in_range( Detail::count_equidistant_floats( m_a, m_b, m_ulp_magnitude ) ),
20845-        m_int_dist(0, m_floats_in_range),
20846-        m_max_steps_in_one_go( Detail::calculate_max_steps_in_one_go(m_ulp_magnitude)),
20847-        m_a_has_leq_magnitude(std::fabs(m_a) <= std::fabs(m_b))
20848-    {
20849-        assert( a <= b );
20850-    }
20851-
20852-    template <typename Generator>
20853-    result_type operator()( Generator& g ) {
20854-        WidthType steps = m_int_dist( g );
20855-        if ( m_a_has_leq_magnitude ) {
20856-            if ( steps == m_floats_in_range ) { return m_a; }
20857-            auto b = m_b;
20858-            while (steps > m_max_steps_in_one_go) {
20859-                b -= m_max_steps_in_one_go * m_ulp_magnitude;
20860-                steps -= m_max_steps_in_one_go;
20861-            }
20862-            return b - steps * m_ulp_magnitude;
20863-        } else {
20864-            if ( steps == m_floats_in_range ) { return m_b; }
20865-            auto a = m_a;
20866-            while (steps > m_max_steps_in_one_go) {
20867-                a += m_max_steps_in_one_go * m_ulp_magnitude;
20868-                steps -= m_max_steps_in_one_go;
20869-            }
20870-            return a + steps * m_ulp_magnitude;
20871-        }
20872-    }
20873-
20874-    result_type a() const { return m_a; }
20875-    result_type b() const { return m_b; }
20876-};
20877-
20878-} // end namespace Catch
20879-
20880-#endif // CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
20881-
20882-namespace Catch {
20883-namespace Generators {
20884-namespace Detail {
20885-    // Returns a suitable seed for a random floating generator based off
20886-    // the primary internal rng. It does so by taking current value from
20887-    // the rng and returning it as the seed.
20888-    std::uint32_t getSeed();
20889-}
20890-
20891-template <typename Float>
20892-class RandomFloatingGenerator final : public IGenerator<Float> {
20893-    Catch::SimplePcg32 m_rng;
20894-    Catch::uniform_floating_point_distribution<Float> m_dist;
20895-    Float m_current_number;
20896-public:
20897-    RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
20898-        m_rng(seed),
20899-        m_dist(a, b) {
20900-        static_cast<void>(next());
20901-    }
20902-
20903-    Float const& get() const override {
20904-        return m_current_number;
20905-    }
20906-    bool next() override {
20907-        m_current_number = m_dist(m_rng);
20908-        return true;
20909-    }
20910-};
20911-
20912-template <>
20913-class RandomFloatingGenerator<long double> final : public IGenerator<long double> {
20914-    // We still rely on <random> for this specialization, but we don't
20915-    // want to drag it into the header.
20916-    struct PImpl;
20917-    Catch::Detail::unique_ptr<PImpl> m_pimpl;
20918-    long double m_current_number;
20919-
20920-public:
20921-    RandomFloatingGenerator( long double a, long double b, std::uint32_t seed );
20922-
20923-    long double const& get() const override { return m_current_number; }
20924-    bool next() override;
20925-
20926-    ~RandomFloatingGenerator() override; // = default
20927-};
20928-
20929-template <typename Integer>
20930-class RandomIntegerGenerator final : public IGenerator<Integer> {
20931-    Catch::SimplePcg32 m_rng;
20932-    Catch::uniform_integer_distribution<Integer> m_dist;
20933-    Integer m_current_number;
20934-public:
20935-    RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
20936-        m_rng(seed),
20937-        m_dist(a, b) {
20938-        static_cast<void>(next());
20939-    }
20940-
20941-    Integer const& get() const override {
20942-        return m_current_number;
20943-    }
20944-    bool next() override {
20945-        m_current_number = m_dist(m_rng);
20946-        return true;
20947-    }
20948-};
20949-
20950-template <typename T>
20951-std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>>
20952-random(T a, T b) {
20953-    return GeneratorWrapper<T>(
20954-        Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
20955-    );
20956-}
20957-
20958-template <typename T>
20959-std::enable_if_t<std::is_floating_point<T>::value,
20960-GeneratorWrapper<T>>
20961-random(T a, T b) {
20962-    return GeneratorWrapper<T>(
20963-        Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed())
20964-    );
20965-}
20966-
20967-
20968-} // namespace Generators
20969-} // namespace Catch
20970-
20971-
20972-#endif // CATCH_GENERATORS_RANDOM_HPP_INCLUDED
20973-
20974-
20975-#ifndef CATCH_GENERATORS_RANGE_HPP_INCLUDED
20976-#define CATCH_GENERATORS_RANGE_HPP_INCLUDED
20977-
20978-
20979-#include <iterator>
20980-#include <type_traits>
20981-
20982-namespace Catch {
20983-namespace Generators {
20984-
20985-
20986-template <typename T>
20987-class RangeGenerator final : public IGenerator<T> {
20988-    T m_current;
20989-    T m_end;
20990-    T m_step;
20991-    bool m_positive;
20992-
20993-public:
20994-    RangeGenerator(T const& start, T const& end, T const& step):
20995-        m_current(start),
20996-        m_end(end),
20997-        m_step(step),
20998-        m_positive(m_step > T(0))
20999-    {
21000-        assert(m_current != m_end && "Range start and end cannot be equal");
21001-        assert(m_step != T(0) && "Step size cannot be zero");
21002-        assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
21003-    }
21004-
21005-    RangeGenerator(T const& start, T const& end):
21006-        RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
21007-    {}
21008-
21009-    T const& get() const override {
21010-        return m_current;
21011-    }
21012-
21013-    bool next() override {
21014-        m_current += m_step;
21015-        return (m_positive) ? (m_current < m_end) : (m_current > m_end);
21016-    }
21017-};
21018-
21019-template <typename T>
21020-GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
21021-    static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
21022-    return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end, step));
21023-}
21024-
21025-template <typename T>
21026-GeneratorWrapper<T> range(T const& start, T const& end) {
21027-    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
21028-    return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end));
21029-}
21030-
21031-
21032-template <typename T>
21033-class IteratorGenerator final : public IGenerator<T> {
21034-    static_assert(!std::is_same<T, bool>::value,
21035-        "IteratorGenerator currently does not support bools"
21036-        "because of std::vector<bool> specialization");
21037-
21038-    std::vector<T> m_elems;
21039-    size_t m_current = 0;
21040-public:
21041-    template <typename InputIterator, typename InputSentinel>
21042-    IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
21043-        if (m_elems.empty()) {
21044-            Detail::throw_generator_exception("IteratorGenerator received no valid values");
21045-        }
21046-    }
21047-
21048-    T const& get() const override {
21049-        return m_elems[m_current];
21050-    }
21051-
21052-    bool next() override {
21053-        ++m_current;
21054-        return m_current != m_elems.size();
21055-    }
21056-};
21057-
21058-template <typename InputIterator,
21059-          typename InputSentinel,
21060-          typename ResultType = std::remove_const_t<typename std::iterator_traits<InputIterator>::value_type>>
21061-GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
21062-    return GeneratorWrapper<ResultType>(Catch::Detail::make_unique<IteratorGenerator<ResultType>>(from, to));
21063-}
21064-
21065-template <typename Container>
21066-auto from_range(Container const& cnt) {
21067-    using std::begin;
21068-    using std::end;
21069-    return from_range( begin( cnt ), end( cnt ) );
21070-}
21071-
21072-
21073-} // namespace Generators
21074-} // namespace Catch
21075-
21076-
21077-#endif // CATCH_GENERATORS_RANGE_HPP_INCLUDED
21078-
21079-#endif // CATCH_GENERATORS_ALL_HPP_INCLUDED
21080-
21081-
21082-/** \file
21083- * This is a convenience header for Catch2's interfaces. It includes
21084- * **all** of Catch2 headers related to interfaces.
21085- *
21086- * Generally the Catch2 users should use specific includes they need,
21087- * but this header can be used instead for ease-of-experimentation, or
21088- * just plain convenience, at the cost of somewhat increased compilation
21089- * times.
21090- *
21091- * When a new header is added to either the `interfaces` folder, or to
21092- * the corresponding internal subfolder, it should be added here.
21093- */
21094-
21095-
21096-#ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED
21097-#define CATCH_INTERFACES_ALL_HPP_INCLUDED
21098-
21099-
21100-
21101-#ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED
21102-#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED
21103-
21104-
21105-#include <map>
21106-#include <string>
21107-#include <vector>
21108-
21109-namespace Catch {
21110-
21111-    struct ReporterDescription;
21112-    struct ListenerDescription;
21113-    struct TagInfo;
21114-    struct TestCaseInfo;
21115-    class TestCaseHandle;
21116-    class IConfig;
21117-    class IStream;
21118-    enum class ColourMode : std::uint8_t;
21119-
21120-    struct ReporterConfig {
21121-        ReporterConfig( IConfig const* _fullConfig,
21122-                        Detail::unique_ptr<IStream> _stream,
21123-                        ColourMode colourMode,
21124-                        std::map<std::string, std::string> customOptions );
21125-
21126-        ReporterConfig( ReporterConfig&& ) = default;
21127-        ReporterConfig& operator=( ReporterConfig&& ) = default;
21128-        ~ReporterConfig(); // = default
21129-
21130-        Detail::unique_ptr<IStream> takeStream() &&;
21131-        IConfig const* fullConfig() const;
21132-        ColourMode colourMode() const;
21133-        std::map<std::string, std::string> const& customOptions() const;
21134-
21135-    private:
21136-        Detail::unique_ptr<IStream> m_stream;
21137-        IConfig const* m_fullConfig;
21138-        ColourMode m_colourMode;
21139-        std::map<std::string, std::string> m_customOptions;
21140-    };
21141-
21142-    struct AssertionStats {
21143-        AssertionStats( AssertionResult const& _assertionResult,
21144-                        std::vector<MessageInfo> const& _infoMessages,
21145-                        Totals const& _totals );
21146-
21147-        AssertionStats( AssertionStats const& )              = default;
21148-        AssertionStats( AssertionStats && )                  = default;
21149-        AssertionStats& operator = ( AssertionStats const& ) = delete;
21150-        AssertionStats& operator = ( AssertionStats && )     = delete;
21151-
21152-        AssertionResult assertionResult;
21153-        std::vector<MessageInfo> infoMessages;
21154-        Totals totals;
21155-    };
21156-
21157-    struct SectionStats {
21158-        SectionStats(   SectionInfo&& _sectionInfo,
21159-                        Counts const& _assertions,
21160-                        double _durationInSeconds,
21161-                        bool _missingAssertions );
21162-
21163-        SectionInfo sectionInfo;
21164-        Counts assertions;
21165-        double durationInSeconds;
21166-        bool missingAssertions;
21167-    };
21168-
21169-    struct TestCaseStats {
21170-        TestCaseStats(  TestCaseInfo const& _testInfo,
21171-                        Totals const& _totals,
21172-                        std::string&& _stdOut,
21173-                        std::string&& _stdErr,
21174-                        bool _aborting );
21175-
21176-        TestCaseInfo const * testInfo;
21177-        Totals totals;
21178-        std::string stdOut;
21179-        std::string stdErr;
21180-        bool aborting;
21181-    };
21182-
21183-    struct TestRunStats {
21184-        TestRunStats(   TestRunInfo const& _runInfo,
21185-                        Totals const& _totals,
21186-                        bool _aborting );
21187-
21188-        TestRunInfo runInfo;
21189-        Totals totals;
21190-        bool aborting;
21191-    };
21192-
21193-    //! By setting up its preferences, a reporter can modify Catch2's behaviour
21194-    //! in some regards, e.g. it can request Catch2 to capture writes to
21195-    //! stdout/stderr during test execution, and pass them to the reporter.
21196-    struct ReporterPreferences {
21197-        //! Catch2 should redirect writes to stdout and pass them to the
21198-        //! reporter
21199-        bool shouldRedirectStdOut = false;
21200-        //! Catch2 should call `Reporter::assertionEnded` even for passing
21201-        //! assertions
21202-        bool shouldReportAllAssertions = false;
21203-        //! Catch2 should call `Reporter::assertionStarting` for all assertions
21204-        // Defaults to true for backwards compatibility, but none of our current
21205-        // reporters actually want this, and it enables a fast path in assertion
21206-        // handling.
21207-        bool shouldReportAllAssertionStarts = true;
21208-    };
21209-
21210-    /**
21211-     * The common base for all reporters and event listeners
21212-     *
21213-     * Implementing classes must also implement:
21214-     *
21215-     *     //! User-friendly description of the reporter/listener type
21216-     *     static std::string getDescription()
21217-     *
21218-     * Generally shouldn't be derived from by users of Catch2 directly,
21219-     * instead they should derive from one of the utility bases that
21220-     * derive from this class.
21221-     */
21222-    class IEventListener {
21223-    protected:
21224-        //! Derived classes can set up their preferences here
21225-        ReporterPreferences m_preferences;
21226-        //! The test run's config as filled in from CLI and defaults
21227-        IConfig const* m_config;
21228-
21229-    public:
21230-        IEventListener( IConfig const* config ): m_config( config ) {}
21231-
21232-        virtual ~IEventListener(); // = default;
21233-
21234-        // Implementing class must also provide the following static methods:
21235-        // static std::string getDescription();
21236-
21237-        ReporterPreferences const& getPreferences() const {
21238-            return m_preferences;
21239-        }
21240-
21241-        //! Called when no test cases match provided test spec
21242-        virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0;
21243-        //! Called for all invalid test specs from the cli
21244-        virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0;
21245-
21246-        /**
21247-         * Called once in a testing run before tests are started
21248-         *
21249-         * Not called if tests won't be run (e.g. only listing will happen)
21250-         */
21251-        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
21252-
21253-        //! Called _once_ for each TEST_CASE, no matter how many times it is entered
21254-        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
21255-        //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
21256-        virtual void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) = 0;
21257-        //! Called when a `SECTION` is being entered. Not called for skipped sections
21258-        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
21259-
21260-        //! Called when user-code is being probed before the actual benchmark runs
21261-        virtual void benchmarkPreparing( StringRef benchmarkName ) = 0;
21262-        //! Called after probe but before the user-code is being benchmarked
21263-        virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0;
21264-        //! Called with the benchmark results if benchmark successfully finishes
21265-        virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0;
21266-        //! Called if running the benchmarks fails for any reason
21267-        virtual void benchmarkFailed( StringRef benchmarkName ) = 0;
21268-
21269-        //! Called before assertion success/failure is evaluated
21270-        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
21271-
21272-        //! Called after assertion was fully evaluated
21273-        virtual void assertionEnded( AssertionStats const& assertionStats ) = 0;
21274-
21275-        //! Called after a `SECTION` has finished running
21276-        virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
21277-        //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
21278-        virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber ) = 0;
21279-        //! Called _once_ for each TEST_CASE, no matter how many times it is entered
21280-        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
21281-        /**
21282-         * Called once after all tests in a testing run are finished
21283-         *
21284-         * Not called if tests weren't run (e.g. only listings happened)
21285-         */
21286-        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
21287-
21288-        /**
21289-         * Called with test cases that are skipped due to the test run aborting.
21290-         * NOT called for test cases that are explicitly skipped using the `SKIP` macro.
21291-         *
21292-         * Deprecated - will be removed in the next major release.
21293-         */
21294-        virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
21295-
21296-        //! Called if a fatal error (signal/structured exception) occurred
21297-        virtual void fatalErrorEncountered( StringRef error ) = 0;
21298-
21299-        //! Writes out information about provided reporters using reporter-specific format
21300-        virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
21301-        //! Writes out the provided listeners descriptions using reporter-specific format
21302-        virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0;
21303-        //! Writes out information about provided tests using reporter-specific format
21304-        virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
21305-        //! Writes out information about the provided tags using reporter-specific format
21306-        virtual void listTags(std::vector<TagInfo> const& tags) = 0;
21307-    };
21308-    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
21309-
21310-} // end namespace Catch
21311-
21312-#endif // CATCH_INTERFACES_REPORTER_HPP_INCLUDED
21313-
21314-
21315-#ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
21316-#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
21317-
21318-
21319-#include <string>
21320-
21321-namespace Catch {
21322-
21323-    struct ReporterConfig;
21324-    class IConfig;
21325-    class IEventListener;
21326-    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
21327-
21328-
21329-    class IReporterFactory {
21330-    public:
21331-        virtual ~IReporterFactory(); // = default
21332-
21333-        virtual IEventListenerPtr
21334-        create( ReporterConfig&& config ) const = 0;
21335-        virtual std::string getDescription() const = 0;
21336-    };
21337-    using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
21338-
21339-    class EventListenerFactory {
21340-    public:
21341-        virtual ~EventListenerFactory(); // = default
21342-        virtual IEventListenerPtr create( IConfig const* config ) const = 0;
21343-        //! Return a meaningful name for the listener, e.g. its type name
21344-        virtual StringRef getName() const = 0;
21345-        //! Return listener's description if available
21346-        virtual std::string getDescription() const = 0;
21347-    };
21348-} // namespace Catch
21349-
21350-#endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
21351-
21352-
21353-#ifndef CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
21354-#define CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
21355-
21356-#include <string>
21357-
21358-namespace Catch {
21359-
21360-    struct TagAlias;
21361-
21362-    class ITagAliasRegistry {
21363-    public:
21364-        virtual ~ITagAliasRegistry(); // = default
21365-        // Nullptr if not present
21366-        virtual TagAlias const* find( std::string const& alias ) const = 0;
21367-        virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
21368-
21369-        static ITagAliasRegistry const& get();
21370-    };
21371-
21372-} // end namespace Catch
21373-
21374-#endif // CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
21375-
21376-
21377-#ifndef CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
21378-#define CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
21379-
21380-#include <vector>
21381-
21382-namespace Catch {
21383-
21384-    struct TestCaseInfo;
21385-    class TestCaseHandle;
21386-    class IConfig;
21387-
21388-    class ITestCaseRegistry {
21389-    public:
21390-        virtual ~ITestCaseRegistry(); // = default
21391-        // TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later
21392-        virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0;
21393-        virtual std::vector<TestCaseHandle> const& getAllTests() const = 0;
21394-        virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0;
21395-    };
21396-
21397-}
21398-
21399-#endif // CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
21400-
21401-#endif // CATCH_INTERFACES_ALL_HPP_INCLUDED
21402-
21403-
21404-#ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
21405-#define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
21406-
21407-
21408-namespace Catch {
21409-    namespace Detail {
21410-        //! Provides case-insensitive `op<` semantics when called
21411-        struct CaseInsensitiveLess {
21412-            bool operator()( StringRef lhs,
21413-                             StringRef rhs ) const;
21414-        };
21415-
21416-        //! Provides case-insensitive `op==` semantics when called
21417-        struct CaseInsensitiveEqualTo {
21418-            bool operator()( StringRef lhs,
21419-                             StringRef rhs ) const;
21420-        };
21421-
21422-    } // namespace Detail
21423-} // namespace Catch
21424-
21425-#endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
21426-
21427-
21428-
21429-/** \file
21430- * Wrapper for ANDROID_LOGWRITE configuration option
21431- *
21432- * We want to default to enabling it when compiled for android, but
21433- * users of the library should also be able to disable it if they want
21434- * to.
21435- */
21436-
21437-#ifndef CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
21438-#define CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
21439-
21440-
21441-#if defined(__ANDROID__)
21442-#    define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
21443-#endif
21444-
21445-
21446-#if defined( CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE ) && \
21447-    !defined( CATCH_CONFIG_NO_ANDROID_LOGWRITE ) &&      \
21448-    !defined( CATCH_CONFIG_ANDROID_LOGWRITE )
21449-#    define CATCH_CONFIG_ANDROID_LOGWRITE
21450-#endif
21451-
21452-#endif // CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
21453-
21454-
21455-
21456-/** \file
21457- * Wrapper for UNCAUGHT_EXCEPTIONS configuration option
21458- *
21459- * For some functionality, Catch2 requires to know whether there is
21460- * an active exception. Because `std::uncaught_exception` is deprecated
21461- * in C++17, we want to use `std::uncaught_exceptions` if possible.
21462- */
21463-
21464-#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
21465-#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
21466-
21467-
21468-#if defined(_MSC_VER)
21469-#  if _MSC_VER >= 1900 // Visual Studio 2015 or newer
21470-#    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
21471-#  endif
21472-#endif
21473-
21474-
21475-#include <exception>
21476-
21477-#if defined(__cpp_lib_uncaught_exceptions) \
21478-    && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
21479-
21480-#  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
21481-#endif // __cpp_lib_uncaught_exceptions
21482-
21483-
21484-#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
21485-    && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
21486-    && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
21487-
21488-#  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
21489-#endif
21490-
21491-
21492-#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
21493-
21494-
21495-#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
21496-#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
21497-
21498-
21499-#include <iosfwd>
21500-#include <cstdint>
21501-
21502-namespace Catch {
21503-
21504-    enum class ColourMode : std::uint8_t;
21505-    class IStream;
21506-
21507-    struct Colour {
21508-        enum Code {
21509-            None = 0,
21510-
21511-            White,
21512-            Red,
21513-            Green,
21514-            Blue,
21515-            Cyan,
21516-            Yellow,
21517-            Grey,
21518-
21519-            Bright = 0x10,
21520-
21521-            BrightRed = Bright | Red,
21522-            BrightGreen = Bright | Green,
21523-            LightGrey = Bright | Grey,
21524-            BrightWhite = Bright | White,
21525-            BrightYellow = Bright | Yellow,
21526-
21527-            // By intention
21528-            FileName = LightGrey,
21529-            Warning = BrightYellow,
21530-            ResultError = BrightRed,
21531-            ResultSuccess = BrightGreen,
21532-            ResultExpectedFailure = Warning,
21533-
21534-            Error = BrightRed,
21535-            Success = Green,
21536-            Skip = LightGrey,
21537-
21538-            OriginalExpression = Cyan,
21539-            ReconstructedExpression = BrightYellow,
21540-
21541-            SecondaryText = LightGrey,
21542-            Headers = White
21543-        };
21544-    };
21545-
21546-    class ColourImpl {
21547-    protected:
21548-        //! The associated stream of this ColourImpl instance
21549-        IStream* m_stream;
21550-    public:
21551-        ColourImpl( IStream* stream ): m_stream( stream ) {}
21552-
21553-        //! RAII wrapper around writing specific colour of text using specific
21554-        //! colour impl into a stream.
21555-        class ColourGuard {
21556-            ColourImpl const* m_colourImpl;
21557-            Colour::Code m_code;
21558-            bool m_engaged = false;
21559-
21560-        public:
21561-            //! Does **not** engage the guard/start the colour
21562-            ColourGuard( Colour::Code code,
21563-                         ColourImpl const* colour );
21564-
21565-            ColourGuard( ColourGuard const& rhs ) = delete;
21566-            ColourGuard& operator=( ColourGuard const& rhs ) = delete;
21567-
21568-            ColourGuard( ColourGuard&& rhs ) noexcept;
21569-            ColourGuard& operator=( ColourGuard&& rhs ) noexcept;
21570-
21571-            //! Removes colour _if_ the guard was engaged
21572-            ~ColourGuard();
21573-
21574-            /**
21575-             * Explicitly engages colour for given stream.
21576-             *
21577-             * The API based on operator<< should be preferred.
21578-             */
21579-            ColourGuard& engage( std::ostream& stream ) &;
21580-            /**
21581-             * Explicitly engages colour for given stream.
21582-             *
21583-             * The API based on operator<< should be preferred.
21584-             */
21585-            ColourGuard&& engage( std::ostream& stream ) &&;
21586-
21587-        private:
21588-            //! Engages the guard and starts using colour
21589-            friend std::ostream& operator<<( std::ostream& lhs,
21590-                                             ColourGuard& guard ) {
21591-                guard.engageImpl( lhs );
21592-                return lhs;
21593-            }
21594-            //! Engages the guard and starts using colour
21595-            friend std::ostream& operator<<( std::ostream& lhs,
21596-                                            ColourGuard&& guard) {
21597-                guard.engageImpl( lhs );
21598-                return lhs;
21599-            }
21600-
21601-            void engageImpl( std::ostream& stream );
21602-
21603-        };
21604-
21605-        virtual ~ColourImpl(); // = default
21606-        /**
21607-         * Creates a guard object for given colour and this colour impl
21608-         *
21609-         * **Important:**
21610-         * the guard starts disengaged, and has to be engaged explicitly.
21611-         */
21612-        ColourGuard guardColour( Colour::Code colourCode );
21613-
21614-    private:
21615-        virtual void use( Colour::Code colourCode ) const = 0;
21616-    };
21617-
21618-    //! Provides ColourImpl based on global config and target compilation platform
21619-    Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
21620-                                                   IStream* stream );
21621-
21622-    //! Checks if specific colour impl has been compiled into the binary
21623-    bool isColourImplAvailable( ColourMode colourSelection );
21624-
21625-} // end namespace Catch
21626-
21627-#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED
21628-
21629-
21630-#ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED
21631-#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED
21632-
21633-// This include must be kept so that user's configured value for CONSOLE_WIDTH
21634-// is used before we attempt to provide a default value
21635-
21636-#ifndef CATCH_CONFIG_CONSOLE_WIDTH
21637-#define CATCH_CONFIG_CONSOLE_WIDTH 80
21638-#endif
21639-
21640-#endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED
21641-
21642-
21643-#ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
21644-#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
21645-
21646-
21647-#include <cstddef>
21648-#include <initializer_list>
21649-
21650-// We want a simple polyfill over `std::empty`, `std::size` and so on
21651-// for C++14 or C++ libraries with incomplete support.
21652-// We also have to handle that MSVC std lib will happily provide these
21653-// under older standards.
21654-#if defined(CATCH_CPP17_OR_GREATER) || defined(_MSC_VER)
21655-
21656-// We are already using this header either way, so there shouldn't
21657-// be much additional overhead in including it to get the feature
21658-// test macros
21659-#include <string>
21660-
21661-#  if !defined(__cpp_lib_nonmember_container_access)
21662-#      define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
21663-#  endif
21664-
21665-#else
21666-#define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
21667-#endif
21668-
21669-
21670-
21671-namespace Catch {
21672-namespace Detail {
21673-
21674-#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
21675-    template <typename Container>
21676-    constexpr auto empty(Container const& cont) -> decltype(cont.empty()) {
21677-        return cont.empty();
21678-    }
21679-    template <typename T, std::size_t N>
21680-    constexpr bool empty(const T (&)[N]) noexcept {
21681-        // GCC < 7 does not support the const T(&)[] parameter syntax
21682-        // so we have to ignore the length explicitly
21683-        (void)N;
21684-        return false;
21685-    }
21686-    template <typename T>
21687-    constexpr bool empty(std::initializer_list<T> list) noexcept {
21688-        return list.size() > 0;
21689-    }
21690-
21691-
21692-    template <typename Container>
21693-    constexpr auto size(Container const& cont) -> decltype(cont.size()) {
21694-        return cont.size();
21695-    }
21696-    template <typename T, std::size_t N>
21697-    constexpr std::size_t size(const T(&)[N]) noexcept {
21698-        return N;
21699-    }
21700-#endif // CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
21701-
21702-} // end namespace Detail
21703-} // end namespace Catch
21704-
21705-
21706-
21707-#endif // CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
21708-
21709-
21710-#ifndef CATCH_DEBUG_CONSOLE_HPP_INCLUDED
21711-#define CATCH_DEBUG_CONSOLE_HPP_INCLUDED
21712-
21713-#include <string>
21714-
21715-namespace Catch {
21716-    void writeToDebugConsole( std::string const& text );
21717-}
21718-
21719-#endif // CATCH_DEBUG_CONSOLE_HPP_INCLUDED
21720-
21721-
21722-#ifndef CATCH_DEBUGGER_HPP_INCLUDED
21723-#define CATCH_DEBUGGER_HPP_INCLUDED
21724-
21725-
21726-namespace Catch {
21727-    bool isDebuggerActive();
21728-}
21729-
21730-#if !defined( CATCH_TRAP ) && defined( __clang__ ) && defined( __has_builtin )
21731-#    if __has_builtin( __builtin_debugtrap )
21732-#        define CATCH_TRAP() __builtin_debugtrap()
21733-#    endif
21734-#endif
21735-
21736-#if !defined( CATCH_TRAP ) && defined( _MSC_VER )
21737-#    define CATCH_TRAP() __debugbreak()
21738-#endif
21739-
21740-#if !defined(CATCH_TRAP) // If we couldn't use compiler-specific impl from above, we get into platform-specific options
21741-#ifdef CATCH_PLATFORM_MAC
21742-
21743-    #if defined(__i386__) || defined(__x86_64__)
21744-        #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
21745-    #elif defined(__aarch64__)
21746-        #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
21747-    #elif defined(__POWERPC__)
21748-        #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
21749-        : : : "memory","r0","r3","r4" ) /* NOLINT */
21750-    #endif
21751-
21752-#elif defined(CATCH_PLATFORM_IPHONE)
21753-
21754-    // use inline assembler
21755-    #if defined(__i386__) || defined(__x86_64__)
21756-        #define CATCH_TRAP()  __asm__("int $3")
21757-    #elif defined(__aarch64__)
21758-        #define CATCH_TRAP()  __asm__(".inst 0xd4200000")
21759-    #elif defined(__arm__) && !defined(__thumb__)
21760-        #define CATCH_TRAP()  __asm__(".inst 0xe7f001f0")
21761-    #elif defined(__arm__) &&  defined(__thumb__)
21762-        #define CATCH_TRAP()  __asm__(".inst 0xde01")
21763-    #endif
21764-
21765-#elif defined(CATCH_PLATFORM_LINUX) || defined(CATCH_PLATFORM_QNX)
21766-    // If we can use inline assembler, do it because this allows us to break
21767-    // directly at the location of the failing check instead of breaking inside
21768-    // raise() called from it, i.e. one stack frame below.
21769-    #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
21770-        #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
21771-    #else // Fall back to the generic way.
21772-        #include <signal.h>
21773-
21774-        #define CATCH_TRAP() raise(SIGTRAP)
21775-    #endif
21776-#elif defined(__MINGW32__)
21777-    extern "C" __declspec(dllimport) void __stdcall DebugBreak();
21778-    #define CATCH_TRAP() DebugBreak()
21779-#endif
21780-#endif // ^^ CATCH_TRAP is not defined yet, so we define it
21781-
21782-
21783-#if !defined(CATCH_BREAK_INTO_DEBUGGER)
21784-    #if defined(CATCH_TRAP)
21785-        #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
21786-    #else
21787-        #define CATCH_BREAK_INTO_DEBUGGER() []{}()
21788-    #endif
21789-#endif
21790-
21791-#endif // CATCH_DEBUGGER_HPP_INCLUDED
21792-
21793-
21794-#ifndef CATCH_ENFORCE_HPP_INCLUDED
21795-#define CATCH_ENFORCE_HPP_INCLUDED
21796-
21797-
21798-#include <exception> // for `std::exception` in no-exception configuration
21799-
21800-namespace Catch {
21801-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
21802-    template <typename Ex>
21803-    [[noreturn]]
21804-    void throw_exception(Ex const& e) {
21805-        throw e;
21806-    }
21807-#else // ^^ Exceptions are enabled //  Exceptions are disabled vv
21808-    [[noreturn]]
21809-    void throw_exception(std::exception const& e);
21810-#endif
21811-
21812-    [[noreturn]]
21813-    void throw_logic_error(std::string const& msg);
21814-    [[noreturn]]
21815-    void throw_domain_error(std::string const& msg);
21816-    [[noreturn]]
21817-    void throw_runtime_error(std::string const& msg);
21818-
21819-} // namespace Catch;
21820-
21821-#define CATCH_MAKE_MSG(...) \
21822-    (Catch::ReusableStringStream() << __VA_ARGS__).str()
21823-
21824-#define CATCH_INTERNAL_ERROR(...) \
21825-    Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
21826-
21827-#define CATCH_ERROR(...) \
21828-    Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
21829-
21830-#define CATCH_RUNTIME_ERROR(...) \
21831-    Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
21832-
21833-#define CATCH_ENFORCE( condition, ... ) \
21834-    do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
21835-
21836-
21837-#endif // CATCH_ENFORCE_HPP_INCLUDED
21838-
21839-
21840-#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
21841-#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
21842-
21843-
21844-#include <vector>
21845-
21846-namespace Catch {
21847-
21848-    namespace Detail {
21849-
21850-        Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
21851-
21852-        class EnumValuesRegistry : public IMutableEnumValuesRegistry {
21853-
21854-            std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
21855-
21856-            EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
21857-        };
21858-
21859-        std::vector<StringRef> parseEnums( StringRef enums );
21860-
21861-    } // Detail
21862-
21863-} // Catch
21864-
21865-#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
21866-
21867-
21868-#ifndef CATCH_ERRNO_GUARD_HPP_INCLUDED
21869-#define CATCH_ERRNO_GUARD_HPP_INCLUDED
21870-
21871-namespace Catch {
21872-
21873-    //! Simple RAII class that stores the value of `errno`
21874-    //! at construction and restores it at destruction.
21875-    class ErrnoGuard {
21876-    public:
21877-        // Keep these outlined to avoid dragging in macros from <cerrno>
21878-
21879-        ErrnoGuard();
21880-        ~ErrnoGuard();
21881-    private:
21882-        int m_oldErrno;
21883-    };
21884-
21885-}
21886-
21887-#endif // CATCH_ERRNO_GUARD_HPP_INCLUDED
21888-
21889-
21890-#ifndef CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
21891-#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
21892-
21893-
21894-#include <string>
21895-
21896-namespace Catch {
21897-
21898-    class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
21899-    public:
21900-        ~ExceptionTranslatorRegistry() override;
21901-        void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator );
21902-        std::string translateActiveException() const override;
21903-
21904-    private:
21905-        ExceptionTranslators m_translators;
21906-    };
21907-}
21908-
21909-#endif // CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
21910-
21911-
21912-#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
21913-#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
21914-
21915-#include <cassert>
21916-
21917-namespace Catch {
21918-
21919-    /**
21920-     * Wrapper for platform-specific fatal error (signals/SEH) handlers
21921-     *
21922-     * Tries to be cooperative with other handlers, and not step over
21923-     * other handlers. This means that unknown structured exceptions
21924-     * are passed on, previous signal handlers are called, and so on.
21925-     *
21926-     * Can only be instantiated once, and assumes that once a signal
21927-     * is caught, the binary will end up terminating. Thus, there
21928-     */
21929-    class FatalConditionHandler {
21930-        bool m_started = false;
21931-
21932-        // Install/disengage implementation for specific platform.
21933-        // Should be if-defed to work on current platform, can assume
21934-        // engage-disengage 1:1 pairing.
21935-        void engage_platform();
21936-        void disengage_platform() noexcept;
21937-    public:
21938-        // Should also have platform-specific implementations as needed
21939-        FatalConditionHandler();
21940-        ~FatalConditionHandler();
21941-
21942-        void engage() {
21943-            assert(!m_started && "Handler cannot be installed twice.");
21944-            m_started = true;
21945-            engage_platform();
21946-        }
21947-
21948-        void disengage() noexcept {
21949-            assert(m_started && "Handler cannot be uninstalled without being installed first");
21950-            m_started = false;
21951-            disengage_platform();
21952-        }
21953-    };
21954-
21955-    //! Simple RAII guard for (dis)engaging the FatalConditionHandler
21956-    class FatalConditionHandlerGuard {
21957-        FatalConditionHandler* m_handler;
21958-    public:
21959-        FatalConditionHandlerGuard(FatalConditionHandler* handler):
21960-            m_handler(handler) {
21961-            m_handler->engage();
21962-        }
21963-        ~FatalConditionHandlerGuard() {
21964-            m_handler->disengage();
21965-        }
21966-    };
21967-
21968-} // end namespace Catch
21969-
21970-#endif // CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
21971-
21972-
21973-#ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
21974-#define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
21975-
21976-
21977-#include <cassert>
21978-#include <cmath>
21979-#include <cstdint>
21980-#include <utility>
21981-#include <limits>
21982-
21983-namespace Catch {
21984-    namespace Detail {
21985-
21986-        uint32_t convertToBits(float f);
21987-        uint64_t convertToBits(double d);
21988-
21989-        // Used when we know we want == comparison of two doubles
21990-        // to centralize warning suppression
21991-        bool directCompare( float lhs, float rhs );
21992-        bool directCompare( double lhs, double rhs );
21993-
21994-    } // end namespace Detail
21995-
21996-
21997-
21998-#if defined( __GNUC__ ) || defined( __clang__ )
21999-#    pragma GCC diagnostic push
22000-    // We do a bunch of direct compensations of floating point numbers,
22001-    // because we know what we are doing and actually do want the direct
22002-    // comparison behaviour.
22003-#    pragma GCC diagnostic ignored "-Wfloat-equal"
22004-#endif
22005-
22006-    /**
22007-     * Calculates the ULP distance between two floating point numbers
22008-     *
22009-     * The ULP distance of two floating point numbers is the count of
22010-     * valid floating point numbers representable between them.
22011-     *
22012-     * There are some exceptions between how this function counts the
22013-     * distance, and the interpretation of the standard as implemented.
22014-     * by e.g. `nextafter`. For this function it always holds that:
22015-     * * `(x == y) => ulpDistance(x, y) == 0` (so `ulpDistance(-0, 0) == 0`)
22016-     * * `ulpDistance(maxFinite, INF) == 1`
22017-     * * `ulpDistance(x, -x) == 2 * ulpDistance(x, 0)`
22018-     *
22019-     * \pre `!isnan( lhs )`
22020-     * \pre `!isnan( rhs )`
22021-     * \pre floating point numbers are represented in IEEE-754 format
22022-     */
22023-    template <typename FP>
22024-    uint64_t ulpDistance( FP lhs, FP rhs ) {
22025-        assert( std::numeric_limits<FP>::is_iec559 &&
22026-            "ulpDistance assumes IEEE-754 format for floating point types" );
22027-        assert( !Catch::isnan( lhs ) &&
22028-                "Distance between NaN and number is not meaningful" );
22029-        assert( !Catch::isnan( rhs ) &&
22030-                "Distance between NaN and number is not meaningful" );
22031-
22032-        // We want X == Y to imply 0 ULP distance even if X and Y aren't
22033-        // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
22034-        if ( lhs == rhs ) { return 0; }
22035-
22036-        // We need a properly typed positive zero for type inference.
22037-        static constexpr FP positive_zero{};
22038-
22039-        // We want to ensure that +/- 0 is always represented as positive zero
22040-        if ( lhs == positive_zero ) { lhs = positive_zero; }
22041-        if ( rhs == positive_zero ) { rhs = positive_zero; }
22042-
22043-        // If arguments have different signs, we can handle them by summing
22044-        // how far are they from 0 each.
22045-        if ( std::signbit( lhs ) != std::signbit( rhs ) ) {
22046-            return ulpDistance( std::abs( lhs ), positive_zero ) +
22047-                   ulpDistance( std::abs( rhs ), positive_zero );
22048-        }
22049-
22050-        // When both lhs and rhs are of the same sign, we can just
22051-        // read the numbers bitwise as integers, and then subtract them
22052-        // (assuming IEEE).
22053-        uint64_t lc = Detail::convertToBits( lhs );
22054-        uint64_t rc = Detail::convertToBits( rhs );
22055-
22056-        // The ulp distance between two numbers is symmetric, so to avoid
22057-        // dealing with overflows we want the bigger converted number on the lhs
22058-        if ( lc < rc ) {
22059-            std::swap( lc, rc );
22060-        }
22061-
22062-        return lc - rc;
22063-    }
22064-
22065-#if defined( __GNUC__ ) || defined( __clang__ )
22066-#    pragma GCC diagnostic pop
22067-#endif
22068-
22069-
22070-} // end namespace Catch
22071-
22072-#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
22073-
22074-
22075-#ifndef CATCH_GETENV_HPP_INCLUDED
22076-#define CATCH_GETENV_HPP_INCLUDED
22077-
22078-namespace Catch {
22079-namespace Detail {
22080-
22081-    //! Wrapper over `std::getenv` that compiles on UWP (and always returns nullptr there)
22082-    char const* getEnv(char const* varName);
22083-
22084-}
22085-}
22086-
22087-#endif // CATCH_GETENV_HPP_INCLUDED
22088-
22089-
22090-#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
22091-#define CATCH_IS_PERMUTATION_HPP_INCLUDED
22092-
22093-#include <iterator>
22094-#include <type_traits>
22095-
22096-namespace Catch {
22097-    namespace Detail {
22098-
22099-        template <typename ForwardIter,
22100-                  typename Sentinel,
22101-                  typename T,
22102-                  typename Comparator>
22103-        constexpr
22104-        ForwardIter find_sentinel( ForwardIter start,
22105-                                   Sentinel sentinel,
22106-                                   T const& value,
22107-                                   Comparator cmp ) {
22108-            while ( start != sentinel ) {
22109-                if ( cmp( *start, value ) ) { break; }
22110-                ++start;
22111-            }
22112-            return start;
22113-        }
22114-
22115-        template <typename ForwardIter,
22116-                  typename Sentinel,
22117-                  typename T,
22118-                  typename Comparator>
22119-        constexpr
22120-        std::ptrdiff_t count_sentinel( ForwardIter start,
22121-                                       Sentinel sentinel,
22122-                                       T const& value,
22123-                                       Comparator cmp ) {
22124-            std::ptrdiff_t count = 0;
22125-            while ( start != sentinel ) {
22126-                if ( cmp( *start, value ) ) { ++count; }
22127-                ++start;
22128-            }
22129-            return count;
22130-        }
22131-
22132-        template <typename ForwardIter, typename Sentinel>
22133-        constexpr
22134-        std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
22135-                         std::ptrdiff_t>
22136-        sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
22137-            std::ptrdiff_t dist = 0;
22138-            while ( iter != sentinel ) {
22139-                ++iter;
22140-                ++dist;
22141-            }
22142-            return dist;
22143-        }
22144-
22145-        template <typename ForwardIter>
22146-        constexpr std::ptrdiff_t sentinel_distance( ForwardIter first,
22147-                                                    ForwardIter last ) {
22148-            return std::distance( first, last );
22149-        }
22150-
22151-        template <typename ForwardIter1,
22152-                  typename Sentinel1,
22153-                  typename ForwardIter2,
22154-                  typename Sentinel2,
22155-                  typename Comparator>
22156-        constexpr bool check_element_counts( ForwardIter1 first_1,
22157-                                             const Sentinel1 end_1,
22158-                                             ForwardIter2 first_2,
22159-                                             const Sentinel2 end_2,
22160-                                             Comparator cmp ) {
22161-            auto cursor = first_1;
22162-            while ( cursor != end_1 ) {
22163-                if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
22164-                     cursor ) {
22165-                    // we haven't checked this element yet
22166-                    const auto count_in_range_2 =
22167-                        count_sentinel( first_2, end_2, *cursor, cmp );
22168-                    // Not a single instance in 2nd range, so it cannot be a
22169-                    // permutation of 1st range
22170-                    if ( count_in_range_2 == 0 ) { return false; }
22171-
22172-                    const auto count_in_range_1 =
22173-                        count_sentinel( cursor, end_1, *cursor, cmp );
22174-                    if ( count_in_range_1 != count_in_range_2 ) {
22175-                        return false;
22176-                    }
22177-                }
22178-
22179-                ++cursor;
22180-            }
22181-
22182-            return true;
22183-        }
22184-
22185-        template <typename ForwardIter1,
22186-                  typename Sentinel1,
22187-                  typename ForwardIter2,
22188-                  typename Sentinel2,
22189-                  typename Comparator>
22190-        constexpr bool is_permutation( ForwardIter1 first_1,
22191-                                       const Sentinel1 end_1,
22192-                                       ForwardIter2 first_2,
22193-                                       const Sentinel2 end_2,
22194-                                       Comparator cmp ) {
22195-            // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types
22196-            // TODO: Comparator has to be "both sides", e.g. a == b => b == a
22197-            // This skips shared prefix of the two ranges
22198-            while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
22199-                ++first_1;
22200-                ++first_2;
22201-            }
22202-
22203-            // We need to handle case where at least one of the ranges has no more elements
22204-            if (first_1 == end_1 || first_2 == end_2) {
22205-                return first_1 == end_1 && first_2 == end_2;
22206-            }
22207-
22208-            // pair counting is n**2, so we pay linear walk to compare the sizes first
22209-            auto dist_1 = sentinel_distance( first_1, end_1 );
22210-            auto dist_2 = sentinel_distance( first_2, end_2 );
22211-
22212-            if (dist_1 != dist_2) { return false; }
22213-
22214-            // Since we do not try to handle stronger iterators pair (e.g.
22215-            // bidir) optimally, the only thing left to do is to check counts in
22216-            // the remaining ranges.
22217-            return check_element_counts( first_1, end_1, first_2, end_2, cmp );
22218-        }
22219-
22220-    } // namespace Detail
22221-} // namespace Catch
22222-
22223-#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED
22224-
22225-
22226-#ifndef CATCH_ISTREAM_HPP_INCLUDED
22227-#define CATCH_ISTREAM_HPP_INCLUDED
22228-
22229-
22230-#include <iosfwd>
22231-#include <string>
22232-
22233-namespace Catch {
22234-
22235-    class IStream {
22236-    public:
22237-        virtual ~IStream(); // = default
22238-        virtual std::ostream& stream() = 0;
22239-        /**
22240-         * Best guess on whether the instance is writing to a console (e.g. via stdout/stderr)
22241-         *
22242-         * This is useful for e.g. Win32 colour support, because the Win32
22243-         * API manipulates console directly, unlike POSIX escape codes,
22244-         * that can be written anywhere.
22245-         *
22246-         * Due to variety of ways to change where the stdout/stderr is
22247-         * _actually_ being written, users should always assume that
22248-         * the answer might be wrong.
22249-         */
22250-        virtual bool isConsole() const { return false; }
22251-    };
22252-
22253-    /**
22254-     * Creates a stream wrapper that writes to specific file.
22255-     *
22256-     * Also recognizes 4 special filenames
22257-     * * `-` for stdout
22258-     * * `%stdout` for stdout
22259-     * * `%stderr` for stderr
22260-     * * `%debug` for platform specific debugging output
22261-     *
22262-     * \throws if passed an unrecognized %-prefixed stream
22263-     */
22264-    auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream>;
22265-
22266-}
22267-
22268-#endif // CATCH_STREAM_HPP_INCLUDED
22269-
22270-
22271-#ifndef CATCH_JSONWRITER_HPP_INCLUDED
22272-#define CATCH_JSONWRITER_HPP_INCLUDED
22273-
22274-
22275-#include <cstdint>
22276-#include <sstream>
22277-
22278-namespace Catch {
22279-    class JsonObjectWriter;
22280-    class JsonArrayWriter;
22281-
22282-    struct JsonUtils {
22283-        static void indent( std::ostream& os, std::uint64_t level );
22284-        static void appendCommaNewline( std::ostream& os,
22285-                                        bool& should_comma,
22286-                                        std::uint64_t level );
22287-    };
22288-
22289-    class JsonValueWriter {
22290-    public:
22291-        JsonValueWriter( std::ostream& os );
22292-        JsonValueWriter( std::ostream& os, std::uint64_t indent_level );
22293-
22294-        JsonObjectWriter writeObject() &&;
22295-        JsonArrayWriter writeArray() &&;
22296-
22297-        template <typename T>
22298-        void write( T const& value ) && {
22299-            writeImpl( value, !std::is_arithmetic<T>::value );
22300-        }
22301-        void write( StringRef value ) &&;
22302-        void write( bool value ) &&;
22303-
22304-    private:
22305-        void writeImpl( StringRef value, bool quote );
22306-
22307-        // Without this SFINAE, this overload is a better match
22308-        // for `std::string`, `char const*`, `char const[N]` args.
22309-        // While it would still work, it would cause code bloat
22310-        // and multiple iteration over the strings
22311-        template <typename T,
22312-                  typename = typename std::enable_if_t<
22313-                      !std::is_convertible<T, StringRef>::value>>
22314-        void writeImpl( T const& value, bool quote_value ) {
22315-            m_sstream << value;
22316-            writeImpl( m_sstream.str(), quote_value );
22317-        }
22318-
22319-        std::ostream& m_os;
22320-        std::stringstream m_sstream;
22321-        std::uint64_t m_indent_level;
22322-    };
22323-
22324-    class JsonObjectWriter {
22325-    public:
22326-        JsonObjectWriter( std::ostream& os );
22327-        JsonObjectWriter( std::ostream& os, std::uint64_t indent_level );
22328-
22329-        JsonObjectWriter( JsonObjectWriter&& source ) noexcept;
22330-        JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete;
22331-
22332-        ~JsonObjectWriter();
22333-
22334-        JsonValueWriter write( StringRef key );
22335-
22336-    private:
22337-        std::ostream& m_os;
22338-        std::uint64_t m_indent_level;
22339-        bool m_should_comma = false;
22340-        bool m_active = true;
22341-    };
22342-
22343-    class JsonArrayWriter {
22344-    public:
22345-        JsonArrayWriter( std::ostream& os );
22346-        JsonArrayWriter( std::ostream& os, std::uint64_t indent_level );
22347-
22348-        JsonArrayWriter( JsonArrayWriter&& source ) noexcept;
22349-        JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete;
22350-
22351-        ~JsonArrayWriter();
22352-
22353-        JsonObjectWriter writeObject();
22354-        JsonArrayWriter writeArray();
22355-
22356-        template <typename T>
22357-        JsonArrayWriter& write( T const& value ) {
22358-            return writeImpl( value );
22359-        }
22360-
22361-        JsonArrayWriter& write( bool value );
22362-
22363-    private:
22364-        template <typename T>
22365-        JsonArrayWriter& writeImpl( T const& value ) {
22366-            JsonUtils::appendCommaNewline(
22367-                m_os, m_should_comma, m_indent_level + 1 );
22368-            JsonValueWriter{ m_os }.write( value );
22369-
22370-            return *this;
22371-        }
22372-
22373-        std::ostream& m_os;
22374-        std::uint64_t m_indent_level;
22375-        bool m_should_comma = false;
22376-        bool m_active = true;
22377-    };
22378-
22379-} // namespace Catch
22380-
22381-#endif // CATCH_JSONWRITER_HPP_INCLUDED
22382-
22383-
22384-#ifndef CATCH_LEAK_DETECTOR_HPP_INCLUDED
22385-#define CATCH_LEAK_DETECTOR_HPP_INCLUDED
22386-
22387-namespace Catch {
22388-
22389-    struct LeakDetector {
22390-        LeakDetector();
22391-        ~LeakDetector();
22392-    };
22393-
22394-}
22395-#endif // CATCH_LEAK_DETECTOR_HPP_INCLUDED
22396-
22397-
22398-#ifndef CATCH_LIST_HPP_INCLUDED
22399-#define CATCH_LIST_HPP_INCLUDED
22400-
22401-
22402-#include <set>
22403-#include <string>
22404-
22405-
22406-namespace Catch {
22407-
22408-    class IEventListener;
22409-    class Config;
22410-
22411-
22412-    struct ReporterDescription {
22413-        std::string name, description;
22414-    };
22415-    struct ListenerDescription {
22416-        StringRef name;
22417-        std::string description;
22418-    };
22419-
22420-    struct TagInfo {
22421-        void add(StringRef spelling);
22422-        std::string all() const;
22423-
22424-        std::set<StringRef> spellings;
22425-        std::size_t count = 0;
22426-    };
22427-
22428-    bool list( IEventListener& reporter, Config const& config );
22429-
22430-} // end namespace Catch
22431-
22432-#endif // CATCH_LIST_HPP_INCLUDED
22433-
22434-
22435-#ifndef CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
22436-#define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
22437-
22438-
22439-#include <cassert>
22440-#include <string>
22441-
22442-namespace Catch {
22443-
22444-    class OutputRedirect {
22445-        bool m_redirectActive = false;
22446-        virtual void activateImpl() = 0;
22447-        virtual void deactivateImpl() = 0;
22448-    public:
22449-        enum Kind {
22450-            //! No redirect (noop implementation)
22451-            None,
22452-            //! Redirect std::cout/std::cerr/std::clog streams internally
22453-            Streams,
22454-            //! Redirect the stdout/stderr file descriptors into files
22455-            FileDescriptors,
22456-        };
22457-
22458-        virtual ~OutputRedirect(); // = default;
22459-
22460-        // TODO: Do we want to check that redirect is not active before retrieving the output?
22461-        virtual std::string getStdout() = 0;
22462-        virtual std::string getStderr() = 0;
22463-        virtual void clearBuffers() = 0;
22464-        bool isActive() const { return m_redirectActive; }
22465-        void activate() {
22466-            assert( !m_redirectActive && "redirect is already active" );
22467-            activateImpl();
22468-            m_redirectActive = true;
22469-        }
22470-        void deactivate() {
22471-            assert( m_redirectActive && "redirect is not active" );
22472-            deactivateImpl();
22473-            m_redirectActive = false;
22474-        }
22475-    };
22476-
22477-    bool isRedirectAvailable( OutputRedirect::Kind kind);
22478-    Detail::unique_ptr<OutputRedirect> makeOutputRedirect( bool actual );
22479-
22480-    class RedirectGuard {
22481-        OutputRedirect* m_redirect;
22482-        bool m_activate;
22483-        bool m_previouslyActive;
22484-        bool m_moved = false;
22485-
22486-    public:
22487-        RedirectGuard( bool activate, OutputRedirect& redirectImpl );
22488-        ~RedirectGuard() noexcept( false );
22489-
22490-        RedirectGuard( RedirectGuard const& ) = delete;
22491-        RedirectGuard& operator=( RedirectGuard const& ) = delete;
22492-
22493-        // C++14 needs move-able guards to return them from functions
22494-        RedirectGuard( RedirectGuard&& rhs ) noexcept;
22495-        RedirectGuard& operator=( RedirectGuard&& rhs ) noexcept;
22496-    };
22497-
22498-    RedirectGuard scopedActivate( OutputRedirect& redirectImpl );
22499-    RedirectGuard scopedDeactivate( OutputRedirect& redirectImpl );
22500-
22501-} // end namespace Catch
22502-
22503-#endif // CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
22504-
22505-
22506-#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED
22507-#define CATCH_PARSE_NUMBERS_HPP_INCLUDED
22508-
22509-
22510-#include <string>
22511-
22512-namespace Catch {
22513-
22514-    /**
22515-     * Parses unsigned int from the input, using provided base
22516-     *
22517-     * Effectively a wrapper around std::stoul but with better error checking
22518-     * e.g. "-1" is rejected, instead of being parsed as UINT_MAX.
22519-     */
22520-    Optional<unsigned int> parseUInt(std::string const& input, int base = 10);
22521-}
22522-
22523-#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED
22524-
22525-
22526-#ifndef CATCH_REPORTER_REGISTRY_HPP_INCLUDED
22527-#define CATCH_REPORTER_REGISTRY_HPP_INCLUDED
22528-
22529-
22530-#include <map>
22531-#include <string>
22532-#include <vector>
22533-
22534-namespace Catch {
22535-
22536-    class IEventListener;
22537-    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
22538-    class IReporterFactory;
22539-    using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
22540-    struct ReporterConfig;
22541-    class EventListenerFactory;
22542-
22543-    class ReporterRegistry {
22544-        struct ReporterRegistryImpl;
22545-        Detail::unique_ptr<ReporterRegistryImpl> m_impl;
22546-
22547-    public:
22548-        ReporterRegistry();
22549-        ~ReporterRegistry(); // = default;
22550-
22551-        IEventListenerPtr create( std::string const& name,
22552-                                  ReporterConfig&& config ) const;
22553-
22554-        void registerReporter( std::string const& name,
22555-                               IReporterFactoryPtr factory );
22556-
22557-        void
22558-        registerListener( Detail::unique_ptr<EventListenerFactory> factory );
22559-
22560-        std::map<std::string,
22561-                 IReporterFactoryPtr,
22562-                 Detail::CaseInsensitiveLess> const&
22563-        getFactories() const;
22564-
22565-        std::vector<Detail::unique_ptr<EventListenerFactory>> const&
22566-        getListeners() const;
22567-    };
22568-
22569-} // end namespace Catch
22570-
22571-#endif // CATCH_REPORTER_REGISTRY_HPP_INCLUDED
22572-
22573-
22574-#ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED
22575-#define CATCH_RUN_CONTEXT_HPP_INCLUDED
22576-
22577-
22578-
22579-#ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
22580-#define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
22581-
22582-
22583-#include <string>
22584-#include <vector>
22585-
22586-namespace Catch {
22587-namespace TestCaseTracking {
22588-
22589-    struct NameAndLocation {
22590-        std::string name;
22591-        SourceLineInfo location;
22592-
22593-        NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
22594-        friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
22595-            // This is a very cheap check that should have a very high hit rate.
22596-            // If we get to SourceLineInfo::operator==, we will redo it, but the
22597-            // cost of repeating is trivial at that point (we will be paying
22598-            // multiple strcmp/memcmps at that point).
22599-            if ( lhs.location.line != rhs.location.line ) { return false; }
22600-            return lhs.name == rhs.name && lhs.location == rhs.location;
22601-        }
22602-        friend bool operator!=(NameAndLocation const& lhs,
22603-                               NameAndLocation const& rhs) {
22604-            return !( lhs == rhs );
22605-        }
22606-    };
22607-
22608-    /**
22609-     * This is a variant of `NameAndLocation` that does not own the name string
22610-     *
22611-     * This avoids extra allocations when trying to locate a tracker by its
22612-     * name and location, as long as we make sure that trackers only keep
22613-     * around the owning variant.
22614-     */
22615-    struct NameAndLocationRef {
22616-        StringRef name;
22617-        SourceLineInfo location;
22618-
22619-        constexpr NameAndLocationRef( StringRef name_,
22620-                                      SourceLineInfo location_ ):
22621-            name( name_ ), location( location_ ) {}
22622-
22623-        friend bool operator==( NameAndLocation const& lhs,
22624-                                NameAndLocationRef const& rhs ) {
22625-            // This is a very cheap check that should have a very high hit rate.
22626-            // If we get to SourceLineInfo::operator==, we will redo it, but the
22627-            // cost of repeating is trivial at that point (we will be paying
22628-            // multiple strcmp/memcmps at that point).
22629-            if ( lhs.location.line != rhs.location.line ) { return false; }
22630-            return StringRef( lhs.name ) == rhs.name &&
22631-                   lhs.location == rhs.location;
22632-        }
22633-        friend bool operator==( NameAndLocationRef const& lhs,
22634-                                NameAndLocation const& rhs ) {
22635-            return rhs == lhs;
22636-        }
22637-    };
22638-
22639-    class ITracker;
22640-
22641-    using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
22642-
22643-    class ITracker {
22644-        NameAndLocation m_nameAndLocation;
22645-
22646-        using Children = std::vector<ITrackerPtr>;
22647-
22648-    protected:
22649-        enum CycleState {
22650-            NotStarted,
22651-            Executing,
22652-            ExecutingChildren,
22653-            NeedsAnotherRun,
22654-            CompletedSuccessfully,
22655-            Failed
22656-        };
22657-
22658-        ITracker* m_parent = nullptr;
22659-        Children m_children;
22660-        CycleState m_runState = NotStarted;
22661-
22662-    public:
22663-        ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
22664-            m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
22665-            m_parent( parent )
22666-        {}
22667-
22668-
22669-        // static queries
22670-        NameAndLocation const& nameAndLocation() const {
22671-            return m_nameAndLocation;
22672-        }
22673-        ITracker* parent() const {
22674-            return m_parent;
22675-        }
22676-
22677-        virtual ~ITracker(); // = default
22678-
22679-
22680-        // dynamic queries
22681-
22682-        //! Returns true if tracker run to completion (successfully or not)
22683-        virtual bool isComplete() const = 0;
22684-        //! Returns true if tracker run to completion successfully
22685-        bool isSuccessfullyCompleted() const {
22686-            return m_runState == CompletedSuccessfully;
22687-        }
22688-        //! Returns true if tracker has started but hasn't been completed
22689-        bool isOpen() const;
22690-        //! Returns true iff tracker has started
22691-        bool hasStarted() const;
22692-
22693-        // actions
22694-        virtual void close() = 0; // Successfully complete
22695-        virtual void fail() = 0;
22696-        void markAsNeedingAnotherRun();
22697-
22698-        //! Register a nested ITracker
22699-        void addChild( ITrackerPtr&& child );
22700-        /**
22701-         * Returns ptr to specific child if register with this tracker.
22702-         *
22703-         * Returns nullptr if not found.
22704-         */
22705-        ITracker* findChild( NameAndLocationRef const& nameAndLocation );
22706-        //! Have any children been added?
22707-        bool hasChildren() const {
22708-            return !m_children.empty();
22709-        }
22710-
22711-
22712-        //! Marks tracker as executing a child, doing se recursively up the tree
22713-        void openChild();
22714-
22715-        /**
22716-         * Returns true if the instance is a section tracker
22717-         *
22718-         * Subclasses should override to true if they are, replaces RTTI
22719-         * for internal debug checks.
22720-         */
22721-        virtual bool isSectionTracker() const;
22722-        /**
22723-         * Returns true if the instance is a generator tracker
22724-         *
22725-         * Subclasses should override to true if they are, replaces RTTI
22726-         * for internal debug checks.
22727-         */
22728-        virtual bool isGeneratorTracker() const;
22729-    };
22730-
22731-    class TrackerContext {
22732-
22733-        enum RunState {
22734-            NotStarted,
22735-            Executing,
22736-            CompletedCycle
22737-        };
22738-
22739-        ITrackerPtr m_rootTracker;
22740-        ITracker* m_currentTracker = nullptr;
22741-        RunState m_runState = NotStarted;
22742-
22743-    public:
22744-
22745-        ITracker& startRun();
22746-
22747-        void startCycle() {
22748-            m_currentTracker = m_rootTracker.get();
22749-            m_runState = Executing;
22750-        }
22751-        void completeCycle();
22752-
22753-        bool completedCycle() const;
22754-        ITracker& currentTracker() { return *m_currentTracker; }
22755-        void setCurrentTracker( ITracker* tracker );
22756-    };
22757-
22758-    class TrackerBase : public ITracker {
22759-    protected:
22760-
22761-        TrackerContext& m_ctx;
22762-
22763-    public:
22764-        TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
22765-
22766-        bool isComplete() const override;
22767-
22768-        void open();
22769-
22770-        void close() override;
22771-        void fail() override;
22772-
22773-    private:
22774-        void moveToParent();
22775-        void moveToThis();
22776-    };
22777-
22778-    class SectionTracker : public TrackerBase {
22779-        std::vector<StringRef> m_filters;
22780-        // Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
22781-        // Currently it allocates owns the name, so this is safe. If it is later refactored
22782-        // to not own the name, the name still has to outlive the `ITracker` parent, so
22783-        // this should still be safe.
22784-        StringRef m_trimmed_name;
22785-    public:
22786-        SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
22787-
22788-        bool isSectionTracker() const override;
22789-
22790-        bool isComplete() const override;
22791-
22792-        static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
22793-
22794-        void tryOpen();
22795-
22796-        void addInitialFilters( std::vector<std::string> const& filters );
22797-        void addNextFilters( std::vector<StringRef> const& filters );
22798-        //! Returns filters active in this tracker
22799-        std::vector<StringRef> const& getFilters() const { return m_filters; }
22800-        //! Returns whitespace-trimmed name of the tracked section
22801-        StringRef trimmedName() const;
22802-    };
22803-
22804-} // namespace TestCaseTracking
22805-
22806-using TestCaseTracking::ITracker;
22807-using TestCaseTracking::TrackerContext;
22808-using TestCaseTracking::SectionTracker;
22809-
22810-} // namespace Catch
22811-
22812-#endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
22813-
22814-
22815-#ifndef CATCH_THREAD_SUPPORT_HPP_INCLUDED
22816-#define CATCH_THREAD_SUPPORT_HPP_INCLUDED
22817-
22818-
22819-#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS )
22820-#    include <atomic>
22821-#    include <mutex>
22822-#endif
22823-
22824-
22825-namespace Catch {
22826-    namespace Detail {
22827-#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS )
22828-        using Mutex = std::mutex;
22829-        using LockGuard = std::lock_guard<std::mutex>;
22830-        struct AtomicCounts {
22831-            std::atomic<std::uint64_t> passed = 0;
22832-            std::atomic<std::uint64_t> failed = 0;
22833-            std::atomic<std::uint64_t> failedButOk = 0;
22834-            std::atomic<std::uint64_t> skipped = 0;
22835-        };
22836-#else // ^^ Use actual mutex, lock and atomics
22837-      // vv Dummy implementations for single-thread performance
22838-
22839-        struct Mutex {
22840-            void lock() {}
22841-            void unlock() {}
22842-        };
22843-
22844-        struct LockGuard {
22845-            LockGuard( Mutex ) {}
22846-        };
22847-
22848-        using AtomicCounts = Counts;
22849-#endif
22850-
22851-    } // namespace Detail
22852-} // namespace Catch
22853-
22854-#endif // CATCH_THREAD_SUPPORT_HPP_INCLUDED
22855-
22856-#include <string>
22857-
22858-namespace Catch {
22859-
22860-    class IGeneratorTracker;
22861-    class IConfig;
22862-    class IEventListener;
22863-    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
22864-    class OutputRedirect;
22865-
22866-    ///////////////////////////////////////////////////////////////////////////
22867-
22868-    class RunContext final : public IResultCapture {
22869-
22870-    public:
22871-        RunContext( RunContext const& ) = delete;
22872-        RunContext& operator =( RunContext const& ) = delete;
22873-
22874-        explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter );
22875-
22876-        ~RunContext() override;
22877-
22878-        Totals runTest(TestCaseHandle const& testCase);
22879-
22880-    public: // IResultCapture
22881-
22882-        // Assertion handlers
22883-        void handleExpr
22884-                (   AssertionInfo const& info,
22885-                    ITransientExpression const& expr,
22886-                    AssertionReaction& reaction ) override;
22887-        void handleMessage
22888-                (   AssertionInfo const& info,
22889-                    ResultWas::OfType resultType,
22890-                    std::string&& message,
22891-                    AssertionReaction& reaction ) override;
22892-        void handleUnexpectedExceptionNotThrown
22893-                (   AssertionInfo const& info,
22894-                    AssertionReaction& reaction ) override;
22895-        void handleUnexpectedInflightException
22896-                (   AssertionInfo const& info,
22897-                    std::string&& message,
22898-                    AssertionReaction& reaction ) override;
22899-        void handleIncomplete
22900-                (   AssertionInfo const& info ) override;
22901-        void handleNonExpr
22902-                (   AssertionInfo const &info,
22903-                    ResultWas::OfType resultType,
22904-                    AssertionReaction &reaction ) override;
22905-
22906-        void notifyAssertionStarted( AssertionInfo const& info ) override;
22907-        bool sectionStarted( StringRef sectionName,
22908-                             SourceLineInfo const& sectionLineInfo,
22909-                             Counts& assertions ) override;
22910-
22911-        void sectionEnded( SectionEndInfo&& endInfo ) override;
22912-        void sectionEndedEarly( SectionEndInfo&& endInfo ) override;
22913-
22914-        IGeneratorTracker*
22915-        acquireGeneratorTracker( StringRef generatorName,
22916-                                 SourceLineInfo const& lineInfo ) override;
22917-        IGeneratorTracker* createGeneratorTracker(
22918-            StringRef generatorName,
22919-            SourceLineInfo lineInfo,
22920-            Generators::GeneratorBasePtr&& generator ) override;
22921-
22922-
22923-        void benchmarkPreparing( StringRef name ) override;
22924-        void benchmarkStarting( BenchmarkInfo const& info ) override;
22925-        void benchmarkEnded( BenchmarkStats<> const& stats ) override;
22926-        void benchmarkFailed( StringRef error ) override;
22927-
22928-        std::string getCurrentTestName() const override;
22929-
22930-        const AssertionResult* getLastResult() const override;
22931-
22932-        void exceptionEarlyReported() override;
22933-
22934-        void handleFatalErrorCondition( StringRef message ) override;
22935-
22936-        bool lastAssertionPassed() override;
22937-
22938-    public:
22939-        // !TBD We need to do this another way!
22940-        bool aborting() const;
22941-
22942-    private:
22943-        void assertionPassedFastPath( SourceLineInfo lineInfo );
22944-        // Update the non-thread-safe m_totals from the atomic assertion counts.
22945-        void updateTotalsFromAtomics();
22946-
22947-        void runCurrentTest();
22948-        void invokeActiveTestCase();
22949-
22950-        bool testForMissingAssertions( Counts& assertions );
22951-
22952-        void assertionEnded( AssertionResult&& result );
22953-        void reportExpr
22954-                (   AssertionInfo const &info,
22955-                    ResultWas::OfType resultType,
22956-                    ITransientExpression const *expr,
22957-                    bool negated );
22958-
22959-        void populateReaction( AssertionReaction& reaction, bool has_normal_disposition );
22960-
22961-        // Creates dummy info for unexpected exceptions/fatal errors,
22962-        // where we do not have the access to one, but we still need
22963-        // to send one to the reporters.
22964-        AssertionInfo makeDummyAssertionInfo();
22965-
22966-    private:
22967-
22968-        void handleUnfinishedSections();
22969-        mutable Detail::Mutex m_assertionMutex;
22970-        TestRunInfo m_runInfo;
22971-        TestCaseHandle const* m_activeTestCase = nullptr;
22972-        ITracker* m_testCaseTracker = nullptr;
22973-        Optional<AssertionResult> m_lastResult;
22974-        IConfig const* m_config;
22975-        Totals m_totals;
22976-        Detail::AtomicCounts m_atomicAssertionCount;
22977-        IEventListenerPtr m_reporter;
22978-        std::vector<SectionEndInfo> m_unfinishedSections;
22979-        std::vector<ITracker*> m_activeSections;
22980-        TrackerContext m_trackerContext;
22981-        Detail::unique_ptr<OutputRedirect> m_outputRedirect;
22982-        FatalConditionHandler m_fatalConditionhandler;
22983-        // Caches m_config->abortAfter() to avoid vptr calls/allow inlining
22984-        size_t m_abortAfterXFailedAssertions;
22985-        bool m_shouldReportUnexpected = true;
22986-        // Caches whether `assertionStarting` events should be sent to the reporter.
22987-        bool m_reportAssertionStarting;
22988-        // Caches whether `assertionEnded` events for successful assertions should be sent to the reporter
22989-        bool m_includeSuccessfulResults;
22990-        // Caches m_config->shouldDebugBreak() to avoid vptr calls/allow inlining
22991-        bool m_shouldDebugBreak;
22992-    };
22993-
22994-    void seedRng(IConfig const& config);
22995-    unsigned int rngSeed();
22996-} // end namespace Catch
22997-
22998-#endif // CATCH_RUN_CONTEXT_HPP_INCLUDED
22999-
23000-
23001-#ifndef CATCH_SHARDING_HPP_INCLUDED
23002-#define CATCH_SHARDING_HPP_INCLUDED
23003-
23004-#include <cassert>
23005-#include <algorithm>
23006-
23007-namespace Catch {
23008-
23009-    template<typename Container>
23010-    Container createShard(Container const& container, std::size_t const shardCount, std::size_t const shardIndex) {
23011-        assert(shardCount > shardIndex);
23012-
23013-        if (shardCount == 1) {
23014-            return container;
23015-        }
23016-
23017-        const std::size_t totalTestCount = container.size();
23018-
23019-        const std::size_t shardSize = totalTestCount / shardCount;
23020-        const std::size_t leftoverTests = totalTestCount % shardCount;
23021-
23022-        const std::size_t startIndex = shardIndex * shardSize + (std::min)(shardIndex, leftoverTests);
23023-        const std::size_t endIndex = (shardIndex + 1) * shardSize + (std::min)(shardIndex + 1, leftoverTests);
23024-
23025-        auto startIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(startIndex));
23026-        auto endIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(endIndex));
23027-
23028-        return Container(startIterator, endIterator);
23029-    }
23030-
23031-}
23032-
23033-#endif // CATCH_SHARDING_HPP_INCLUDED
23034-
23035-
23036-#ifndef CATCH_SINGLETONS_HPP_INCLUDED
23037-#define CATCH_SINGLETONS_HPP_INCLUDED
23038-
23039-namespace Catch {
23040-
23041-    struct ISingleton {
23042-        virtual ~ISingleton(); // = default
23043-    };
23044-
23045-
23046-    void addSingleton( ISingleton* singleton );
23047-    void cleanupSingletons();
23048-
23049-
23050-    template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
23051-    class Singleton : SingletonImplT, public ISingleton {
23052-
23053-        static auto getInternal() -> Singleton* {
23054-            static Singleton* s_instance = nullptr;
23055-            if( !s_instance ) {
23056-                s_instance = new Singleton;
23057-                addSingleton( s_instance );
23058-            }
23059-            return s_instance;
23060-        }
23061-
23062-    public:
23063-        static auto get() -> InterfaceT const& {
23064-            return *getInternal();
23065-        }
23066-        static auto getMutable() -> MutableInterfaceT& {
23067-            return *getInternal();
23068-        }
23069-    };
23070-
23071-} // namespace Catch
23072-
23073-#endif // CATCH_SINGLETONS_HPP_INCLUDED
23074-
23075-
23076-#ifndef CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
23077-#define CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
23078-
23079-
23080-#include <vector>
23081-#include <exception>
23082-
23083-namespace Catch {
23084-
23085-    class StartupExceptionRegistry {
23086-#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
23087-    public:
23088-        void add(std::exception_ptr const& exception) noexcept;
23089-        std::vector<std::exception_ptr> const& getExceptions() const noexcept;
23090-    private:
23091-        std::vector<std::exception_ptr> m_exceptions;
23092-#endif
23093-    };
23094-
23095-} // end namespace Catch
23096-
23097-#endif // CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
23098-
23099-
23100-
23101-#ifndef CATCH_STDSTREAMS_HPP_INCLUDED
23102-#define CATCH_STDSTREAMS_HPP_INCLUDED
23103-
23104-#include <iosfwd>
23105-
23106-namespace Catch {
23107-
23108-    std::ostream& cout();
23109-    std::ostream& cerr();
23110-    std::ostream& clog();
23111-
23112-} // namespace Catch
23113-
23114-#endif
23115-
23116-
23117-#ifndef CATCH_STRING_MANIP_HPP_INCLUDED
23118-#define CATCH_STRING_MANIP_HPP_INCLUDED
23119-
23120-
23121-#include <cstdint>
23122-#include <string>
23123-#include <iosfwd>
23124-#include <vector>
23125-
23126-namespace Catch {
23127-
23128-    bool startsWith( std::string const& s, std::string const& prefix );
23129-    bool startsWith( StringRef s, char prefix );
23130-    bool endsWith( std::string const& s, std::string const& suffix );
23131-    bool endsWith( std::string const& s, char suffix );
23132-    bool contains( std::string const& s, std::string const& infix );
23133-    void toLowerInPlace( std::string& s );
23134-    std::string toLower( std::string const& s );
23135-    char toLower( char c );
23136-    //! Returns a new string without whitespace at the start/end
23137-    std::string trim( std::string const& str );
23138-    //! Returns a substring of the original ref without whitespace. Beware lifetimes!
23139-    StringRef trim(StringRef ref);
23140-
23141-    // !!! Be aware, returns refs into original string - make sure original string outlives them
23142-    std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
23143-    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
23144-
23145-    /**
23146-     * Helper for streaming a "count [maybe-plural-of-label]" human-friendly string
23147-     *
23148-     * Usage example:
23149-     * ```cpp
23150-     * std::cout << "Found " << pluralise(count, "error") << '\n';
23151-     * ```
23152-     *
23153-     * **Important:** The provided string must outlive the instance
23154-     */
23155-    class pluralise {
23156-        std::uint64_t m_count;
23157-        StringRef m_label;
23158-
23159-    public:
23160-        constexpr pluralise(std::uint64_t count, StringRef label):
23161-            m_count(count),
23162-            m_label(label)
23163-        {}
23164-
23165-        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
23166-    };
23167-}
23168-
23169-#endif // CATCH_STRING_MANIP_HPP_INCLUDED
23170-
23171-
23172-#ifndef CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
23173-#define CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
23174-
23175-
23176-#include <map>
23177-#include <string>
23178-
23179-namespace Catch {
23180-    struct SourceLineInfo;
23181-
23182-    class TagAliasRegistry : public ITagAliasRegistry {
23183-    public:
23184-        ~TagAliasRegistry() override;
23185-        TagAlias const* find( std::string const& alias ) const override;
23186-        std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
23187-        void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
23188-
23189-    private:
23190-        std::map<std::string, TagAlias> m_registry;
23191-    };
23192-
23193-} // end namespace Catch
23194-
23195-#endif // CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
23196-
23197-
23198-#ifndef CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
23199-#define CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
23200-
23201-#include <cstdint>
23202-
23203-namespace Catch {
23204-
23205-    struct TestCaseInfo;
23206-
23207-    class TestCaseInfoHasher {
23208-    public:
23209-        using hash_t = std::uint64_t;
23210-        TestCaseInfoHasher( hash_t seed );
23211-        uint32_t operator()( TestCaseInfo const& t ) const;
23212-
23213-    private:
23214-        hash_t m_seed;
23215-    };
23216-
23217-} // namespace Catch
23218-
23219-#endif /* CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED */
23220-
23221-
23222-#ifndef CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
23223-#define CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
23224-
23225-
23226-#include <vector>
23227-
23228-namespace Catch {
23229-
23230-    class IConfig;
23231-    class ITestInvoker;
23232-    class TestCaseHandle;
23233-    class TestSpec;
23234-
23235-    std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases );
23236-
23237-    bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config );
23238-
23239-    std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
23240-    std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
23241-
23242-    class TestRegistry : public ITestCaseRegistry {
23243-    public:
23244-        void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
23245-
23246-        std::vector<TestCaseInfo*> const& getAllInfos() const override;
23247-        std::vector<TestCaseHandle> const& getAllTests() const override;
23248-        std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override;
23249-
23250-        ~TestRegistry() override; // = default
23251-
23252-    private:
23253-        std::vector<Detail::unique_ptr<TestCaseInfo>> m_owned_test_infos;
23254-        // Keeps a materialized vector for `getAllInfos`.
23255-        // We should get rid of that eventually (see interface note)
23256-        std::vector<TestCaseInfo*> m_viewed_test_infos;
23257-
23258-        std::vector<Detail::unique_ptr<ITestInvoker>> m_invokers;
23259-        std::vector<TestCaseHandle> m_handles;
23260-        mutable TestRunOrder m_currentSortOrder = TestRunOrder::Declared;
23261-        mutable std::vector<TestCaseHandle> m_sortedFunctions;
23262-    };
23263-
23264-    ///////////////////////////////////////////////////////////////////////////
23265-
23266-
23267-} // end namespace Catch
23268-
23269-
23270-#endif // CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
23271-
23272-
23273-#ifndef CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
23274-#define CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
23275-
23276-#ifdef __clang__
23277-#pragma clang diagnostic push
23278-#pragma clang diagnostic ignored "-Wpadded"
23279-#endif
23280-
23281-
23282-#include <vector>
23283-#include <string>
23284-
23285-namespace Catch {
23286-
23287-    class ITagAliasRegistry;
23288-
23289-    class TestSpecParser {
23290-        enum Mode{ None, Name, QuotedName, Tag, EscapedName };
23291-        Mode m_mode = None;
23292-        Mode lastMode = None;
23293-        bool m_exclusion = false;
23294-        std::size_t m_pos = 0;
23295-        std::size_t m_realPatternPos = 0;
23296-        std::string m_arg;
23297-        std::string m_substring;
23298-        std::string m_patternName;
23299-        std::vector<std::size_t> m_escapeChars;
23300-        TestSpec::Filter m_currentFilter;
23301-        TestSpec m_testSpec;
23302-        ITagAliasRegistry const* m_tagAliases = nullptr;
23303-
23304-    public:
23305-        TestSpecParser( ITagAliasRegistry const& tagAliases );
23306-
23307-        TestSpecParser& parse( std::string const& arg );
23308-        TestSpec testSpec();
23309-
23310-    private:
23311-        bool visitChar( char c );
23312-        void startNewMode( Mode mode );
23313-        bool processNoneChar( char c );
23314-        void processNameChar( char c );
23315-        bool processOtherChar( char c );
23316-        void endMode();
23317-        void escape();
23318-        bool isControlChar( char c ) const;
23319-        void saveLastMode();
23320-        void revertBackToLastMode();
23321-        void addFilter();
23322-        bool separate();
23323-
23324-        // Handles common preprocessing of the pattern for name/tag patterns
23325-        std::string preprocessPattern();
23326-        // Adds the current pattern as a test name
23327-        void addNamePattern();
23328-        // Adds the current pattern as a tag
23329-        void addTagPattern();
23330-
23331-        inline void addCharToPattern(char c) {
23332-            m_substring += c;
23333-            m_patternName += c;
23334-            m_realPatternPos++;
23335-        }
23336-
23337-    };
23338-
23339-} // namespace Catch
23340-
23341-#ifdef __clang__
23342-#pragma clang diagnostic pop
23343-#endif
23344-
23345-#endif // CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
23346-
23347-
23348-#ifndef CATCH_TEXTFLOW_HPP_INCLUDED
23349-#define CATCH_TEXTFLOW_HPP_INCLUDED
23350-
23351-
23352-#include <cassert>
23353-#include <string>
23354-#include <vector>
23355-
23356-namespace Catch {
23357-    namespace TextFlow {
23358-
23359-        class Columns;
23360-
23361-        /**
23362-         * Abstraction for a string with ansi escape sequences that
23363-         * automatically skips over escapes when iterating. Only graphical
23364-         * escape sequences are considered.
23365-         *
23366-         * Internal representation:
23367-         * An escape sequence looks like \033[39;49m
23368-         * We need bidirectional iteration and the unbound length of escape
23369-         * sequences poses a problem for operator-- To make this work we'll
23370-         * replace the last `m` with a 0xff (this is a codepoint that won't have
23371-         * any utf-8 meaning).
23372-         */
23373-        class AnsiSkippingString {
23374-            std::string m_string;
23375-            std::size_t m_size = 0;
23376-
23377-            // perform 0xff replacement and calculate m_size
23378-            void preprocessString();
23379-
23380-        public:
23381-            class const_iterator;
23382-            using iterator = const_iterator;
23383-            // note: must be u-suffixed or this will cause a "truncation of
23384-            // constant value" warning on MSVC
23385-            static constexpr char sentinel = static_cast<char>( 0xffu );
23386-
23387-            explicit AnsiSkippingString( std::string const& text );
23388-            explicit AnsiSkippingString( std::string&& text );
23389-
23390-            const_iterator begin() const;
23391-            const_iterator end() const;
23392-
23393-            size_t size() const { return m_size; }
23394-
23395-            std::string substring( const_iterator begin,
23396-                                   const_iterator end ) const;
23397-        };
23398-
23399-        class AnsiSkippingString::const_iterator {
23400-            friend AnsiSkippingString;
23401-            struct EndTag {};
23402-
23403-            const std::string* m_string;
23404-            std::string::const_iterator m_it;
23405-
23406-            explicit const_iterator( const std::string& string, EndTag ):
23407-                m_string( &string ), m_it( string.end() ) {}
23408-
23409-            void tryParseAnsiEscapes();
23410-            void advance();
23411-            void unadvance();
23412-
23413-        public:
23414-            using difference_type = std::ptrdiff_t;
23415-            using value_type = char;
23416-            using pointer = value_type*;
23417-            using reference = value_type&;
23418-            using iterator_category = std::bidirectional_iterator_tag;
23419-
23420-            explicit const_iterator( const std::string& string ):
23421-                m_string( &string ), m_it( string.begin() ) {
23422-                tryParseAnsiEscapes();
23423-            }
23424-
23425-            char operator*() const { return *m_it; }
23426-
23427-            const_iterator& operator++() {
23428-                advance();
23429-                return *this;
23430-            }
23431-            const_iterator operator++( int ) {
23432-                iterator prev( *this );
23433-                operator++();
23434-                return prev;
23435-            }
23436-            const_iterator& operator--() {
23437-                unadvance();
23438-                return *this;
23439-            }
23440-            const_iterator operator--( int ) {
23441-                iterator prev( *this );
23442-                operator--();
23443-                return prev;
23444-            }
23445-
23446-            bool operator==( const_iterator const& other ) const {
23447-                return m_it == other.m_it;
23448-            }
23449-            bool operator!=( const_iterator const& other ) const {
23450-                return !operator==( other );
23451-            }
23452-            bool operator<=( const_iterator const& other ) const {
23453-                return m_it <= other.m_it;
23454-            }
23455-
23456-            const_iterator oneBefore() const {
23457-                auto it = *this;
23458-                return --it;
23459-            }
23460-        };
23461-
23462-        /**
23463-         * Represents a column of text with specific width and indentation
23464-         *
23465-         * When written out to a stream, it will perform linebreaking
23466-         * of the provided text so that the written lines fit within
23467-         * target width.
23468-         */
23469-        class Column {
23470-            // String to be written out
23471-            AnsiSkippingString m_string;
23472-            // Width of the column for linebreaking
23473-            size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1;
23474-            // Indentation of other lines (including first if initial indent is
23475-            // unset)
23476-            size_t m_indent = 0;
23477-            // Indentation of the first line
23478-            size_t m_initialIndent = std::string::npos;
23479-
23480-        public:
23481-            /**
23482-             * Iterates "lines" in `Column` and returns them
23483-             */
23484-            class const_iterator {
23485-                friend Column;
23486-                struct EndTag {};
23487-
23488-                Column const& m_column;
23489-                // Where does the current line start?
23490-                AnsiSkippingString::const_iterator m_lineStart;
23491-                // How long should the current line be?
23492-                AnsiSkippingString::const_iterator m_lineEnd;
23493-                // How far have we checked the string to iterate?
23494-                AnsiSkippingString::const_iterator m_parsedTo;
23495-                // Should a '-' be appended to the line?
23496-                bool m_addHyphen = false;
23497-
23498-                const_iterator( Column const& column, EndTag ):
23499-                    m_column( column ),
23500-                    m_lineStart( m_column.m_string.end() ),
23501-                    m_lineEnd( column.m_string.end() ),
23502-                    m_parsedTo( column.m_string.end() ) {}
23503-
23504-                // Calculates the length of the current line
23505-                void calcLength();
23506-
23507-                // Returns current indentation width
23508-                size_t indentSize() const;
23509-
23510-                // Creates an indented and (optionally) suffixed string from
23511-                // current iterator position, indentation and length.
23512-                std::string addIndentAndSuffix(
23513-                    AnsiSkippingString::const_iterator start,
23514-                    AnsiSkippingString::const_iterator end ) const;
23515-
23516-            public:
23517-                using difference_type = std::ptrdiff_t;
23518-                using value_type = std::string;
23519-                using pointer = value_type*;
23520-                using reference = value_type&;
23521-                using iterator_category = std::forward_iterator_tag;
23522-
23523-                explicit const_iterator( Column const& column );
23524-
23525-                std::string operator*() const;
23526-
23527-                const_iterator& operator++();
23528-                const_iterator operator++( int );
23529-
23530-                bool operator==( const_iterator const& other ) const {
23531-                    return m_lineStart == other.m_lineStart &&
23532-                           &m_column == &other.m_column;
23533-                }
23534-                bool operator!=( const_iterator const& other ) const {
23535-                    return !operator==( other );
23536-                }
23537-            };
23538-            using iterator = const_iterator;
23539-
23540-            explicit Column( std::string const& text ): m_string( text ) {}
23541-            explicit Column( std::string&& text ):
23542-                m_string( CATCH_MOVE( text ) ) {}
23543-
23544-            Column& width( size_t newWidth ) & {
23545-                assert( newWidth > 0 );
23546-                m_width = newWidth;
23547-                return *this;
23548-            }
23549-            Column&& width( size_t newWidth ) && {
23550-                assert( newWidth > 0 );
23551-                m_width = newWidth;
23552-                return CATCH_MOVE( *this );
23553-            }
23554-            Column& indent( size_t newIndent ) & {
23555-                m_indent = newIndent;
23556-                return *this;
23557-            }
23558-            Column&& indent( size_t newIndent ) && {
23559-                m_indent = newIndent;
23560-                return CATCH_MOVE( *this );
23561-            }
23562-            Column& initialIndent( size_t newIndent ) & {
23563-                m_initialIndent = newIndent;
23564-                return *this;
23565-            }
23566-            Column&& initialIndent( size_t newIndent ) && {
23567-                m_initialIndent = newIndent;
23568-                return CATCH_MOVE( *this );
23569-            }
23570-
23571-            size_t width() const { return m_width; }
23572-            const_iterator begin() const { return const_iterator( *this ); }
23573-            const_iterator end() const {
23574-                return { *this, const_iterator::EndTag{} };
23575-            }
23576-
23577-            friend std::ostream& operator<<( std::ostream& os,
23578-                                             Column const& col );
23579-
23580-            friend Columns operator+( Column const& lhs, Column const& rhs );
23581-            friend Columns operator+( Column&& lhs, Column&& rhs );
23582-        };
23583-
23584-        //! Creates a column that serves as an empty space of specific width
23585-        Column Spacer( size_t spaceWidth );
23586-
23587-        class Columns {
23588-            std::vector<Column> m_columns;
23589-
23590-        public:
23591-            class iterator {
23592-                friend Columns;
23593-                struct EndTag {};
23594-
23595-                std::vector<Column> const& m_columns;
23596-                std::vector<Column::const_iterator> m_iterators;
23597-                size_t m_activeIterators;
23598-
23599-                iterator( Columns const& columns, EndTag );
23600-
23601-            public:
23602-                using difference_type = std::ptrdiff_t;
23603-                using value_type = std::string;
23604-                using pointer = value_type*;
23605-                using reference = value_type&;
23606-                using iterator_category = std::forward_iterator_tag;
23607-
23608-                explicit iterator( Columns const& columns );
23609-
23610-                auto operator==( iterator const& other ) const -> bool {
23611-                    return m_iterators == other.m_iterators;
23612-                }
23613-                auto operator!=( iterator const& other ) const -> bool {
23614-                    return m_iterators != other.m_iterators;
23615-                }
23616-                std::string operator*() const;
23617-                iterator& operator++();
23618-                iterator operator++( int );
23619-            };
23620-            using const_iterator = iterator;
23621-
23622-            iterator begin() const { return iterator( *this ); }
23623-            iterator end() const { return { *this, iterator::EndTag() }; }
23624-
23625-            friend Columns& operator+=( Columns& lhs, Column const& rhs );
23626-            friend Columns& operator+=( Columns& lhs, Column&& rhs );
23627-            friend Columns operator+( Columns const& lhs, Column const& rhs );
23628-            friend Columns operator+( Columns&& lhs, Column&& rhs );
23629-
23630-            friend std::ostream& operator<<( std::ostream& os,
23631-                                             Columns const& cols );
23632-        };
23633-
23634-    } // namespace TextFlow
23635-} // namespace Catch
23636-#endif // CATCH_TEXTFLOW_HPP_INCLUDED
23637-
23638-
23639-#ifndef CATCH_TO_STRING_HPP_INCLUDED
23640-#define CATCH_TO_STRING_HPP_INCLUDED
23641-
23642-#include <string>
23643-
23644-
23645-namespace Catch {
23646-    template <typename T>
23647-    std::string to_string(T const& t) {
23648-#if defined(CATCH_CONFIG_CPP11_TO_STRING)
23649-        return std::to_string(t);
23650-#else
23651-        ReusableStringStream rss;
23652-        rss << t;
23653-        return rss.str();
23654-#endif
23655-    }
23656-} // end namespace Catch
23657-
23658-#endif // CATCH_TO_STRING_HPP_INCLUDED
23659-
23660-
23661-#ifndef CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
23662-#define CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
23663-
23664-namespace Catch {
23665-    bool uncaught_exceptions();
23666-} // end namespace Catch
23667-
23668-#endif // CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
23669-
23670-
23671-#ifndef CATCH_XMLWRITER_HPP_INCLUDED
23672-#define CATCH_XMLWRITER_HPP_INCLUDED
23673-
23674-
23675-#include <iosfwd>
23676-#include <vector>
23677-#include <cstdint>
23678-
23679-namespace Catch {
23680-    enum class XmlFormatting : std::uint8_t {
23681-        None = 0x00,
23682-        Indent = 0x01,
23683-        Newline = 0x02,
23684-    };
23685-
23686-    constexpr XmlFormatting operator|( XmlFormatting lhs, XmlFormatting rhs ) {
23687-        return static_cast<XmlFormatting>( static_cast<std::uint8_t>( lhs ) |
23688-                                           static_cast<std::uint8_t>( rhs ) );
23689-    }
23690-
23691-    constexpr XmlFormatting operator&( XmlFormatting lhs, XmlFormatting rhs ) {
23692-        return static_cast<XmlFormatting>( static_cast<std::uint8_t>( lhs ) &
23693-                                           static_cast<std::uint8_t>( rhs ) );
23694-    }
23695-
23696-
23697-    /**
23698-     * Helper for XML-encoding text (escaping angle brackets, quotes, etc)
23699-     *
23700-     * Note: doesn't take ownership of passed strings, and thus the
23701-     *       encoded string must outlive the encoding instance.
23702-     */
23703-    class XmlEncode {
23704-    public:
23705-        enum ForWhat { ForTextNodes, ForAttributes };
23706-
23707-        constexpr XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ):
23708-            m_str( str ), m_forWhat( forWhat ) {}
23709-
23710-
23711-        void encodeTo( std::ostream& os ) const;
23712-
23713-        friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
23714-
23715-    private:
23716-        StringRef m_str;
23717-        ForWhat m_forWhat;
23718-    };
23719-
23720-    class XmlWriter {
23721-    public:
23722-
23723-        class ScopedElement {
23724-        public:
23725-            ScopedElement( XmlWriter* writer, XmlFormatting fmt );
23726-
23727-            ScopedElement( ScopedElement&& other ) noexcept;
23728-            ScopedElement& operator=( ScopedElement&& other ) noexcept;
23729-
23730-            ~ScopedElement();
23731-
23732-            ScopedElement&
23733-            writeText( StringRef text,
23734-                       XmlFormatting fmt = XmlFormatting::Newline |
23735-                                           XmlFormatting::Indent );
23736-
23737-            ScopedElement& writeAttribute( StringRef name,
23738-                                           StringRef attribute );
23739-            template <typename T,
23740-                      // Without this SFINAE, this overload is a better match
23741-                      // for `std::string`, `char const*`, `char const[N]` args.
23742-                      // While it would still work, it would cause code bloat
23743-                      // and multiple iteration over the strings
23744-                      typename = typename std::enable_if_t<
23745-                          !std::is_convertible<T, StringRef>::value>>
23746-            ScopedElement& writeAttribute( StringRef name,
23747-                                           T const& attribute ) {
23748-                m_writer->writeAttribute( name, attribute );
23749-                return *this;
23750-            }
23751-
23752-        private:
23753-            XmlWriter* m_writer = nullptr;
23754-            XmlFormatting m_fmt;
23755-        };
23756-
23757-        XmlWriter( std::ostream& os );
23758-        ~XmlWriter();
23759-
23760-        XmlWriter( XmlWriter const& ) = delete;
23761-        XmlWriter& operator=( XmlWriter const& ) = delete;
23762-
23763-        XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
23764-
23765-        ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
23766-
23767-        XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
23768-
23769-        //! The attribute content is XML-encoded
23770-        XmlWriter& writeAttribute( StringRef name, StringRef attribute );
23771-
23772-        //! Writes the attribute as "true/false"
23773-        XmlWriter& writeAttribute( StringRef name, bool attribute );
23774-
23775-        //! The attribute content is XML-encoded
23776-        XmlWriter& writeAttribute( StringRef name, char const* attribute );
23777-
23778-        //! The attribute value must provide op<<(ostream&, T). The resulting
23779-        //! serialization is XML-encoded
23780-        template <typename T,
23781-                  // Without this SFINAE, this overload is a better match
23782-                  // for `std::string`, `char const*`, `char const[N]` args.
23783-                  // While it would still work, it would cause code bloat
23784-                  // and multiple iteration over the strings
23785-                  typename = typename std::enable_if_t<
23786-                      !std::is_convertible<T, StringRef>::value>>
23787-        XmlWriter& writeAttribute( StringRef name, T const& attribute ) {
23788-            ReusableStringStream rss;
23789-            rss << attribute;
23790-            return writeAttribute( name, rss.str() );
23791-        }
23792-
23793-        //! Writes escaped `text` in a element
23794-        XmlWriter& writeText( StringRef text,
23795-                              XmlFormatting fmt = XmlFormatting::Newline |
23796-                                                  XmlFormatting::Indent );
23797-
23798-        //! Writes XML comment as "<!-- text -->"
23799-        XmlWriter& writeComment( StringRef text,
23800-                                 XmlFormatting fmt = XmlFormatting::Newline |
23801-                                                     XmlFormatting::Indent );
23802-
23803-        void writeStylesheetRef( StringRef url );
23804-
23805-        void ensureTagClosed();
23806-
23807-    private:
23808-
23809-        void applyFormatting(XmlFormatting fmt);
23810-
23811-        void writeDeclaration();
23812-
23813-        void newlineIfNecessary();
23814-
23815-        bool m_tagIsOpen = false;
23816-        bool m_needsNewline = false;
23817-        std::vector<std::string> m_tags;
23818-        std::string m_indent;
23819-        std::ostream& m_os;
23820-    };
23821-
23822-}
23823-
23824-#endif // CATCH_XMLWRITER_HPP_INCLUDED
23825-
23826-
23827-/** \file
23828- * This is a convenience header for Catch2's Matcher support. It includes
23829- * **all** of Catch2 headers related to matchers.
23830- *
23831- * Generally the Catch2 users should use specific includes they need,
23832- * but this header can be used instead for ease-of-experimentation, or
23833- * just plain convenience, at the cost of increased compilation times.
23834- *
23835- * When a new header is added to either the `matchers` folder, or to
23836- * the corresponding internal subfolder, it should be added here.
23837- */
23838-
23839-#ifndef CATCH_MATCHERS_ALL_HPP_INCLUDED
23840-#define CATCH_MATCHERS_ALL_HPP_INCLUDED
23841-
23842-
23843-
23844-#ifndef CATCH_MATCHERS_HPP_INCLUDED
23845-#define CATCH_MATCHERS_HPP_INCLUDED
23846-
23847-
23848-
23849-#ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED
23850-#define CATCH_MATCHERS_IMPL_HPP_INCLUDED
23851-
23852-
23853-#include <string>
23854-
23855-namespace Catch {
23856-
23857-#ifdef __clang__
23858-#    pragma clang diagnostic push
23859-#    pragma clang diagnostic ignored "-Wsign-compare"
23860-#    pragma clang diagnostic ignored "-Wnon-virtual-dtor"
23861-#elif defined __GNUC__
23862-#    pragma GCC diagnostic push
23863-#    pragma GCC diagnostic ignored "-Wsign-compare"
23864-#    pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
23865-#endif
23866-
23867-    template<typename ArgT, typename MatcherT>
23868-    class MatchExpr : public ITransientExpression {
23869-        ArgT && m_arg;
23870-        MatcherT const& m_matcher;
23871-    public:
23872-        constexpr MatchExpr( ArgT && arg, MatcherT const& matcher )
23873-        :   ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose
23874-            m_arg( CATCH_FORWARD(arg) ),
23875-            m_matcher( matcher )
23876-        {}
23877-
23878-        void streamReconstructedExpression( std::ostream& os ) const override {
23879-            os << Catch::Detail::stringify( m_arg )
23880-               << ' '
23881-               << m_matcher.toString();
23882-        }
23883-    };
23884-
23885-#ifdef __clang__
23886-#    pragma clang diagnostic pop
23887-#elif defined __GNUC__
23888-#    pragma GCC diagnostic pop
23889-#endif
23890-
23891-
23892-    namespace Matchers {
23893-        template <typename ArgT>
23894-        class MatcherBase;
23895-    }
23896-
23897-    using StringMatcher = Matchers::MatcherBase<std::string>;
23898-
23899-    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher );
23900-
23901-    template<typename ArgT, typename MatcherT>
23902-    constexpr MatchExpr<ArgT, MatcherT>
23903-    makeMatchExpr( ArgT&& arg, MatcherT const& matcher ) {
23904-        return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher );
23905-    }
23906-
23907-} // namespace Catch
23908-
23909-
23910-///////////////////////////////////////////////////////////////////////////////
23911-#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
23912-    do { \
23913-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
23914-        INTERNAL_CATCH_TRY { \
23915-            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher ) ); \
23916-        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
23917-        catchAssertionHandler.complete(); \
23918-    } while( false )
23919-
23920-
23921-///////////////////////////////////////////////////////////////////////////////
23922-#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
23923-    do { \
23924-        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
23925-        if( catchAssertionHandler.allowThrows() ) \
23926-            try { \
23927-                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
23928-                CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
23929-                static_cast<void>(__VA_ARGS__ ); \
23930-                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
23931-                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
23932-            } \
23933-            catch( exceptionType const& ex ) { \
23934-                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher ) ); \
23935-            } \
23936-            catch( ... ) { \
23937-                catchAssertionHandler.handleUnexpectedInflightException(); \
23938-            } \
23939-        else \
23940-            catchAssertionHandler.handleThrowingCallSkipped(); \
23941-        catchAssertionHandler.complete(); \
23942-    } while( false )
23943-
23944-
23945-#endif // CATCH_MATCHERS_IMPL_HPP_INCLUDED
23946-
23947-#include <string>
23948-#include <vector>
23949-
23950-namespace Catch {
23951-namespace Matchers {
23952-
23953-    class MatcherUntypedBase {
23954-    public:
23955-        MatcherUntypedBase() = default;
23956-
23957-        MatcherUntypedBase(MatcherUntypedBase const&) = default;
23958-        MatcherUntypedBase(MatcherUntypedBase&&) = default;
23959-
23960-        MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete;
23961-        MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete;
23962-
23963-        std::string toString() const;
23964-
23965-    protected:
23966-        virtual ~MatcherUntypedBase(); // = default;
23967-        virtual std::string describe() const = 0;
23968-        mutable std::string m_cachedToString;
23969-    };
23970-
23971-
23972-    template<typename T>
23973-    class MatcherBase : public MatcherUntypedBase {
23974-    public:
23975-        virtual bool match( T const& arg ) const = 0;
23976-    };
23977-
23978-    namespace Detail {
23979-
23980-        template<typename ArgT>
23981-        class MatchAllOf final : public MatcherBase<ArgT> {
23982-            std::vector<MatcherBase<ArgT> const*> m_matchers;
23983-
23984-        public:
23985-            MatchAllOf() = default;
23986-            MatchAllOf(MatchAllOf const&) = delete;
23987-            MatchAllOf& operator=(MatchAllOf const&) = delete;
23988-            MatchAllOf(MatchAllOf&&) = default;
23989-            MatchAllOf& operator=(MatchAllOf&&) = default;
23990-
23991-
23992-            bool match( ArgT const& arg ) const override {
23993-                for( auto matcher : m_matchers ) {
23994-                    if (!matcher->match(arg))
23995-                        return false;
23996-                }
23997-                return true;
23998-            }
23999-            std::string describe() const override {
24000-                std::string description;
24001-                description.reserve( 4 + m_matchers.size()*32 );
24002-                description += "( ";
24003-                bool first = true;
24004-                for( auto matcher : m_matchers ) {
24005-                    if( first )
24006-                        first = false;
24007-                    else
24008-                        description += " and ";
24009-                    description += matcher->toString();
24010-                }
24011-                description += " )";
24012-                return description;
24013-            }
24014-
24015-            friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) {
24016-                lhs.m_matchers.push_back(&rhs);
24017-                return CATCH_MOVE(lhs);
24018-            }
24019-            friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) {
24020-                rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
24021-                return CATCH_MOVE(rhs);
24022-            }
24023-        };
24024-
24025-        //! lvalue overload is intentionally deleted, users should
24026-        //! not be trying to compose stored composition matchers
24027-        template<typename ArgT>
24028-        MatchAllOf<ArgT> operator&& (MatchAllOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
24029-        //! lvalue overload is intentionally deleted, users should
24030-        //! not be trying to compose stored composition matchers
24031-        template<typename ArgT>
24032-        MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete;
24033-
24034-        template<typename ArgT>
24035-        class MatchAnyOf final : public MatcherBase<ArgT> {
24036-            std::vector<MatcherBase<ArgT> const*> m_matchers;
24037-        public:
24038-            MatchAnyOf() = default;
24039-            MatchAnyOf(MatchAnyOf const&) = delete;
24040-            MatchAnyOf& operator=(MatchAnyOf const&) = delete;
24041-            MatchAnyOf(MatchAnyOf&&) = default;
24042-            MatchAnyOf& operator=(MatchAnyOf&&) = default;
24043-
24044-            bool match( ArgT const& arg ) const override {
24045-                for( auto matcher : m_matchers ) {
24046-                    if (matcher->match(arg))
24047-                        return true;
24048-                }
24049-                return false;
24050-            }
24051-            std::string describe() const override {
24052-                std::string description;
24053-                description.reserve( 4 + m_matchers.size()*32 );
24054-                description += "( ";
24055-                bool first = true;
24056-                for( auto matcher : m_matchers ) {
24057-                    if( first )
24058-                        first = false;
24059-                    else
24060-                        description += " or ";
24061-                    description += matcher->toString();
24062-                }
24063-                description += " )";
24064-                return description;
24065-            }
24066-
24067-            friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) {
24068-                lhs.m_matchers.push_back(&rhs);
24069-                return CATCH_MOVE(lhs);
24070-            }
24071-            friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) {
24072-                rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
24073-                return CATCH_MOVE(rhs);
24074-            }
24075-        };
24076-
24077-        //! lvalue overload is intentionally deleted, users should
24078-        //! not be trying to compose stored composition matchers
24079-        template<typename ArgT>
24080-        MatchAnyOf<ArgT> operator|| (MatchAnyOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
24081-        //! lvalue overload is intentionally deleted, users should
24082-        //! not be trying to compose stored composition matchers
24083-        template<typename ArgT>
24084-        MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete;
24085-
24086-        template<typename ArgT>
24087-        class MatchNotOf final : public MatcherBase<ArgT> {
24088-            MatcherBase<ArgT> const& m_underlyingMatcher;
24089-
24090-        public:
24091-            explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ):
24092-                m_underlyingMatcher( underlyingMatcher )
24093-            {}
24094-
24095-            bool match( ArgT const& arg ) const override {
24096-                return !m_underlyingMatcher.match( arg );
24097-            }
24098-
24099-            std::string describe() const override {
24100-                return "not " + m_underlyingMatcher.toString();
24101-            }
24102-        };
24103-
24104-    } // namespace Detail
24105-
24106-    template <typename T>
24107-    Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
24108-        return Detail::MatchAllOf<T>{} && lhs && rhs;
24109-    }
24110-    template <typename T>
24111-    Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
24112-        return Detail::MatchAnyOf<T>{} || lhs || rhs;
24113-    }
24114-
24115-    template <typename T>
24116-    Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) {
24117-        return Detail::MatchNotOf<T>{ matcher };
24118-    }
24119-
24120-
24121-} // namespace Matchers
24122-} // namespace Catch
24123-
24124-
24125-#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
24126-  #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
24127-  #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
24128-
24129-  #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
24130-  #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
24131-
24132-  #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
24133-  #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
24134-
24135-#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
24136-
24137-  #define CATCH_REQUIRE_THROWS_WITH( expr, matcher )                   (void)(0)
24138-  #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
24139-
24140-  #define CATCH_CHECK_THROWS_WITH( expr, matcher )                     (void)(0)
24141-  #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher )   (void)(0)
24142-
24143-  #define CATCH_CHECK_THAT( arg, matcher )                             (void)(0)
24144-  #define CATCH_REQUIRE_THAT( arg, matcher )                           (void)(0)
24145-
24146-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
24147-
24148-  #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
24149-  #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
24150-
24151-  #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
24152-  #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
24153-
24154-  #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
24155-  #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
24156-
24157-#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
24158-
24159-  #define REQUIRE_THROWS_WITH( expr, matcher )                   (void)(0)
24160-  #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
24161-
24162-  #define CHECK_THROWS_WITH( expr, matcher )                     (void)(0)
24163-  #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher )   (void)(0)
24164-
24165-  #define CHECK_THAT( arg, matcher )                             (void)(0)
24166-  #define REQUIRE_THAT( arg, matcher )                           (void)(0)
24167-
24168-#endif // end of user facing macro declarations
24169-
24170-#endif // CATCH_MATCHERS_HPP_INCLUDED
24171-
24172-
24173-#ifndef CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
24174-#define CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
24175-
24176-
24177-
24178-#ifndef CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
24179-#define CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
24180-
24181-
24182-#include <array>
24183-#include <algorithm>
24184-#include <string>
24185-#include <type_traits>
24186-
24187-namespace Catch {
24188-namespace Matchers {
24189-    class MatcherGenericBase : public MatcherUntypedBase {
24190-    public:
24191-        MatcherGenericBase() = default;
24192-        ~MatcherGenericBase() override; // = default;
24193-
24194-        MatcherGenericBase(MatcherGenericBase const&) = default;
24195-        MatcherGenericBase(MatcherGenericBase&&) = default;
24196-
24197-        MatcherGenericBase& operator=(MatcherGenericBase const&) = delete;
24198-        MatcherGenericBase& operator=(MatcherGenericBase&&) = delete;
24199-    };
24200-
24201-
24202-    namespace Detail {
24203-        template<std::size_t N, std::size_t M>
24204-        std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
24205-            std::array<void const*, N + M> arr{};
24206-            std::copy_n(lhs.begin(), N, arr.begin());
24207-            std::copy_n(rhs.begin(), M, arr.begin() + N);
24208-            return arr;
24209-        }
24210-
24211-        template<std::size_t N>
24212-        std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
24213-            std::array<void const*, N+1> arr{};
24214-            std::copy_n(lhs.begin(), N, arr.begin());
24215-            arr[N] = rhs;
24216-            return arr;
24217-        }
24218-
24219-        template<std::size_t N>
24220-        std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
24221-            std::array<void const*, N + 1> arr{ {lhs} };
24222-            std::copy_n(rhs.begin(), N, arr.begin() + 1);
24223-            return arr;
24224-        }
24225-
24226-        template<typename T>
24227-        static constexpr bool is_generic_matcher_v = std::is_base_of<
24228-            Catch::Matchers::MatcherGenericBase,
24229-            std::remove_cv_t<std::remove_reference_t<T>>
24230-        >::value;
24231-
24232-        template<typename... Ts>
24233-        static constexpr bool are_generic_matchers_v = Catch::Detail::conjunction<std::integral_constant<bool,is_generic_matcher_v<Ts>>...>::value;
24234-
24235-        template<typename T>
24236-        static constexpr bool is_matcher_v = std::is_base_of<
24237-            Catch::Matchers::MatcherUntypedBase,
24238-            std::remove_cv_t<std::remove_reference_t<T>>
24239-        >::value;
24240-
24241-
24242-        template<std::size_t N, typename Arg>
24243-        bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
24244-            return true;
24245-        }
24246-
24247-        template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
24248-        bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
24249-            return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
24250-        }
24251-
24252-
24253-        template<std::size_t N, typename Arg>
24254-        bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
24255-            return false;
24256-        }
24257-
24258-        template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
24259-        bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
24260-            return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
24261-        }
24262-
24263-        std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end);
24264-
24265-        template<typename... MatcherTs, std::size_t... Idx>
24266-        std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) {
24267-            std::array<std::string, sizeof...(MatcherTs)> descriptions {{
24268-                static_cast<MatcherTs const*>(matchers[Idx])->toString()...
24269-            }};
24270-
24271-            return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size());
24272-        }
24273-
24274-
24275-        template<typename... MatcherTs>
24276-        class MatchAllOfGeneric final : public MatcherGenericBase {
24277-        public:
24278-            MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
24279-            MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
24280-            MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
24281-            MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
24282-
24283-            MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
24284-            explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
24285-
24286-            template<typename Arg>
24287-            bool match(Arg&& arg) const {
24288-                return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
24289-            }
24290-
24291-            std::string describe() const override {
24292-                return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
24293-            }
24294-
24295-            // Has to be public to enable the concatenating operators
24296-            // below, because they are not friend of the RHS, only LHS,
24297-            // and thus cannot access private fields of RHS
24298-            std::array<void const*, sizeof...( MatcherTs )> m_matchers;
24299-
24300-
24301-            //! Avoids type nesting for `GenericAllOf && GenericAllOf` case
24302-            template<typename... MatchersRHS>
24303-            friend
24304-            MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
24305-                    MatchAllOfGeneric<MatcherTs...>&& lhs,
24306-                    MatchAllOfGeneric<MatchersRHS...>&& rhs) {
24307-                return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
24308-            }
24309-
24310-            //! Avoids type nesting for `GenericAllOf && some matcher` case
24311-            template<typename MatcherRHS>
24312-            friend std::enable_if_t<is_matcher_v<MatcherRHS>,
24313-            MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
24314-                    MatchAllOfGeneric<MatcherTs...>&& lhs,
24315-                    MatcherRHS const& rhs) {
24316-                return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))};
24317-            }
24318-
24319-            //! Avoids type nesting for `some matcher && GenericAllOf` case
24320-            template<typename MatcherLHS>
24321-            friend std::enable_if_t<is_matcher_v<MatcherLHS>,
24322-            MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
24323-                    MatcherLHS const& lhs,
24324-                    MatchAllOfGeneric<MatcherTs...>&& rhs) {
24325-                return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
24326-            }
24327-        };
24328-
24329-
24330-        template<typename... MatcherTs>
24331-        class MatchAnyOfGeneric final : public MatcherGenericBase {
24332-        public:
24333-            MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
24334-            MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
24335-            MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
24336-            MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
24337-
24338-            MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
24339-            explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
24340-
24341-            template<typename Arg>
24342-            bool match(Arg&& arg) const {
24343-                return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
24344-            }
24345-
24346-            std::string describe() const override {
24347-                return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
24348-            }
24349-
24350-
24351-            // Has to be public to enable the concatenating operators
24352-            // below, because they are not friend of the RHS, only LHS,
24353-            // and thus cannot access private fields of RHS
24354-            std::array<void const*, sizeof...( MatcherTs )> m_matchers;
24355-
24356-            //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
24357-            template<typename... MatchersRHS>
24358-            friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
24359-                    MatchAnyOfGeneric<MatcherTs...>&& lhs,
24360-                    MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
24361-                return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
24362-            }
24363-
24364-            //! Avoids type nesting for `GenericAnyOf || some matcher` case
24365-            template<typename MatcherRHS>
24366-            friend std::enable_if_t<is_matcher_v<MatcherRHS>,
24367-            MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
24368-                    MatchAnyOfGeneric<MatcherTs...>&& lhs,
24369-                    MatcherRHS const& rhs) {
24370-                return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
24371-            }
24372-
24373-            //! Avoids type nesting for `some matcher || GenericAnyOf` case
24374-            template<typename MatcherLHS>
24375-            friend std::enable_if_t<is_matcher_v<MatcherLHS>,
24376-            MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
24377-                MatcherLHS const& lhs,
24378-                MatchAnyOfGeneric<MatcherTs...>&& rhs) {
24379-                return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
24380-            }
24381-        };
24382-
24383-
24384-        template<typename MatcherT>
24385-        class MatchNotOfGeneric final : public MatcherGenericBase {
24386-            MatcherT const& m_matcher;
24387-
24388-        public:
24389-            MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
24390-            MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
24391-            MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
24392-            MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
24393-
24394-            explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {}
24395-
24396-            template<typename Arg>
24397-            bool match(Arg&& arg) const {
24398-                return !m_matcher.match(arg);
24399-            }
24400-
24401-            std::string describe() const override {
24402-                return "not " + m_matcher.toString();
24403-            }
24404-
24405-            //! Negating negation can just unwrap and return underlying matcher
24406-            friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
24407-                return matcher.m_matcher;
24408-            }
24409-        };
24410-    } // namespace Detail
24411-
24412-
24413-    // compose only generic matchers
24414-    template<typename MatcherLHS, typename MatcherRHS>
24415-    std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
24416-        operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
24417-        return { lhs, rhs };
24418-    }
24419-
24420-    template<typename MatcherLHS, typename MatcherRHS>
24421-    std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
24422-        operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
24423-        return { lhs, rhs };
24424-    }
24425-
24426-    //! Wrap provided generic matcher in generic negator
24427-    template<typename MatcherT>
24428-    std::enable_if_t<Detail::is_generic_matcher_v<MatcherT>, Detail::MatchNotOfGeneric<MatcherT>>
24429-        operator ! (MatcherT const& matcher) {
24430-        return Detail::MatchNotOfGeneric<MatcherT>{matcher};
24431-    }
24432-
24433-
24434-    // compose mixed generic and non-generic matchers
24435-    template<typename MatcherLHS, typename ArgRHS>
24436-    std::enable_if_t<Detail::is_generic_matcher_v<MatcherLHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
24437-        operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
24438-        return { lhs, rhs };
24439-    }
24440-
24441-    template<typename ArgLHS, typename MatcherRHS>
24442-    std::enable_if_t<Detail::is_generic_matcher_v<MatcherRHS>, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
24443-        operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
24444-        return { lhs, rhs };
24445-    }
24446-
24447-    template<typename MatcherLHS, typename ArgRHS>
24448-    std::enable_if_t<Detail::is_generic_matcher_v<MatcherLHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
24449-        operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
24450-        return { lhs, rhs };
24451-    }
24452-
24453-    template<typename ArgLHS, typename MatcherRHS>
24454-    std::enable_if_t<Detail::is_generic_matcher_v<MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
24455-        operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
24456-        return { lhs, rhs };
24457-    }
24458-
24459-} // namespace Matchers
24460-} // namespace Catch
24461-
24462-#endif // CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
24463-
24464-namespace Catch {
24465-    namespace Matchers {
24466-
24467-        class IsEmptyMatcher final : public MatcherGenericBase {
24468-        public:
24469-            template <typename RangeLike>
24470-            bool match(RangeLike&& rng) const {
24471-#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
24472-                using Catch::Detail::empty;
24473-#else
24474-                using std::empty;
24475-#endif
24476-                return empty(rng);
24477-            }
24478-
24479-            std::string describe() const override;
24480-        };
24481-
24482-        class HasSizeMatcher final : public MatcherGenericBase {
24483-            std::size_t m_target_size;
24484-        public:
24485-            explicit HasSizeMatcher(std::size_t target_size):
24486-                m_target_size(target_size)
24487-            {}
24488-
24489-            template <typename RangeLike>
24490-            bool match(RangeLike&& rng) const {
24491-#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
24492-                using Catch::Detail::size;
24493-#else
24494-                using std::size;
24495-#endif
24496-                return size(rng) == m_target_size;
24497-            }
24498-
24499-            std::string describe() const override;
24500-        };
24501-
24502-        template <typename Matcher>
24503-        class SizeMatchesMatcher final : public MatcherGenericBase {
24504-            Matcher m_matcher;
24505-        public:
24506-            explicit SizeMatchesMatcher(Matcher m):
24507-                m_matcher(CATCH_MOVE(m))
24508-            {}
24509-
24510-            template <typename RangeLike>
24511-            bool match(RangeLike&& rng) const {
24512-#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
24513-                using Catch::Detail::size;
24514-#else
24515-                using std::size;
24516-#endif
24517-                return m_matcher.match(size(rng));
24518-            }
24519-
24520-            std::string describe() const override {
24521-                return "size matches " + m_matcher.describe();
24522-            }
24523-        };
24524-
24525-
24526-        //! Creates a matcher that accepts empty ranges/containers
24527-        IsEmptyMatcher IsEmpty();
24528-        //! Creates a matcher that accepts ranges/containers with specific size
24529-        HasSizeMatcher SizeIs(std::size_t sz);
24530-        template <typename Matcher>
24531-        std::enable_if_t<Detail::is_matcher_v<Matcher>,
24532-        SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) {
24533-            return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
24534-        }
24535-
24536-    } // end namespace Matchers
24537-} // end namespace Catch
24538-
24539-#endif // CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
24540-
24541-
24542-#ifndef CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
24543-#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
24544-
24545-
24546-#include <functional>
24547-#include <type_traits>
24548-
24549-namespace Catch {
24550-    namespace Matchers {
24551-        //! Matcher for checking that an element in range is equal to specific element
24552-        template <typename T, typename Equality>
24553-        class ContainsElementMatcher final : public MatcherGenericBase {
24554-            T m_desired;
24555-            Equality m_eq;
24556-        public:
24557-            template <typename T2, typename Equality2>
24558-            ContainsElementMatcher(T2&& target, Equality2&& predicate):
24559-                m_desired(CATCH_FORWARD(target)),
24560-                m_eq(CATCH_FORWARD(predicate))
24561-            {}
24562-
24563-            std::string describe() const override {
24564-                return "contains element " + Catch::Detail::stringify(m_desired);
24565-            }
24566-
24567-            template <typename RangeLike>
24568-            bool match( RangeLike&& rng ) const {
24569-                for ( auto&& elem : rng ) {
24570-                    if ( m_eq( elem, m_desired ) ) { return true; }
24571-                }
24572-                return false;
24573-            }
24574-        };
24575-
24576-        //! Meta-matcher for checking that an element in a range matches a specific matcher
24577-        template <typename Matcher>
24578-        class ContainsMatcherMatcher final : public MatcherGenericBase {
24579-            Matcher m_matcher;
24580-        public:
24581-            // Note that we do a copy+move to avoid having to SFINAE this
24582-            // constructor (and also avoid some perfect forwarding failure
24583-            // cases)
24584-            ContainsMatcherMatcher(Matcher matcher):
24585-                m_matcher(CATCH_MOVE(matcher))
24586-            {}
24587-
24588-            template <typename RangeLike>
24589-            bool match(RangeLike&& rng) const {
24590-                for (auto&& elem : rng) {
24591-                    if (m_matcher.match(elem)) {
24592-                        return true;
24593-                    }
24594-                }
24595-                return false;
24596-            }
24597-
24598-            std::string describe() const override {
24599-                return "contains element matching " + m_matcher.describe();
24600-            }
24601-        };
24602-
24603-        /**
24604-         * Creates a matcher that checks whether a range contains a specific element.
24605-         *
24606-         * Uses `std::equal_to` to do the comparison
24607-         */
24608-        template <typename T>
24609-        std::enable_if_t<!Detail::is_matcher_v<T>,
24610-        ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
24611-            return { CATCH_FORWARD(elem), std::equal_to<>{} };
24612-        }
24613-
24614-        //! Creates a matcher that checks whether a range contains element matching a matcher
24615-        template <typename Matcher>
24616-        std::enable_if_t<Detail::is_matcher_v<Matcher>,
24617-        ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
24618-            return { CATCH_FORWARD(matcher) };
24619-        }
24620-
24621-        /**
24622-         * Creates a matcher that checks whether a range contains a specific element.
24623-         *
24624-         * Uses `eq` to do the comparisons, the element is provided on the rhs
24625-         */
24626-        template <typename T, typename Equality>
24627-        ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
24628-            return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) };
24629-        }
24630-
24631-    }
24632-}
24633-
24634-#endif // CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
24635-
24636-
24637-#ifndef CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
24638-#define CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
24639-
24640-
24641-namespace Catch {
24642-namespace Matchers {
24643-
24644-class ExceptionMessageMatcher final : public MatcherBase<std::exception> {
24645-    std::string m_message;
24646-public:
24647-
24648-    ExceptionMessageMatcher(std::string const& message):
24649-        m_message(message)
24650-    {}
24651-
24652-    bool match(std::exception const& ex) const override;
24653-
24654-    std::string describe() const override;
24655-};
24656-
24657-//! Creates a matcher that checks whether a std derived exception has the provided message
24658-ExceptionMessageMatcher Message(std::string const& message);
24659-
24660-template <typename StringMatcherType>
24661-class ExceptionMessageMatchesMatcher final
24662-    : public MatcherBase<std::exception> {
24663-    StringMatcherType m_matcher;
24664-
24665-public:
24666-    ExceptionMessageMatchesMatcher( StringMatcherType matcher ):
24667-        m_matcher( CATCH_MOVE( matcher ) ) {}
24668-
24669-    bool match( std::exception const& ex ) const override {
24670-        return m_matcher.match( ex.what() );
24671-    }
24672-
24673-    std::string describe() const override {
24674-        return " matches \"" + m_matcher.describe() + '"';
24675-    }
24676-};
24677-
24678-//! Creates a matcher that checks whether a message from an std derived
24679-//! exception matches a provided matcher
24680-template <typename StringMatcherType>
24681-ExceptionMessageMatchesMatcher<StringMatcherType>
24682-MessageMatches( StringMatcherType&& matcher ) {
24683-    return { CATCH_FORWARD( matcher ) };
24684-}
24685-
24686-} // namespace Matchers
24687-} // namespace Catch
24688-
24689-#endif // CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
24690-
24691-
24692-#ifndef CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
24693-#define CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
24694-
24695-
24696-namespace Catch {
24697-namespace Matchers {
24698-
24699-    namespace Detail {
24700-        enum class FloatingPointKind : uint8_t;
24701-    }
24702-
24703-    class  WithinAbsMatcher final : public MatcherBase<double> {
24704-    public:
24705-        WithinAbsMatcher(double target, double margin);
24706-        bool match(double const& matchee) const override;
24707-        std::string describe() const override;
24708-    private:
24709-        double m_target;
24710-        double m_margin;
24711-    };
24712-
24713-    //! Creates a matcher that accepts numbers within certain range of target
24714-    WithinAbsMatcher WithinAbs( double target, double margin );
24715-
24716-
24717-
24718-    class WithinUlpsMatcher final : public MatcherBase<double> {
24719-    public:
24720-        WithinUlpsMatcher( double target,
24721-                           uint64_t ulps,
24722-                           Detail::FloatingPointKind baseType );
24723-        bool match(double const& matchee) const override;
24724-        std::string describe() const override;
24725-    private:
24726-        double m_target;
24727-        uint64_t m_ulps;
24728-        Detail::FloatingPointKind m_type;
24729-    };
24730-
24731-    //! Creates a matcher that accepts doubles within certain ULP range of target
24732-    WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
24733-    //! Creates a matcher that accepts floats within certain ULP range of target
24734-    WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
24735-
24736-
24737-
24738-    // Given IEEE-754 format for floats and doubles, we can assume
24739-    // that float -> double promotion is lossless. Given this, we can
24740-    // assume that if we do the standard relative comparison of
24741-    // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
24742-    // the same result if we do this for floats, as if we do this for
24743-    // doubles that were promoted from floats.
24744-    class WithinRelMatcher final : public MatcherBase<double> {
24745-    public:
24746-        WithinRelMatcher( double target, double epsilon );
24747-        bool match(double const& matchee) const override;
24748-        std::string describe() const override;
24749-    private:
24750-        double m_target;
24751-        double m_epsilon;
24752-    };
24753-
24754-    //! Creates a matcher that accepts doubles within certain relative range of target
24755-    WithinRelMatcher WithinRel(double target, double eps);
24756-    //! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
24757-    WithinRelMatcher WithinRel(double target);
24758-    //! Creates a matcher that accepts doubles within certain relative range of target
24759-    WithinRelMatcher WithinRel(float target, float eps);
24760-    //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
24761-    WithinRelMatcher WithinRel(float target);
24762-
24763-
24764-
24765-    class IsNaNMatcher final : public MatcherBase<double> {
24766-    public:
24767-        IsNaNMatcher() = default;
24768-        bool match( double const& matchee ) const override;
24769-        std::string describe() const override;
24770-    };
24771-
24772-    IsNaNMatcher IsNaN();
24773-
24774-} // namespace Matchers
24775-} // namespace Catch
24776-
24777-#endif // CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
24778-
24779-
24780-#ifndef CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
24781-#define CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
24782-
24783-
24784-#include <string>
24785-
24786-namespace Catch {
24787-namespace Matchers {
24788-
24789-namespace Detail {
24790-    std::string finalizeDescription(const std::string& desc);
24791-} // namespace Detail
24792-
24793-template <typename T, typename Predicate>
24794-class PredicateMatcher final : public MatcherBase<T> {
24795-    Predicate m_predicate;
24796-    std::string m_description;
24797-public:
24798-
24799-    PredicateMatcher(Predicate&& elem, std::string const& descr)
24800-        :m_predicate(CATCH_FORWARD(elem)),
24801-        m_description(Detail::finalizeDescription(descr))
24802-    {}
24803-
24804-    bool match( T const& item ) const override {
24805-        return m_predicate(item);
24806-    }
24807-
24808-    std::string describe() const override {
24809-        return m_description;
24810-    }
24811-};
24812-
24813-    /**
24814-     * Creates a matcher that calls delegates `match` to the provided predicate.
24815-     *
24816-     * The user has to explicitly specify the argument type to the matcher
24817-     */
24818-    template<typename T, typename Pred>
24819-    PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") {
24820-        static_assert(is_callable<Pred(T)>::value, "Predicate not callable with argument T");
24821-        static_assert(std::is_same<bool, FunctionReturnType<Pred, T>>::value, "Predicate does not return bool");
24822-        return PredicateMatcher<T, Pred>(CATCH_FORWARD(predicate), description);
24823-    }
24824-
24825-} // namespace Matchers
24826-} // namespace Catch
24827-
24828-#endif // CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
24829-
24830-
24831-#ifndef CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
24832-#define CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
24833-
24834-
24835-namespace Catch {
24836-    namespace Matchers {
24837-        // Matcher for checking that all elements in range matches a given matcher.
24838-        template <typename Matcher>
24839-        class AllMatchMatcher final : public MatcherGenericBase {
24840-            Matcher m_matcher;
24841-        public:
24842-            AllMatchMatcher(Matcher matcher):
24843-                m_matcher(CATCH_MOVE(matcher))
24844-            {}
24845-
24846-            std::string describe() const override {
24847-                return "all match " + m_matcher.describe();
24848-            }
24849-
24850-            template <typename RangeLike>
24851-            bool match(RangeLike&& rng) const {
24852-                for (auto&& elem : rng) {
24853-                    if (!m_matcher.match(elem)) {
24854-                        return false;
24855-                    }
24856-                }
24857-                return true;
24858-            }
24859-        };
24860-
24861-        // Matcher for checking that no element in range matches a given matcher.
24862-        template <typename Matcher>
24863-        class NoneMatchMatcher final : public MatcherGenericBase {
24864-            Matcher m_matcher;
24865-        public:
24866-            NoneMatchMatcher(Matcher matcher):
24867-                m_matcher(CATCH_MOVE(matcher))
24868-            {}
24869-
24870-            std::string describe() const override {
24871-                return "none match " + m_matcher.describe();
24872-            }
24873-
24874-            template <typename RangeLike>
24875-            bool match(RangeLike&& rng) const {
24876-                for (auto&& elem : rng) {
24877-                    if (m_matcher.match(elem)) {
24878-                        return false;
24879-                    }
24880-                }
24881-                return true;
24882-            }
24883-        };
24884-
24885-        // Matcher for checking that at least one element in range matches a given matcher.
24886-        template <typename Matcher>
24887-        class AnyMatchMatcher final : public MatcherGenericBase {
24888-            Matcher m_matcher;
24889-        public:
24890-            AnyMatchMatcher(Matcher matcher):
24891-                m_matcher(CATCH_MOVE(matcher))
24892-            {}
24893-
24894-            std::string describe() const override {
24895-                return "any match " + m_matcher.describe();
24896-            }
24897-
24898-            template <typename RangeLike>
24899-            bool match(RangeLike&& rng) const {
24900-                for (auto&& elem : rng) {
24901-                    if (m_matcher.match(elem)) {
24902-                        return true;
24903-                    }
24904-                }
24905-                return false;
24906-            }
24907-        };
24908-
24909-        // Matcher for checking that all elements in range are true.
24910-        class AllTrueMatcher final : public MatcherGenericBase {
24911-        public:
24912-            std::string describe() const override;
24913-
24914-            template <typename RangeLike>
24915-            bool match(RangeLike&& rng) const {
24916-                for (auto&& elem : rng) {
24917-                    if (!elem) {
24918-                        return false;
24919-                    }
24920-                }
24921-                return true;
24922-            }
24923-        };
24924-
24925-        // Matcher for checking that no element in range is true.
24926-        class NoneTrueMatcher final : public MatcherGenericBase {
24927-        public:
24928-            std::string describe() const override;
24929-
24930-            template <typename RangeLike>
24931-            bool match(RangeLike&& rng) const {
24932-                for (auto&& elem : rng) {
24933-                    if (elem) {
24934-                        return false;
24935-                    }
24936-                }
24937-                return true;
24938-            }
24939-        };
24940-
24941-        // Matcher for checking that any element in range is true.
24942-        class AnyTrueMatcher final : public MatcherGenericBase {
24943-        public:
24944-            std::string describe() const override;
24945-
24946-            template <typename RangeLike>
24947-            bool match(RangeLike&& rng) const {
24948-                for (auto&& elem : rng) {
24949-                    if (elem) {
24950-                        return true;
24951-                    }
24952-                }
24953-                return false;
24954-            }
24955-        };
24956-
24957-        // Creates a matcher that checks whether all elements in a range match a matcher
24958-        template <typename Matcher>
24959-        AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
24960-            return { CATCH_FORWARD(matcher) };
24961-        }
24962-
24963-        // Creates a matcher that checks whether no element in a range matches a matcher.
24964-        template <typename Matcher>
24965-        NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
24966-            return { CATCH_FORWARD(matcher) };
24967-        }
24968-
24969-        // Creates a matcher that checks whether any element in a range matches a matcher.
24970-        template <typename Matcher>
24971-        AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
24972-            return { CATCH_FORWARD(matcher) };
24973-        }
24974-
24975-        // Creates a matcher that checks whether all elements in a range are true
24976-        AllTrueMatcher AllTrue();
24977-
24978-        // Creates a matcher that checks whether no element in a range is true
24979-        NoneTrueMatcher NoneTrue();
24980-
24981-        // Creates a matcher that checks whether any element in a range is true
24982-        AnyTrueMatcher AnyTrue();
24983-    }
24984-}
24985-
24986-#endif // CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
24987-
24988-
24989-#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
24990-#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
24991-
24992-
24993-#include <functional>
24994-
24995-namespace Catch {
24996-    namespace Matchers {
24997-
24998-        /**
24999-         * Matcher for checking that an element contains the same
25000-         * elements in the same order
25001-         */
25002-        template <typename TargetRangeLike, typename Equality>
25003-        class RangeEqualsMatcher final : public MatcherGenericBase {
25004-            TargetRangeLike m_desired;
25005-            Equality m_predicate;
25006-
25007-        public:
25008-            template <typename TargetRangeLike2, typename Equality2>
25009-            constexpr
25010-            RangeEqualsMatcher( TargetRangeLike2&& range,
25011-                                Equality2&& predicate ):
25012-                m_desired( CATCH_FORWARD( range ) ),
25013-                m_predicate( CATCH_FORWARD( predicate ) ) {}
25014-
25015-            template <typename RangeLike>
25016-            constexpr
25017-            bool match( RangeLike&& rng ) const {
25018-                auto rng_start = begin( rng );
25019-                const auto rng_end = end( rng );
25020-                auto target_start = begin( m_desired );
25021-                const auto target_end = end( m_desired );
25022-
25023-                while (rng_start != rng_end && target_start != target_end) {
25024-                    if (!m_predicate(*rng_start, *target_start)) {
25025-                        return false;
25026-                    }
25027-                    ++rng_start;
25028-                    ++target_start;
25029-                }
25030-                return rng_start == rng_end && target_start == target_end;
25031-            }
25032-
25033-            std::string describe() const override {
25034-                return "elements are " + Catch::Detail::stringify( m_desired );
25035-            }
25036-        };
25037-
25038-        /**
25039-         * Matcher for checking that an element contains the same
25040-         * elements (but not necessarily in the same order)
25041-         */
25042-        template <typename TargetRangeLike, typename Equality>
25043-        class UnorderedRangeEqualsMatcher final : public MatcherGenericBase {
25044-            TargetRangeLike m_desired;
25045-            Equality m_predicate;
25046-
25047-        public:
25048-            template <typename TargetRangeLike2, typename Equality2>
25049-            constexpr
25050-            UnorderedRangeEqualsMatcher( TargetRangeLike2&& range,
25051-                                         Equality2&& predicate ):
25052-                m_desired( CATCH_FORWARD( range ) ),
25053-                m_predicate( CATCH_FORWARD( predicate ) ) {}
25054-
25055-            template <typename RangeLike>
25056-            constexpr
25057-            bool match( RangeLike&& rng ) const {
25058-                using std::begin;
25059-                using std::end;
25060-                return Catch::Detail::is_permutation( begin( m_desired ),
25061-                                                      end( m_desired ),
25062-                                                      begin( rng ),
25063-                                                      end( rng ),
25064-                                                      m_predicate );
25065-            }
25066-
25067-            std::string describe() const override {
25068-                return "unordered elements are " +
25069-                       ::Catch::Detail::stringify( m_desired );
25070-            }
25071-        };
25072-
25073-        /**
25074-         * Creates a matcher that checks if all elements in a range are equal
25075-         * to all elements in another range.
25076-         *
25077-         * Uses the provided predicate `predicate` to do the comparisons
25078-         * (defaulting to `std::equal_to`)
25079-         */
25080-        template <typename RangeLike,
25081-                  typename Equality = decltype( std::equal_to<>{} )>
25082-        constexpr
25083-        RangeEqualsMatcher<RangeLike, Equality>
25084-        RangeEquals( RangeLike&& range,
25085-                     Equality&& predicate = std::equal_to<>{} ) {
25086-            return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
25087-        }
25088-
25089-        /**
25090-         * Creates a matcher that checks if all elements in a range are equal
25091-         * to all elements in an initializer list.
25092-         *
25093-         * Uses the provided predicate `predicate` to do the comparisons
25094-         * (defaulting to `std::equal_to`)
25095-         */
25096-        template <typename T,
25097-                  typename Equality = decltype( std::equal_to<>{} )>
25098-        constexpr
25099-        RangeEqualsMatcher<std::initializer_list<T>, Equality>
25100-        RangeEquals( std::initializer_list<T> range,
25101-                     Equality&& predicate = std::equal_to<>{} ) {
25102-            return { range, CATCH_FORWARD( predicate ) };
25103-        }
25104-
25105-        /**
25106-         * Creates a matcher that checks if all elements in a range are equal
25107-         * to all elements in another range, in some permutation.
25108-         *
25109-         * Uses the provided predicate `predicate` to do the comparisons
25110-         * (defaulting to `std::equal_to`)
25111-         */
25112-        template <typename RangeLike,
25113-                  typename Equality = decltype( std::equal_to<>{} )>
25114-        constexpr
25115-        UnorderedRangeEqualsMatcher<RangeLike, Equality>
25116-        UnorderedRangeEquals( RangeLike&& range,
25117-                              Equality&& predicate = std::equal_to<>{} ) {
25118-            return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
25119-        }
25120-
25121-        /**
25122-         * Creates a matcher that checks if all elements in a range are equal
25123-         * to all elements in an initializer list, in some permutation.
25124-         *
25125-         * Uses the provided predicate `predicate` to do the comparisons
25126-         * (defaulting to `std::equal_to`)
25127-         */
25128-        template <typename T,
25129-                  typename Equality = decltype( std::equal_to<>{} )>
25130-        constexpr
25131-        UnorderedRangeEqualsMatcher<std::initializer_list<T>, Equality>
25132-        UnorderedRangeEquals( std::initializer_list<T> range,
25133-                              Equality&& predicate = std::equal_to<>{} ) {
25134-            return { range, CATCH_FORWARD( predicate ) };
25135-        }
25136-    } // namespace Matchers
25137-} // namespace Catch
25138-
25139-#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
25140-
25141-
25142-#ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED
25143-#define CATCH_MATCHERS_STRING_HPP_INCLUDED
25144-
25145-
25146-#include <string>
25147-
25148-namespace Catch {
25149-namespace Matchers {
25150-
25151-    struct CasedString {
25152-        CasedString( std::string const& str, CaseSensitive caseSensitivity );
25153-        std::string adjustString( std::string const& str ) const;
25154-        StringRef caseSensitivitySuffix() const;
25155-
25156-        CaseSensitive m_caseSensitivity;
25157-        std::string m_str;
25158-    };
25159-
25160-    class StringMatcherBase : public MatcherBase<std::string> {
25161-    protected:
25162-        CasedString m_comparator;
25163-        StringRef m_operation;
25164-
25165-    public:
25166-        StringMatcherBase( StringRef operation,
25167-                           CasedString const& comparator );
25168-        std::string describe() const override;
25169-    };
25170-
25171-    class StringEqualsMatcher final : public StringMatcherBase {
25172-    public:
25173-        StringEqualsMatcher( CasedString const& comparator );
25174-        bool match( std::string const& source ) const override;
25175-    };
25176-    class StringContainsMatcher final : public StringMatcherBase {
25177-    public:
25178-        StringContainsMatcher( CasedString const& comparator );
25179-        bool match( std::string const& source ) const override;
25180-    };
25181-    class StartsWithMatcher final : public StringMatcherBase {
25182-    public:
25183-        StartsWithMatcher( CasedString const& comparator );
25184-        bool match( std::string const& source ) const override;
25185-    };
25186-    class EndsWithMatcher final : public StringMatcherBase {
25187-    public:
25188-        EndsWithMatcher( CasedString const& comparator );
25189-        bool match( std::string const& source ) const override;
25190-    };
25191-
25192-    class RegexMatcher final : public MatcherBase<std::string> {
25193-        std::string m_regex;
25194-        CaseSensitive m_caseSensitivity;
25195-
25196-    public:
25197-        RegexMatcher( std::string regex, CaseSensitive caseSensitivity );
25198-        bool match( std::string const& matchee ) const override;
25199-        std::string describe() const override;
25200-    };
25201-
25202-    //! Creates matcher that accepts strings that are exactly equal to `str`
25203-    StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
25204-    //! Creates matcher that accepts strings that contain `str`
25205-    StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
25206-    //! Creates matcher that accepts strings that _end_ with `str`
25207-    EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
25208-    //! Creates matcher that accepts strings that _start_ with `str`
25209-    StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
25210-    //! Creates matcher that accepts strings matching `regex`
25211-    RegexMatcher Matches( std::string const& regex, CaseSensitive caseSensitivity = CaseSensitive::Yes );
25212-
25213-} // namespace Matchers
25214-} // namespace Catch
25215-
25216-#endif // CATCH_MATCHERS_STRING_HPP_INCLUDED
25217-
25218-
25219-#ifndef CATCH_MATCHERS_VECTOR_HPP_INCLUDED
25220-#define CATCH_MATCHERS_VECTOR_HPP_INCLUDED
25221-
25222-
25223-#include <algorithm>
25224-
25225-namespace Catch {
25226-namespace Matchers {
25227-
25228-    template<typename T, typename Alloc>
25229-    class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> {
25230-        T const& m_comparator;
25231-
25232-    public:
25233-        VectorContainsElementMatcher(T const& comparator):
25234-            m_comparator(comparator)
25235-        {}
25236-
25237-        bool match(std::vector<T, Alloc> const& v) const override {
25238-            for (auto const& el : v) {
25239-                if (el == m_comparator) {
25240-                    return true;
25241-                }
25242-            }
25243-            return false;
25244-        }
25245-
25246-        std::string describe() const override {
25247-            return "Contains: " + ::Catch::Detail::stringify( m_comparator );
25248-        }
25249-    };
25250-
25251-    template<typename T, typename AllocComp, typename AllocMatch>
25252-    class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
25253-        std::vector<T, AllocComp> const& m_comparator;
25254-
25255-    public:
25256-        ContainsMatcher(std::vector<T, AllocComp> const& comparator):
25257-            m_comparator( comparator )
25258-        {}
25259-
25260-        bool match(std::vector<T, AllocMatch> const& v) const override {
25261-            // !TBD: see note in EqualsMatcher
25262-            if (m_comparator.size() > v.size())
25263-                return false;
25264-            for (auto const& comparator : m_comparator) {
25265-                auto present = false;
25266-                for (const auto& el : v) {
25267-                    if (el == comparator) {
25268-                        present = true;
25269-                        break;
25270-                    }
25271-                }
25272-                if (!present) {
25273-                    return false;
25274-                }
25275-            }
25276-            return true;
25277-        }
25278-        std::string describe() const override {
25279-            return "Contains: " + ::Catch::Detail::stringify( m_comparator );
25280-        }
25281-    };
25282-
25283-    template<typename T, typename AllocComp, typename AllocMatch>
25284-    class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
25285-        std::vector<T, AllocComp> const& m_comparator;
25286-
25287-    public:
25288-        EqualsMatcher(std::vector<T, AllocComp> const& comparator):
25289-            m_comparator( comparator )
25290-        {}
25291-
25292-        bool match(std::vector<T, AllocMatch> const& v) const override {
25293-            // !TBD: This currently works if all elements can be compared using !=
25294-            // - a more general approach would be via a compare template that defaults
25295-            // to using !=. but could be specialised for, e.g. std::vector<T> etc
25296-            // - then just call that directly
25297-            if ( m_comparator.size() != v.size() ) { return false; }
25298-            for ( std::size_t i = 0; i < v.size(); ++i ) {
25299-                if ( !( m_comparator[i] == v[i] ) ) { return false; }
25300-            }
25301-            return true;
25302-        }
25303-        std::string describe() const override {
25304-            return "Equals: " + ::Catch::Detail::stringify( m_comparator );
25305-        }
25306-    };
25307-
25308-    template<typename T, typename AllocComp, typename AllocMatch>
25309-    class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
25310-        std::vector<T, AllocComp> const& m_comparator;
25311-        mutable Catch::Approx approx = Catch::Approx::custom();
25312-
25313-    public:
25314-        ApproxMatcher(std::vector<T, AllocComp> const& comparator):
25315-            m_comparator( comparator )
25316-        {}
25317-
25318-        bool match(std::vector<T, AllocMatch> const& v) const override {
25319-            if (m_comparator.size() != v.size())
25320-                return false;
25321-            for (std::size_t i = 0; i < v.size(); ++i)
25322-                if (m_comparator[i] != approx(v[i]))
25323-                    return false;
25324-            return true;
25325-        }
25326-        std::string describe() const override {
25327-            return "is approx: " + ::Catch::Detail::stringify( m_comparator );
25328-        }
25329-        template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
25330-        ApproxMatcher& epsilon( T const& newEpsilon ) {
25331-            approx.epsilon(static_cast<double>(newEpsilon));
25332-            return *this;
25333-        }
25334-        template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
25335-        ApproxMatcher& margin( T const& newMargin ) {
25336-            approx.margin(static_cast<double>(newMargin));
25337-            return *this;
25338-        }
25339-        template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
25340-        ApproxMatcher& scale( T const& newScale ) {
25341-            approx.scale(static_cast<double>(newScale));
25342-            return *this;
25343-        }
25344-    };
25345-
25346-    template<typename T, typename AllocComp, typename AllocMatch>
25347-    class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
25348-        std::vector<T, AllocComp> const& m_target;
25349-
25350-    public:
25351-        UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target):
25352-            m_target(target)
25353-        {}
25354-        bool match(std::vector<T, AllocMatch> const& vec) const override {
25355-            if (m_target.size() != vec.size()) {
25356-                return false;
25357-            }
25358-            return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
25359-        }
25360-
25361-        std::string describe() const override {
25362-            return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
25363-        }
25364-    };
25365-
25366-
25367-    // The following functions create the actual matcher objects.
25368-    // This allows the types to be inferred
25369-
25370-    //! Creates a matcher that matches vectors that contain all elements in `comparator`
25371-    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
25372-    ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
25373-        return ContainsMatcher<T, AllocComp, AllocMatch>(comparator);
25374-    }
25375-
25376-    //! Creates a matcher that matches vectors that contain `comparator` as an element
25377-    template<typename T, typename Alloc = std::allocator<T>>
25378-    VectorContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
25379-        return VectorContainsElementMatcher<T, Alloc>(comparator);
25380-    }
25381-
25382-    //! Creates a matcher that matches vectors that are exactly equal to `comparator`
25383-    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
25384-    EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
25385-        return EqualsMatcher<T, AllocComp, AllocMatch>(comparator);
25386-    }
25387-
25388-    //! Creates a matcher that matches vectors that `comparator` as an element
25389-    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
25390-    ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
25391-        return ApproxMatcher<T, AllocComp, AllocMatch>(comparator);
25392-    }
25393-
25394-    //! Creates a matcher that matches vectors that is equal to `target` modulo permutation
25395-    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
25396-    UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
25397-        return UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target);
25398-    }
25399-
25400-} // namespace Matchers
25401-} // namespace Catch
25402-
25403-#endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED
25404-
25405-#endif // CATCH_MATCHERS_ALL_HPP_INCLUDED
25406-
25407-
25408-/** \file
25409- * This is a convenience header for Catch2's Reporter support. It includes
25410- * **all** of Catch2 headers related to reporters, including all reporters.
25411- *
25412- * Generally the Catch2 users should use specific includes they need,
25413- * but this header can be used instead for ease-of-experimentation, or
25414- * just plain convenience, at the cost of (significantly) increased
25415- * compilation times.
25416- *
25417- * When a new header (reporter) is added to either the `reporter` folder,
25418- * or to the corresponding internal subfolder, it should be added here.
25419- */
25420-
25421-#ifndef CATCH_REPORTERS_ALL_HPP_INCLUDED
25422-#define CATCH_REPORTERS_ALL_HPP_INCLUDED
25423-
25424-
25425-
25426-#ifndef CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
25427-#define CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
25428-
25429-
25430-
25431-#ifndef CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
25432-#define CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
25433-
25434-
25435-
25436-#ifndef CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
25437-#define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
25438-
25439-
25440-#include <map>
25441-#include <string>
25442-
25443-namespace Catch {
25444-    class ColourImpl;
25445-
25446-    /**
25447-     * This is the base class for all reporters.
25448-     *
25449-     * If are writing a reporter, you must derive from this type, or one
25450-     * of the helper reporter bases that are derived from this type.
25451-     *
25452-     * ReporterBase centralizes handling of various common tasks in reporters,
25453-     * like storing the right stream for the reporters to write to, and
25454-     * providing the default implementation of the different listing events.
25455-     */
25456-    class ReporterBase : public IEventListener {
25457-    protected:
25458-        //! The stream wrapper as passed to us by outside code
25459-        Detail::unique_ptr<IStream> m_wrapped_stream;
25460-        //! Cached output stream from `m_wrapped_stream` to reduce
25461-        //! number of indirect calls needed to write output.
25462-        std::ostream& m_stream;
25463-        //! Colour implementation this reporter was configured for
25464-        Detail::unique_ptr<ColourImpl> m_colour;
25465-        //! The custom reporter options user passed down to the reporter
25466-        std::map<std::string, std::string> m_customOptions;
25467-
25468-    public:
25469-        ReporterBase( ReporterConfig&& config );
25470-        ~ReporterBase() override; // = default;
25471-
25472-        /**
25473-         * Provides a simple default listing of reporters.
25474-         *
25475-         * Should look roughly like the reporter listing in v2 and earlier
25476-         * versions of Catch2.
25477-         */
25478-        void listReporters(
25479-            std::vector<ReporterDescription> const& descriptions ) override;
25480-        /**
25481-         * Provides a simple default listing of listeners
25482-         *
25483-         * Looks similarly to listing of reporters, but with listener type
25484-         * instead of reporter name.
25485-         */
25486-        void listListeners(
25487-            std::vector<ListenerDescription> const& descriptions ) override;
25488-        /**
25489-         * Provides a simple default listing of tests.
25490-         *
25491-         * Should look roughly like the test listing in v2 and earlier versions
25492-         * of Catch2. Especially supports low-verbosity listing that mimics the
25493-         * old `--list-test-names-only` output.
25494-         */
25495-        void listTests( std::vector<TestCaseHandle> const& tests ) override;
25496-        /**
25497-         * Provides a simple default listing of tags.
25498-         *
25499-         * Should look roughly like the tag listing in v2 and earlier versions
25500-         * of Catch2.
25501-         */
25502-        void listTags( std::vector<TagInfo> const& tags ) override;
25503-    };
25504-} // namespace Catch
25505-
25506-#endif // CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
25507-
25508-#include <vector>
25509-
25510-namespace Catch {
25511-
25512-    class StreamingReporterBase : public ReporterBase {
25513-    public:
25514-        // GCC5 compat: we cannot use inherited constructor, because it
25515-        //              doesn't implement backport of P0136
25516-        StreamingReporterBase(ReporterConfig&& _config):
25517-            ReporterBase(CATCH_MOVE(_config))
25518-        {}
25519-        ~StreamingReporterBase() override;
25520-
25521-        void benchmarkPreparing( StringRef ) override {}
25522-        void benchmarkStarting( BenchmarkInfo const& ) override {}
25523-        void benchmarkEnded( BenchmarkStats<> const& ) override {}
25524-        void benchmarkFailed( StringRef ) override {}
25525-
25526-        void fatalErrorEncountered( StringRef /*error*/ ) override {}
25527-        void noMatchingTestCases( StringRef /*unmatchedSpec*/ ) override {}
25528-        void reportInvalidTestSpec( StringRef /*invalidArgument*/ ) override {}
25529-
25530-        void testRunStarting( TestRunInfo const& _testRunInfo ) override;
25531-
25532-        void testCaseStarting(TestCaseInfo const& _testInfo) override  {
25533-            currentTestCaseInfo = &_testInfo;
25534-        }
25535-        void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
25536-        void sectionStarting(SectionInfo const& _sectionInfo) override {
25537-            m_sectionStack.push_back(_sectionInfo);
25538-        }
25539-
25540-        void assertionStarting( AssertionInfo const& ) override {}
25541-        void assertionEnded( AssertionStats const& ) override {}
25542-
25543-        void sectionEnded(SectionStats const& /* _sectionStats */) override {
25544-            m_sectionStack.pop_back();
25545-        }
25546-        void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
25547-        void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
25548-            currentTestCaseInfo = nullptr;
25549-        }
25550-        void testRunEnded( TestRunStats const& /* _testRunStats */ ) override;
25551-
25552-        void skipTest(TestCaseInfo const&) override {
25553-            // Don't do anything with this by default.
25554-            // It can optionally be overridden in the derived class.
25555-        }
25556-
25557-    protected:
25558-        TestRunInfo currentTestRunInfo{ "test run has not started yet"_sr };
25559-        TestCaseInfo const* currentTestCaseInfo = nullptr;
25560-
25561-        //! Stack of all _active_ sections in the _current_ test case
25562-        std::vector<SectionInfo> m_sectionStack;
25563-    };
25564-
25565-} // end namespace Catch
25566-
25567-#endif // CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
25568-
25569-#include <string>
25570-
25571-namespace Catch {
25572-
25573-    class AutomakeReporter final : public StreamingReporterBase {
25574-    public:
25575-        // GCC5 compat: we cannot use inherited constructor, because it
25576-        //              doesn't implement backport of P0136
25577-        AutomakeReporter( ReporterConfig&& _config ):
25578-            StreamingReporterBase( CATCH_MOVE( _config ) ) {
25579-            m_preferences.shouldReportAllAssertionStarts = false;
25580-        }
25581-
25582-        ~AutomakeReporter() override;
25583-
25584-        static std::string getDescription() {
25585-            using namespace std::string_literals;
25586-            return "Reports test results in the format of Automake .trs files"s;
25587-        }
25588-
25589-        void testCaseEnded(TestCaseStats const& _testCaseStats) override;
25590-        void skipTest(TestCaseInfo const& testInfo) override;
25591-    };
25592-
25593-} // end namespace Catch
25594-
25595-#endif // CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
25596-
25597-
25598-#ifndef CATCH_REPORTER_COMPACT_HPP_INCLUDED
25599-#define CATCH_REPORTER_COMPACT_HPP_INCLUDED
25600-
25601-
25602-
25603-
25604-namespace Catch {
25605-
25606-    class CompactReporter final : public StreamingReporterBase {
25607-    public:
25608-        CompactReporter( ReporterConfig&& _config ):
25609-            StreamingReporterBase( CATCH_MOVE( _config ) ) {
25610-            m_preferences.shouldReportAllAssertionStarts = false;
25611-        }
25612-
25613-        ~CompactReporter() override;
25614-
25615-        static std::string getDescription();
25616-
25617-        void noMatchingTestCases( StringRef unmatchedSpec ) override;
25618-
25619-        void testRunStarting( TestRunInfo const& _testInfo ) override;
25620-
25621-        void assertionEnded(AssertionStats const& _assertionStats) override;
25622-
25623-        void sectionEnded(SectionStats const& _sectionStats) override;
25624-
25625-        void testRunEnded(TestRunStats const& _testRunStats) override;
25626-
25627-    };
25628-
25629-} // end namespace Catch
25630-
25631-#endif // CATCH_REPORTER_COMPACT_HPP_INCLUDED
25632-
25633-
25634-#ifndef CATCH_REPORTER_CONSOLE_HPP_INCLUDED
25635-#define CATCH_REPORTER_CONSOLE_HPP_INCLUDED
25636-
25637-
25638-namespace Catch {
25639-    // Fwd decls
25640-    class TablePrinter;
25641-
25642-    class ConsoleReporter final : public StreamingReporterBase {
25643-        Detail::unique_ptr<TablePrinter> m_tablePrinter;
25644-
25645-    public:
25646-        ConsoleReporter(ReporterConfig&& config);
25647-        ~ConsoleReporter() override;
25648-        static std::string getDescription();
25649-
25650-        void noMatchingTestCases( StringRef unmatchedSpec ) override;
25651-        void reportInvalidTestSpec( StringRef arg ) override;
25652-
25653-        void assertionEnded(AssertionStats const& _assertionStats) override;
25654-
25655-        void sectionStarting(SectionInfo const& _sectionInfo) override;
25656-        void sectionEnded(SectionStats const& _sectionStats) override;
25657-
25658-        void benchmarkPreparing( StringRef name ) override;
25659-        void benchmarkStarting(BenchmarkInfo const& info) override;
25660-        void benchmarkEnded(BenchmarkStats<> const& stats) override;
25661-        void benchmarkFailed( StringRef error ) override;
25662-
25663-        void testCaseEnded(TestCaseStats const& _testCaseStats) override;
25664-        void testRunEnded(TestRunStats const& _testRunStats) override;
25665-        void testRunStarting(TestRunInfo const& _testRunInfo) override;
25666-
25667-    private:
25668-        void lazyPrint();
25669-
25670-        void lazyPrintWithoutClosingBenchmarkTable();
25671-        void lazyPrintRunInfo();
25672-        void printTestCaseAndSectionHeader();
25673-
25674-        void printClosedHeader(std::string const& _name);
25675-        void printOpenHeader(std::string const& _name);
25676-
25677-        // if string has a : in first line will set indent to follow it on
25678-        // subsequent lines
25679-        void printHeaderString(std::string const& _string, std::size_t indent = 0);
25680-
25681-        void printTotalsDivider(Totals const& totals);
25682-
25683-        bool m_headerPrinted = false;
25684-        bool m_testRunInfoPrinted = false;
25685-    };
25686-
25687-} // end namespace Catch
25688-
25689-#endif // CATCH_REPORTER_CONSOLE_HPP_INCLUDED
25690-
25691-
25692-#ifndef CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
25693-#define CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
25694-
25695-
25696-#include <string>
25697-#include <vector>
25698-
25699-namespace Catch {
25700-
25701-    namespace Detail {
25702-
25703-        //! Represents either an assertion or a benchmark result to be handled by cumulative reporter later
25704-        class AssertionOrBenchmarkResult {
25705-            // This should really be a variant, but this is much faster
25706-            // to write and the data layout here is already terrible
25707-            // enough that we do not have to care about the object size.
25708-            Optional<AssertionStats> m_assertion;
25709-            Optional<BenchmarkStats<>> m_benchmark;
25710-        public:
25711-            AssertionOrBenchmarkResult(AssertionStats const& assertion);
25712-            AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark);
25713-
25714-            bool isAssertion() const;
25715-            bool isBenchmark() const;
25716-
25717-            AssertionStats const& asAssertion() const;
25718-            BenchmarkStats<> const& asBenchmark() const;
25719-        };
25720-    }
25721-
25722-    /**
25723-     * Utility base for reporters that need to handle all results at once
25724-     *
25725-     * It stores tree of all test cases, sections and assertions, and after the
25726-     * test run is finished, calls into `testRunEndedCumulative` to pass the
25727-     * control to the deriving class.
25728-     *
25729-     * If you are deriving from this class and override any testing related
25730-     * member functions, you should first call into the base's implementation to
25731-     * avoid breaking the tree construction.
25732-     *
25733-     * Due to the way this base functions, it has to expand assertions up-front,
25734-     * even if they are later unused (e.g. because the deriving reporter does
25735-     * not report successful assertions, or because the deriving reporter does
25736-     * not use assertion expansion at all). Derived classes can use two
25737-     * customization points, `m_shouldStoreSuccesfulAssertions` and
25738-     * `m_shouldStoreFailedAssertions`, to disable the expansion and gain extra
25739-     * performance. **Accessing the assertion expansions if it wasn't stored is
25740-     * UB.**
25741-     */
25742-    class CumulativeReporterBase : public ReporterBase {
25743-    public:
25744-        template<typename T, typename ChildNodeT>
25745-        struct Node {
25746-            explicit Node( T const& _value ) : value( _value ) {}
25747-
25748-            using ChildNodes = std::vector<Detail::unique_ptr<ChildNodeT>>;
25749-            T value;
25750-            ChildNodes children;
25751-        };
25752-        struct SectionNode {
25753-            explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
25754-
25755-            bool operator == (SectionNode const& other) const {
25756-                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
25757-            }
25758-
25759-            bool hasAnyAssertions() const;
25760-
25761-            SectionStats stats;
25762-            std::vector<Detail::unique_ptr<SectionNode>> childSections;
25763-            std::vector<Detail::AssertionOrBenchmarkResult> assertionsAndBenchmarks;
25764-            std::string stdOut;
25765-            std::string stdErr;
25766-        };
25767-
25768-
25769-        using TestCaseNode = Node<TestCaseStats, SectionNode>;
25770-        using TestRunNode = Node<TestRunStats, TestCaseNode>;
25771-
25772-        // GCC5 compat: we cannot use inherited constructor, because it
25773-        //              doesn't implement backport of P0136
25774-        CumulativeReporterBase(ReporterConfig&& _config):
25775-            ReporterBase(CATCH_MOVE(_config))
25776-        {}
25777-        ~CumulativeReporterBase() override;
25778-
25779-        void benchmarkPreparing( StringRef ) override {}
25780-        void benchmarkStarting( BenchmarkInfo const& ) override {}
25781-        void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
25782-        void benchmarkFailed( StringRef ) override {}
25783-
25784-        void noMatchingTestCases( StringRef ) override {}
25785-        void reportInvalidTestSpec( StringRef ) override {}
25786-        void fatalErrorEncountered( StringRef /*error*/ ) override {}
25787-
25788-        void testRunStarting( TestRunInfo const& ) override {}
25789-
25790-        void testCaseStarting( TestCaseInfo const& ) override {}
25791-        void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
25792-        void sectionStarting( SectionInfo const& sectionInfo ) override;
25793-
25794-        void assertionStarting( AssertionInfo const& ) override {}
25795-
25796-        void assertionEnded( AssertionStats const& assertionStats ) override;
25797-        void sectionEnded( SectionStats const& sectionStats ) override;
25798-        void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
25799-        void testCaseEnded( TestCaseStats const& testCaseStats ) override;
25800-        void testRunEnded( TestRunStats const& testRunStats ) override;
25801-        //! Customization point: called after last test finishes (testRunEnded has been handled)
25802-        virtual void testRunEndedCumulative() = 0;
25803-
25804-        void skipTest(TestCaseInfo const&) override {}
25805-
25806-    protected:
25807-        //! Should the cumulative base store the assertion expansion for successful assertions?
25808-        bool m_shouldStoreSuccesfulAssertions = true;
25809-        //! Should the cumulative base store the assertion expansion for failed assertions?
25810-        bool m_shouldStoreFailedAssertions = true;
25811-
25812-        // We need lazy construction here. We should probably refactor it
25813-        // later, after the events are redone.
25814-        //! The root node of the test run tree.
25815-        Detail::unique_ptr<TestRunNode> m_testRun;
25816-
25817-    private:
25818-        // Note: We rely on pointer identity being stable, which is why
25819-        //       we store pointers to the nodes rather than the values.
25820-        std::vector<Detail::unique_ptr<TestCaseNode>> m_testCases;
25821-        // Root section of the _current_ test case
25822-        Detail::unique_ptr<SectionNode> m_rootSection;
25823-        // Deepest section of the _current_ test case
25824-        SectionNode* m_deepestSection = nullptr;
25825-        // Stack of _active_ sections in the _current_ test case
25826-        std::vector<SectionNode*> m_sectionStack;
25827-    };
25828-
25829-} // end namespace Catch
25830-
25831-#endif // CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
25832-
25833-
25834-#ifndef CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
25835-#define CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
25836-
25837-
25838-namespace Catch {
25839-
25840-    /**
25841-     * Base class to simplify implementing listeners.
25842-     *
25843-     * Provides empty default implementation for all IEventListener member
25844-     * functions, so that a listener implementation can pick which
25845-     * member functions it actually cares about.
25846-     */
25847-    class EventListenerBase : public IEventListener {
25848-    public:
25849-        using IEventListener::IEventListener;
25850-
25851-        void reportInvalidTestSpec( StringRef unmatchedSpec ) override;
25852-        void fatalErrorEncountered( StringRef error ) override;
25853-
25854-        void benchmarkPreparing( StringRef name ) override;
25855-        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
25856-        void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
25857-        void benchmarkFailed( StringRef error ) override;
25858-
25859-        void assertionStarting( AssertionInfo const& assertionInfo ) override;
25860-        void assertionEnded( AssertionStats const& assertionStats ) override;
25861-
25862-        void listReporters(
25863-            std::vector<ReporterDescription> const& descriptions ) override;
25864-        void listListeners(
25865-            std::vector<ListenerDescription> const& descriptions ) override;
25866-        void listTests( std::vector<TestCaseHandle> const& tests ) override;
25867-        void listTags( std::vector<TagInfo> const& tagInfos ) override;
25868-
25869-        void noMatchingTestCases( StringRef unmatchedSpec ) override;
25870-        void testRunStarting( TestRunInfo const& testRunInfo ) override;
25871-        void testCaseStarting( TestCaseInfo const& testInfo ) override;
25872-        void testCasePartialStarting( TestCaseInfo const& testInfo,
25873-                                      uint64_t partNumber ) override;
25874-        void sectionStarting( SectionInfo const& sectionInfo ) override;
25875-        void sectionEnded( SectionStats const& sectionStats ) override;
25876-        void testCasePartialEnded( TestCaseStats const& testCaseStats,
25877-                                   uint64_t partNumber ) override;
25878-        void testCaseEnded( TestCaseStats const& testCaseStats ) override;
25879-        void testRunEnded( TestRunStats const& testRunStats ) override;
25880-        void skipTest( TestCaseInfo const& testInfo ) override;
25881-    };
25882-
25883-} // end namespace Catch
25884-
25885-#endif // CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
25886-
25887-
25888-#ifndef CATCH_REPORTER_HELPERS_HPP_INCLUDED
25889-#define CATCH_REPORTER_HELPERS_HPP_INCLUDED
25890-
25891-#include <iosfwd>
25892-#include <string>
25893-#include <vector>
25894-
25895-
25896-namespace Catch {
25897-
25898-    class IConfig;
25899-    class TestCaseHandle;
25900-    class ColourImpl;
25901-
25902-    // Returns double formatted as %.3f (format expected on output)
25903-    std::string getFormattedDuration( double duration );
25904-
25905-    //! Should the reporter show duration of test given current configuration?
25906-    bool shouldShowDuration( IConfig const& config, double duration );
25907-
25908-    std::string serializeFilters( std::vector<std::string> const& filters );
25909-
25910-    struct lineOfChars {
25911-        char c;
25912-        constexpr lineOfChars( char c_ ): c( c_ ) {}
25913-
25914-        friend std::ostream& operator<<( std::ostream& out, lineOfChars value );
25915-    };
25916-
25917-    /**
25918-     * Lists reporter descriptions to the provided stream in user-friendly
25919-     * format
25920-     *
25921-     * Used as the default listing implementation by the first party reporter
25922-     * bases. The output should be backwards compatible with the output of
25923-     * Catch2 v2 binaries.
25924-     */
25925-    void
25926-    defaultListReporters( std::ostream& out,
25927-                          std::vector<ReporterDescription> const& descriptions,
25928-                          Verbosity verbosity );
25929-
25930-    /**
25931-     * Lists listeners descriptions to the provided stream in user-friendly
25932-     * format
25933-     */
25934-    void defaultListListeners( std::ostream& out,
25935-                               std::vector<ListenerDescription> const& descriptions );
25936-
25937-    /**
25938-     * Lists tag information to the provided stream in user-friendly format
25939-     *
25940-     * Used as the default listing implementation by the first party reporter
25941-     * bases. The output should be backwards compatible with the output of
25942-     * Catch2 v2 binaries.
25943-     */
25944-    void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered );
25945-
25946-    /**
25947-     * Lists test case information to the provided stream in user-friendly
25948-     * format
25949-     *
25950-     * Used as the default listing implementation by the first party reporter
25951-     * bases. The output is backwards compatible with the output of Catch2
25952-     * v2 binaries, and also supports the format specific to the old
25953-     * `--list-test-names-only` option, for people who used it in integrations.
25954-     */
25955-    void defaultListTests( std::ostream& out,
25956-                           ColourImpl* streamColour,
25957-                           std::vector<TestCaseHandle> const& tests,
25958-                           bool isFiltered,
25959-                           Verbosity verbosity );
25960-
25961-    /**
25962-     * Prints test run totals to the provided stream in user-friendly format
25963-     *
25964-     * Used by the console and compact reporters.
25965-     */
25966-    void printTestRunTotals( std::ostream& stream,
25967-                      ColourImpl& streamColour,
25968-                      Totals const& totals );
25969-
25970-} // end namespace Catch
25971-
25972-#endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED
25973-
25974-
25975-
25976-#ifndef CATCH_REPORTER_JSON_HPP_INCLUDED
25977-#define CATCH_REPORTER_JSON_HPP_INCLUDED
25978-
25979-
25980-#include <stack>
25981-
25982-namespace Catch {
25983-    class JsonReporter : public StreamingReporterBase {
25984-    public:
25985-        JsonReporter( ReporterConfig&& config );
25986-
25987-        ~JsonReporter() override;
25988-
25989-        static std::string getDescription();
25990-
25991-    public: // StreamingReporterBase
25992-        void testRunStarting( TestRunInfo const& runInfo ) override;
25993-        void testRunEnded( TestRunStats const& runStats ) override;
25994-
25995-        void testCaseStarting( TestCaseInfo const& tcInfo ) override;
25996-        void testCaseEnded( TestCaseStats const& tcStats ) override;
25997-
25998-        void testCasePartialStarting( TestCaseInfo const& tcInfo,
25999-                                      uint64_t index ) override;
26000-        void testCasePartialEnded( TestCaseStats const& tcStats,
26001-                                   uint64_t index ) override;
26002-
26003-        void sectionStarting( SectionInfo const& sectionInfo ) override;
26004-        void sectionEnded( SectionStats const& sectionStats ) override;
26005-
26006-        void assertionEnded( AssertionStats const& assertionStats ) override;
26007-
26008-        //void testRunEndedCumulative() override;
26009-
26010-        void benchmarkPreparing( StringRef name ) override;
26011-        void benchmarkStarting( BenchmarkInfo const& ) override;
26012-        void benchmarkEnded( BenchmarkStats<> const& ) override;
26013-        void benchmarkFailed( StringRef error ) override;
26014-
26015-        void listReporters(
26016-            std::vector<ReporterDescription> const& descriptions ) override;
26017-        void listListeners(
26018-            std::vector<ListenerDescription> const& descriptions ) override;
26019-        void listTests( std::vector<TestCaseHandle> const& tests ) override;
26020-        void listTags( std::vector<TagInfo> const& tags ) override;
26021-
26022-    private:
26023-        Timer m_testCaseTimer;
26024-        enum class Writer {
26025-            Object,
26026-            Array
26027-        };
26028-
26029-        JsonArrayWriter& startArray();
26030-        JsonArrayWriter& startArray( StringRef key );
26031-
26032-        JsonObjectWriter& startObject();
26033-        JsonObjectWriter& startObject( StringRef key );
26034-
26035-        void endObject();
26036-        void endArray();
26037-
26038-        bool isInside( Writer writer );
26039-
26040-        void startListing();
26041-        void endListing();
26042-
26043-        // Invariant:
26044-        // When m_writers is not empty and its top element is
26045-        // - Writer::Object, then m_objectWriters is not be empty
26046-        // - Writer::Array,  then m_arrayWriters shall not be empty
26047-        std::stack<JsonObjectWriter> m_objectWriters{};
26048-        std::stack<JsonArrayWriter> m_arrayWriters{};
26049-        std::stack<Writer> m_writers{};
26050-
26051-        bool m_startedListing = false;
26052-
26053-        // std::size_t m_sectionDepth = 0;
26054-        // std::size_t m_sectionStarted = 0;
26055-    };
26056-} // namespace Catch
26057-
26058-#endif // CATCH_REPORTER_JSON_HPP_INCLUDED
26059-
26060-
26061-#ifndef CATCH_REPORTER_JUNIT_HPP_INCLUDED
26062-#define CATCH_REPORTER_JUNIT_HPP_INCLUDED
26063-
26064-
26065-
26066-namespace Catch {
26067-
26068-    class JunitReporter final : public CumulativeReporterBase {
26069-    public:
26070-        JunitReporter(ReporterConfig&& _config);
26071-
26072-        static std::string getDescription();
26073-
26074-        void testRunStarting(TestRunInfo const& runInfo) override;
26075-
26076-        void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
26077-        void assertionEnded(AssertionStats const& assertionStats) override;
26078-
26079-        void testCaseEnded(TestCaseStats const& testCaseStats) override;
26080-
26081-        void testRunEndedCumulative() override;
26082-
26083-    private:
26084-        void writeRun(TestRunNode const& testRunNode, double suiteTime);
26085-
26086-        void writeTestCase(TestCaseNode const& testCaseNode);
26087-
26088-        void writeSection( std::string const& className,
26089-                           std::string const& rootName,
26090-                           SectionNode const& sectionNode,
26091-                           bool testOkToFail );
26092-
26093-        void writeAssertions(SectionNode const& sectionNode);
26094-        void writeAssertion(AssertionStats const& stats);
26095-
26096-        XmlWriter xml;
26097-        Timer suiteTimer;
26098-        std::string stdOutForSuite;
26099-        std::string stdErrForSuite;
26100-        unsigned int unexpectedExceptions = 0;
26101-        bool m_okToFail = false;
26102-    };
26103-
26104-} // end namespace Catch
26105-
26106-#endif // CATCH_REPORTER_JUNIT_HPP_INCLUDED
26107-
26108-
26109-#ifndef CATCH_REPORTER_MULTI_HPP_INCLUDED
26110-#define CATCH_REPORTER_MULTI_HPP_INCLUDED
26111-
26112-
26113-namespace Catch {
26114-
26115-    class MultiReporter final : public IEventListener {
26116-        /*
26117-         * Stores all added reporters and listeners
26118-         *
26119-         * All Listeners are stored before all reporters, and individual
26120-         * listeners/reporters are stored in order of insertion.
26121-         */
26122-        std::vector<IEventListenerPtr> m_reporterLikes;
26123-        bool m_haveNoncapturingReporters = false;
26124-
26125-        // Keep track of how many listeners we have already inserted,
26126-        // so that we can insert them into the main vector at the right place
26127-        size_t m_insertedListeners = 0;
26128-
26129-        void updatePreferences(IEventListener const& reporterish);
26130-
26131-    public:
26132-        MultiReporter( IConfig const* config ):
26133-            IEventListener( config ) {
26134-            m_preferences.shouldReportAllAssertionStarts = false;
26135-        }
26136-
26137-        using IEventListener::IEventListener;
26138-
26139-        void addListener( IEventListenerPtr&& listener );
26140-        void addReporter( IEventListenerPtr&& reporter );
26141-
26142-    public: // IEventListener
26143-
26144-        void noMatchingTestCases( StringRef unmatchedSpec ) override;
26145-        void fatalErrorEncountered( StringRef error ) override;
26146-        void reportInvalidTestSpec( StringRef arg ) override;
26147-
26148-        void benchmarkPreparing( StringRef name ) override;
26149-        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
26150-        void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
26151-        void benchmarkFailed( StringRef error ) override;
26152-
26153-        void testRunStarting( TestRunInfo const& testRunInfo ) override;
26154-        void testCaseStarting( TestCaseInfo const& testInfo ) override;
26155-        void testCasePartialStarting(TestCaseInfo const& testInfo, uint64_t partNumber) override;
26156-        void sectionStarting( SectionInfo const& sectionInfo ) override;
26157-        void assertionStarting( AssertionInfo const& assertionInfo ) override;
26158-
26159-        void assertionEnded( AssertionStats const& assertionStats ) override;
26160-        void sectionEnded( SectionStats const& sectionStats ) override;
26161-        void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override;
26162-        void testCaseEnded( TestCaseStats const& testCaseStats ) override;
26163-        void testRunEnded( TestRunStats const& testRunStats ) override;
26164-
26165-        void skipTest( TestCaseInfo const& testInfo ) override;
26166-
26167-        void listReporters(std::vector<ReporterDescription> const& descriptions) override;
26168-        void listListeners(std::vector<ListenerDescription> const& descriptions) override;
26169-        void listTests(std::vector<TestCaseHandle> const& tests) override;
26170-        void listTags(std::vector<TagInfo> const& tags) override;
26171-
26172-
26173-    };
26174-
26175-} // end namespace Catch
26176-
26177-#endif // CATCH_REPORTER_MULTI_HPP_INCLUDED
26178-
26179-
26180-#ifndef CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
26181-#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
26182-
26183-
26184-#include <type_traits>
26185-
26186-namespace Catch {
26187-
26188-    namespace Detail {
26189-
26190-        template <typename T, typename = void>
26191-        struct has_description : std::false_type {};
26192-
26193-        template <typename T>
26194-        struct has_description<
26195-            T,
26196-            void_t<decltype( T::getDescription() )>>
26197-            : std::true_type {};
26198-
26199-        //! Indirection for reporter registration, so that the error handling is
26200-        //! independent on the reporter's concrete type
26201-        void registerReporterImpl( std::string const& name,
26202-                                   IReporterFactoryPtr reporterPtr );
26203-        //! Actually registers the factory, independent on listener's concrete type
26204-        void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory );
26205-    } // namespace Detail
26206-
26207-    class IEventListener;
26208-    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
26209-
26210-    template <typename T>
26211-    class ReporterFactory : public IReporterFactory {
26212-
26213-        IEventListenerPtr create( ReporterConfig&& config ) const override {
26214-            return Detail::make_unique<T>( CATCH_MOVE(config) );
26215-        }
26216-
26217-        std::string getDescription() const override {
26218-            return T::getDescription();
26219-        }
26220-    };
26221-
26222-
26223-    template<typename T>
26224-    class ReporterRegistrar {
26225-    public:
26226-        explicit ReporterRegistrar( std::string const& name ) {
26227-            registerReporterImpl( name,
26228-                                  Detail::make_unique<ReporterFactory<T>>() );
26229-        }
26230-    };
26231-
26232-    template<typename T>
26233-    class ListenerRegistrar {
26234-
26235-        class TypedListenerFactory : public EventListenerFactory {
26236-            StringRef m_listenerName;
26237-
26238-            std::string getDescriptionImpl( std::true_type ) const {
26239-                return T::getDescription();
26240-            }
26241-
26242-            std::string getDescriptionImpl( std::false_type ) const {
26243-                return "(No description provided)";
26244-            }
26245-
26246-        public:
26247-            TypedListenerFactory( StringRef listenerName ):
26248-                m_listenerName( listenerName ) {}
26249-
26250-            IEventListenerPtr create( IConfig const* config ) const override {
26251-                return Detail::make_unique<T>( config );
26252-            }
26253-
26254-            StringRef getName() const override {
26255-                return m_listenerName;
26256-            }
26257-
26258-            std::string getDescription() const override {
26259-                return getDescriptionImpl( Detail::has_description<T>{} );
26260-            }
26261-        };
26262-
26263-    public:
26264-        ListenerRegistrar(StringRef listenerName) {
26265-            registerListenerImpl( Detail::make_unique<TypedListenerFactory>(listenerName) );
26266-        }
26267-    };
26268-}
26269-
26270-#if !defined(CATCH_CONFIG_DISABLE)
26271-
26272-#    define CATCH_REGISTER_REPORTER( name, reporterType )                  \
26273-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                          \
26274-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                           \
26275-        namespace {                                                        \
26276-            const Catch::ReporterRegistrar<reporterType>                   \
26277-                INTERNAL_CATCH_UNIQUE_NAME( catch_internal_RegistrarFor )( \
26278-                    name );                                                \
26279-        }                                                                  \
26280-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
26281-
26282-#    define CATCH_REGISTER_LISTENER( listenerType )                        \
26283-        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                          \
26284-        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                           \
26285-        namespace {                                                        \
26286-            const Catch::ListenerRegistrar<listenerType>                   \
26287-                INTERNAL_CATCH_UNIQUE_NAME( catch_internal_RegistrarFor )( \
26288-                    #listenerType##_catch_sr );                            \
26289-        }                                                                  \
26290-        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
26291-
26292-#else // CATCH_CONFIG_DISABLE
26293-
26294-#define CATCH_REGISTER_REPORTER(name, reporterType)
26295-#define CATCH_REGISTER_LISTENER(listenerType)
26296-
26297-#endif // CATCH_CONFIG_DISABLE
26298-
26299-#endif // CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
26300-
26301-
26302-#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
26303-#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
26304-
26305-
26306-
26307-namespace Catch {
26308-
26309-    class SonarQubeReporter final : public CumulativeReporterBase {
26310-    public:
26311-        SonarQubeReporter(ReporterConfig&& config)
26312-        : CumulativeReporterBase(CATCH_MOVE(config))
26313-        , xml(m_stream) {
26314-            m_preferences.shouldRedirectStdOut = true;
26315-            m_preferences.shouldReportAllAssertions = false;
26316-            m_preferences.shouldReportAllAssertionStarts = false;
26317-            m_shouldStoreSuccesfulAssertions = false;
26318-        }
26319-
26320-        static std::string getDescription() {
26321-            using namespace std::string_literals;
26322-            return "Reports test results in the Generic Test Data SonarQube XML format"s;
26323-        }
26324-
26325-        void testRunStarting( TestRunInfo const& testRunInfo ) override;
26326-
26327-        void testRunEndedCumulative() override {
26328-            writeRun( *m_testRun );
26329-            xml.endElement();
26330-        }
26331-
26332-        void writeRun( TestRunNode const& runNode );
26333-
26334-        void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
26335-
26336-        void writeTestCase(TestCaseNode const& testCaseNode);
26337-
26338-        void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail);
26339-
26340-        void writeAssertions(SectionNode const& sectionNode, bool okToFail);
26341-
26342-        void writeAssertion(AssertionStats const& stats, bool okToFail);
26343-
26344-    private:
26345-        XmlWriter xml;
26346-    };
26347-
26348-
26349-} // end namespace Catch
26350-
26351-#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
26352-
26353-
26354-#ifndef CATCH_REPORTER_TAP_HPP_INCLUDED
26355-#define CATCH_REPORTER_TAP_HPP_INCLUDED
26356-
26357-
26358-namespace Catch {
26359-
26360-    class TAPReporter final : public StreamingReporterBase {
26361-    public:
26362-        TAPReporter( ReporterConfig&& config ):
26363-            StreamingReporterBase( CATCH_MOVE(config) ) {
26364-            m_preferences.shouldReportAllAssertions = true;
26365-            m_preferences.shouldReportAllAssertionStarts = false;
26366-        }
26367-
26368-        static std::string getDescription() {
26369-            using namespace std::string_literals;
26370-            return "Reports test results in TAP format, suitable for test harnesses"s;
26371-        }
26372-
26373-        void testRunStarting( TestRunInfo const& testInfo ) override;
26374-
26375-        void noMatchingTestCases( StringRef unmatchedSpec ) override;
26376-
26377-        void assertionEnded(AssertionStats const& _assertionStats) override;
26378-
26379-        void testRunEnded(TestRunStats const& _testRunStats) override;
26380-
26381-    private:
26382-        std::size_t counter = 0;
26383-    };
26384-
26385-} // end namespace Catch
26386-
26387-#endif // CATCH_REPORTER_TAP_HPP_INCLUDED
26388-
26389-
26390-#ifndef CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
26391-#define CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
26392-
26393-
26394-#include <cstring>
26395-
26396-#ifdef __clang__
26397-#   pragma clang diagnostic push
26398-#   pragma clang diagnostic ignored "-Wpadded"
26399-#endif
26400-
26401-namespace Catch {
26402-
26403-    class TeamCityReporter final : public StreamingReporterBase {
26404-    public:
26405-        TeamCityReporter( ReporterConfig&& _config )
26406-        :   StreamingReporterBase( CATCH_MOVE(_config) )
26407-        {
26408-            m_preferences.shouldRedirectStdOut = true;
26409-            m_preferences.shouldReportAllAssertionStarts = false;
26410-        }
26411-
26412-        ~TeamCityReporter() override;
26413-
26414-        static std::string getDescription() {
26415-            using namespace std::string_literals;
26416-            return "Reports test results as TeamCity service messages"s;
26417-        }
26418-
26419-        void testRunStarting( TestRunInfo const& runInfo ) override;
26420-        void testRunEnded( TestRunStats const& runStats ) override;
26421-
26422-
26423-        void assertionEnded(AssertionStats const& assertionStats) override;
26424-
26425-        void sectionStarting(SectionInfo const& sectionInfo) override {
26426-            m_headerPrintedForThisSection = false;
26427-            StreamingReporterBase::sectionStarting( sectionInfo );
26428-        }
26429-
26430-        void testCaseStarting(TestCaseInfo const& testInfo) override;
26431-
26432-        void testCaseEnded(TestCaseStats const& testCaseStats) override;
26433-
26434-    private:
26435-        void printSectionHeader(std::ostream& os);
26436-
26437-        bool m_headerPrintedForThisSection = false;
26438-        Timer m_testTimer;
26439-    };
26440-
26441-} // end namespace Catch
26442-
26443-#ifdef __clang__
26444-#   pragma clang diagnostic pop
26445-#endif
26446-
26447-#endif // CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
26448-
26449-
26450-#ifndef CATCH_REPORTER_XML_HPP_INCLUDED
26451-#define CATCH_REPORTER_XML_HPP_INCLUDED
26452-
26453-
26454-
26455-
26456-namespace Catch {
26457-    class XmlReporter : public StreamingReporterBase {
26458-    public:
26459-        XmlReporter(ReporterConfig&& _config);
26460-
26461-        ~XmlReporter() override;
26462-
26463-        static std::string getDescription();
26464-
26465-        virtual std::string getStylesheetRef() const;
26466-
26467-        void writeSourceInfo(SourceLineInfo const& sourceInfo);
26468-
26469-    public: // StreamingReporterBase
26470-
26471-        void testRunStarting(TestRunInfo const& testInfo) override;
26472-
26473-        void testCaseStarting(TestCaseInfo const& testInfo) override;
26474-
26475-        void sectionStarting(SectionInfo const& sectionInfo) override;
26476-
26477-        void assertionEnded(AssertionStats const& assertionStats) override;
26478-
26479-        void sectionEnded(SectionStats const& sectionStats) override;
26480-
26481-        void testCaseEnded(TestCaseStats const& testCaseStats) override;
26482-
26483-        void testRunEnded(TestRunStats const& testRunStats) override;
26484-
26485-        void benchmarkPreparing( StringRef name ) override;
26486-        void benchmarkStarting(BenchmarkInfo const&) override;
26487-        void benchmarkEnded(BenchmarkStats<> const&) override;
26488-        void benchmarkFailed( StringRef error ) override;
26489-
26490-        void listReporters(std::vector<ReporterDescription> const& descriptions) override;
26491-        void listListeners(std::vector<ListenerDescription> const& descriptions) override;
26492-        void listTests(std::vector<TestCaseHandle> const& tests) override;
26493-        void listTags(std::vector<TagInfo> const& tags) override;
26494-
26495-    private:
26496-        Timer m_testCaseTimer;
26497-        XmlWriter m_xml;
26498-        int m_sectionDepth = 0;
26499-    };
26500-
26501-} // end namespace Catch
26502-
26503-#endif // CATCH_REPORTER_XML_HPP_INCLUDED
26504-
26505-#endif // CATCH_REPORTERS_ALL_HPP_INCLUDED
26506-
26507-#endif // CATCH_ALL_HPP_INCLUDED
26508-#endif // CATCH_AMALGAMATED_HPP_INCLUDED
26509diff --git a/include/grim.h b/include/grim.h
26510index c27f237..53ee278 100755
26511--- a/include/grim.h
26512+++ b/include/grim.h
26513@@ -2,24 +2,19 @@
26514 #ifndef GRIM_H
26515 #define GRIM_H
26516 
26517-#include <iostream>
26518-#include <string>
26519-#include <string_view>
26520-#include <vector>
26521-#include <unordered_map>
26522-#include <unordered_set>
26523-#include <memory>
26524-#include <charconv>
26525-#include <optional>
26526-#include <stdexcept>
26527-#include <deque>
26528+#include <stdio.h>
26529+#include <stddef.h>
26530 
26531-// TODO:
26532-// * templates
26533 
26534+#define MAX_TOKENS 32
26535+#define MAX_GROUPS 16
26536+#define MAX_STR_LEN 128
26537 
26538 
26539-enum class UnitType : short {
26540+
26541+
26542+/*
26543+typedef enum {
26544 	// Color
26545 		TEST, HEX, 
26546 	// Logic
26547@@ -114,182 +109,9 @@ enum class UnitType : short {
26548 		// Image & Grouping
26549 		URL, IMAGE_SET, CROSS_FADE, ELEMENT, GROUP, GRADIENT,
26550 	NON_FUNC_PADDING
26551-};
26552-
26553+} UnitType;
26554 
26555-// 8 bytes 
26556-struct Unit {
26557-	UnitType type; // short
26558-	float value;
26559-};
26560-
26561-struct Range {
26562-	size_t start;
26563-	size_t end;
26564-};
26565-
26566-struct Context {
26567-	int id;
26568-	size_t index;
26569-	size_t length;
26570-	Context* previous;
26571-};
26572-
26573-struct Snapshot {
26574-	Context* ctx;
26575-	size_t pointer;
26576-};
26577-
26578-class Memory {
26579-	private:
26580-		std::deque<Context> arena;
26581-		Context* current = nullptr;
26582-		size_t pointer = 0;
26583-	public:
26584-		std::vector<Unit> heap;
26585-
26586-		Memory() { heap.resize(1024); }
26587-
26588-		void push(int id, std::vector<Unit>& units, size_t start, size_t end) {
26589-			size_t len = end-start;
26590-			arena.push_back({id, pointer, len, current});
26591-			current = &arena.back();
26592-			std::copy(units.begin() + start, units.begin() + end, heap.begin() + pointer);
26593-			pointer += len;
26594-		}
26595-
26596-		void alloc(int id, size_t size) {
26597-			arena.push_back({id, pointer, size, current});
26598-			current = &arena.back();
26599-			pointer += size;
26600-
26601-		}
26602-
26603-		// Used to prefill the heap
26604-		void push_back(int id, Unit unit) {
26605-			arena.push_back({id, pointer, 1, current});
26606-			current = &arena.back();
26607-			heap[pointer] = unit;
26608-			pointer += 1;
26609-		}
26610-
26611-		Range get(int id) {
26612-			Context* walker = current;
26613-			while (walker != nullptr) {
26614-		    		if (walker->id == id) return {walker->index, walker->index+walker->length};
26615-			    	walker = walker->previous;
26616-			}
26617-			return {0,0}; // Not found
26618-		}
26619-
26620-		Snapshot save() {
26621-			return {current, pointer};
26622-		}
26623-
26624-		void restore(Snapshot s) {
26625-			current = s.ctx;
26626-			pointer = s.pointer;
26627-		}
26628-};
26629-
26630-class Window;
26631-
26632-struct ClassList {
26633-	private:
26634-		std::string* classString;
26635-		std::vector<std::pair<int, int>> indexes;
26636-		size_t len;
26637-		// No return, modifies indexes directly
26638-		void createIndex();
26639-		bool checkIndex();
26640-
26641-	public:
26642-		ClassList(std::string* cs) : classString(cs) {}
26643-		void add(std::string value);
26644-		void remove(std::string value);
26645-		void toggle(std::string value);
26646-		void replace(std::string key, std::string value);
26647-		bool contains(std::string value);
26648-		std::string item(size_t key);
26649-		size_t length();
26650-};
26651-
26652-struct StyleList {
26653-	private:
26654-		std::string* styleString;
26655-		std::vector<std::tuple<int, int, int>> indexes;
26656-		size_t len;
26657-		void createIndex();
26658-		bool checkIndex();
26659-	public:
26660-		StyleList(std::string* sS) : styleString(sS) {}
26661-		std::string get(std::string key);
26662-		void set(std::string key, std::string value);
26663-		void remove(std::string key);
26664-		std::pair<std::string, std::string> item(size_t index);
26665-		size_t length();
26666-};
26667-
26668-struct dom_list {
26669-	std::vector<Node> elements;
26670-}
26671-
26672-struct Node {
26673-	std::vector<Pair> attributes;
26674-	std::vector<Pair> computed_style;
26675-}
26676-
26677-struct Pair {
26678-	std::string key;
26679-	std::string value;
26680-}
26681-
26682-class Node {
26683-	private:
26684-		std::string TagName = "";
26685-		std::unordered_map<std::string, std::string> attributes;
26686-		float em = 0;
26687-		float width = 0;
26688-		float height = 0;
26689-	public:
26690-		Window* window;
26691-
26692-		Node* parent;
26693-		
26694-		std::vector<Node> children;
26695-		ClassList classList() { return ClassList(&this->attributes["class"]); }
26696-		StyleList style() { return StyleList(&this->attributes["style"]); }
26697-
26698-		Node() : parent(nullptr) {}
26699-
26700-		std::string getTagName() const;
26701-		void setTagName(const std::string& name);
26702-
26703-		float getEM() const; // Returns value from the cache
26704-		float getWidth() const;
26705-		float getHeight() const;
26706-		void cacheEM(const float value); // Sets the cache value (should not be manually used)
26707-		void cacheWidth(const float value);
26708-		void cacheHeight(const float value);
26709-
26710-		Node* createElement(std::string name);
26711-
26712-		void setAttribute(const std::string& name, const std::string& value);
26713-		void deleteAttribute(const std::string& name);
26714-		std::string getAttribute(const std::string& name) const;
26715-		bool hasAttribute(const std::string& name) const;
26716-
26717-		const std::unordered_map<std::string, std::string>& getAttributes() const;
26718-		std::vector<std::string> getAttributeKeys();
26719-
26720-		std::string print(int indent = 0);
26721-};
26722-
26723-std::vector<std::vector<std::string>> parseSelectorParts(std::string_view);
26724-
26725-bool testSelector(Node*, std::vector<std::vector<std::string>>);
26726-
26727-enum class KeyType : short {
26728+typedef enum {
26729 	ACCENT_COLOR, ALIGN_CONTENT, ALIGN_ITEMS, ALIGN_SELF, ALIGNMENT_BASELINE, ALL, ANCHOR_NAME, ANIMATION_COMPOSITION, ANIMATION_DELAY,
26730 	ANIMATION_DIRECTION, ANIMATION_DURATION, ANIMATION_FILL_MODE, ANIMATION_ITERATION_COUNT, ANIMATION_NAME, ANIMATION_PLAY_STATE, ANIMATION_RANGE_END,
26731 	ANIMATION_RANGE_START, ANIMATION_RANGE, ANIMATION_TIMELINE, ANIMATION_TIMING_FUNCTION, ANIMATION, APPEARANCE, ASPECT_RATIO,
26732@@ -361,84 +183,9 @@ enum class KeyType : short {
26733 	X,
26734 	Y,
26735 	Z_INDEX, ZOOM
26736-};
26737+} KeyType;
26738 
26739-class IndexedMap {
26740-	public:
26741-		std::vector<std::pair<std::string, std::vector<Unit>>> map{};
26742-		std::vector<Unit> find(std::string key) {
26743-			for (size_t i = 0; i < map.size(); i++) {
26744-				if (map[i].first == key) {
26745-					return map[i].second;
26746-				}
26747-			}
26748-		}
26749-
26750-		bool contains(std::string key) {
26751-			for (size_t i = 0; i < map.size(); i++) {
26752-				if (map[i].first == key) {
26753-					return true;
26754-				}
26755-			}
26756-			return false;
26757-		}
26758-
26759-		size_t index(std::string key) {
26760-			for (size_t i = 0; i < map.size(); i++) {
26761-				if (map[i].first == key) {
26762-					return i;
26763-				}
26764-			}
26765-		}
26766-		std::vector<Unit> at(size_t i) {
26767-			return map[i].second;
26768-		}
26769-
26770-		std::string key(size_t i) {
26771-			return map[i].first;
26772-		}
26773-
26774-		size_t set(std::string key, std::vector<Unit> value) {
26775-			for (size_t i = 0; i < map.size(); i++) {
26776-				if (map[i].first == key) {
26777-					map[i].second = value;
26778-					return i;
26779-				}
26780-			}
26781-			map.push_back({key, value});
26782-			return map.size()-1;
26783-		}
26784-
26785-
26786-		// add
26787-
26788-		// function to build Context and heap
26789-
26790-		//
26791-};
26792-
26793-class Style {
26794-	public:
26795-		std::unordered_map<std::string, std::vector<size_t>> basemap{};
26796-
26797-		std::string name; // remove
26798-		std::vector<std::vector<std::string>> selector{};
26799-		
26800-		std::unordered_map<KeyType, std::vector<Unit>> properties{}; // When computing have a is rel function that if not full compute the value
26801-									     // like if the value is calc(1px + 10px) then just store 11px but if its 10vw
26802-									     // then you can't
26803-
26804-		IndexedMap variables{};
26805-
26806-		// Nesting
26807-		std::vector<Style> children{};
26808-
26809-		// Functions
26810-		void addChild(Style s);
26811-		std::unordered_map<KeyType, UnitType> getStyles(Node* n);
26812-};
26813-
26814-enum class Media : char {
26815+typedef enum {
26816 	All,
26817 	Print,
26818 	Screen,
26819@@ -456,158 +203,59 @@ enum class Media : char {
26820 	Reduce,
26821 	Fast,
26822 	Slow
26823-};
26824+} Media;
26825 
26826-class Window {
26827-	private:
26828-		float width = 0;
26829-		float height = 0;
26830-		float resolution = 0;
26831-		float em = 16;
26832-	public:
26833-		
26834-		std::unordered_map<std::string, Media> MediaFeatures {
26835-			{"any-hover", Media::Hover},
26836-			{"any-pointer", Media::Fine},
26837-			{"orientation", Media::Landscape},
26838-			{"pefers-color-scheme", Media::Light},
26839-			{"contrast", Media::NoPreference},
26840-			{"prefers-reduced-motion", Media::NoPreference},
26841-			{"prefers-reduced-transparency", Media::NoPreference},
26842-			{"update", Media::Fast},
26843-			{"media", Media::All},
26844-		};
26845-
26846-		
26847-		void parseHTML(std::istream& inputStream);
26848-		
26849-		Node document;
26850-		Style CSS;
26851-	
26852-		// +---------------------------------------------------+
26853-		// | (hldfk) Window Properties                         |
26854-		// +---------------------------------------------------+
26855-
26856-		void setWidth(float value) {
26857-			width = value;
26858-		}
26859-		void setHeight(float value) {
26860-			height = value;
26861-		}
26862-		void setResolution(float value) {
26863-			resolution = value;
26864-		}
26865-
26866-		void setEM(float value) {
26867-			em = value;
26868-		}
26869-
26870-		void setMouse(Media value) {
26871-			// Accepts: Media::Hover && Media::None
26872-			MediaFeatures.at("any-hover") = value;
26873-			MediaFeatures.at("any-pointer") = value;
26874-		}
26875-
26876-		void setOrientation(Media value) {
26877-			MediaFeatures.at("orientation") = value;
26878-		}
26879-
26880-		void setColorScheme(Media value) {
26881-			MediaFeatures.at("prefers-color-scheme") = value;
26882-		}
26883-
26884-		void setContrast(Media value) {
26885-			MediaFeatures.at("contrast") = value;
26886-		}
26887-
26888-		void setReducedMotion(Media value) {
26889-			MediaFeatures.at("prefers-reduced-motion") = value;
26890-		}
26891-
26892-		void setReducedTransparency(Media value) {
26893-			MediaFeatures.at("prefers-reduced-transparency") = value;
26894-		}
26895-
26896-		void setUpdate(Media value) {
26897-			MediaFeatures.at("update") = value;
26898-		}
26899-
26900-		void setMedia(Media value) {
26901-			MediaFeatures.at("media") = value;
26902-		}
26903-
26904-		// Getters
26905-		float getWidth() const {
26906-			return width;
26907-		}
26908-		float getHeight() const {
26909-			return height;
26910-		}
26911-		float getResolution() const {
26912-			return resolution;
26913-		}
26914-		float getEM() const {
26915-			return em;
26916-		}
26917-		float getAspectRatio() const {
26918-			if (height == 0) return 0.0;
26919-			return static_cast<double>(width) / height;
26920-		}
26921-		Media getMedia() const {
26922-			auto it = MediaFeatures.find("media");
26923-			return it->second;
26924-		}
26925-
26926-		Media getAnyHover() const {
26927-			auto it = MediaFeatures.find("any-hover");
26928-			return it->second;
26929-		}
26930-
26931-		Media getAnyPointer() const {
26932-			auto it = MediaFeatures.find("any-pointer");
26933-			return it->second;
26934-		}
26935+// 8 bytes 
26936+struct Unit {
26937+	UnitType type; // short
26938+	float value;
26939+};
26940 
26941-		Media getOrientation() const {
26942-			auto it = MediaFeatures.find("orientation");
26943-			return it->second;
26944-		}
26945+struct Range {
26946+	size_t start;
26947+	size_t end;
26948+};
26949 
26950-		Media getColorScheme() const {
26951-			auto it = MediaFeatures.find("prefers-color-scheme");
26952-			return it->second;
26953-		}
26954+struct Context {
26955+	int id;
26956+	size_t index;
26957+	size_t length;
26958+	Context* previous;
26959+};
26960 
26961-		Media getContrast() const {
26962-			auto it = MediaFeatures.find("contrast");
26963-			return it->second;
26964-		}
26965+struct Snapshot {
26966+	Context* ctx;
26967+	size_t pointer;
26968+};
26969 
26970-		Media getReducedMotion() const {
26971-			auto it = MediaFeatures.find("prefers-reduced-motion");
26972-			return it->second;
26973-		}
26974+struct dom_list {
26975+	std::vector<Node> elements;
26976+}
26977 
26978-		Media getReducedTransparency() const {
26979-			auto it = MediaFeatures.find("prefers-reduced-motion");
26980-			return it->second;
26981-		}
26982+struct Node {
26983+	std::vector<Pair> attributes;
26984+	std::vector<Pair> computed_style;
26985+}
26986 
26987-		Media getUpdate() const {
26988-			auto it = MediaFeatures.find("update");
26989-			return it->second;
26990-		}
26991-};
26992+struct Pair {
26993+	std::string key;
26994+	std::string value;
26995+}
26996+*/
26997+typedef struct {
26998+    char items[MAX_TOKENS][MAX_STR_LEN];
26999+    int size;
27000+} SelectorParts;
27001 
27002-// Will need to require an adapter later
27003-// for now I just want to work on at rules
27004+typedef struct {
27005+    SelectorParts items[MAX_GROUPS];
27006+    int size;
27007+} ParsedSelector;
27008 
27009+ParsedSelector parseSelectorParts(const char*);
27010 /*
27011-For the adapter, it will take a window as a argument to set the adapters capabilties
27012-*/
27013-Window createWindow();
27014-
27015+bool testSelector(Node*, std::vector<std::vector<std::string>>);
27016 
27017 Unit UnitValue(Memory&, std::vector<Unit>&, size_t, size_t);
27018-
27019+*/
27020 #endif // NODE_H
27021diff --git a/include/parser.h b/include/parser.h
27022index abcbdca..7f5b328 100755
27023--- a/include/parser.h
27024+++ b/include/parser.h
27025@@ -2,20 +2,6 @@
27026 #ifndef PARSER_H
27027 #define PARSER_H
27028 
27029-#include <memory>
27030-#include <istream>
27031-#include <unordered_map>
27032-#include <string>
27033-#include <string_view>
27034-
27035-class Node;
27036-class Style;
27037-
27038-struct ParsedDocument {
27039-	Node document;
27040-	Style CSS;
27041-};
27042-
27043 struct SymbolTable {
27044 	std::unordered_map<std::string, int> table;
27045 	int next;
27046diff --git a/playground/parseselectorparts.c b/playground/parseselectorparts.c
27047new file mode 100644
27048index 0000000..0a826bb
27049--- /dev/null
27050+++ b/playground/parseselectorparts.c
27051@@ -0,0 +1,188 @@
27052+#define _POSIX_C_SOURCE 199309L
27053+#include <stdio.h>
27054+#include <time.h>
27055+#include <string.h>
27056+
27057+#include "../include/grim.h"
27058+
27059+#include <stdbool.h>
27060+
27061+// Helper to check if a single part (buffer) matches expected strings
27062+bool verify_part(SelectorParts actual, const char* expected[], int expected_count, int part_idx) {
27063+    if (actual.size != expected_count) {
27064+        printf("  ❌ Fail Part %d: Got %d items, expected %d\n", part_idx, actual.size, expected_count);
27065+        return false;
27066+    }
27067+    for (int i = 0; i < expected_count; i++) {
27068+        if (strcmp(actual.items[i], expected[i]) != 0) {
27069+            printf("  ❌ Fail Part %d index %d: Got \"%s\", expected \"%s\"\n", 
27070+                    part_idx, i, actual.items[i], expected[i]);
27071+            return false;
27072+        }
27073+    }
27074+    return true;
27075+}
27076+
27077+// The main test runner
27078+void test_selector(const char* query, const char* expected_parts[][MAX_TOKENS], int item_counts[], int part_count) {
27079+    ParsedSelector actual = parseSelectorParts(query);
27080+    bool pass = true;
27081+
27082+    printf("Test: %s\n", query);
27083+
27084+    if (actual.size != part_count) {
27085+        printf("  ❌ Fail: Got %d comma-separated parts, expected %d\n", actual.size, part_count);
27086+        pass = false;
27087+    } else {
27088+        for (int i = 0; i < part_count; i++) {
27089+            if (!verify_part(actual.items[i], expected_parts[i], item_counts[i], i)) {
27090+                pass = false;
27091+            }
27092+        }
27093+    }
27094+
27095+    if (pass) printf("  ✅ Passed\n");
27096+}
27097+
27098+void print_parsed_selector(ParsedSelector p) {
27099+	puts("[\n");
27100+	for (int i = 0; i < p.size; i++) {
27101+		puts("[");
27102+		for (int j = 0; j < p.items[i].size; j++) {
27103+			printf("\"%s\", ", p.items[i].items[j]);
27104+		}
27105+		puts("],\n");
27106+	}
27107+	puts("]\n");
27108+}
27109+
27110+void benchmark_parse_selector_parts(const char* query) {
27111+	struct timespec start, end;
27112+
27113+	int iterations = 10000;
27114+	ParsedSelector r;
27115+
27116+	// Get start time
27117+	clock_gettime(CLOCK_MONOTONIC, &start);
27118+
27119+	for (int i = 0; i < iterations; i++) {
27120+		r = parseSelectorParts(query);
27121+	}
27122+
27123+	// Get end time
27124+	clock_gettime(CLOCK_MONOTONIC, &end);
27125+
27126+	print_parsed_selector(r);	
27127+
27128+	// Calculate time difference in seconds
27129+	double total_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
27130+	printf("Average execution time: %.9f seconds (%f us)\n", 
27131+		total_time / iterations, 
27132+	       (total_time / iterations) * 1000000);
27133+}
27134+
27135+void run_css_test_suite() {
27136+    // 1. Simple CSS selector
27137+    {
27138+        const char* exp[1][MAX_TOKENS] = {{"div", ">", "h1"}};
27139+        int counts[] = {3};
27140+        test_selector("div > h1", exp, counts, 1);
27141+    }
27142+
27143+    // 2. Simple with pseudo class
27144+    {
27145+        const char* exp[1][MAX_TOKENS] = {{"div", ">", "h1", ":checked"}};
27146+        int counts[] = {4};
27147+        test_selector("div > h1:checked", exp, counts, 1);
27148+    }
27149+
27150+    // 3. Attribute selector
27151+    {
27152+        const char* exp[1][MAX_TOKENS] = {{"a", "[href=\"https://www.example.com/\"]"}};
27153+        int counts[] = {2};
27154+        test_selector("a[href=\"https://www.example.com/\"]", exp, counts, 1);
27155+    }
27156+
27157+    // 4. has() logic
27158+    {
27159+        const char* exp[1][MAX_TOKENS] = {{"h1", ":has", "(+ h2)"}};
27160+        int counts[] = {3};
27161+        test_selector("h1:has(+ h2)", exp, counts, 1);
27162+    }
27163+
27164+    // 5. where() with internal commas (should be one token)
27165+    {
27166+        const char* exp[1][MAX_TOKENS] = {{":where", "(ol, ul, menu:unsupported)"}};
27167+        int counts[] = {2};
27168+        test_selector(":where(ol, ul, menu:unsupported)", exp, counts, 1);
27169+    }
27170+
27171+    // 6. Multiple simple selectors (Commas!)
27172+    {
27173+        const char* exp[3][MAX_TOKENS] = {
27174+            {"input", ":required"},
27175+            {"div", "#id", "+", "h1", ".c1", ".c2"},
27176+            {"input", "[type=\"password\"]", ".class"}
27177+        };
27178+        int counts[] = {2, 6, 3};
27179+        test_selector("input:required, div#id + h1.c1.c2, input[type='password'].class", exp, counts, 3);
27180+    }
27181+
27182+    // 7. Descendant combinator (The space)
27183+    {
27184+        const char* exp[1][MAX_TOKENS] = {{"div", " ", "h1"}};
27185+        int counts[] = {3};
27186+        test_selector("div h1", exp, counts, 1);
27187+    }
27188+
27189+    // 8. has() + pseudo
27190+    {
27191+        const char* exp[1][MAX_TOKENS] = {{"div", ":has", "(h1)", ":checked"}};
27192+        int counts[] = {4};
27193+        test_selector("div:has(h1):checked", exp, counts, 1);
27194+    }
27195+
27196+    // 9. ID only
27197+    {
27198+        const char* exp[1][MAX_TOKENS] = {{"#id"}};
27199+        int counts[] = {1};
27200+        test_selector("#id", exp, counts, 1);
27201+    }
27202+
27203+    // 10. Multiple selectors (Mixed)
27204+    {
27205+        const char* exp[3][MAX_TOKENS] = {
27206+            {"h1"},
27207+            {"h1", "~", "p"},
27208+            {":last-child"}
27209+        };
27210+        int counts[] = {1, 3, 1};
27211+        test_selector("h1, h1 ~p, :last-child", exp, counts, 3);
27212+    }
27213+
27214+    // 11. Relative selector
27215+    {
27216+        const char* exp[1][MAX_TOKENS] = {{"+", "p"}};
27217+        int counts[] = {2};
27218+        test_selector("+ p", exp, counts, 1);
27219+    }
27220+
27221+    // 12. Tag + Attr + Pseudo
27222+    {
27223+        const char* exp[1][MAX_TOKENS] = {{"input", "[type=\"text\"]", ":disabled"}};
27224+        int counts[] = {3};
27225+        test_selector("input[type=\"text\"]:disabled", exp, counts, 1);
27226+    }
27227+
27228+    // 13. Pseudo element
27229+    {
27230+        const char* exp[1][MAX_TOKENS] = {{"h1", ":before"}}; // Note: Your code currently strips the second colon
27231+        int counts[] = {2};
27232+        test_selector("h1::before", exp, counts, 1);
27233+    }
27234+}
27235+
27236+int main() {
27237+	benchmark_parse_selector_parts("input:required, div#id + h1.c1.c2, input[type='password'].class");
27238+	run_css_test_suite();
27239+}
27240diff --git a/playground/parseselectorparts.cc b/playground/parseselectorparts.cc
27241deleted file mode 100644
27242index ca566fe..0000000
27243--- a/playground/parseselectorparts.cc
27244+++ /dev/null
27245@@ -1,21 +0,0 @@
27246-#include "../include/grim.h"
27247-#include "../include/parser.h" 
27248-#include <string>
27249-#include <vector>
27250-#include <iostream>
27251-
27252-int main() {
27253-	std::vector<std::vector<std::string>> parts = parseSelectorParts("@media (min-width: 60px)");
27254-
27255-
27256-	std::cout << "[" << std::endl;
27257-	for (size_t i = 0; i < parts.size(); i++) {
27258-		std::cout << "[";
27259-		for (size_t j = 0; j < parts[i].size(); j++) {
27260-			std::cout << "\"" << parts[i][j] << "\", ";
27261-		}
27262-		std::cout << "]," << std::endl;
27263-	}
27264-	std::cout << "]" << std::endl;
27265-}
27266-
27267diff --git a/src/grim.cc b/src/grim.c
27268similarity index 73%
27269rename from src/grim.cc
27270rename to src/grim.c
27271index 18f1ccd..0c6051e 100755
27272--- a/src/grim.cc
27273+++ b/src/grim.c
27274@@ -1,19 +1,9 @@
27275 #include "grim.h"
27276-#include "parser.h"
27277-#include <iostream>
27278-#include <sstream>
27279-#include <algorithm>
27280-#include <stdexcept>
27281-#include <cctype>
27282-#include <string_view>
27283-#include <queue>
27284-#include <set>
27285-#include <tuple>
27286-#include <optional>
27287-#include <stdexcept>
27288-#include <limits>
27289-#include <cmath>
27290-#include <string>
27291+//#include "parser.h"
27292+#include <stdio.h>
27293+#include <stddef.h>
27294+#include <string.h>
27295+#include <ctype.h>
27296 
27297 // +------------------------------------------------------+
27298 // |(TOC) Table of contents                               |
27299@@ -35,54 +25,6 @@
27300 // | (p98ym) Utils                                     |
27301 // +---------------------------------------------------+
27302 
27303-void trimSpace(std::string& str) {
27304-    if (str.empty()) {
27305-        return;
27306-    }
27307-
27308-    // Find first non-space
27309-    size_t first_non_space = 0;
27310-    while (first_non_space < str.length() && std::isspace(str[first_non_space])) {
27311-        first_non_space++;
27312-    }
27313-
27314-    // If all spaces or empty
27315-    if (first_non_space == str.length()) {
27316-        str.clear(); // Set to empty string
27317-        return;
27318-    }
27319-
27320-    // Find last non-space
27321-    size_t last_non_space = str.length() - 1;
27322-    while (last_non_space >= first_non_space && std::isspace(str[last_non_space])) {
27323-        last_non_space--;
27324-    }
27325-
27326-    // Erase trailing spaces
27327-    if (last_non_space < str.length() - 1) {
27328-        str.erase(last_non_space + 1);
27329-    }
27330-
27331-    // Erase leading spaces
27332-    if (first_non_space > 0) {
27333-        str.erase(0, first_non_space);
27334-    }
27335-}
27336-// +---------------------------------------------------+
27337-// | (hldfk) Window                                    |
27338-// +---------------------------------------------------+
27339-// All of windows props will come from the adapter setting
27340-// them
27341-Window createWindow() {
27342-	Window window;
27343-	return window;
27344-}
27345-
27346-void Window::parseHTML(std::istream& inputStream) {
27347-	ParsedDocument doc = parseDocument(inputStream);
27348-	document = doc.document;
27349-	CSS = doc.CSS;
27350-}
27351 
27352 // +---------------------------------------------------+
27353 // | (tigfn) Attribute Handling                        |
27354@@ -96,461 +38,15 @@ void Window::parseHTML(std::istream& inputStream) {
27355 // handlers like ClassList (.classList) and StyleList 
27356 // (.style) for more information on each view
27357 // f98y0 and lhujn respectively.
27358+/*
27359+void SET_ATTRIBUTE(Node* n, char* key, char* value) {
27360 
27361-// The Attribute class is defined in the header file
27362-
27363-static const std::unordered_map<std::string, std::string> DEFAULT_ATTRIBUTE_VALUES = {
27364-	{"tabindex", "-1"},
27365-	{"hidden", "false"}
27366-};
27367-
27368-// Tag Name is not a attribute so it needs to be handled differently
27369-std::string Node::getTagName() const { 
27370-		return TagName;
27371-}
27372-void Node::setTagName(const std::string& name) { TagName = name; }
27373-
27374-void Node::setAttribute(const std::string& name, const std::string& value) {
27375-	attributes[name] = value;
27376-}
27377-
27378-void Node::deleteAttribute(const std::string& name) {
27379-	attributes.erase(name);
27380-}
27381-
27382-std::string Node::getAttribute(const std::string& name) const {
27383-	// First check in the user set attributes
27384-	auto it = attributes.find(name);
27385-	if (it != attributes.end()) {
27386-		// return the value wrapped in the Attribute class
27387-		return it->second;
27388-	} else {
27389-		// If its not set by the user then find it in the
27390-		// default values map
27391-		it = DEFAULT_ATTRIBUTE_VALUES.find(name);
27392-		if (it != DEFAULT_ATTRIBUTE_VALUES.end()) {
27393-			return it->second;
27394-		} else {
27395-			return "";
27396-		}
27397-	}
27398-}
27399-
27400-bool Node::hasAttribute(const std::string& name) const {
27401-    return attributes.contains(name) || DEFAULT_ATTRIBUTE_VALUES.contains(name);
27402-}
27403-
27404-std::vector<std::string> Node::getAttributeKeys() {
27405-	std::vector<std::string> keys;
27406-
27407-	for(auto p : attributes) {
27408-		keys.push_back(p.first);
27409-	}
27410-	return keys;
27411-}
27412-
27413-const std::unordered_map<std::string, std::string>& Node::getAttributes() const {
27414-    return attributes;
27415-}
27416-
27417-// +---------------------------------------------------+
27418-// | (o78ty) Cache                                     |
27419-// +---------------------------------------------------+
27420-// For frequently accessed values like em, width, height
27421-// it makes sense to not fully calculate the value access
27422-// during rendering as it is very intensive. The functions
27423-// below are used to store/retrive the last calculated
27424-// value. cache*() will not set the real value for the 
27425-// Nodei, it only effects the interval variables. 
27426-
27427-float Node::getEM() const {
27428-	return em;
27429-}
27430-float Node::getWidth() const {
27431-	return width;
27432-}
27433-float Node::getHeight() const {
27434-	return height;
27435-}
27436-void Node::cacheEM(const float value) {
27437-	em = value;
27438-}
27439-void Node::cacheWidth(const float value) {
27440-	width = value;
27441-}
27442-void Node::cacheHeight(const float value) {
27443-	height = value;
27444-}
27445-
27446-
27447-// +---------------------------------------------------+
27448-// | (f98y0) ClassList                                 |
27449-// +---------------------------------------------------+
27450-
27451-void ClassList::createIndex() {
27452-	int index = 0;
27453-	// Add a space to the back to help trigger the adding of the 
27454-	// last item
27455-	std::string classes = *classString+" ";
27456-	// Update the stored length
27457-	len = classes.length();
27458-	indexes.clear();
27459-
27460-	bool waitForFirstChar = true;
27461-
27462-	for (size_t i = 0; i < len; i++) {
27463-		if (waitForFirstChar && classes[i] != ' ') {
27464-			index = i;
27465-			waitForFirstChar = false;
27466-		} else if (!waitForFirstChar) {
27467-			if (classes[i] == ' ') {
27468-				indexes.push_back({index, i-index});
27469-				waitForFirstChar = true;
27470-			}
27471-		}
27472-	}
27473-}
27474-
27475-
27476-bool ClassList::checkIndex() {
27477-	if (classString->length() != len) {
27478-		return false;
27479-	} else {
27480-		// Skip the first one because there is a space
27481-		// also we don't care if the values are the same
27482-		// just that the array indexing is the same. If the 
27483-		// value is the same size and position it doesn't matter
27484-		for (size_t i = 1; i < indexes.size(); i++) {
27485-			// See if the index position is a space
27486-			// if not return false
27487-			if (!std::isspace(classString->at(indexes[i-1].first))) {
27488-				return false;
27489-			}
27490-		}
27491-		return true;
27492-	}
27493-}
27494-
27495-size_t ClassList::length() {
27496-	if (!checkIndex()) {
27497-		createIndex();
27498-	}
27499-	return indexes.size();
27500-}
27501-
27502-
27503-std::string ClassList::item(size_t key) {
27504-	if (!checkIndex()) {
27505-		createIndex();
27506-	}
27507-	if (key < indexes.size()) {
27508-		std::pair<int, int> pair = indexes[key];
27509-		return classString->substr(pair.first, pair.second);
27510-	} else {
27511-		return "";
27512-	}
27513-}
27514-
27515-void ClassList::add(std::string value) {
27516-	if (!checkIndex()) {
27517-		createIndex();
27518-	}
27519-
27520-	if (classString->length() == 0) {
27521-		classString->append(value);
27522-	} else {
27523-		classString->append(" "+value);
27524-	}
27525-	// len because the index of the added space will be the length of 
27526-	// the prevous string
27527-	int vl = value.length();
27528-	indexes.push_back({len, vl});
27529-	len += vl+1;
27530-}
27531-
27532-void ClassList::remove(std::string value) {
27533-	if (!checkIndex()) {
27534-		createIndex();
27535-	}
27536-
27537-	int newLen = value.length();
27538-	size_t cLen = indexes.size();
27539-
27540-	for (size_t i = 0; i < cLen; i++) {
27541-		std::pair<int, int> pair = indexes[i];
27542-		if (newLen == pair.second) {
27543-			if (classString->substr(pair.first, pair.second) == value) {
27544-				// Splice out the value to be removed 
27545-				// ISSUE: This will keep the surounding spaces and cause the size to grow when 
27546-				// classes are added and removed
27547-				classString->erase(pair.first, pair.second);
27548-			}
27549-		}
27550-	}	
27551-}
27552-
27553-bool ClassList::contains(std::string value) {
27554-	if (!checkIndex()) {
27555-		createIndex();
27556-	}
27557-
27558-	int newLen = value.length();
27559-	size_t cLen = indexes.size();
27560-	bool found = false;
27561-
27562-	for (size_t i = 0; i < cLen; i++) {
27563-		std::pair<int, int> pair = indexes[i];
27564-		if (newLen == pair.second) {
27565-			if (classString->substr(pair.first, pair.second) == value) {
27566-				// Same logic as remove but turns found true then breaks
27567-				found = true;
27568-				break;
27569-			}
27570-		}
27571-	}
27572-	return found;
27573-}
27574-
27575-void ClassList::toggle(std::string value) {
27576-	if (contains(value)) {
27577-		remove(value);
27578-	} else {
27579-		add(value);
27580-	}
27581-}
27582-
27583-// +---------------------------------------------------+
27584-// | (lhujn) StyleList                                 |
27585-// +---------------------------------------------------+
27586-// StyleList provides the JS .style API with a few changes
27587-// to get/set values use .get or .set. To get the entire
27588-// value call .getAttribute("style"). The StyleList stores
27589-// a index of the positions of the first charactor, the ':',
27590-// and the position of the ';'. On every read/write the index
27591-// is verified then the change or read is made. If the value
27592-// changes the positions of the index it will be updated on the
27593-// next read/write. This allows the attribute "style" to always
27594-// contain the true value of the inline style and still have an
27595-// easy to use API for .style. To get all styles, call .length()
27596-// and itterate through all items using .item(<size_t>).
27597-
27598-void StyleList::createIndex() {
27599-	// Update the stored length
27600-	len = styleString->length();
27601-	indexes.clear();
27602-
27603-	// "  background-color: white;"
27604-	//    ^
27605-	
27606-	int firstLetter = 0;
27607-	bool firstNonWhiteSpace = false;
27608-	// "  background-color: white;"
27609-	//                    ^
27610-	int splitPoint = 0;
27611-	bool keyFound = false;
27612-	// "  background-color: white;"
27613-	//                      ^
27614-	int end = 0;
27615-	bool secondNonWhiteSpace = false;
27616-	// "  background-color: white;"
27617-	//                           ^
27618-	// Reset all to false and add the indexs
27619-
27620-
27621-	for (size_t i = 0; i < len; i++) {
27622-		char s = styleString->at(i);
27623-		if (firstNonWhiteSpace) {
27624-			if (keyFound) {
27625-				if (secondNonWhiteSpace) {
27626-					if (s == ';' || i >= len-1) {
27627-						if (i >= len-1 && s != ';') {
27628-							end = i+1;
27629-						} else {
27630-							end = i;
27631-						}
27632-						indexes.push_back({firstLetter, splitPoint, end});
27633-						firstNonWhiteSpace = false;
27634-						secondNonWhiteSpace = false;
27635-						keyFound = false;
27636-					}
27637-				} else if (!std::isspace(s)) {
27638-					secondNonWhiteSpace = true;
27639-				}
27640-			} else if (s == ':') {
27641-				splitPoint = i;
27642-				keyFound = true;
27643-			}
27644-		} else if (!std::isspace(s)) {
27645-			firstLetter = i;
27646-			firstNonWhiteSpace = true;
27647-		}
27648-	}
27649-}
27650-
27651-
27652-bool StyleList::checkIndex() {
27653-	if (styleString->length() != len) {
27654-		return false;
27655-	} else {
27656-		for (size_t i = 0; i < indexes.size(); i++) {
27657-			if (std::isspace(styleString->at(std::get<0>(indexes[i]))) ||
27658-					styleString->at(std::get<1>(indexes[i])) != ':' || 
27659-					styleString->at(std::get<2>(indexes[i])) != ';'
27660-					) {
27661-				return false;
27662-			}
27663-		}
27664-		return true;
27665-	}
27666-}
27667-
27668-std::pair<std::string, std::string> StyleList::item(size_t index) {
27669-	if (!checkIndex()) {
27670-		createIndex();
27671-	}
27672-
27673-	std::pair<std::string, std::string> property;
27674-
27675-	int f = std::get<0>(indexes[index]);
27676-	int s = std::get<1>(indexes[index]);
27677-	property.first = styleString->substr(f, s-f);
27678-	trimSpace(property.first);
27679-
27680-	int t = std::get<2>(indexes[index]);
27681-	property.second = styleString->substr(s+1, t-(s+1));
27682-	trimSpace(property.second);
27683-	return property;
27684-
27685-}
27686-
27687-size_t StyleList::length() {
27688-	if (!checkIndex()) {
27689-		createIndex();
27690-	}
27691-	return indexes.size();
27692-}
27693-
27694-std::string StyleList::get(std::string key) {
27695-	if (!checkIndex()) {
27696-		createIndex();
27697-	}
27698-	for (size_t i = 0; i < indexes.size(); i++) {
27699-		int f = std::get<0>(indexes[i]);
27700-		int s = std::get<1>(indexes[i]);
27701-		std::string slicedKey = styleString->substr(f, s-f);
27702-		trimSpace(slicedKey);
27703-		if (slicedKey == key) {
27704-			int t = std::get<2>(indexes[i]);
27705-			std::string value = styleString->substr(s+1, t-(s+1));
27706-			trimSpace(value);
27707-			return value;
27708-		}
27709-	}
27710-	return "";
27711-}
27712-
27713-void StyleList::set(std::string key, std::string value) {
27714-	if (!checkIndex()) {
27715-		createIndex();
27716-	}
27717-
27718-	for (size_t i = 0; i < indexes.size(); i++) {
27719-		int f = std::get<0>(indexes[i]);
27720-		int s = std::get<1>(indexes[i]);
27721-
27722-		std::string slicedKey = styleString->substr(f, s-f);
27723-		trimSpace(slicedKey);
27724-		if (slicedKey == key) {
27725-			int t = std::get<2>(indexes[i]);
27726-			styleString->replace(f,t-f," "+key+":"+value+";");
27727-			// Return early to skip the appending value;
27728-			return;
27729-		}
27730-	}
27731-
27732-	// If the property wasn't replaced then add it
27733-
27734-	if (!indexes.empty()) {
27735-		char lastChar = styleString->at(std::get<2>(indexes[indexes.size()-1]));
27736-
27737-		if (lastChar == ';') {
27738-			styleString->append(" "+key+":"+value+";");
27739-		} else {
27740-			// If the user didn't terminate the last style
27741-			// terminate it for them
27742-			styleString->append("; "+key+":"+value+";");
27743-		}
27744-	}
27745-}
27746-
27747-void StyleList::remove(std::string key) {
27748-	if (!checkIndex()) {
27749-		createIndex();
27750-	}
27751-
27752-	for (size_t i = 0; i < indexes.size(); i++) {
27753-		int f = std::get<0>(indexes[i]);
27754-		int s = std::get<1>(indexes[i]);
27755-		std::string slicedKey = styleString->substr(f, s-f);
27756-		trimSpace(slicedKey);
27757-		if (slicedKey == key) {
27758-			int t = std::get<2>(indexes[i]);
27759-			styleString->erase(f, t);
27760-			return;
27761-		}
27762-	}
27763 }
27764 
27765-// +---------------------------------------------------+
27766-// | (kuib7) Other Node functions                      |
27767-// +---------------------------------------------------+
27768+void GET_ATTRIBUTE(Node* n, char* key) {
27769 
27770-Node* Node::createElement(std::string name) {
27771-	Node newNode;
27772-	newNode.setTagName(name);
27773-	newNode.parent = this;
27774-	children.push_back(newNode);
27775-	return &children.back();
27776 }
27777-
27778-std::string Node::print(int indent) {
27779-	std::string out = "";
27780-	for (int i = 0; i < indent; ++i) {
27781-		out += "  ";
27782-	}
27783-
27784-	out += "<" + getTagName();
27785-	for (const auto& attr_pair : getAttributes()) {
27786-		if (attr_pair.first == "innerText" || attr_pair.first == "tagName") {
27787-			continue;
27788-		}
27789-		out += " " + attr_pair.first;
27790-		if (!attr_pair.second.empty()) {
27791-			out += "=\"" + attr_pair.second + "\"";
27792-		}
27793-	}
27794-	out += ">";
27795-
27796-	std::string innerText = getAttribute("innerText"); 
27797-
27798-	if (innerText != "") {
27799-		out += "\n" + innerText;
27800-	}
27801-
27802-	out += "\n";
27803-
27804-	for (auto& child : children) {
27805-		out += child.print(indent + 1)+"\n";
27806-	}
27807-
27808-	for (int i = 0; i < indent; ++i) {
27809-		out += "  ";
27810-	}
27811-	out += "</" + getTagName() + ">\n";
27812-
27813-	return out;
27814-}
27815-
27816+*/
27817 // +---------------------------------------------------+
27818 // | (mnjki) CSS Style Handling                        |
27819 // +---------------------------------------------------+
27820@@ -567,35 +63,38 @@ std::string Node::print(int indent) {
27821 // that should be ran once parselector and the results saved somewhere due to
27822 // the high cost to run the function
27823 
27824-std::vector<std::vector<std::string>> parseSelectorParts(std::string_view selector) {
27825+ParsedSelector parseSelectorParts(const char* selector) {
27826 	// need to account for selectors with parenthesis like: h1:(+ input:required)
27827 	// need to convert all single quotes to double quotes
27828 	// need to account for commas, will return
27829 	// need to colapse all spaces to a single space
27830 	// need to trim spaces
27831 
27832-	std::vector<std::vector<std::string>> parts;
27833-	std::vector<std::string> buffer;
27834-	std::string current;
27835+	ParsedSelector parts;
27836+	int parts_index = 0;
27837+
27838+	SelectorParts buffer;
27839+	int buffer_index = 0;
27840+
27841+	char current[MAX_STR_LEN] = {0};
27842+	int current_index = 0;
27843 
27844 	size_t start = 0;
27845-	size_t end = selector.length();
27846+	size_t end = strlen(selector);
27847 
27848 	for (size_t i = start; i < end; i++) {
27849-		if (!std::isspace(selector[i])) {
27850+		if (!isspace(selector[i])) {
27851 			start = i;
27852 			break;
27853 		}
27854 	}
27855 	for (size_t i = end; i > start; i--) {
27856-		if (!std::isspace(selector[i])) {
27857+		if (!isspace(selector[i])) {
27858 			end = i;
27859 			break;
27860 		}
27861 	}
27862 
27863-	current.reserve(end);
27864-
27865 	size_t nesting = 0;
27866 
27867 	for (size_t i = start; i < end; i++) {
27868@@ -603,90 +102,111 @@ std::vector<std::vector<std::string>> parseSelectorParts(std::string_view select
27869 		if (s == '\'') s = '"';
27870 
27871 		if ((s == '(' || s == '[' || s == '{')) {
27872-			if (!current.empty() && nesting == 0) {
27873-				buffer.push_back(current);
27874-				current.clear();
27875+			if (current_index > 0 && nesting == 0) {
27876+				current[current_index++] = '\0';
27877+				strcpy(buffer.items[buffer_index++], current);
27878+				current_index = 0;
27879 			}
27880 
27881-			current.push_back(s);
27882+			current[current_index++] = s;
27883 			nesting++;
27884 			continue;
27885 		}
27886 		
27887 		if ((s == ')' || s == ']' || s == '}')) {
27888 			nesting--;
27889-			current.push_back(s);
27890-			if (!current.empty() && nesting == 0) {
27891-				
27892-				buffer.push_back(current);
27893-				current.clear();
27894+			current[current_index++] = s;
27895+			if (current_index > 0 && nesting == 0) {
27896+				current[current_index++] = '\0';
27897+				strcpy(buffer.items[buffer_index++], current);
27898+				current_index = 0;
27899 			}
27900 			continue;
27901 		} else {
27902-
27903 			if (nesting > 0) {
27904-				current.push_back(s);
27905+				current[current_index++] = s;
27906 				continue;
27907 			}
27908 		}
27909 
27910-		if (std::isspace(s)) {
27911-			if (i < end-1 && std::isspace(selector[i+1])) {
27912+		if (isspace(s)) {
27913+			if (i < end-1 && isspace(selector[i+1])) {
27914 				continue;
27915 			} else {
27916-				if (!current.empty()) {
27917-					buffer.push_back(current);
27918-					buffer.push_back(" ");
27919-					current.clear();
27920+				if (current_index > 0) {
27921+					current[current_index++] = '\0';
27922+					strcpy(buffer.items[buffer_index++], current);
27923+					buffer.items[buffer_index][0] = ' ';
27924+					buffer.items[buffer_index][1] = '\0';
27925+					buffer_index++;
27926+					current_index = 0;
27927 				}
27928 			}
27929 		} else {
27930 			if (s == ',') {
27931-				if (!current.empty()) {
27932-					buffer.push_back(current);
27933-					current.clear();
27934+				if (current_index > 0) {
27935+					current[current_index++] = '\0';
27936+					strcpy(buffer.items[buffer_index++], current);
27937+					current_index = 0;
27938 				}
27939-				parts.push_back(buffer);
27940-				buffer.clear();
27941+				buffer.size = buffer_index;
27942+				parts.items[parts_index++] = buffer;
27943+				buffer_index = 0;
27944 			} else if (s == '~' || s == '+' || s == '|' || s == '>') {
27945-				if (!current.empty()) {
27946-					buffer.push_back(current);
27947-					current.clear();
27948+				if (current_index > 0) {
27949+					current[current_index++] = '\0';
27950+					strcpy(buffer.items[buffer_index++], current);
27951+					current_index = 0;
27952 				}
27953 				// A few lines above we add a empty space when the next char is not a space
27954 				// and the current is not empty. This is to create the decendant combinator
27955-				// but if one of the symbols in the statement are folling then we need to replace
27956+				// but if one of the symbols in the statement are following then we need to replace
27957 				// the empty space with the correct combinator
27958-				if (buffer.size() == 0) {
27959-					buffer.push_back("");
27960-				}
27961-				buffer.back() = s;
27962+			
27963+				// Look back at the previous item in the buffer
27964+				if (buffer_index > 0 && isspace(buffer.items[buffer_index - 1][0])) {
27965+					// Overwrite the existing space with the combinator
27966+					buffer.items[buffer_index - 1][0] = s;
27967+					buffer.items[buffer_index - 1][1] = '\0'; 
27968+				} else {
27969+					// No space preceded this, just add the combinator as a new part
27970+					buffer.items[buffer_index][0] = s;
27971+					buffer.items[buffer_index][1] = '\0';
27972+					buffer_index++;
27973+				} 
27974 			} else if (s == ':' || s == '#' || s == '.') {
27975 				if (i < end-1 && selector[i+1] == ':') continue; 
27976-				if (!current.empty()) {
27977-					buffer.push_back(current);
27978+				if (current_index > 0) {
27979+					current[current_index++] = '\0';
27980+					strcpy(buffer.items[buffer_index++], current);
27981 				}
27982-				current = s;
27983+				current[0] = s;
27984+				current_index = 1;
27985 
27986 			} else {
27987-				current.push_back(s);
27988+				current[current_index++] = s;
27989 			}
27990 		}
27991 
27992 		
27993 	}
27994 
27995-	if (!current.empty()) {
27996-		buffer.push_back(current);
27997+	if (current_index > 0) {
27998+		current[current_index++] = '\0';
27999+		strcpy(buffer.items[buffer_index++], current);
28000 	}
28001 
28002-	if (!buffer.empty()) {
28003-		parts.push_back(buffer);
28004+	if (buffer_index > 0) {
28005+		buffer.size = buffer_index;
28006+		parts.items[parts_index++] = buffer;
28007 	}
28008 
28009+	parts.size = parts_index;
28010+
28011 	return parts;
28012 }
28013 
28014+/*
28015 
28016 // +---------------------------------------------------+
28017 // | (luoiy) Node Selector Parsing                     |
28018@@ -735,77 +255,6 @@ std::vector<std::string> parseNodeParts(Node* node) {
28019 	return parts;
28020 }
28021 
28022-
28023-void Style::addChild(Style s) {	
28024-	size_t index = children.size();
28025-
28026-	children.push_back(s);
28027-
28028-	// Get the last selector group from the parsed selector parts
28029-	// because that is the selector that applies to an element
28030-	// and map them into basemap
28031-	if (s.selector.size() > 0) {
28032-		std::vector<std::string> targetParts = s.selector[s.selector.size()-1];
28033-		for (auto p : targetParts) {
28034-			if (basemap.find(p) != basemap.end()) {
28035-				basemap[p].push_back(index);
28036-			} else {
28037-				std::vector<size_t> bm = {index};
28038-				basemap[p] = bm;
28039-			}
28040-		}
28041-	}
28042-}
28043-
28044-
28045-std::unordered_map<KeyType, UnitType> Style::getStyles(Node* node) {
28046-	std::vector<std::string> node_parts = parseNodeParts(node);
28047-	/*
28048-	std::vector<size_t> canidates;
28049-
28050-	// Now we have to start from the window.CSS.root, use the basemap to find styles
28051-	// | test each selector, if a selector matches, go into its children and repeat
28052-
28053-	for (std::string p : node_parts) { 
28054-		if (auto sty = sheet->basemap.find(p); sty != sheet->basemap.end()) {
28055-			for (auto s : sty->second) {
28056-				bool found = false;
28057-				// This makes sure we aren't adding the same styles to the candidates list
28058-				for (auto c : canidates) {
28059-					if (c == s) {
28060-						found = true;
28061-						break;
28062-					}
28063-				}
28064-				if (!found) {
28065-					canidates.push_back(s);
28066-				}
28067-			}
28068-		}
28069-	}
28070-
28071-	// Now we have the list of candidates next we will refined our selection
28072-	// we need to pull the selectors from each candidate then run testSelector on it
28073-
28074-	for (size_t c : canidates) {
28075-		// need to check the type of sheet it is
28076-		std::vector<std::vector<std::string>> selector = sheet->children[c].selector;
28077-
28078-		// Run testSelector with the preparsed parts
28079-		if (testSelector(node, selector)) {
28080-			std::unordered_map<std::string, std::string> props = sheet->children[c].properties;
28081-			for (auto p : props) {
28082-				styles->insert(p);
28083-			}
28084-
28085-			// If the Sheet matches then we will repeat the same process with that sheet
28086-			if (sheet->children[c].children.size() > 0) {
28087-				getstyles(node, node_parts, &sheet->children[c], styles);
28088-			}
28089-		}
28090-	}*/
28091-}
28092-
28093 // +------------------------------------------------------+
28094 // |(7tygl) Query matching 				  |
28095 // +------------------------------------------------------+
28096@@ -816,7 +265,7 @@ bool testQuery(Node* node, std::vector<std::vector<std::string>> parts) {
28097 	// Takes a fully parsed selector. If it is a at-rule even multiple,
28098 	// the at-rule tag must but the first.
28099 
28100-/*
28101+
28102 Just a ref
28103 bool result = false;
28104 for (auto& condition : conditions) {
28105@@ -825,7 +274,7 @@ for (auto& condition : conditions) {
28106 
28107 
28108 also not can only be at the start
28109-*/
28110+
28111 	
28112 	Window* w = node->window;
28113 
28114@@ -847,11 +296,11 @@ also not can only be at the start
28115 	return true;	
28116 }
28117 
28118-/*
28119+
28120 	at-rules consist of "query's" the are tre or false given the stat of the window.
28121 	executeQuery runs the non-logic (and, or etc..) and returns the value of the 
28122 	executed query.
28123-*/
28124+
28125 
28126 std::unordered_map<std::string, Media> MediaLookup {
28127 	{"all", Media::All},
28128@@ -872,7 +321,7 @@ std::unordered_map<std::string, Media> MediaLookup {
28129 	{"fast", Media::Fast},
28130 	{"slow", Media::Slow},
28131 };
28132-/*
28133+
28134 // Media queries like @media (hover: hover) are written like @media (hover)
28135 bool executeQuery(Window* w, std::string p) {
28136 	Context c;
28137@@ -900,7 +349,7 @@ bool executeQuery(Window* w, std::string p) {
28138 	}
28139 	return matches;
28140 }
28141-*/
28142+
28143 
28144 Range getNextUnit(const std::vector<Unit>& units, size_t& offset, size_t end) {
28145     if (offset >= end) return {0, 0}; // Done
28146@@ -2319,4 +1768,4 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
28147 
28148 	return matched;
28149 }
28150-
28151+*/