Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src/Progmasoft/Catch3/Interfaces/IGeneratorTracker.hpp
blob: 8977e32f8848354c3cafeec6d0216fbf4fcfd680 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

//              Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
//   (See accompanying file LICENSE.txt or copy at
//        https://www.boost.org/LICENSE_1_0.txt)

// SPDX-License-Identifier: BSL-1.0
#pragma once

#include <Progmasoft/Catch3/Internal/UniquePtr.hpp>
#include <Progmasoft/Catch3/Internal/StringRef.hpp>

#include <string>

namespace Catch {

    namespace Generators {
        class GeneratorUntypedBase {
            // Caches result from `toStringImpl`, assume that when it is an
            // empty string, the cache is invalidated.
            mutable std::string m_stringReprCache;

            // Counts based on `next` returning true
            std::size_t m_currentElementIndex = 0;

            /**
             * Attempts to move the generator to the next element
             *
             * Returns true iff the move succeeded (and a valid element
             * can be retrieved).
             */
            virtual bool next() = 0;

            //! Customization point for `currentElementAsString`
            virtual std::string stringifyImpl() const = 0;

            /**
             * Customization point for skipping to the n-th element
             *
             * Defaults to successively calling `countedNext`. If there
             * are not enough elements to reach the nth one, will throw
             * an error.
             */
            virtual void skipToNthElementImpl( std::size_t n );

        public:
            GeneratorUntypedBase() = default;
            // Generation of copy ops is deprecated (and Clang will complain)
            // if there is a user destructor defined
            GeneratorUntypedBase(GeneratorUntypedBase const&) = default;
            GeneratorUntypedBase& operator=(GeneratorUntypedBase const&) = default;

            virtual ~GeneratorUntypedBase(); // = default;

            /**
             * Attempts to move the generator to the next element
             *
             * Serves as a non-virtual interface to `next`, so that the
             * top level interface can provide sanity checking and shared
             * features.
             *
             * As with `next`, returns true iff the move succeeded and
             * the generator has new valid element to provide.
             */
            bool countedNext();

            std::size_t currentElementIndex() const { return m_currentElementIndex; }

            /**
             * Moves the generator forward **to** the n-th element
             *
             * Cannot move backwards. Can stay in place.
             */
            void skipToNthElement( std::size_t n );

            /**
             * Returns generator's current element as user-friendly string.
             *
             * By default returns string equivalent to calling
             * `Catch::Detail::stringify` on the current element, but generators
             * can customize their implementation as needed.
             *
             * Not thread-safe due to internal caching.
             *
             * The returned ref is valid only until the generator instance
             * is destructed, or it moves onto the next element, whichever
             * comes first.
             */
            StringRef currentElementAsString() const;

            /**
             * Returns true if calls to `next` will eventually return false
             *
             * Note that for backwards compatibility this is currently defaulted
             * to return `true`, but in the future all generators will have to
             * provide their own implementation.
             */
            virtual bool isFinite() const;
        };
        using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;

    } // namespace Generators

    class IGeneratorTracker {
    public:
        virtual ~IGeneratorTracker(); // = default;
        virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
    };

} // namespace Catch