1 /* 2 * Created by Phil on 11/5/2012. 3 * Copyright 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_EXPRESSION_LHS_HPP_INCLUDED 9 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED 10 11 #include "catch_result_builder.h" 12 #include "catch_evaluate.hpp" 13 #include "catch_tostring.h" 14 15 namespace Catch { 16 17 template<typename LhsT, Internal::Operator Op, typename RhsT> 18 class BinaryExpression; 19 20 template<typename ArgT, typename MatcherT> 21 class MatchExpression; 22 23 // Wraps the LHS of an expression and overloads comparison operators 24 // for also capturing those and RHS (if any) 25 template<typename T> 26 class ExpressionLhs : public DecomposedExpression { 27 public: ExpressionLhs(ResultBuilder & rb,T lhs)28 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} 29 30 ExpressionLhs& operator = ( const ExpressionLhs& ); 31 32 template<typename RhsT> 33 BinaryExpression<T, Internal::IsEqualTo, RhsT const&> operator ==(RhsT const & rhs)34 operator == ( RhsT const& rhs ) { 35 return captureExpression<Internal::IsEqualTo>( rhs ); 36 } 37 38 template<typename RhsT> 39 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&> operator !=(RhsT const & rhs)40 operator != ( RhsT const& rhs ) { 41 return captureExpression<Internal::IsNotEqualTo>( rhs ); 42 } 43 44 template<typename RhsT> 45 BinaryExpression<T, Internal::IsLessThan, RhsT const&> operator <(RhsT const & rhs)46 operator < ( RhsT const& rhs ) { 47 return captureExpression<Internal::IsLessThan>( rhs ); 48 } 49 50 template<typename RhsT> 51 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&> operator >(RhsT const & rhs)52 operator > ( RhsT const& rhs ) { 53 return captureExpression<Internal::IsGreaterThan>( rhs ); 54 } 55 56 template<typename RhsT> 57 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&> operator <=(RhsT const & rhs)58 operator <= ( RhsT const& rhs ) { 59 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); 60 } 61 62 template<typename RhsT> 63 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&> operator >=(RhsT const & rhs)64 operator >= ( RhsT const& rhs ) { 65 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); 66 } 67 operator ==(bool rhs)68 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) { 69 return captureExpression<Internal::IsEqualTo>( rhs ); 70 } 71 operator !=(bool rhs)72 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) { 73 return captureExpression<Internal::IsNotEqualTo>( rhs ); 74 } 75 endExpression()76 void endExpression() { 77 m_truthy = m_lhs ? true : false; 78 m_rb 79 .setResultType( m_truthy ) 80 .endExpression( *this ); 81 } 82 reconstructExpression(std::string & dest) const83 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { 84 dest = Catch::toString( m_lhs ); 85 } 86 87 private: 88 template<Internal::Operator Op, typename RhsT> captureExpression(RhsT & rhs) const89 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const { 90 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs ); 91 } 92 93 template<Internal::Operator Op> captureExpression(bool rhs) const94 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const { 95 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs ); 96 } 97 98 private: 99 ResultBuilder& m_rb; 100 T m_lhs; 101 bool m_truthy; 102 }; 103 104 template<typename LhsT, Internal::Operator Op, typename RhsT> 105 class BinaryExpression : public DecomposedExpression { 106 public: BinaryExpression(ResultBuilder & rb,LhsT lhs,RhsT rhs)107 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) 108 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} 109 110 BinaryExpression& operator = ( BinaryExpression& ); 111 endExpression() const112 void endExpression() const { 113 m_rb 114 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) ) 115 .endExpression( *this ); 116 } 117 isBinaryExpression() const118 virtual bool isBinaryExpression() const CATCH_OVERRIDE { 119 return true; 120 } 121 reconstructExpression(std::string & dest) const122 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { 123 std::string lhs = Catch::toString( m_lhs ); 124 std::string rhs = Catch::toString( m_rhs ); 125 char delim = lhs.size() + rhs.size() < 40 && 126 lhs.find('\n') == std::string::npos && 127 rhs.find('\n') == std::string::npos ? ' ' : '\n'; 128 dest.reserve( 7 + lhs.size() + rhs.size() ); 129 // 2 for spaces around operator 130 // 2 for operator 131 // 2 for parentheses (conditionally added later) 132 // 1 for negation (conditionally added later) 133 dest = lhs; 134 dest += delim; 135 dest += Internal::OperatorTraits<Op>::getName(); 136 dest += delim; 137 dest += rhs; 138 } 139 140 private: 141 ResultBuilder& m_rb; 142 LhsT m_lhs; 143 RhsT m_rhs; 144 }; 145 146 template<typename ArgT, typename MatcherT> 147 class MatchExpression : public DecomposedExpression { 148 public: MatchExpression(ArgT arg,MatcherT matcher,char const * matcherString)149 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) 150 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} 151 isBinaryExpression() const152 virtual bool isBinaryExpression() const CATCH_OVERRIDE { 153 return true; 154 } 155 reconstructExpression(std::string & dest) const156 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { 157 std::string matcherAsString = m_matcher.toString(); 158 dest = Catch::toString( m_arg ); 159 dest += ' '; 160 if( matcherAsString == Detail::unprintableString ) 161 dest += m_matcherString; 162 else 163 dest += matcherAsString; 164 } 165 166 private: 167 ArgT m_arg; 168 MatcherT m_matcher; 169 char const* m_matcherString; 170 }; 171 172 } // end namespace Catch 173 174 #endif // TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED 175