File indexing completed on 2024-06-16 04:58:32

0001 /*
0002     utils/algorithm.h
0003 
0004     This file is part of libkleopatra, the KDE keymanagement library
0005     SPDX-FileCopyrightText: 2021 g10 Code GmbH
0006     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #pragma once
0012 
0013 #include <algorithm>
0014 #include <iterator>
0015 
0016 namespace Kleo
0017 {
0018 
0019 template<typename ForwardIterator, typename T>
0020 ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T &value)
0021 {
0022     const ForwardIterator it = std::lower_bound(first, last, value);
0023     return (it == last || value < *it) ? last : it;
0024 }
0025 
0026 template<typename ForwardIterator, typename T, typename Compare>
0027 ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T &value, Compare comp)
0028 {
0029     const ForwardIterator it = std::lower_bound(first, last, value, comp);
0030     return (it == last || comp(value, *it)) ? last : it;
0031 }
0032 
0033 template<typename Container, typename UnaryOperation>
0034 Container transformInPlace(Container &&c, UnaryOperation op)
0035 {
0036     std::transform(std::begin(c), std::end(c), std::begin(c), op);
0037     return std::move(c);
0038 }
0039 
0040 /** Convenience helper for checking if the predicate @p p returns @c true
0041  *  for all elements in the range @p range. Returns @c true if the range is empty.
0042  *  Use ranges::all_of() instead if you can use C++20.
0043  */
0044 template<typename InputRange, typename UnaryPredicate>
0045 bool all_of(const InputRange &range, UnaryPredicate p)
0046 {
0047     return std::all_of(std::begin(range), std::end(range), p);
0048 }
0049 
0050 /** Convenience helper for checking if a @p range contains at least one element
0051  *  for which predicate @p p returns @c true. Returns @c false if @p range is
0052  *  empty.
0053  *  Use ranges::any_of() instead if you can use C++20.
0054  */
0055 template<typename InputRange, typename UnaryPredicate>
0056 bool any_of(const InputRange &range, UnaryPredicate p)
0057 {
0058     return std::any_of(std::begin(range), std::end(range), p);
0059 }
0060 
0061 /** Convenience helper for counting the number of elements in the range @p range
0062  *  for which the predicate @p p returns @c true.
0063  *  Use ranges::count_if() instead if you can use C++20.
0064  */
0065 template<typename InputRange, typename UnaryPredicate>
0066 auto count_if(const InputRange &range, UnaryPredicate p)
0067 {
0068     return std::count_if(std::begin(range), std::end(range), p);
0069 }
0070 
0071 /** Convenience helper for finding the first element in the range @p range
0072  *  for which predicate @p p returns @c true.
0073  *  Use ranges::find_if() instead if you can use C++20.
0074  */
0075 template<typename InputRange, typename UnaryPredicate>
0076 auto find_if(const InputRange &range, UnaryPredicate p)
0077 {
0078     return std::find_if(std::begin(range), std::end(range), p);
0079 }
0080 
0081 /** Convenience helper for applying the function @p f on all elements of the
0082  *  range @p range.
0083  *  Use ranges::for_each() instead if you can use C++20.
0084  */
0085 template<typename InputRange, typename UnaryFunction>
0086 UnaryFunction for_each(const InputRange &range, UnaryFunction f)
0087 {
0088     return std::for_each(std::begin(range), std::end(range), f);
0089 }
0090 
0091 /** Convenience helper for checking if a @p container contains an element
0092  *  with key equivalent to @p key. This is mainly meant to be used for the
0093  *  associative standard containers until we can use their corresponding
0094  *  member function in C++20.
0095  */
0096 template<typename Container, typename Key>
0097 bool contains(const Container &container, const Key &key)
0098 {
0099     return std::find(std::begin(container), std::end(container), key) != std::end(container);
0100 }
0101 
0102 /** Convenience helper for checking if a range @p range contains an element
0103  *  for which predicate @p p returns @c true.
0104  */
0105 template<typename InputRange, typename UnaryPredicate>
0106 bool contains_if(const InputRange &range, UnaryPredicate p)
0107 {
0108     return Kleo::find_if(range, p) != std::end(range);
0109 }
0110 
0111 /**
0112  * Convenience helper for copying elements of @p range.
0113  * Use std::ranges::copy_if() instead if you can use C++20.
0114  */
0115 template<typename InputRange, typename OutputIterator, typename UnaryPredicate>
0116 OutputIterator copy(InputRange &&range, OutputIterator result)
0117 {
0118     return std::copy(std::begin(range), std::end(range), result);
0119 }
0120 
0121 /**
0122  * Convenience helper for copying elements of @p range for which predicate @p p
0123  * returns @c true.
0124  * Use std::ranges::copy_if() instead if you can use C++20.
0125  */
0126 template<typename InputRange, typename OutputIterator, typename UnaryPredicate>
0127 OutputIterator copy_if(InputRange &&range, OutputIterator result, UnaryPredicate p)
0128 {
0129     return std::copy_if(std::begin(range), std::end(range), result, p);
0130 }
0131 
0132 /**
0133  * Convenience helper for transforming the elements of @p range.
0134  * Use std::ranges::transform() instead if you can use C++20.
0135  */
0136 template<typename InputRange, typename OutputIterator, typename UnaryOperation>
0137 OutputIterator transform(InputRange &&range, OutputIterator result, UnaryOperation op)
0138 {
0139     return std::transform(std::begin(range), std::end(range), result, op);
0140 }
0141 
0142 /**
0143  * Convenience helper for removing elements from a vector @p v for which
0144  * predicate @p p returns @c true.
0145  * Use std::erase_if() instead if you can use C++20.
0146  */
0147 template<typename Vector, typename UnaryPredicate>
0148 void erase_if(Vector &v, UnaryPredicate p)
0149 {
0150     v.erase(std::remove_if(std::begin(v), std::end(v), p), std::end(v));
0151 }
0152 
0153 }