• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Created by Phil Nash on 04/03/2012.
3  *  Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
4  *
5  * Distributed under the Boost Software License, Version 1.0. (See accompanying
6  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 #ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
9 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
10 
11 #include "catch_common.h"
12 
13 #include <string>
14 #include <vector>
15 
16 namespace Catch {
17 namespace Matchers {
18     namespace Impl {
19 
20         template<typename ArgT> struct MatchAllOf;
21         template<typename ArgT> struct MatchAnyOf;
22         template<typename ArgT> struct MatchNotOf;
23 
24         class MatcherUntypedBase {
25         public:
26             MatcherUntypedBase() = default;
27             MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
28             MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
29             std::string toString() const;
30 
31         protected:
32             virtual ~MatcherUntypedBase();
33             virtual std::string describe() const = 0;
34             mutable std::string m_cachedToString;
35         };
36 
37 #ifdef __clang__
38 #    pragma clang diagnostic push
39 #    pragma clang diagnostic ignored "-Wnon-virtual-dtor"
40 #endif
41 
42         template<typename ObjectT>
43         struct MatcherMethod {
44             virtual bool match( ObjectT const& arg ) const = 0;
45         };
46 
47 #ifdef __clang__
48 #    pragma clang diagnostic pop
49 #endif
50 
51         template<typename T>
52         struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
53 
54 
55             MatchAllOf<T> operator && ( MatcherBase const& other ) const;
56             MatchAnyOf<T> operator || ( MatcherBase const& other ) const;
57             MatchNotOf<T> operator ! () const;
58         };
59 
60         template<typename ArgT>
61         struct MatchAllOf : MatcherBase<ArgT> {
matchMatchAllOf62             bool match( ArgT const& arg ) const override {
63                 for( auto matcher : m_matchers ) {
64                     if (!matcher->match(arg))
65                         return false;
66                 }
67                 return true;
68             }
describeMatchAllOf69             std::string describe() const override {
70                 std::string description;
71                 description.reserve( 4 + m_matchers.size()*32 );
72                 description += "( ";
73                 bool first = true;
74                 for( auto matcher : m_matchers ) {
75                     if( first )
76                         first = false;
77                     else
78                         description += " and ";
79                     description += matcher->toString();
80                 }
81                 description += " )";
82                 return description;
83             }
84 
85             MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
86                 m_matchers.push_back( &other );
87                 return *this;
88             }
89 
90             std::vector<MatcherBase<ArgT> const*> m_matchers;
91         };
92         template<typename ArgT>
93         struct MatchAnyOf : MatcherBase<ArgT> {
94 
matchMatchAnyOf95             bool match( ArgT const& arg ) const override {
96                 for( auto matcher : m_matchers ) {
97                     if (matcher->match(arg))
98                         return true;
99                 }
100                 return false;
101             }
describeMatchAnyOf102             std::string describe() const override {
103                 std::string description;
104                 description.reserve( 4 + m_matchers.size()*32 );
105                 description += "( ";
106                 bool first = true;
107                 for( auto matcher : m_matchers ) {
108                     if( first )
109                         first = false;
110                     else
111                         description += " or ";
112                     description += matcher->toString();
113                 }
114                 description += " )";
115                 return description;
116             }
117 
118             MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
119                 m_matchers.push_back( &other );
120                 return *this;
121             }
122 
123             std::vector<MatcherBase<ArgT> const*> m_matchers;
124         };
125 
126         template<typename ArgT>
127         struct MatchNotOf : MatcherBase<ArgT> {
128 
MatchNotOfMatchNotOf129             MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
130 
matchMatchNotOf131             bool match( ArgT const& arg ) const override {
132                 return !m_underlyingMatcher.match( arg );
133             }
134 
describeMatchNotOf135             std::string describe() const override {
136                 return "not " + m_underlyingMatcher.toString();
137             }
138             MatcherBase<ArgT> const& m_underlyingMatcher;
139         };
140 
141         template<typename T>
142         MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const {
143             return MatchAllOf<T>() && *this && other;
144         }
145         template<typename T>
146         MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const {
147             return MatchAnyOf<T>() || *this || other;
148         }
149         template<typename T>
150         MatchNotOf<T> MatcherBase<T>::operator ! () const {
151             return MatchNotOf<T>( *this );
152         }
153 
154     } // namespace Impl
155 
156 } // namespace Matchers
157 
158 using namespace Matchers;
159 using Matchers::Impl::MatcherBase;
160 
161 } // namespace Catch
162 
163 #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
164