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: