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
17 #include <type_traits>
22 // forward declared because it's default template arg for sorted_vector
23 template<class Value
, class Compare
>
26 /** Represents a sorted vector of values.
28 @tpl Value class of item to be stored in container
29 @tpl Compare comparison method
30 @tpl Find look up index of a Value in the array
34 typename Compare
= std::less
<Value
>,
35 template<typename
, typename
> class Find
= find_unique
,
36 bool = std::is_copy_constructible
<Value
>::value
>
40 typedef Find
<Value
, Compare
> Find_t
;
41 typedef typename
std::vector
<Value
> vector_t
;
42 typedef typename
std::vector
<Value
>::iterator iterator
;
44 typedef typename
std::vector
<Value
>::const_iterator const_iterator
;
45 typedef typename
std::vector
<Value
>::const_reverse_iterator const_reverse_iterator
;
46 typedef typename
std::vector
<Value
>::difference_type difference_type
;
47 typedef typename
std::vector
<Value
>::size_type size_type
;
48 typedef Value value_type
;
50 constexpr sorted_vector( std::initializer_list
<Value
> init
)
53 std::sort(m_vector
.begin(), m_vector
.end(), Compare());
55 sorted_vector() = default;
56 sorted_vector(sorted_vector
const&) = default;
57 sorted_vector(sorted_vector
&&) = default;
59 sorted_vector
& operator=(sorted_vector
const&) = default;
60 sorted_vector
& operator=(sorted_vector
&&) = default;
64 std::pair
<const_iterator
,bool> insert( Value
&& x
)
66 std::pair
<const_iterator
, bool> const ret(Find_t()(m_vector
.begin(), m_vector
.end(), x
));
69 const_iterator
const it
= m_vector
.insert(m_vector
.begin() + (ret
.first
- m_vector
.begin()), std::move(x
));
70 return std::make_pair(it
, true);
72 return std::make_pair(ret
.first
, false);
75 std::pair
<const_iterator
,bool> insert( const Value
& x
)
77 std::pair
<const_iterator
, bool> const ret(Find_t()(m_vector
.begin(), m_vector
.end(), x
));
80 const_iterator
const it
= m_vector
.insert(m_vector
.begin() + (ret
.first
- m_vector
.begin()), x
);
81 return std::make_pair(it
, true);
83 return std::make_pair(ret
.first
, false);
86 size_type
erase( const Value
& x
)
88 std::pair
<const_iterator
, bool> const ret(Find_t()(m_vector
.begin(), m_vector
.end(), x
));
91 m_vector
.erase(m_vector
.begin() + (ret
.first
- m_vector
.begin()));
97 void erase( size_t index
)
99 m_vector
.erase(m_vector
.begin() + index
);
102 // like C++ 2011: erase with const_iterator (doesn't change sort order)
103 const_iterator
erase(const_iterator
const& position
)
104 { // C++98 has vector::erase(iterator), so call that
105 return m_vector
.erase(m_vector
.begin() + (position
- m_vector
.begin()));
108 void erase(const_iterator
const& first
, const_iterator
const& last
)
110 m_vector
.erase(m_vector
.begin() + (first
- m_vector
.begin()),
111 m_vector
.begin() + (last
- m_vector
.begin()));
115 * make erase return the removed element, otherwise there is no useful way of extracting a std::unique_ptr
118 Value
erase_extract( size_t index
)
120 Value val
= std::move(m_vector
[index
]);
121 m_vector
.erase(m_vector
.begin() + index
);
130 void swap(sorted_vector
& other
)
132 m_vector
.swap(other
.m_vector
);
135 void reserve(size_type amount
)
137 m_vector
.reserve(amount
);
142 size_type
size() const
144 return m_vector
.size();
149 return m_vector
.empty();
152 // Only return a const iterator, so that the vector cannot be directly updated.
153 const_iterator
begin() const
155 return m_vector
.begin();
158 // Only return a const iterator, so that the vector cannot be directly updated.
159 const_iterator
end() const
161 return m_vector
.end();
164 // Only return a const iterator, so that the vector cannot be directly updated.
165 const_reverse_iterator
rbegin() const
167 return m_vector
.rbegin();
170 // Only return a const iterator, so that the vector cannot be directly updated.
171 const_reverse_iterator
rend() const
173 return m_vector
.rend();
176 const Value
& front() const
178 return m_vector
.front();
181 const Value
& back() const
183 return m_vector
.back();
186 const Value
& operator[]( size_t index
) const
188 return m_vector
.operator[]( index
);
193 const_iterator
lower_bound( const Value
& x
) const
195 return std::lower_bound( m_vector
.begin(), m_vector
.end(), x
, Compare() );
198 const_iterator
upper_bound( const Value
& x
) const
200 return std::upper_bound( m_vector
.begin(), m_vector
.end(), x
, Compare() );
203 /* Searches the container for an element with a value of x
204 * and returns an iterator to it if found, otherwise it returns an
205 * iterator to sorted_vector::end (the element past the end of the container).
207 * Only return a const iterator, so that the vector cannot be directly updated.
209 const_iterator
find( const Value
& x
) const
211 std::pair
<const_iterator
, bool> const ret(Find_t()(m_vector
.begin(), m_vector
.end(), x
));
212 return (ret
.second
) ? ret
.first
: m_vector
.end();
215 size_type
count(const Value
& v
) const
217 return find(v
) != end() ? 1 : 0;
220 bool operator==(const sorted_vector
& other
) const
222 return m_vector
== other
.m_vector
;
225 bool operator!=(const sorted_vector
& other
) const
227 return m_vector
!= other
.m_vector
;
230 void insert(sorted_vector
<Value
,Compare
,Find
> const& rOther
)
232 // optimization for the rather common case that we are overwriting this with the contents
233 // of another sorted vector
236 m_vector
.insert(m_vector
.begin(), rOther
.m_vector
.begin(), rOther
.m_vector
.end());
240 for (const_iterator it
= rOther
.m_vector
.begin(); it
!= rOther
.m_vector
.end(); ++it
)
247 /* Clear() elements in the vector, and free them one by one. */
248 void DeleteAndDestroyAll()
250 for (const_iterator it
= m_vector
.begin(); it
!= m_vector
.end(); ++it
)
258 // fdo#58793: some existing code in Writer (SwpHintsArray)
259 // routinely modifies the members of the vector in a way that
260 // violates the sort order, and then re-sorts the array.
261 // This is a kludge to enable that code to work.
262 // If you are calling this function, you are Doing It Wrong!
265 std::stable_sort(m_vector
.begin(), m_vector
.end(), Compare());
273 /* Specialise the template for cases like Value = std::unique_ptr<T>, where
274 MSVC2017 needs some help
279 template<typename
, typename
> class Find
>
280 class sorted_vector
<Value
,Compare
,Find
,false> : public sorted_vector
<Value
, Compare
, Find
, true>
283 using sorted_vector
<Value
, Compare
, Find
, true>::sorted_vector
;
284 typedef sorted_vector
<Value
, Compare
, Find
, true> super_sorted_vector
;
286 sorted_vector(sorted_vector
const&) = delete;
287 sorted_vector
& operator=(sorted_vector
const&) = delete;
289 sorted_vector() = default;
290 sorted_vector(sorted_vector
&&) = default;
291 sorted_vector
& operator=(sorted_vector
&&) = default;
294 * implement find for sorted_vectors containing std::unique_ptr
296 typename
super_sorted_vector::const_iterator
find( typename
Value::element_type
const * x
) const
298 Value
tmp(const_cast<typename
Value::element_type
*>(x
));
299 auto ret
= super_sorted_vector::find(tmp
);
304 * implement upper_bound for sorted_vectors containing std::unique_ptr
306 typename
super_sorted_vector::const_iterator
upper_bound( typename
Value::element_type
const * x
) const
308 Value
tmp(const_cast<typename
Value::element_type
*>(x
));
309 auto ret
= super_sorted_vector::upper_bound(tmp
);
314 * implement lower_bound for sorted_vectors containing std::unique_ptr
316 typename
super_sorted_vector::const_iterator
lower_bound( typename
Value::element_type
const * x
) const
318 Value
tmp(const_cast<typename
Value::element_type
*>(x
));
319 auto ret
= super_sorted_vector::lower_bound(tmp
);
326 /** Implements an ordering function over a pointer, where the comparison uses the < operator on the pointed-to types.
327 Very useful for the cases where we put pointers to objects inside a sorted_vector.
329 template <class T
> struct less_ptr_to
331 bool operator() ( T
* const& lhs
, T
* const& rhs
) const
333 return (*lhs
) < (*rhs
);
337 template <class T
> struct less_uniqueptr_to
339 bool operator() ( std::unique_ptr
<T
> const& lhs
, std::unique_ptr
<T
> const& rhs
) const
341 return (*lhs
) < (*rhs
);
345 /** the elements are totally ordered by Compare,
346 for no 2 elements !Compare(a,b) && !Compare(b,a) is true
348 template<class Value
, class Compare
>
351 typedef typename sorted_vector
<Value
, Compare
,
352 o3tl::find_unique
> ::const_iterator const_iterator
;
353 std::pair
<const_iterator
, bool> operator()(
354 const_iterator first
, const_iterator last
,
357 const_iterator
const it
= std::lower_bound(first
, last
, v
, Compare());
358 return std::make_pair(it
, (it
!= last
&& !Compare()(v
, *it
)));
362 /** the elements are partially ordered by Compare,
363 2 elements are allowed if they are not the same element (pointer equal)
365 template<class Value
, class Compare
>
366 struct find_partialorder_ptrequals
368 typedef typename sorted_vector
<Value
, Compare
,
369 o3tl::find_partialorder_ptrequals
>::const_iterator const_iterator
;
370 std::pair
<const_iterator
, bool> operator()(
371 const_iterator first
, const_iterator last
,
374 std::pair
<const_iterator
, const_iterator
> const its
=
375 std::equal_range(first
, last
, v
, Compare());
376 for (const_iterator it
= its
.first
; it
!= its
.second
; ++it
)
380 return std::make_pair(it
, true);
383 return std::make_pair(its
.first
, false);
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */