catch2/include/internal/catch_matchers.hpp

186 lines
6.6 KiB
C++
Raw Normal View History

2012-05-09 20:37:14 +02:00
/*
* Created by Phil Nash on 04/03/2012.
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
2012-03-04 21:10:36 +01:00
#ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
#include "catch_common.h"
#include <vector>
2012-05-15 08:42:26 +02:00
namespace Catch {
namespace Matchers {
namespace Impl {
template<typename ArgT> struct MatchAllOf;
template<typename ArgT> struct MatchAnyOf;
template<typename ArgT> struct MatchNotOf;
2012-10-12 08:58:17 +02:00
class MatcherUntypedBase {
public:
std::string toString() const {
if( m_cachedToString.empty() )
2017-02-14 10:04:26 +01:00
m_cachedToString = describe();
return m_cachedToString;
2015-08-12 11:05:16 +02:00
}
protected:
2017-03-06 10:23:31 +01:00
virtual ~MatcherUntypedBase();
2017-02-14 10:04:26 +01:00
virtual std::string describe() const = 0;
mutable std::string m_cachedToString;
2017-02-22 09:26:52 +01:00
private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
2015-08-12 11:05:16 +02:00
};
2012-10-12 08:58:17 +02:00
2017-03-13 16:40:21 +01:00
template<typename ObjectT>
struct MatcherMethod {
virtual bool match( ObjectT const& arg ) const = 0;
};
template<typename PtrT>
struct MatcherMethod<PtrT*> {
virtual bool match( PtrT* arg ) const = 0;
};
template<typename ObjectT, typename ComparatorT = ObjectT>
2017-03-13 16:40:21 +01:00
struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
2012-10-12 08:58:17 +02:00
MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
MatchNotOf<ComparatorT> operator ! () const;
};
template<typename ArgT>
struct MatchAllOf : MatcherBase<ArgT> {
virtual bool match( ArgT const& arg ) const override {
for( auto matcher : m_matchers ) {
if (!matcher->match(arg))
2012-10-12 08:58:17 +02:00
return false;
}
2012-10-12 08:58:17 +02:00
return true;
}
virtual std::string describe() const override {
std::string description;
description.reserve( 4 + m_matchers.size()*32 );
description += "( ";
bool first = true;
for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += " and ";
description += matcher->toString();
2012-10-12 08:58:17 +02:00
}
description += " )";
return description;
2012-10-12 08:58:17 +02:00
}
MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
m_matchers.push_back( &other );
return *this;
}
std::vector<MatcherBase<ArgT> const*> m_matchers;
2012-10-12 08:58:17 +02:00
};
template<typename ArgT>
struct MatchAnyOf : MatcherBase<ArgT> {
virtual bool match( ArgT const& arg ) const override {
for( auto matcher : m_matchers ) {
if (matcher->match(arg))
2012-10-12 08:58:17 +02:00
return true;
}
2012-10-12 08:58:17 +02:00
return false;
}
virtual std::string describe() const override {
std::string description;
description.reserve( 4 + m_matchers.size()*32 );
description += "( ";
bool first = true;
for( auto matcher : m_matchers ) {
if( first )
first = false;
else
description += " or ";
description += matcher->toString();
2012-10-12 08:58:17 +02:00
}
description += " )";
return description;
2012-05-24 09:27:50 +02:00
}
2012-10-12 08:58:17 +02:00
MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
m_matchers.push_back( &other );
return *this;
2012-10-12 08:58:17 +02:00
}
std::vector<MatcherBase<ArgT> const*> m_matchers;
2012-05-24 09:27:50 +02:00
};
template<typename ArgT>
struct MatchNotOf : MatcherBase<ArgT> {
2012-10-12 08:58:17 +02:00
MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
2012-10-12 08:58:17 +02:00
virtual bool match( ArgT const& arg ) const override {
return !m_underlyingMatcher.match( arg );
2012-03-04 21:10:36 +01:00
}
2012-10-12 08:58:17 +02:00
virtual std::string describe() const override {
return "not " + m_underlyingMatcher.toString();
2012-03-04 21:10:36 +01:00
}
MatcherBase<ArgT> const& m_underlyingMatcher;
2012-03-04 21:10:36 +01:00
};
template<typename ObjectT, typename ComparatorT>
MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
return MatchAllOf<ComparatorT>() && *this && other;
}
template<typename ObjectT, typename ComparatorT>
MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
return MatchAnyOf<ComparatorT>() || *this || other;
}
template<typename ObjectT, typename ComparatorT>
MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
return MatchNotOf<ComparatorT>( *this );
}
2012-10-12 08:58:17 +02:00
2012-03-04 21:10:36 +01:00
} // namespace Impl
2012-10-12 08:58:17 +02:00
2012-10-12 08:58:17 +02:00
// The following functions create the actual matcher objects.
// This allows the types to be inferred
// - deprecated: prefer ||, && and !
template<typename T>
Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
return Impl::MatchNotOf<T>( underlyingMatcher );
}
template<typename T>
Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
return Impl::MatchAllOf<T>() && m1 && m2;
}
template<typename T>
Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
return Impl::MatchAllOf<T>() && m1 && m2 && m3;
}
template<typename T>
Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
return Impl::MatchAnyOf<T>() || m1 || m2;
}
template<typename T>
Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
}
2012-03-04 21:10:36 +01:00
} // namespace Matchers
2012-03-04 21:10:36 +01:00
using namespace Matchers;
2017-02-14 10:15:08 +01:00
using Matchers::Impl::MatcherBase;
2012-03-04 21:10:36 +01:00
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED