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