/* * 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) */ #ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED namespace Catch { namespace Matchers { namespace Impl { template struct Matcher : SharedImpl { virtual ~Matcher() {} virtual Ptr clone() const = 0; virtual bool match( const ExpressionT& expr ) const = 0; virtual std::string toString() const = 0; }; template struct MatcherImpl : Matcher { virtual Ptr > clone() const { return Ptr >( new DerivedT( static_cast( *this ) ) ); } }; namespace Generic { template class AllOf : public MatcherImpl, ExpressionT> { public: AllOf() {} AllOf( const AllOf& other ) : m_matchers( other.m_matchers ) {} AllOf& add( const Matcher& matcher ) { m_matchers.push_back( matcher.clone() ); return *this; } virtual bool match( const ExpressionT& expr ) const { for( std::size_t i = 0; i < m_matchers.size(); ++i ) if( !m_matchers[i]->match( expr ) ) return false; return true; } virtual std::string toString() const { std::ostringstream oss; oss << "( "; for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if( i != 0 ) oss << " and "; oss << m_matchers[i]->toString(); } oss << " )"; return oss.str(); } private: std::vector > > m_matchers; }; template class AnyOf : public MatcherImpl, ExpressionT> { public: AnyOf() {} AnyOf( const AnyOf& other ) : m_matchers( other.m_matchers ) {} AnyOf& add( const Matcher& matcher ) { m_matchers.push_back( matcher.clone() ); return *this; } virtual bool match( const ExpressionT& expr ) const { for( std::size_t i = 0; i < m_matchers.size(); ++i ) if( m_matchers[i]->match( expr ) ) return true; return false; } virtual std::string toString() const { std::ostringstream oss; oss << "( "; for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if( i != 0 ) oss << " or "; oss << m_matchers[i]->toString(); } oss << " )"; return oss.str(); } private: std::vector > > m_matchers; }; } namespace StdString { struct Equals : MatcherImpl { Equals( const std::string& str ) : m_str( str ){} Equals( const Equals& other ) : m_str( other.m_str ){} virtual ~Equals(); virtual bool match( const std::string& expr ) const { return m_str == expr; } virtual std::string toString() const { return "equals: \"" + m_str + "\""; } std::string m_str; }; struct Contains : MatcherImpl { Contains( const std::string& substr ) : m_substr( substr ){} Contains( const Contains& other ) : m_substr( other.m_substr ){} virtual ~Contains(); virtual bool match( const std::string& expr ) const { return expr.find( m_substr ) != std::string::npos; } virtual std::string toString() const { return "contains: \"" + m_substr + "\""; } std::string m_substr; }; struct StartsWith : MatcherImpl { StartsWith( const std::string& substr ) : m_substr( substr ){} StartsWith( const StartsWith& other ) : m_substr( other.m_substr ){} virtual ~StartsWith(); virtual bool match( const std::string& expr ) const { return expr.find( m_substr ) == 0; } virtual std::string toString() const { return "starts with: \"" + m_substr + "\""; } std::string m_substr; }; struct EndsWith : MatcherImpl { EndsWith( const std::string& substr ) : m_substr( substr ){} EndsWith( const EndsWith& other ) : m_substr( other.m_substr ){} virtual ~EndsWith(); virtual bool match( const std::string& expr ) const { return expr.find( m_substr ) == expr.size() - m_substr.size(); } virtual std::string toString() const { return "ends with: \"" + m_substr + "\""; } std::string m_substr; }; } // namespace StdString } // namespace Impl // The following functions create the actual matcher objects. // This allows the types to be inferred template inline Impl::Generic::AllOf AllOf( const Impl::Matcher& m1, const Impl::Matcher& m2 ) { return Impl::Generic::AllOf().add( m1 ).add( m2 ); } template inline Impl::Generic::AllOf AllOf( const Impl::Matcher& m1, const Impl::Matcher& m2, const Impl::Matcher& m3 ) { return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); } template inline Impl::Generic::AnyOf AnyOf( const Impl::Matcher& m1, const Impl::Matcher& m2 ) { return Impl::Generic::AnyOf().add( m1 ).add( m2 ); } template inline Impl::Generic::AnyOf AnyOf( const Impl::Matcher& m1, const Impl::Matcher& m2, const Impl::Matcher& m3 ) { return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); } inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); } inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); } inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); } inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); } } // namespace Matchers using namespace Matchers; } // namespace Catch #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED