File indexing completed on 2024-12-22 05:13:36
0001 /* 0002 SPDX-FileCopyrightText: 2015 Ivan Cukic <ivan.cukic(at)kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef UTILS_MEMBER_MATCHER_H 0008 #define UTILS_MEMBER_MATCHER_H 0009 0010 namespace kamd 0011 { 0012 namespace utils 0013 { 0014 namespace member_matcher 0015 { 0016 struct placeholder { 0017 } _; 0018 0019 namespace detail 0020 { //_ 0021 enum ComparisonOperation { 0022 Less, 0023 LessOrEqual, 0024 Equal, 0025 GreaterOrEqual, 0026 Greater, 0027 }; 0028 0029 // Member comparison object 0030 // Call operator returns true if: 0031 // collection item <comparison> specified item 0032 // where <comparison> can be <, >, ==, >=, <= 0033 template<typename Member, typename Value> 0034 struct member_comparator { //_ 0035 0036 member_comparator(ComparisonOperation comparison, Member member, Value value) 0037 : m_comparator(comparison) 0038 , m_member(member) 0039 , m_value(value) 0040 { 0041 } 0042 0043 const ComparisonOperation m_comparator; 0044 const Member m_member; 0045 const Value m_value; 0046 0047 // When passing only a item to compare with, 0048 // it means that we already have the value for comparison. 0049 // For example (member(M) > 5)(2) 0050 template<typename T> 0051 inline bool operator()(const T &collItem) const 0052 { 0053 return operator()(collItem, m_value); 0054 } 0055 0056 // When passing the placeholder aka 'ignore' as a value, 0057 // it means that we already have the value for comparison. 0058 // For example (member(M) > 5)(collItem, _) 0059 template<typename T> 0060 inline bool operator()(const T &collItem, const placeholder &) const 0061 { 0062 return operator()(collItem, m_value); 0063 } 0064 0065 // Like the previous one, but with reversed argument order 0066 template<typename T> 0067 inline bool operator()(const placeholder &, const T &collItem) const 0068 { 0069 return compare(m_value, (collItem.*m_member)()); 0070 } 0071 0072 // Comparing two values 0073 // For example (member(M) > _)(item, 5) 0074 template<typename T, typename V> 0075 inline bool operator()(const T &collItem, const V &value) const 0076 { 0077 // TODO: Make this work if the arguments are reversed, 0078 // or even if both arhuments need to be checked 0079 // for the specified member 0080 return compare((collItem.*m_member)(), value); 0081 } 0082 0083 private: 0084 template<typename Left, typename Right> 0085 inline bool compare(const Left &left, const Right &right) const 0086 { 0087 return m_comparator == Less ? left < right 0088 : m_comparator == LessOrEqual ? left <= right 0089 : m_comparator == Equal ? left == right 0090 : m_comparator == GreaterOrEqual ? left >= right 0091 : m_comparator == Greater ? left > right 0092 : false; 0093 } 0094 0095 }; //^ 0096 0097 // Chaining multiple comparators to achieve lexicographical 0098 // comparison of multiple members in order. 0099 // This would me so much nicer with variadic templates... f**ing MSVC. 0100 template<typename First, typename Second> 0101 struct member_comparator_chain { 0102 member_comparator_chain(First first, Second second) 0103 : first(first) 0104 , second(second) 0105 { 0106 } 0107 0108 // Implement if needed... 0109 // template <typename T> 0110 // inline bool operator()(const T &item) const 0111 // { 0112 // return first(item) || second(item); 0113 // } 0114 0115 template<typename T, typename V> 0116 inline bool operator()(const T &item, const V &value) const 0117 { 0118 return first(item, value) || (!first(value, item) && second(item, value)); 0119 } 0120 0121 First first; 0122 Second second; 0123 }; 0124 0125 template<typename First, typename Second> 0126 inline member_comparator_chain<First, Second> operator&&(First first, Second second) 0127 { 0128 return member_comparator_chain<First, Second>(first, second); 0129 } 0130 0131 // Provides syntax sugar for building member comparators 0132 template<typename Member> 0133 struct member_matcher { //_ 0134 member_matcher(Member m) 0135 : m_member(m) 0136 { 0137 } 0138 0139 #define IMPLEMENT_COMPARISON_OPERATOR(OPERATOR, NAME) \ 0140 template<typename Value> \ 0141 inline member_comparator<Member, Value> operator OPERATOR(const Value &value) const \ 0142 { \ 0143 return member_comparator<Member, Value>(NAME, m_member, value); \ 0144 } 0145 0146 IMPLEMENT_COMPARISON_OPERATOR(<, Less) 0147 IMPLEMENT_COMPARISON_OPERATOR(<=, LessOrEqual) 0148 IMPLEMENT_COMPARISON_OPERATOR(==, Equal) 0149 IMPLEMENT_COMPARISON_OPERATOR(>=, GreaterOrEqual) 0150 IMPLEMENT_COMPARISON_OPERATOR(>, Greater) 0151 0152 #undef IMPLEMENT_COMPARISON_OPERATOR 0153 0154 Member m_member; 0155 }; //^ 0156 0157 } //^ namespace detail 0158 0159 template<typename Member> 0160 detail::member_matcher<Member> member(Member m) 0161 { 0162 return detail::member_matcher<Member>(m); 0163 } 0164 } // namespace member 0165 0166 } // namespace utils 0167 } // namespace kamd 0168 0169 #endif // UTILS_MEMBER_MATCHER_H