1 /*
2  *  Created by Phil on 04/03/2011.
3  *  Copyright 2011 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_EVALUATE_HPP_INCLUDED
9 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
10 
11 #ifdef _MSC_VER
12 #pragma warning(push)
13 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
14 #pragma warning(disable:4018) // more "signed/unsigned mismatch"
15 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
16 #endif
17 
18 #include <cstddef>
19 
20 namespace Catch {
21 namespace Internal {
22 
23     enum Operator {
24         IsEqualTo,
25         IsNotEqualTo,
26         IsLessThan,
27         IsGreaterThan,
28         IsLessThanOrEqualTo,
29         IsGreaterThanOrEqualTo
30     };
31 
getNameCatch::Internal::OperatorTraits32     template<Operator Op> struct OperatorTraits             { static const char* getName(){ return "*error*"; } };
getNameCatch::Internal::OperatorTraits33     template<> struct OperatorTraits<IsEqualTo>             { static const char* getName(){ return "=="; } };
getNameCatch::Internal::OperatorTraits34     template<> struct OperatorTraits<IsNotEqualTo>          { static const char* getName(){ return "!="; } };
getNameCatch::Internal::OperatorTraits35     template<> struct OperatorTraits<IsLessThan>            { static const char* getName(){ return "<"; } };
getNameCatch::Internal::OperatorTraits36     template<> struct OperatorTraits<IsGreaterThan>         { static const char* getName(){ return ">"; } };
getNameCatch::Internal::OperatorTraits37     template<> struct OperatorTraits<IsLessThanOrEqualTo>   { static const char* getName(){ return "<="; } };
getNameCatch::Internal::OperatorTraits38     template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
39 
40     template<typename T>
opCast(T const & t)41     T& opCast(T const& t) { return const_cast<T&>(t); }
42 
43 // nullptr_t support based on pull request #154 from Konstantin Baumann
44 #ifdef CATCH_CONFIG_CPP11_NULLPTR
opCast(std::nullptr_t)45     inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
46 #endif // CATCH_CONFIG_CPP11_NULLPTR
47 
48 
49     // So the compare overloads can be operator agnostic we convey the operator as a template
50     // enum, which is used to specialise an Evaluator for doing the comparison.
51     template<typename T1, typename T2, Operator Op>
52     struct Evaluator{};
53 
54     template<typename T1, typename T2>
55     struct Evaluator<T1, T2, IsEqualTo> {
evaluateCatch::Internal::Evaluator56         static bool evaluate( T1 const& lhs, T2 const& rhs) {
57             return bool( opCast( lhs ) ==  opCast( rhs ) );
58         }
59     };
60     template<typename T1, typename T2>
61     struct Evaluator<T1, T2, IsNotEqualTo> {
evaluateCatch::Internal::Evaluator62         static bool evaluate( T1 const& lhs, T2 const& rhs ) {
63             return bool( opCast( lhs ) != opCast( rhs ) );
64         }
65     };
66     template<typename T1, typename T2>
67     struct Evaluator<T1, T2, IsLessThan> {
evaluateCatch::Internal::Evaluator68         static bool evaluate( T1 const& lhs, T2 const& rhs ) {
69             return bool( opCast( lhs ) < opCast( rhs ) );
70         }
71     };
72     template<typename T1, typename T2>
73     struct Evaluator<T1, T2, IsGreaterThan> {
evaluateCatch::Internal::Evaluator74         static bool evaluate( T1 const& lhs, T2 const& rhs ) {
75             return bool( opCast( lhs ) > opCast( rhs ) );
76         }
77     };
78     template<typename T1, typename T2>
79     struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
evaluateCatch::Internal::Evaluator80         static bool evaluate( T1 const& lhs, T2 const& rhs ) {
81             return bool( opCast( lhs ) >= opCast( rhs ) );
82         }
83     };
84     template<typename T1, typename T2>
85     struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
evaluateCatch::Internal::Evaluator86         static bool evaluate( T1 const& lhs, T2 const& rhs ) {
87             return bool( opCast( lhs ) <= opCast( rhs ) );
88         }
89     };
90 
91     template<Operator Op, typename T1, typename T2>
applyEvaluator(T1 const & lhs,T2 const & rhs)92     bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
93         return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
94     }
95 
96     // This level of indirection allows us to specialise for integer types
97     // to avoid signed/ unsigned warnings
98 
99     // "base" overload
100     template<Operator Op, typename T1, typename T2>
compare(T1 const & lhs,T2 const & rhs)101     bool compare( T1 const& lhs, T2 const& rhs ) {
102         return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
103     }
104 
105     // unsigned X to int
compare(unsigned int lhs,int rhs)106     template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
107         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
108     }
compare(unsigned long lhs,int rhs)109     template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
110         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
111     }
compare(unsigned char lhs,int rhs)112     template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
113         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
114     }
115 
116     // unsigned X to long
compare(unsigned int lhs,long rhs)117     template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
118         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
119     }
compare(unsigned long lhs,long rhs)120     template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
121         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
122     }
compare(unsigned char lhs,long rhs)123     template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
124         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
125     }
126 
127     // int to unsigned X
compare(int lhs,unsigned int rhs)128     template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
129         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
130     }
compare(int lhs,unsigned long rhs)131     template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
132         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
133     }
compare(int lhs,unsigned char rhs)134     template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
135         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
136     }
137 
138     // long to unsigned X
compare(long lhs,unsigned int rhs)139     template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
140         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
141     }
compare(long lhs,unsigned long rhs)142     template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
143         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
144     }
compare(long lhs,unsigned char rhs)145     template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
146         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
147     }
148 
149     // pointer to long (when comparing against NULL)
compare(long lhs,T * rhs)150     template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
151         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
152     }
compare(T * lhs,long rhs)153     template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
154         return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
155     }
156 
157     // pointer to int (when comparing against NULL)
compare(int lhs,T * rhs)158     template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
159         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
160     }
compare(T * lhs,int rhs)161     template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
162         return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
163     }
164 
165 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
166     // long long to unsigned X
compare(long long lhs,unsigned int rhs)167     template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
168         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
169     }
compare(long long lhs,unsigned long rhs)170     template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
171         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
172     }
compare(long long lhs,unsigned long long rhs)173     template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
174         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
175     }
compare(long long lhs,unsigned char rhs)176     template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
177         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
178     }
179 
180     // unsigned long long to X
compare(unsigned long long lhs,int rhs)181     template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
182         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
183     }
compare(unsigned long long lhs,long rhs)184     template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
185         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
186     }
compare(unsigned long long lhs,long long rhs)187     template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
188         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
189     }
compare(unsigned long long lhs,char rhs)190     template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
191         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
192     }
193 
194     // pointer to long long (when comparing against NULL)
compare(long long lhs,T * rhs)195     template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
196         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
197     }
compare(T * lhs,long long rhs)198     template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
199         return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
200     }
201 #endif // CATCH_CONFIG_CPP11_LONG_LONG
202 
203 #ifdef CATCH_CONFIG_CPP11_NULLPTR
204     // pointer to nullptr_t (when comparing against nullptr)
compare(std::nullptr_t,T * rhs)205     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
206         return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
207     }
compare(T * lhs,std::nullptr_t)208     template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
209         return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
210     }
211 #endif // CATCH_CONFIG_CPP11_NULLPTR
212 
213 } // end of namespace Internal
214 } // end of namespace Catch
215 
216 #ifdef _MSC_VER
217 #pragma warning(pop)
218 #endif
219 
220 #endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
221