File indexing completed on 2025-02-16 05:06:23
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 QUICKCHECK_DATABASE_COMMON_H 0008 #define QUICKCHECK_DATABASE_COMMON_H 0009 0010 struct PrimaryKeyOrdering { 0011 template<typename T> 0012 bool operator()(const T &left, const T &right) const 0013 { 0014 return left.primaryKey() < right.primaryKey(); 0015 } 0016 }; 0017 0018 #define TABLE(Table) std::set<Table::Item, PrimaryKeyOrdering> 0019 0020 #define DECL_COLUMN(ColumnType, ColumnName) \ 0021 inline Column<Item, ColumnType> ColumnName() \ 0022 { \ 0023 return Column<Item, ColumnType>(&Item::ColumnName); \ 0024 } 0025 0026 template<typename Type, typename ColumnType> 0027 class Column 0028 { 0029 typedef Column<Type, ColumnType> ThisType; 0030 0031 public: 0032 Column(const ColumnType Type::*memberptr) 0033 : memberptr(memberptr) 0034 { 0035 } 0036 0037 //_ Column comparator functor 0038 template<typename Comp1, typename Comp2> 0039 class CompositeComparator 0040 { 0041 public: 0042 CompositeComparator(Comp1 comp1, Comp2 comp2) 0043 : comp1(comp1) 0044 , comp2(comp2) 0045 { 0046 } 0047 0048 inline bool operator()(const Type &left, const Type &right) const 0049 { 0050 return comp1(left, right) ? true : comp1(right, left) ? false : comp2(left, right); 0051 } 0052 0053 private: 0054 const Comp1 comp1; 0055 const Comp2 comp2; 0056 }; 0057 0058 class Comparator 0059 { 0060 public: 0061 Comparator(const ColumnType Type::*memberptr, bool invert) 0062 : memberptr(memberptr) 0063 , invert(invert) 0064 { 0065 } 0066 0067 inline bool operator()(const Type &left, const Type &right) const 0068 { 0069 return (invert) ? right.*memberptr < left.*memberptr // 0070 : left.*memberptr < right.*memberptr; 0071 } 0072 0073 template<typename Comp2> 0074 CompositeComparator<Comparator, Comp2> operator|(const Comp2 &comp2) 0075 { 0076 return CompositeComparator<Comparator, Comp2>(*this, comp2); 0077 } 0078 0079 private: 0080 const ColumnType Type::*memberptr; 0081 const bool invert; 0082 }; 0083 //^ 0084 0085 inline Comparator asc() const 0086 { 0087 return Comparator(memberptr, false); 0088 } 0089 0090 inline Comparator desc() const 0091 { 0092 return Comparator(memberptr, true); 0093 } 0094 0095 //_ Column filtering functor 0096 enum ComparisonOperation { 0097 Less, 0098 LessOrEqual, 0099 Equal, 0100 GreaterOrEqual, 0101 Greater, 0102 }; 0103 0104 template<typename T> 0105 class Filterer 0106 { 0107 public: 0108 Filterer(const ColumnType Type::*memberptr, ComparisonOperation comparison, const T &value) 0109 : memberptr(memberptr) 0110 , comparison(comparison) 0111 , value(value) 0112 { 0113 } 0114 0115 inline bool operator()(const Type &item) const 0116 { 0117 return comparison == Less ? item.*memberptr < value 0118 : comparison == LessOrEqual ? item.*memberptr <= value 0119 : comparison == Equal ? item.*memberptr == value 0120 : comparison == GreaterOrEqual ? item.*memberptr >= value 0121 : comparison == Greater ? item.*memberptr > value 0122 : false; 0123 } 0124 0125 private: 0126 const ColumnType Type::*memberptr; 0127 const ComparisonOperation comparison; 0128 const T value; 0129 }; 0130 0131 #define IMPLEMENT_COMPARISON_OPERATOR(OPERATOR, NAME) \ 0132 template<typename T> \ 0133 inline Filterer<T> operator OPERATOR(const T &value) const \ 0134 { \ 0135 return Filterer<T>(memberptr, NAME, value); \ 0136 } 0137 //^ 0138 0139 IMPLEMENT_COMPARISON_OPERATOR(<, Less) 0140 IMPLEMENT_COMPARISON_OPERATOR(<=, LessOrEqual) 0141 IMPLEMENT_COMPARISON_OPERATOR(==, Equal) 0142 IMPLEMENT_COMPARISON_OPERATOR(>=, GreaterOrEqual) 0143 IMPLEMENT_COMPARISON_OPERATOR(>, Greater) 0144 0145 #undef IMPLEMENT_COMPARISON_OPERATOR 0146 0147 // Column stuff 0148 0149 private: 0150 const ColumnType Type::*memberptr; 0151 }; 0152 0153 template<typename Range, typename ColumnMemberPointer, typename MergeFunction> 0154 inline auto groupBy(const Range &range, const ColumnMemberPointer &memberptr, const MergeFunction &merge) -> std::vector<typename Range::value_type> 0155 { 0156 std::vector<typename Range::value_type> result; 0157 0158 for (const auto &item : range) { 0159 if (result.size() == 0 || result.back().*memberptr != item.*memberptr) { 0160 result.push_back(item); 0161 } else { 0162 merge(result.back(), item); 0163 } 0164 } 0165 0166 return result; 0167 } 0168 0169 #endif // QUICKCHECK_DATABASE_COMMON_H 0170 0171 // vim: set foldmethod=marker: