/* * Created by Phil Nash on 8/8/2017. * Copyright 2017 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_DECOMPOSER_H_INCLUDED #define TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED #include "catch_tostring.h" #include "catch_stringref.h" #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4389) // '==' : signed/unsigned mismatch #pragma warning(disable:4018) // more "signed/unsigned mismatch" #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) #endif namespace Catch { struct ITransientExpression { virtual auto isBinaryExpression() const -> bool = 0; virtual auto getResult() const -> bool = 0; virtual void streamReconstructedExpression( std::ostream &os ) const = 0; // We don't actually need a virtual destructore, but many static analysers // complain if it's not here :-( virtual ~ITransientExpression() = default; }; void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); template class BinaryExpr : public ITransientExpression { bool m_result; LhsT m_lhs; std::string m_op; RhsT m_rhs; auto isBinaryExpression() const -> bool override { return true; } auto getResult() const -> bool override { return m_result; } void streamReconstructedExpression( std::ostream &os ) const override { formatReconstructedExpression ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); } public: BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) : m_result( comparisionResult ), m_lhs( lhs ), m_op( op ), m_rhs( rhs ) {} }; template class UnaryExpr : public ITransientExpression { LhsT m_lhs; auto isBinaryExpression() const -> bool override { return false; } auto getResult() const -> bool override { return m_lhs ? true : false; } void streamReconstructedExpression( std::ostream &os ) const override { os << Catch::Detail::stringify( m_lhs ); } public: UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {} }; // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) == rhs; }; template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; template auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; template auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; template auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; template auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) != rhs; }; template auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; template auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; template auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; template auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; template class ExprLhs { LhsT m_lhs; public: ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} template auto operator == ( RhsT&& rhs ) -> BinaryExpr const { return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); } auto operator == ( bool rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs == rhs, m_lhs, "==", rhs ); } template auto operator != ( RhsT&& rhs ) -> BinaryExpr const { return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); } auto operator != ( bool rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs != rhs, m_lhs, "!=", rhs ); } template auto operator > ( RhsT&& rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); } template auto operator < ( RhsT&& rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); } template auto operator >= ( RhsT&& rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); } template auto operator <= ( RhsT&& rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); } auto makeUnaryExpr() const -> UnaryExpr { return UnaryExpr( m_lhs ); } }; void handleExpression( ITransientExpression const& expr ); template void handleExpression( ExprLhs const& expr ) { handleExpression( expr.makeUnaryExpr() ); } struct Decomposer { template auto operator <= ( T& lhs ) -> ExprLhs { return ExprLhs( lhs ); } template auto operator <= ( T const& lhs ) -> ExprLhs { return ExprLhs( lhs ); } auto operator <=( bool value ) -> ExprLhs { return ExprLhs( value ); } }; } // end namespace Catch #ifdef _MSC_VER #pragma warning(pop) #endif #endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED