1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qbs.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QBS_STLUTILS_H
41 #define QBS_STLUTILS_H
42 
43 #include <algorithm>
44 #include <iterator>
45 
46 namespace qbs {
47 namespace Internal {
48 
49 template <class C>
sorted(const C & container)50 C sorted(const C &container)
51 {
52     C result = container;
53     std::sort(std::begin(result), std::end(result));
54     return result;
55 }
56 
57 template <class C, class T>
contains(const C & container,const T & v)58 bool contains(const C &container, const T &v)
59 {
60     const auto &end = std::cend(container);
61     return std::find(std::cbegin(container), end, v) != end;
62 }
63 
64 template <class T, size_t N, class U>
contains(const T (& container)[N],const U & v)65 bool contains(const T (&container)[N], const U &v)
66 {
67     const auto &end = std::cend(container);
68     return std::find(std::cbegin(container), end, v) != end;
69 }
70 
71 template <class C>
containsKey(const C & container,const typename C::key_type & v)72 bool containsKey(const C &container, const typename C::key_type &v)
73 {
74     const auto &end = container.cend();
75     return container.find(v) != end;
76 }
77 
78 template <class C>
79 typename C::mapped_type mapValue(
80         const C &container,
81         const typename C::key_type &key,
82         const typename C::mapped_type &value = typename C::mapped_type())
83 {
84     const auto end = container.cend();
85     const auto it = container.find(key);
86     return it != end ? it->second : value;
87 }
88 
89 template <typename C>
removeOne(C & container,const typename C::value_type & v)90 bool removeOne(C &container, const typename C::value_type &v)
91 {
92     auto end = std::end(container);
93     auto it = std::find(std::begin(container), end, v);
94     if (it == end)
95         return false;
96     container.erase(it);
97     return true;
98 }
99 
100 template <typename C>
removeAll(C & container,const typename C::value_type & v)101 void removeAll(C &container, const typename C::value_type &v)
102 {
103     container.erase(std::remove(std::begin(container), std::end(container), v),
104                     std::end(container));
105 }
106 
107 template <typename C, typename Pred>
removeIf(C & container,const Pred & pred)108 void removeIf(C &container, const Pred &pred)
109 {
110     container.erase(std::remove_if(std::begin(container), std::end(container), pred),
111                     std::end(container));
112 }
113 
114 template <class Container, class UnaryPredicate>
any_of(const Container & container,const UnaryPredicate & predicate)115 bool any_of(const Container &container, const UnaryPredicate &predicate)
116 {
117     return std::any_of(std::begin(container), std::end(container), predicate);
118 }
119 
120 template <class Container, class UnaryPredicate>
none_of(const Container & container,const UnaryPredicate & predicate)121 bool none_of(const Container &container, const UnaryPredicate &predicate)
122 {
123     return std::none_of(std::begin(container), std::end(container), predicate);
124 }
125 
126 template <class It, class T, class Compare>
binaryFind(It begin,It end,const T & value,Compare comp)127 It binaryFind(It begin, It end, const T &value, Compare comp)
128 {
129     const auto it = std::lower_bound(begin, end, value, comp);
130     if (it == end || comp(value, *it))
131         return end;
132     return it;
133 }
134 
135 template <class It, class T>
binaryFind(It begin,It end,const T & value)136 It binaryFind(It begin, It end, const T &value)
137 {
138     return binaryFind(begin, end, value, std::less<T>());
139 }
140 
141 template <class C>
142 C &operator<<(C &container, const typename C::value_type &v)
143 {
144     container.push_back(v);
145     return container;
146 }
147 
148 template <class C>
149 C &operator<<(C &container, const C &other)
150 {
151     container.insert(container.end(), other.cbegin(), other.cend());
152     return container;
153 }
154 
155 // based on http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0814r0.pdf
156 template<typename T>
hashCombineHelper(size_t & seed,const T & val)157 void hashCombineHelper(size_t &seed, const T &val)
158 {
159     seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
160 }
161 
162 template<typename... Types>
hashCombine(const Types &...args)163 size_t hashCombine(const Types &... args)
164 {
165     size_t seed = 0;
166     (hashCombineHelper(seed, args), ...); // create hash value with seed over all args return seed;
167     return seed;
168 }
169 
170 template<typename It>
hashRange(It first,It last)171 size_t hashRange(It first, It last)
172 {
173     size_t seed = 0;
174     for (; first != last; ++first)
175         hashCombineHelper(seed, *first);
176 
177     return seed;
178 }
179 
180 template<typename R>
hashRange(R && range)181 size_t hashRange(R &&range)
182 {
183     return hashRange(std::begin(range), std::end(range));
184 }
185 
186 // based on qcontainertools_impl.h
187 template <typename Iterator>
188 using IfIsForwardIterator_t = typename std::enable_if_t<
189     std::is_convertible_v<
190         typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>,
191     bool>;
192 
193 template <typename Iterator>
194 using IfIsNotForwardIterator = typename std::enable_if_t<
195     !std::is_convertible_v<
196         typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>,
197     bool>;
198 
199 template <typename Container,
200           typename InputIterator,
201           IfIsNotForwardIterator<InputIterator> = true>
reserveIfForwardIterator(Container *,InputIterator,InputIterator)202 void reserveIfForwardIterator(Container *, InputIterator, InputIterator)
203 {
204 }
205 
206 template <typename Container,
207           typename ForwardIterator,
208           IfIsForwardIterator_t<ForwardIterator> = true>
reserveIfForwardIterator(Container * c,ForwardIterator f,ForwardIterator l)209 void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l)
210 {
211     c->reserve(static_cast<typename Container::size_type>(std::distance(f, l)));
212 }
213 
214 // similar to ranges::to proposal
215 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1206r1.pdf
216 template <class C, class R>
rangeTo(R && r)217 C rangeTo(R &&r)
218 {
219     return C(std::begin(r), std::end(r));
220 }
221 
222 template<class Enum>
toUnderlying(Enum e)223 constexpr std::underlying_type_t<Enum> toUnderlying(Enum e) noexcept
224 {
225     return static_cast<std::underlying_type_t<Enum>>(e);
226 }
227 
228 } // namespace Internal
229 } // namespace qbs
230 
231 #endif // QBS_STLUTILS_H
232