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 template<typename ObjectT> 38 struct MatcherMethod { 39 virtual bool match( ObjectT const& arg ) const = 0; 40 }; 41 template<typename PtrT> 42 struct MatcherMethod<PtrT*> { 43 virtual bool match( PtrT* arg ) const = 0; 44 }; 45 46 template<typename T> 47 struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { 48 49 50 MatchAllOf<T> operator && ( MatcherBase const& other ) const; 51 MatchAnyOf<T> operator || ( MatcherBase const& other ) const; 52 MatchNotOf<T> operator ! () const; 53 }; 54 55 template<typename ArgT> 56 struct MatchAllOf : MatcherBase<ArgT> { 57 bool match( ArgT const& arg ) const override { 58 for( auto matcher : m_matchers ) { 59 if (!matcher->match(arg)) 60 return false; 61 } 62 return true; 63 } 64 std::string describe() const override { 65 std::string description; 66 description.reserve( 4 + m_matchers.size()*32 ); 67 description += "( "; 68 bool first = true; 69 for( auto matcher : m_matchers ) { 70 if( first ) 71 first = false; 72 else 73 description += " and "; 74 description += matcher->toString(); 75 } 76 description += " )"; 77 return description; 78 } 79 80 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) { 81 m_matchers.push_back( &other ); 82 return *this; 83 } 84 85 std::vector<MatcherBase<ArgT> const*> m_matchers; 86 }; 87 template<typename ArgT> 88 struct MatchAnyOf : MatcherBase<ArgT> { 89 90 bool match( ArgT const& arg ) const override { 91 for( auto matcher : m_matchers ) { 92 if (matcher->match(arg)) 93 return true; 94 } 95 return false; 96 } 97 std::string describe() const override { 98 std::string description; 99 description.reserve( 4 + m_matchers.size()*32 ); 100 description += "( "; 101 bool first = true; 102 for( auto matcher : m_matchers ) { 103 if( first ) 104 first = false; 105 else 106 description += " or "; 107 description += matcher->toString(); 108 } 109 description += " )"; 110 return description; 111 } 112 113 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) { 114 m_matchers.push_back( &other ); 115 return *this; 116 } 117 118 std::vector<MatcherBase<ArgT> const*> m_matchers; 119 }; 120 121 template<typename ArgT> 122 struct MatchNotOf : MatcherBase<ArgT> { 123 124 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} 125 126 bool match( ArgT const& arg ) const override { 127 return !m_underlyingMatcher.match( arg ); 128 } 129 130 std::string describe() const override { 131 return "not " + m_underlyingMatcher.toString(); 132 } 133 MatcherBase<ArgT> const& m_underlyingMatcher; 134 }; 135 136 template<typename T> 137 MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const { 138 return MatchAllOf<T>() && *this && other; 139 } 140 template<typename T> 141 MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const { 142 return MatchAnyOf<T>() || *this || other; 143 } 144 template<typename T> 145 MatchNotOf<T> MatcherBase<T>::operator ! () const { 146 return MatchNotOf<T>( *this ); 147 } 148 149 } // namespace Impl 150 151 } // namespace Matchers 152 153 using namespace Matchers; 154 using Matchers::Impl::MatcherBase; 155 156 } // namespace Catch 157 158 #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED 159