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