1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #ifndef INCLUDED_O3TL_SORTED_VECTOR_HXX
11 #define INCLUDED_O3TL_SORTED_VECTOR_HXX
19 #include <type_traits>
24 // forward declared because it's default template arg for sorted_vector
25 template<class Value
, class Compare
>
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
36 typename Compare
= std::less
<Value
>,
37 template<typename
, typename
> class Find
= find_unique
,
38 bool = std::is_copy_constructible
<Value
>::value
>
42 typedef Find
<Value
, Compare
> Find_t
;
43 typedef typename
std::vector
<Value
> vector_t
;
44 typedef typename
std::vector
<Value
>::iterator iterator
;
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
)
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;
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
));
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
));
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
));
93 m_vector
.erase(m_vector
.begin() + (ret
.first
- m_vector
.begin()));
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
120 Value
erase_extract( size_t index
)
122 Value val
= std::move(m_vector
[index
]);
123 m_vector
.erase(m_vector
.begin() + index
);
132 void swap(sorted_vector
& other
)
134 m_vector
.swap(other
.m_vector
);
137 void reserve(size_type amount
)
139 m_vector
.reserve(amount
);
144 size_type
size() const
146 return m_vector
.size();
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
);
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
237 m_vector
.insert(m_vector
.begin(), rOther
.m_vector
.begin(), rOther
.m_vector
.end());
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());
247 m_vector
.insert(m_vector
.begin(), rOther
.m_vector
.begin(), rOther
.m_vector
.end());
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());
257 m_vector
.swap( rOther
);
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
)
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!
280 std::stable_sort(m_vector
.begin(), m_vector
.end(), Compare());
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.
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
);
304 /* Specialise the template for cases like Value = std::unique_ptr<T>, where
305 MSVC2017 needs some help
310 template<typename
, typename
> class Find
>
311 class sorted_vector
<Value
,Compare
,Find
,false> : public sorted_vector
<Value
, Compare
, Find
, true>
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
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
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
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
>
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
,
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
,
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
)
414 return std::make_pair(it
, true);
417 return std::make_pair(its
.first
, false);
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */