1 /* 2 * Created by Phil Nash on 08/02/2017. 3 * Copyright (c) 2017 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 9 #include "catch_matchers_string.h" 10 #include "catch_string_manip.h" 11 #include "catch_tostring.h" 12 13 #include <regex> 14 15 namespace Catch { 16 namespace Matchers { 17 18 namespace StdString { 19 CasedString(std::string const & str,CaseSensitive::Choice caseSensitivity)20 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) 21 : m_caseSensitivity( caseSensitivity ), 22 m_str( adjustString( str ) ) 23 {} adjustString(std::string const & str) const24 std::string CasedString::adjustString( std::string const& str ) const { 25 return m_caseSensitivity == CaseSensitive::No 26 ? toLower( str ) 27 : str; 28 } caseSensitivitySuffix() const29 std::string CasedString::caseSensitivitySuffix() const { 30 return m_caseSensitivity == CaseSensitive::No 31 ? " (case insensitive)" 32 : std::string(); 33 } 34 35 StringMatcherBase(std::string const & operation,CasedString const & comparator)36 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) 37 : m_comparator( comparator ), 38 m_operation( operation ) { 39 } 40 describe() const41 std::string StringMatcherBase::describe() const { 42 std::string description; 43 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + 44 m_comparator.caseSensitivitySuffix().size()); 45 description += m_operation; 46 description += ": \""; 47 description += m_comparator.m_str; 48 description += "\""; 49 description += m_comparator.caseSensitivitySuffix(); 50 return description; 51 } 52 EqualsMatcher(CasedString const & comparator)53 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} 54 match(std::string const & source) const55 bool EqualsMatcher::match( std::string const& source ) const { 56 return m_comparator.adjustString( source ) == m_comparator.m_str; 57 } 58 59 ContainsMatcher(CasedString const & comparator)60 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} 61 match(std::string const & source) const62 bool ContainsMatcher::match( std::string const& source ) const { 63 return contains( m_comparator.adjustString( source ), m_comparator.m_str ); 64 } 65 66 StartsWithMatcher(CasedString const & comparator)67 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} 68 match(std::string const & source) const69 bool StartsWithMatcher::match( std::string const& source ) const { 70 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 71 } 72 73 EndsWithMatcher(CasedString const & comparator)74 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} 75 match(std::string const & source) const76 bool EndsWithMatcher::match( std::string const& source ) const { 77 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 78 } 79 80 81 RegexMatcher(std::string regex,CaseSensitive::Choice caseSensitivity)82 RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} 83 match(std::string const & matchee) const84 bool RegexMatcher::match(std::string const& matchee) const { 85 auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway 86 if (m_caseSensitivity == CaseSensitive::Choice::No) { 87 flags |= std::regex::icase; 88 } 89 auto reg = std::regex(m_regex, flags); 90 return std::regex_match(matchee, reg); 91 } 92 describe() const93 std::string RegexMatcher::describe() const { 94 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively"); 95 } 96 97 } // namespace StdString 98 99 Equals(std::string const & str,CaseSensitive::Choice caseSensitivity)100 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 101 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); 102 } Contains(std::string const & str,CaseSensitive::Choice caseSensitivity)103 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 104 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); 105 } EndsWith(std::string const & str,CaseSensitive::Choice caseSensitivity)106 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 107 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 108 } StartsWith(std::string const & str,CaseSensitive::Choice caseSensitivity)109 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 110 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 111 } 112 Matches(std::string const & regex,CaseSensitive::Choice caseSensitivity)113 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) { 114 return StdString::RegexMatcher(regex, caseSensitivity); 115 } 116 117 } // namespace Matchers 118 } // namespace Catch 119