Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / include / o3tl / sorted_vector.hxx
blob0f31bc5176513eba32de433454b62958291904d6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #ifndef INCLUDED_O3TL_SORTED_VECTOR_HXX
11 #define INCLUDED_O3TL_SORTED_VECTOR_HXX
13 #include <vector>
14 #include <algorithm>
15 #include <cassert>
16 #include <functional>
17 #include <iterator>
18 #include <memory>
19 #include <type_traits>
21 namespace o3tl
24 // forward declared because it's default template arg for sorted_vector
25 template<class Value, class Compare>
26 struct find_unique;
28 /** Represents a sorted vector of values.
30 @tpl Value class of item to be stored in container
31 @tpl Compare comparison method
32 @tpl Find look up index of a Value in the array
34 template<
35 typename Value,
36 typename Compare = std::less<Value>,
37 template<typename, typename> class Find = find_unique,
38 bool = std::is_copy_constructible<Value>::value >
39 class sorted_vector
41 private:
42 typedef Find<Value, Compare> Find_t;
43 typedef typename std::vector<Value> vector_t;
44 typedef typename std::vector<Value>::iterator iterator;
45 public:
46 typedef typename std::vector<Value>::const_iterator const_iterator;
47 typedef typename std::vector<Value>::const_reverse_iterator const_reverse_iterator;
48 typedef typename std::vector<Value>::difference_type difference_type;
49 typedef typename std::vector<Value>::size_type size_type;
50 typedef Value value_type;
52 constexpr sorted_vector( std::initializer_list<Value> init )
53 : m_vector(init)
55 std::sort(m_vector.begin(), m_vector.end(), Compare());
57 sorted_vector() = default;
58 sorted_vector(sorted_vector const&) = default;
59 sorted_vector(sorted_vector&&) = default;
61 sorted_vector& operator=(sorted_vector const&) = default;
62 sorted_vector& operator=(sorted_vector&&) = default;
64 // MODIFIERS
66 std::pair<const_iterator,bool> insert( Value&& x )
68 std::pair<const_iterator, bool> const ret(Find_t()(m_vector.begin(), m_vector.end(), x));
69 if (!ret.second)
71 const_iterator const it = m_vector.insert(m_vector.begin() + (ret.first - m_vector.begin()), std::move(x));
72 return std::make_pair(it, true);
74 return std::make_pair(ret.first, false);
77 std::pair<const_iterator,bool> insert( const Value& x )
79 std::pair<const_iterator, bool> const ret(Find_t()(m_vector.begin(), m_vector.end(), x));
80 if (!ret.second)
82 const_iterator const it = m_vector.insert(m_vector.begin() + (ret.first - m_vector.begin()), x);
83 return std::make_pair(it, true);
85 return std::make_pair(ret.first, false);
88 size_type erase( const Value& x )
90 std::pair<const_iterator, bool> const ret(Find_t()(m_vector.begin(), m_vector.end(), x));
91 if (ret.second)
93 m_vector.erase(m_vector.begin() + (ret.first - m_vector.begin()));
94 return 1;
96 return 0;
99 void erase_at(size_t index)
101 m_vector.erase(m_vector.begin() + index);
104 // like C++ 2011: erase with const_iterator (doesn't change sort order)
105 const_iterator erase(const_iterator const& position)
106 { // C++98 has vector::erase(iterator), so call that
107 return m_vector.erase(m_vector.begin() + (position - m_vector.begin()));
110 void erase(const_iterator const& first, const_iterator const& last)
112 m_vector.erase(m_vector.begin() + (first - m_vector.begin()),
113 m_vector.begin() + (last - m_vector.begin()));
117 * make erase return the removed element, otherwise there is no useful way of extracting a std::unique_ptr
118 * from this.
120 Value erase_extract( size_t index )
122 Value val = std::move(m_vector[index]);
123 m_vector.erase(m_vector.begin() + index);
124 return val;
127 void clear()
129 m_vector.clear();
132 void swap(sorted_vector & other)
134 m_vector.swap(other.m_vector);
137 void reserve(size_type amount)
139 m_vector.reserve(amount);
142 // ACCESSORS
144 size_type size() const
146 return m_vector.size();
149 bool empty() const
151 return m_vector.empty();
154 // Only return a const iterator, so that the vector cannot be directly updated.
155 const_iterator begin() const
157 return m_vector.begin();
160 // Only return a const iterator, so that the vector cannot be directly updated.
161 const_iterator end() const
163 return m_vector.end();
166 // Only return a const iterator, so that the vector cannot be directly updated.
167 const_reverse_iterator rbegin() const
169 return m_vector.rbegin();
172 // Only return a const iterator, so that the vector cannot be directly updated.
173 const_reverse_iterator rend() const
175 return m_vector.rend();
178 const Value& front() const
180 return m_vector.front();
183 const Value& back() const
185 return m_vector.back();
188 const Value& operator[]( size_t index ) const
190 return m_vector.operator[]( index );
193 // OPERATIONS
195 const_iterator lower_bound( const Value& x ) const
197 return std::lower_bound( m_vector.begin(), m_vector.end(), x, Compare() );
200 const_iterator upper_bound( const Value& x ) const
202 return std::upper_bound( m_vector.begin(), m_vector.end(), x, Compare() );
205 /* Searches the container for an element with a value of x
206 * and returns an iterator to it if found, otherwise it returns an
207 * iterator to sorted_vector::end (the element past the end of the container).
209 * Only return a const iterator, so that the vector cannot be directly updated.
211 const_iterator find( const Value& x ) const
213 std::pair<const_iterator, bool> const ret(Find_t()(m_vector.begin(), m_vector.end(), x));
214 return (ret.second) ? ret.first : m_vector.end();
217 size_type count(const Value& v) const
219 return find(v) != end() ? 1 : 0;
222 bool operator==(const sorted_vector & other) const
224 return m_vector == other.m_vector;
227 bool operator!=(const sorted_vector & other) const
229 return m_vector != other.m_vector;
232 void insert(sorted_vector<Value,Compare,Find> const& rOther)
234 // optimization for the rather common case that we are overwriting this with the contents
235 // of another sorted vector
236 if ( empty() )
237 m_vector.insert(m_vector.begin(), rOther.m_vector.begin(), rOther.m_vector.end());
238 else
239 insert_internal( rOther.m_vector );
242 void insert_sorted_unique_vector(const std::vector<Value>& rOther)
244 assert( std::is_sorted(rOther.begin(), rOther.end(), Compare()));
245 assert( std::unique(rOther.begin(), rOther.end(), compare_equal) == rOther.end());
246 if ( empty() )
247 m_vector.insert(m_vector.begin(), rOther.m_vector.begin(), rOther.m_vector.end());
248 else
249 insert_internal( rOther );
252 void insert_sorted_unique_vector(std::vector<Value>&& rOther)
254 assert( std::is_sorted(rOther.begin(), rOther.end(), Compare()));
255 assert( std::unique(rOther.begin(), rOther.end(), compare_equal) == rOther.end());
256 if ( empty() )
257 m_vector.swap( rOther );
258 else
259 insert_internal( rOther );
262 /* Clear() elements in the vector, and free them one by one. */
263 void DeleteAndDestroyAll()
265 for (const_iterator it = m_vector.begin(); it != m_vector.end(); ++it)
267 delete *it;
270 clear();
273 // fdo#58793: some existing code in Writer (SwpHintsArray)
274 // routinely modifies the members of the vector in a way that
275 // violates the sort order, and then re-sorts the array.
276 // This is a kludge to enable that code to work.
277 // If you are calling this function, you are Doing It Wrong!
278 void Resort()
280 std::stable_sort(m_vector.begin(), m_vector.end(), Compare());
283 private:
284 static bool compare_equal( const Value& v1, const Value& v2 )
285 { // Synthetize == check from < check for std::unique asserts above.
286 return !Compare()( v1, v2 ) && !Compare()( v2, v1 );
289 void insert_internal( const std::vector<Value>& rOther )
291 // Do a union in one pass rather than repeated insert() that could repeatedly
292 // move large amounts of data.
293 vector_t tmp;
294 tmp.reserve( m_vector.size() + rOther.size());
295 std::set_union( m_vector.begin(), m_vector.end(),
296 rOther.begin(), rOther.end(),
297 std::back_inserter( tmp ), Compare());
298 m_vector.swap( tmp );
301 vector_t m_vector;
304 /* Specialise the template for cases like Value = std::unique_ptr<T>, where
305 MSVC2017 needs some help
307 template<
308 typename Value,
309 typename Compare,
310 template<typename, typename> class Find >
311 class sorted_vector<Value,Compare,Find,false> : public sorted_vector<Value, Compare, Find, true>
313 public:
314 using sorted_vector<Value, Compare, Find, true>::sorted_vector;
315 typedef sorted_vector<Value, Compare, Find, true> super_sorted_vector;
317 sorted_vector(sorted_vector const&) = delete;
318 sorted_vector& operator=(sorted_vector const&) = delete;
320 sorted_vector() = default;
321 sorted_vector(sorted_vector&&) = default;
322 sorted_vector& operator=(sorted_vector&&) = default;
325 * implement find for sorted_vectors containing std::unique_ptr
327 typename super_sorted_vector::const_iterator find( typename Value::element_type const * x ) const
329 Value tmp(const_cast<typename Value::element_type*>(x));
330 auto ret = super_sorted_vector::find(tmp);
331 // coverity[ resource_leak : FALSE] - this is only a pretend unique_ptr, to avoid allocating a temporary
332 tmp.release();
333 return ret;
336 * implement upper_bound for sorted_vectors containing std::unique_ptr
338 typename super_sorted_vector::const_iterator upper_bound( typename Value::element_type const * x ) const
340 Value tmp(const_cast<typename Value::element_type*>(x));
341 auto ret = super_sorted_vector::upper_bound(tmp);
342 // coverity[ resource_leak : FALSE] - this is only a pretend unique_ptr, to avoid allocating a temporary
343 tmp.release();
344 return ret;
347 * implement lower_bound for sorted_vectors containing std::unique_ptr
349 typename super_sorted_vector::const_iterator lower_bound( typename Value::element_type const * x ) const
351 Value tmp(const_cast<typename Value::element_type*>(x));
352 auto ret = super_sorted_vector::lower_bound(tmp);
353 // coverity[ resource_leak : FALSE] - this is only a pretend unique_ptr, to avoid allocating a temporary
354 tmp.release();
355 return ret;
360 /** Implements an ordering function over a pointer, where the comparison uses the < operator on the pointed-to types.
361 Very useful for the cases where we put pointers to objects inside a sorted_vector.
363 template <class T> struct less_ptr_to
365 bool operator() ( T* const& lhs, T* const& rhs ) const
367 return (*lhs) < (*rhs);
371 template <class T> struct less_uniqueptr_to
373 bool operator() ( std::unique_ptr<T> const& lhs, std::unique_ptr<T> const& rhs ) const
375 return (*lhs) < (*rhs);
379 /** the elements are totally ordered by Compare,
380 for no 2 elements !Compare(a,b) && !Compare(b,a) is true
382 template<class Value, class Compare>
383 struct find_unique
385 typedef typename sorted_vector<Value, Compare,
386 o3tl::find_unique> ::const_iterator const_iterator;
387 std::pair<const_iterator, bool> operator()(
388 const_iterator first, const_iterator last,
389 Value const& v)
391 const_iterator const it = std::lower_bound(first, last, v, Compare());
392 return std::make_pair(it, (it != last && !Compare()(v, *it)));
396 /** the elements are partially ordered by Compare,
397 2 elements are allowed if they are not the same element (pointer equal)
399 template<class Value, class Compare>
400 struct find_partialorder_ptrequals
402 typedef typename sorted_vector<Value, Compare,
403 o3tl::find_partialorder_ptrequals>::const_iterator const_iterator;
404 std::pair<const_iterator, bool> operator()(
405 const_iterator first, const_iterator last,
406 Value const& v)
408 std::pair<const_iterator, const_iterator> const its =
409 std::equal_range(first, last, v, Compare());
410 for (const_iterator it = its.first; it != its.second; ++it)
412 if (v == *it)
414 return std::make_pair(it, true);
417 return std::make_pair(its.first, false);
421 } // namespace o3tl
422 #endif
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */