2017-08-08 18:53:01 +02:00
|
|
|
/*
|
|
|
|
* 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 <ostream>
|
|
|
|
|
2017-08-09 10:29:44 +02:00
|
|
|
#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
|
|
|
|
|
2017-08-08 18:53:01 +02:00
|
|
|
namespace Catch {
|
|
|
|
|
|
|
|
struct ITransientExpression {
|
|
|
|
virtual auto isBinaryExpression() const -> bool = 0;
|
|
|
|
virtual auto getResult() const -> bool = 0;
|
|
|
|
virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
|
2017-08-09 10:29:44 +02:00
|
|
|
|
|
|
|
// We don't actually need a virtual destructore, but many static analysers
|
|
|
|
// complain if it's not here :-(
|
|
|
|
virtual ~ITransientExpression() = default;
|
2017-08-08 18:53:01 +02:00
|
|
|
};
|
|
|
|
|
2017-09-06 15:15:48 +02:00
|
|
|
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
|
2017-08-08 18:53:01 +02:00
|
|
|
|
|
|
|
template<typename LhsT, typename RhsT>
|
|
|
|
class BinaryExpr : public ITransientExpression {
|
|
|
|
bool m_result;
|
|
|
|
LhsT m_lhs;
|
2017-09-06 15:15:48 +02:00
|
|
|
StringRef m_op;
|
2017-08-08 18:53:01 +02:00
|
|
|
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:
|
2017-08-30 15:42:01 +02:00
|
|
|
BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
|
|
|
|
: m_result( comparisonResult ),
|
2017-08-08 18:53:01 +02:00
|
|
|
m_lhs( lhs ),
|
2017-08-14 09:54:57 +02:00
|
|
|
m_op( op ),
|
2017-08-08 18:53:01 +02:00
|
|
|
m_rhs( rhs )
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename LhsT>
|
|
|
|
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<typename LhsT, typename RhsT>
|
2017-09-06 14:42:44 +02:00
|
|
|
auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs == rhs; };
|
2017-08-08 18:53:01 +02:00
|
|
|
template<typename T>
|
|
|
|
auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); };
|
|
|
|
template<typename T>
|
2017-08-30 11:40:29 +02:00
|
|
|
auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); };
|
|
|
|
template<typename T>
|
2017-08-08 18:53:01 +02:00
|
|
|
auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; };
|
2017-08-30 11:40:29 +02:00
|
|
|
template<typename T>
|
|
|
|
auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; };
|
2017-08-08 18:53:01 +02:00
|
|
|
|
|
|
|
template<typename LhsT, typename RhsT>
|
2017-09-06 14:42:44 +02:00
|
|
|
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; };
|
2017-08-08 18:53:01 +02:00
|
|
|
template<typename T>
|
|
|
|
auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); };
|
|
|
|
template<typename T>
|
2017-08-30 11:40:29 +02:00
|
|
|
auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); };
|
|
|
|
template<typename T>
|
2017-08-08 18:53:01 +02:00
|
|
|
auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; };
|
2017-08-30 11:40:29 +02:00
|
|
|
template<typename T>
|
|
|
|
auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; };
|
2017-08-08 18:53:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
template<typename LhsT>
|
|
|
|
class ExprLhs {
|
|
|
|
LhsT m_lhs;
|
|
|
|
public:
|
|
|
|
ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
|
|
|
|
|
|
|
|
template<typename RhsT>
|
|
|
|
auto operator == ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
|
|
|
return BinaryExpr<LhsT, RhsT&>( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs );
|
|
|
|
}
|
|
|
|
auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
|
|
|
return BinaryExpr<LhsT, bool>( m_lhs == rhs, m_lhs, "==", rhs );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename RhsT>
|
|
|
|
auto operator != ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
|
|
|
return BinaryExpr<LhsT, RhsT&>( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs );
|
|
|
|
}
|
|
|
|
auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
|
|
|
|
return BinaryExpr<LhsT, bool>( m_lhs != rhs, m_lhs, "!=", rhs );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename RhsT>
|
|
|
|
auto operator > ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
|
|
|
return BinaryExpr<LhsT, RhsT&>( m_lhs > rhs, m_lhs, ">", rhs );
|
|
|
|
}
|
|
|
|
template<typename RhsT>
|
|
|
|
auto operator < ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
|
|
|
return BinaryExpr<LhsT, RhsT&>( m_lhs < rhs, m_lhs, "<", rhs );
|
|
|
|
}
|
|
|
|
template<typename RhsT>
|
|
|
|
auto operator >= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
|
|
|
return BinaryExpr<LhsT, RhsT&>( m_lhs >= rhs, m_lhs, ">=", rhs );
|
|
|
|
}
|
|
|
|
template<typename RhsT>
|
|
|
|
auto operator <= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const {
|
|
|
|
return BinaryExpr<LhsT, RhsT&>( m_lhs <= rhs, m_lhs, "<=", rhs );
|
|
|
|
}
|
|
|
|
|
|
|
|
auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
|
|
|
|
return UnaryExpr<LhsT>( m_lhs );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void handleExpression( ITransientExpression const& expr );
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void handleExpression( ExprLhs<T> const& expr ) {
|
|
|
|
handleExpression( expr.makeUnaryExpr() );
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Decomposer {
|
|
|
|
template<typename T>
|
|
|
|
auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
|
|
|
|
return ExprLhs<T const&>( lhs );
|
|
|
|
}
|
|
|
|
auto operator <=( bool value ) -> ExprLhs<bool> {
|
|
|
|
return ExprLhs<bool>( value );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace Catch
|
|
|
|
|
2017-08-09 10:29:44 +02:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(pop)
|
|
|
|
#endif
|
|
|
|
|
2017-08-08 18:53:01 +02:00
|
|
|
#endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED
|