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
|
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
#include "catch_common.h"
|
|
|
|
|
2017-08-01 18:46:33 +02:00
|
|
|
#include <string>
|
2017-07-06 22:28:42 +02:00
|
|
|
#include <vector>
|
|
|
|
|
2012-05-15 08:42:26 +02:00
|
|
|
namespace Catch {
|
|
|
|
namespace Matchers {
|
|
|
|
namespace Impl {
|
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
template<typename ArgT> struct MatchAllOf;
|
|
|
|
template<typename ArgT> struct MatchAnyOf;
|
|
|
|
template<typename ArgT> struct MatchNotOf;
|
2012-10-12 08:58:17 +02:00
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
class MatcherUntypedBase {
|
2015-11-06 19:05:35 +01:00
|
|
|
public:
|
2017-07-20 00:27:28 +02:00
|
|
|
MatcherUntypedBase() = default;
|
|
|
|
MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
|
|
|
|
MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
|
|
|
|
std::string toString() const;
|
2015-08-12 11:05:16 +02:00
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
protected:
|
2017-07-20 00:27:28 +02:00
|
|
|
virtual ~MatcherUntypedBase() = default;
|
2017-02-14 10:04:26 +01:00
|
|
|
virtual std::string describe() const = 0;
|
2017-02-08 15:17:17 +01:00
|
|
|
mutable std::string m_cachedToString;
|
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;
|
|
|
|
};
|
|
|
|
|
2017-02-21 16:52:03 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
2017-02-21 16:52:03 +01:00
|
|
|
MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
|
|
|
|
MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
|
|
|
|
MatchNotOf<ComparatorT> operator ! () const;
|
2017-02-08 15:17:17 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename ArgT>
|
|
|
|
struct MatchAllOf : MatcherBase<ArgT> {
|
2017-07-20 16:57:17 +02:00
|
|
|
bool match( ArgT const& arg ) const override {
|
2017-04-25 12:06:52 +02:00
|
|
|
for( auto matcher : m_matchers ) {
|
|
|
|
if (!matcher->match(arg))
|
2012-10-12 08:58:17 +02:00
|
|
|
return false;
|
2017-02-08 15:17:17 +01:00
|
|
|
}
|
2012-10-12 08:58:17 +02:00
|
|
|
return true;
|
|
|
|
}
|
2017-07-20 16:57:17 +02:00
|
|
|
std::string describe() const override {
|
2017-02-08 15:17:17 +01:00
|
|
|
std::string description;
|
|
|
|
description.reserve( 4 + m_matchers.size()*32 );
|
|
|
|
description += "( ";
|
2017-04-25 12:06:52 +02:00
|
|
|
bool first = true;
|
|
|
|
for( auto matcher : m_matchers ) {
|
|
|
|
if( first )
|
|
|
|
first = false;
|
|
|
|
else
|
2017-02-08 15:17:17 +01:00
|
|
|
description += " and ";
|
2017-04-25 12:06:52 +02:00
|
|
|
description += matcher->toString();
|
2012-10-12 08:58:17 +02:00
|
|
|
}
|
2017-02-08 15:17:17 +01:00
|
|
|
description += " )";
|
|
|
|
return description;
|
2012-10-12 08:58:17 +02:00
|
|
|
}
|
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
|
|
|
|
m_matchers.push_back( &other );
|
|
|
|
return *this;
|
2015-11-05 19:46:00 +01:00
|
|
|
}
|
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
2012-10-12 08:58:17 +02:00
|
|
|
};
|
2017-02-08 15:17:17 +01:00
|
|
|
template<typename ArgT>
|
|
|
|
struct MatchAnyOf : MatcherBase<ArgT> {
|
2013-07-03 20:14:59 +02:00
|
|
|
|
2017-07-20 16:57:17 +02:00
|
|
|
bool match( ArgT const& arg ) const override {
|
2017-04-25 12:06:52 +02:00
|
|
|
for( auto matcher : m_matchers ) {
|
|
|
|
if (matcher->match(arg))
|
2012-10-12 08:58:17 +02:00
|
|
|
return true;
|
2017-02-08 15:17:17 +01:00
|
|
|
}
|
2012-10-12 08:58:17 +02:00
|
|
|
return false;
|
|
|
|
}
|
2017-07-20 16:57:17 +02:00
|
|
|
std::string describe() const override {
|
2017-02-08 15:17:17 +01:00
|
|
|
std::string description;
|
|
|
|
description.reserve( 4 + m_matchers.size()*32 );
|
|
|
|
description += "( ";
|
2017-04-25 12:06:52 +02:00
|
|
|
bool first = true;
|
|
|
|
for( auto matcher : m_matchers ) {
|
|
|
|
if( first )
|
|
|
|
first = false;
|
|
|
|
else
|
2017-02-08 15:17:17 +01:00
|
|
|
description += " or ";
|
2017-04-25 12:06:52 +02:00
|
|
|
description += matcher->toString();
|
2012-10-12 08:58:17 +02:00
|
|
|
}
|
2017-02-08 15:17:17 +01:00
|
|
|
description += " )";
|
|
|
|
return description;
|
2012-05-24 09:27:50 +02:00
|
|
|
}
|
2012-10-12 08:58:17 +02:00
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
|
|
|
|
m_matchers.push_back( &other );
|
|
|
|
return *this;
|
2012-10-12 08:58:17 +02:00
|
|
|
}
|
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
std::vector<MatcherBase<ArgT> const*> m_matchers;
|
2012-05-24 09:27:50 +02:00
|
|
|
};
|
2013-07-03 20:14:59 +02:00
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
template<typename ArgT>
|
|
|
|
struct MatchNotOf : MatcherBase<ArgT> {
|
2012-10-12 08:58:17 +02:00
|
|
|
|
2017-02-08 15:17:17 +01:00
|
|
|
MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
|
2012-10-12 08:58:17 +02:00
|
|
|
|
2017-07-20 16:57:17 +02:00
|
|
|
bool match( ArgT const& arg ) const override {
|
2017-02-08 15:17:17 +01:00
|
|
|
return !m_underlyingMatcher.match( arg );
|
2012-03-04 21:10:36 +01:00
|
|
|
}
|
2012-10-12 08:58:17 +02:00
|
|
|
|
2017-07-20 16:57:17 +02:00
|
|
|
std::string describe() const override {
|
2017-02-08 15:17:17 +01:00
|
|
|
return "not " + m_underlyingMatcher.toString();
|
2012-03-04 21:10:36 +01:00
|
|
|
}
|
2017-02-08 15:17:17 +01:00
|
|
|
MatcherBase<ArgT> const& m_underlyingMatcher;
|
2012-03-04 21:10:36 +01:00
|
|
|
};
|
2013-07-03 20:14:59 +02:00
|
|
|
|
2017-02-21 16:52:03 +01:00
|
|
|
template<typename ObjectT, typename ComparatorT>
|
|
|
|
MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
|
|
|
|
return MatchAllOf<ComparatorT>() && *this && other;
|
2017-02-08 15:17:17 +01:00
|
|
|
}
|
2017-02-21 16:52:03 +01:00
|
|
|
template<typename ObjectT, typename ComparatorT>
|
|
|
|
MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
|
|
|
|
return MatchAnyOf<ComparatorT>() || *this || other;
|
2017-02-08 15:17:17 +01:00
|
|
|
}
|
2017-02-21 16:52:03 +01:00
|
|
|
template<typename ObjectT, typename ComparatorT>
|
|
|
|
MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
|
|
|
|
return MatchNotOf<ComparatorT>( *this );
|
2017-02-08 15:17:17 +01:00
|
|
|
}
|
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-03-04 21:10:36 +01:00
|
|
|
} // namespace Matchers
|
2013-07-03 20:14:59 +02:00
|
|
|
|
2012-03-04 21:10:36 +01:00
|
|
|
using namespace Matchers;
|
2017-02-14 10:15:08 +01:00
|
|
|
using Matchers::Impl::MatcherBase;
|
2013-07-03 20:14:59 +02:00
|
|
|
|
2012-03-04 21:10:36 +01:00
|
|
|
} // namespace Catch
|
|
|
|
|
|
|
|
#endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
|