mirror of https://github.com/procxx/kepka.git
Use ranges:: algorithms instead of base::
This commit is contained in:
parent
bc7c88c511
commit
ac99318f34
|
@ -1873,11 +1873,15 @@ void ApiWrap::checkForUnreadMentions(const base::flat_set<MsgId> &possiblyReadMe
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::cancelEditChatAdmins(not_null<ChatData*> chat) {
|
void ApiWrap::cancelEditChatAdmins(not_null<ChatData*> chat) {
|
||||||
_chatAdminsEnabledRequests.take(chat)
|
_chatAdminsEnabledRequests.take(
|
||||||
| requestCanceller();
|
chat
|
||||||
|
) | requestCanceller();
|
||||||
|
|
||||||
_chatAdminsSaveRequests.take(chat)
|
_chatAdminsSaveRequests.take(
|
||||||
| base::for_each_apply(requestCanceller());
|
chat
|
||||||
|
) | [&](auto &&requests) {
|
||||||
|
ranges::for_each(std::move(requests), requestCanceller());
|
||||||
|
};
|
||||||
|
|
||||||
_chatAdminsToSave.remove(chat);
|
_chatAdminsToSave.remove(chat);
|
||||||
}
|
}
|
||||||
|
@ -1975,8 +1979,8 @@ void ApiWrap::sendSaveChatAdminsRequests(not_null<ChatData*> chat) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base::for_each(toRemove, removeOne);
|
ranges::for_each(toRemove, removeOne);
|
||||||
base::for_each(toAppoint, appointOne);
|
ranges::for_each(toAppoint, appointOne);
|
||||||
requestSendDelayed();
|
requestSendDelayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,109 +32,4 @@ inline constexpr size_t array_size(const Type(&)[Size]) {
|
||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range, typename Method>
|
|
||||||
decltype(auto) for_each(Range &&range, Method &&method) {
|
|
||||||
return std::for_each(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Method>(method));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Method>
|
|
||||||
decltype(auto) for_each_apply(Method &&method) {
|
|
||||||
return [&method](auto &&range) {
|
|
||||||
return for_each(std::forward<decltype(range)>(range), std::forward<Method>(method));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Value>
|
|
||||||
decltype(auto) find(Range &&range, Value &&value) {
|
|
||||||
return std::find(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Value>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Predicate>
|
|
||||||
decltype(auto) find_if(Range &&range, Predicate &&predicate) {
|
|
||||||
return std::find_if(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Predicate>(predicate));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Type>
|
|
||||||
decltype(auto) lower_bound(Range &&range, Type &&value) {
|
|
||||||
return std::lower_bound(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Type>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Type, typename Predicate>
|
|
||||||
decltype(auto) lower_bound(Range &&range, Type &&value, Predicate &&predicate) {
|
|
||||||
return std::lower_bound(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Type>(value),
|
|
||||||
std::forward<Predicate>(predicate));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Type>
|
|
||||||
decltype(auto) upper_bound(Range &&range, Type &&value) {
|
|
||||||
return std::upper_bound(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Type>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Type, typename Predicate>
|
|
||||||
decltype(auto) upper_bound(Range &&range, Type &&value, Predicate &&predicate) {
|
|
||||||
return std::upper_bound(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Type>(value),
|
|
||||||
std::forward<Predicate>(predicate));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Type>
|
|
||||||
decltype(auto) equal_range(Range &&range, Type &&value) {
|
|
||||||
return std::equal_range(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Type>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Type, typename Predicate>
|
|
||||||
decltype(auto) equal_range(Range &&range, Type &&value, Predicate &&predicate) {
|
|
||||||
return std::equal_range(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Type>(value),
|
|
||||||
std::forward<Predicate>(predicate));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range>
|
|
||||||
decltype(auto) sort(Range &&range) {
|
|
||||||
return std::sort(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Predicate>
|
|
||||||
decltype(auto) sort(Range &&range, Predicate &&predicate) {
|
|
||||||
return std::sort(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Predicate>(predicate));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Range, typename Predicate>
|
|
||||||
decltype(auto) stable_partition(Range &&range, Predicate &&predicate) {
|
|
||||||
return std::stable_partition(
|
|
||||||
std::begin(std::forward<Range>(range)),
|
|
||||||
std::end(std::forward<Range>(range)),
|
|
||||||
std::forward<Predicate>(predicate));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
|
|
@ -21,8 +21,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <algorithm>
|
||||||
#include "base/optional.h"
|
#include "base/optional.h"
|
||||||
#include "base/algorithm.h"
|
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
|
@ -39,18 +39,41 @@ template <
|
||||||
class flat_multi_map;
|
class flat_multi_map;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
|
typename Me,
|
||||||
typename Key,
|
typename Key,
|
||||||
typename Type,
|
typename Type,
|
||||||
typename Compare,
|
|
||||||
typename iterator_impl,
|
typename iterator_impl,
|
||||||
typename pointer_impl,
|
typename pointer_impl,
|
||||||
typename reference_impl>
|
typename reference_impl>
|
||||||
class flat_multi_map_iterator_base_impl;
|
class flat_multi_map_iterator_base_impl;
|
||||||
|
|
||||||
|
template <typename Key>
|
||||||
|
class flat_multi_map_key_const_wrap {
|
||||||
|
public:
|
||||||
|
constexpr flat_multi_map_key_const_wrap(const Key &value)
|
||||||
|
: _value(value) {
|
||||||
|
}
|
||||||
|
constexpr flat_multi_map_key_const_wrap(Key &&value)
|
||||||
|
: _value(std::move(value)) {
|
||||||
|
}
|
||||||
|
inline constexpr operator const Key&() const {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Key _value;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Key, typename Type>
|
||||||
|
using flat_multi_map_pair_type = std::pair<
|
||||||
|
flat_multi_map_key_const_wrap<Key>,
|
||||||
|
Type>;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
|
typename Me,
|
||||||
typename Key,
|
typename Key,
|
||||||
typename Type,
|
typename Type,
|
||||||
typename Compare,
|
|
||||||
typename iterator_impl,
|
typename iterator_impl,
|
||||||
typename pointer_impl,
|
typename pointer_impl,
|
||||||
typename reference_impl>
|
typename reference_impl>
|
||||||
|
@ -58,12 +81,13 @@ class flat_multi_map_iterator_base_impl {
|
||||||
public:
|
public:
|
||||||
using iterator_category = typename iterator_impl::iterator_category;
|
using iterator_category = typename iterator_impl::iterator_category;
|
||||||
|
|
||||||
using value_type = typename flat_multi_map<Key, Type, Compare>::value_type;
|
using pair_type = flat_multi_map_pair_type<Key, Type>;
|
||||||
|
using value_type = pair_type;
|
||||||
using difference_type = typename iterator_impl::difference_type;
|
using difference_type = typename iterator_impl::difference_type;
|
||||||
using pointer = pointer_impl;
|
using pointer = pointer_impl;
|
||||||
using const_pointer = typename flat_multi_map<Key, Type, Compare>::const_pointer;
|
using const_pointer = const pair_type*;
|
||||||
using reference = reference_impl;
|
using reference = reference_impl;
|
||||||
using const_reference = typename flat_multi_map<Key, Type, Compare>::const_reference;
|
using const_reference = const pair_type&;
|
||||||
|
|
||||||
flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl())
|
flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl())
|
||||||
: _impl(impl) {
|
: _impl(impl) {
|
||||||
|
@ -81,43 +105,44 @@ public:
|
||||||
const_pointer operator->() const {
|
const_pointer operator->() const {
|
||||||
return std::addressof(**this);
|
return std::addressof(**this);
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl &operator++() {
|
Me &operator++() {
|
||||||
++_impl;
|
++_impl;
|
||||||
return *this;
|
return static_cast<Me&>(*this);
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl operator++(int) {
|
Me operator++(int) {
|
||||||
return _impl++;
|
return _impl++;
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl &operator--() {
|
Me &operator--() {
|
||||||
--_impl;
|
--_impl;
|
||||||
return *this;
|
return static_cast<Me&>(*this);
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl operator--(int) {
|
Me operator--(int) {
|
||||||
return _impl--;
|
return _impl--;
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl &operator+=(difference_type offset) {
|
Me &operator+=(difference_type offset) {
|
||||||
_impl += offset;
|
_impl += offset;
|
||||||
return *this;
|
return static_cast<Me&>(*this);
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl operator+(difference_type offset) const {
|
Me operator+(difference_type offset) const {
|
||||||
return _impl + offset;
|
return _impl + offset;
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl &operator-=(difference_type offset) {
|
Me &operator-=(difference_type offset) {
|
||||||
_impl -= offset;
|
_impl -= offset;
|
||||||
return *this;
|
return static_cast<Me&>(*this);
|
||||||
}
|
}
|
||||||
flat_multi_map_iterator_base_impl operator-(difference_type offset) const {
|
Me operator-(difference_type offset) const {
|
||||||
return _impl - offset;
|
return _impl - offset;
|
||||||
}
|
}
|
||||||
template <
|
template <
|
||||||
|
typename other_me,
|
||||||
typename other_iterator_impl,
|
typename other_iterator_impl,
|
||||||
typename other_pointer_impl,
|
typename other_pointer_impl,
|
||||||
typename other_reference_impl>
|
typename other_reference_impl>
|
||||||
difference_type operator-(
|
difference_type operator-(
|
||||||
const flat_multi_map_iterator_base_impl<
|
const flat_multi_map_iterator_base_impl<
|
||||||
|
other_me,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
|
||||||
other_iterator_impl,
|
other_iterator_impl,
|
||||||
other_pointer_impl,
|
other_pointer_impl,
|
||||||
other_reference_impl> &right) const {
|
other_reference_impl> &right) const {
|
||||||
|
@ -131,42 +156,45 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
|
typename other_me,
|
||||||
typename other_iterator_impl,
|
typename other_iterator_impl,
|
||||||
typename other_pointer_impl,
|
typename other_pointer_impl,
|
||||||
typename other_reference_impl>
|
typename other_reference_impl>
|
||||||
bool operator==(
|
bool operator==(
|
||||||
const flat_multi_map_iterator_base_impl<
|
const flat_multi_map_iterator_base_impl<
|
||||||
|
other_me,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
|
||||||
other_iterator_impl,
|
other_iterator_impl,
|
||||||
other_pointer_impl,
|
other_pointer_impl,
|
||||||
other_reference_impl> &right) const {
|
other_reference_impl> &right) const {
|
||||||
return _impl == right._impl;
|
return _impl == right._impl;
|
||||||
}
|
}
|
||||||
template <
|
template <
|
||||||
|
typename other_me,
|
||||||
typename other_iterator_impl,
|
typename other_iterator_impl,
|
||||||
typename other_pointer_impl,
|
typename other_pointer_impl,
|
||||||
typename other_reference_impl>
|
typename other_reference_impl>
|
||||||
bool operator!=(
|
bool operator!=(
|
||||||
const flat_multi_map_iterator_base_impl<
|
const flat_multi_map_iterator_base_impl<
|
||||||
|
other_me,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
|
||||||
other_iterator_impl,
|
other_iterator_impl,
|
||||||
other_pointer_impl,
|
other_pointer_impl,
|
||||||
other_reference_impl> &right) const {
|
other_reference_impl> &right) const {
|
||||||
return _impl != right._impl;
|
return _impl != right._impl;
|
||||||
}
|
}
|
||||||
template <
|
template <
|
||||||
|
typename other_me,
|
||||||
typename other_iterator_impl,
|
typename other_iterator_impl,
|
||||||
typename other_pointer_impl,
|
typename other_pointer_impl,
|
||||||
typename other_reference_impl>
|
typename other_reference_impl>
|
||||||
bool operator<(
|
bool operator<(
|
||||||
const flat_multi_map_iterator_base_impl<
|
const flat_multi_map_iterator_base_impl<
|
||||||
|
other_me,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
|
||||||
other_iterator_impl,
|
other_iterator_impl,
|
||||||
other_pointer_impl,
|
other_pointer_impl,
|
||||||
other_reference_impl> &right) const {
|
other_reference_impl> &right) const {
|
||||||
|
@ -175,12 +203,17 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iterator_impl _impl;
|
iterator_impl _impl;
|
||||||
friend class flat_multi_map<Key, Type, Compare>;
|
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename OtherKey,
|
typename OtherKey,
|
||||||
typename OtherType,
|
typename OtherType,
|
||||||
typename OtherCompare,
|
typename OtherCompare>
|
||||||
|
friend class flat_multi_map;
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename OtherMe,
|
||||||
|
typename OtherKey,
|
||||||
|
typename OtherType,
|
||||||
typename other_iterator_impl,
|
typename other_iterator_impl,
|
||||||
typename other_pointer_impl,
|
typename other_pointer_impl,
|
||||||
typename other_reference_impl>
|
typename other_reference_impl>
|
||||||
|
@ -190,131 +223,50 @@ private:
|
||||||
|
|
||||||
template <typename Key, typename Type, typename Compare>
|
template <typename Key, typename Type, typename Compare>
|
||||||
class flat_multi_map {
|
class flat_multi_map {
|
||||||
class key_const_wrap {
|
public:
|
||||||
public:
|
class iterator;
|
||||||
constexpr key_const_wrap(const Key &value) : _value(value) {
|
class const_iterator;
|
||||||
}
|
class reverse_iterator;
|
||||||
constexpr key_const_wrap(Key &&value) : _value(std::move(value)) {
|
class const_reverse_iterator;
|
||||||
}
|
|
||||||
inline constexpr operator const Key&() const {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Key _value;
|
using key_const_wrap = flat_multi_map_key_const_wrap<Key>;
|
||||||
|
using pair_type = flat_multi_map_pair_type<Key, Type>;
|
||||||
};
|
using impl_t = std::deque<pair_type>;
|
||||||
using pair_type = std::pair<key_const_wrap, Type>;
|
|
||||||
|
|
||||||
class compare {
|
|
||||||
public:
|
|
||||||
template <
|
|
||||||
typename OtherType1,
|
|
||||||
typename OtherType2,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType1>, key_const_wrap> &&
|
|
||||||
!std::is_same_v<std::decay_t<OtherType1>, pair_type> &&
|
|
||||||
!std::is_same_v<std::decay_t<OtherType2>, key_const_wrap> &&
|
|
||||||
!std::is_same_v<std::decay_t<OtherType2>, pair_type>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
OtherType1 &&a,
|
|
||||||
OtherType2 &b) const {
|
|
||||||
return Compare()(
|
|
||||||
std::forward<OtherType1>(a),
|
|
||||||
std::forward<OtherType2>(b));
|
|
||||||
}
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
const key_const_wrap &a,
|
|
||||||
const key_const_wrap &b) const {
|
|
||||||
return operator()(
|
|
||||||
static_cast<const Key&>(a),
|
|
||||||
static_cast<const Key&>(b));
|
|
||||||
}
|
|
||||||
template <
|
|
||||||
typename OtherType,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
const key_const_wrap &a,
|
|
||||||
OtherType &&b) const {
|
|
||||||
return operator()(
|
|
||||||
static_cast<const Key&>(a),
|
|
||||||
std::forward<OtherType>(b));
|
|
||||||
}
|
|
||||||
template <
|
|
||||||
typename OtherType,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
OtherType &&a,
|
|
||||||
const key_const_wrap &b) const {
|
|
||||||
return operator()(
|
|
||||||
std::forward<OtherType>(a),
|
|
||||||
static_cast<const Key&>(b));
|
|
||||||
}
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
const pair_type &a,
|
|
||||||
const pair_type &b) const {
|
|
||||||
return operator()(a.first, b.first);
|
|
||||||
}
|
|
||||||
template <
|
|
||||||
typename OtherType,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
const pair_type &a,
|
|
||||||
OtherType &&b) const {
|
|
||||||
return operator()(a.first, std::forward<OtherType>(b));
|
|
||||||
}
|
|
||||||
template <
|
|
||||||
typename OtherType,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
OtherType &&a,
|
|
||||||
const pair_type &b) const {
|
|
||||||
return operator()(std::forward<OtherType>(a), b.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
using impl = std::deque<pair_type>;
|
|
||||||
|
|
||||||
using iterator_base = flat_multi_map_iterator_base_impl<
|
using iterator_base = flat_multi_map_iterator_base_impl<
|
||||||
|
iterator,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::iterator,
|
||||||
typename impl::iterator,
|
|
||||||
pair_type*,
|
pair_type*,
|
||||||
pair_type&>;
|
pair_type&>;
|
||||||
using const_iterator_base = flat_multi_map_iterator_base_impl<
|
using const_iterator_base = flat_multi_map_iterator_base_impl<
|
||||||
|
const_iterator,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::const_iterator,
|
||||||
typename impl::const_iterator,
|
|
||||||
const pair_type*,
|
const pair_type*,
|
||||||
const pair_type&>;
|
const pair_type&>;
|
||||||
using reverse_iterator_base = flat_multi_map_iterator_base_impl<
|
using reverse_iterator_base = flat_multi_map_iterator_base_impl<
|
||||||
|
reverse_iterator,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::reverse_iterator,
|
||||||
typename impl::reverse_iterator,
|
|
||||||
pair_type*,
|
pair_type*,
|
||||||
pair_type&>;
|
pair_type&>;
|
||||||
using const_reverse_iterator_base = flat_multi_map_iterator_base_impl<
|
using const_reverse_iterator_base = flat_multi_map_iterator_base_impl<
|
||||||
|
const_reverse_iterator,
|
||||||
Key,
|
Key,
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::const_reverse_iterator,
|
||||||
typename impl::const_reverse_iterator,
|
|
||||||
const pair_type*,
|
const pair_type*,
|
||||||
const pair_type&>;
|
const pair_type&>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = pair_type;
|
using value_type = pair_type;
|
||||||
using size_type = typename impl::size_type;
|
using size_type = typename impl_t::size_type;
|
||||||
using difference_type = typename impl::difference_type;
|
using difference_type = typename impl_t::difference_type;
|
||||||
using pointer = pair_type*;
|
using pointer = pair_type*;
|
||||||
using const_pointer = const pair_type*;
|
using const_pointer = const pair_type*;
|
||||||
using reference = pair_type&;
|
using reference = pair_type&;
|
||||||
|
@ -324,6 +276,7 @@ public:
|
||||||
class iterator : public iterator_base {
|
class iterator : public iterator_base {
|
||||||
public:
|
public:
|
||||||
using iterator_base::iterator_base;
|
using iterator_base::iterator_base;
|
||||||
|
iterator() = default;
|
||||||
iterator(const iterator_base &other) : iterator_base(other) {
|
iterator(const iterator_base &other) : iterator_base(other) {
|
||||||
}
|
}
|
||||||
friend class const_iterator;
|
friend class const_iterator;
|
||||||
|
@ -332,6 +285,7 @@ public:
|
||||||
class const_iterator : public const_iterator_base {
|
class const_iterator : public const_iterator_base {
|
||||||
public:
|
public:
|
||||||
using const_iterator_base::const_iterator_base;
|
using const_iterator_base::const_iterator_base;
|
||||||
|
const_iterator() = default;
|
||||||
const_iterator(const_iterator_base other) : const_iterator_base(other) {
|
const_iterator(const_iterator_base other) : const_iterator_base(other) {
|
||||||
}
|
}
|
||||||
const_iterator(const iterator &other) : const_iterator_base(other._impl) {
|
const_iterator(const iterator &other) : const_iterator_base(other._impl) {
|
||||||
|
@ -342,6 +296,7 @@ public:
|
||||||
class reverse_iterator : public reverse_iterator_base {
|
class reverse_iterator : public reverse_iterator_base {
|
||||||
public:
|
public:
|
||||||
using reverse_iterator_base::reverse_iterator_base;
|
using reverse_iterator_base::reverse_iterator_base;
|
||||||
|
reverse_iterator() = default;
|
||||||
reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) {
|
reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) {
|
||||||
}
|
}
|
||||||
friend class const_reverse_iterator;
|
friend class const_reverse_iterator;
|
||||||
|
@ -350,6 +305,7 @@ public:
|
||||||
class const_reverse_iterator : public const_reverse_iterator_base {
|
class const_reverse_iterator : public const_reverse_iterator_base {
|
||||||
public:
|
public:
|
||||||
using const_reverse_iterator_base::const_reverse_iterator_base;
|
using const_reverse_iterator_base::const_reverse_iterator_base;
|
||||||
|
const_reverse_iterator() = default;
|
||||||
const_reverse_iterator(const_reverse_iterator_base other) : const_reverse_iterator_base(other) {
|
const_reverse_iterator(const_reverse_iterator_base other) : const_reverse_iterator_base(other) {
|
||||||
}
|
}
|
||||||
const_reverse_iterator(const reverse_iterator &other) : const_reverse_iterator_base(other._impl) {
|
const_reverse_iterator(const reverse_iterator &other) : const_reverse_iterator_base(other._impl) {
|
||||||
|
@ -358,50 +314,50 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
size_type size() const {
|
size_type size() const {
|
||||||
return _impl.size();
|
return impl().size();
|
||||||
}
|
}
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return _impl.empty();
|
return impl().empty();
|
||||||
}
|
}
|
||||||
void clear() {
|
void clear() {
|
||||||
_impl.clear();
|
impl().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
return _impl.begin();
|
return impl().begin();
|
||||||
}
|
}
|
||||||
iterator end() {
|
iterator end() {
|
||||||
return _impl.end();
|
return impl().end();
|
||||||
}
|
}
|
||||||
const_iterator begin() const {
|
const_iterator begin() const {
|
||||||
return _impl.begin();
|
return impl().begin();
|
||||||
}
|
}
|
||||||
const_iterator end() const {
|
const_iterator end() const {
|
||||||
return _impl.end();
|
return impl().end();
|
||||||
}
|
}
|
||||||
const_iterator cbegin() const {
|
const_iterator cbegin() const {
|
||||||
return _impl.cbegin();
|
return impl().cbegin();
|
||||||
}
|
}
|
||||||
const_iterator cend() const {
|
const_iterator cend() const {
|
||||||
return _impl.cend();
|
return impl().cend();
|
||||||
}
|
}
|
||||||
reverse_iterator rbegin() {
|
reverse_iterator rbegin() {
|
||||||
return _impl.rbegin();
|
return impl().rbegin();
|
||||||
}
|
}
|
||||||
reverse_iterator rend() {
|
reverse_iterator rend() {
|
||||||
return _impl.rend();
|
return impl().rend();
|
||||||
}
|
}
|
||||||
const_reverse_iterator rbegin() const {
|
const_reverse_iterator rbegin() const {
|
||||||
return _impl.rbegin();
|
return impl().rbegin();
|
||||||
}
|
}
|
||||||
const_reverse_iterator rend() const {
|
const_reverse_iterator rend() const {
|
||||||
return _impl.rend();
|
return impl().rend();
|
||||||
}
|
}
|
||||||
const_reverse_iterator crbegin() const {
|
const_reverse_iterator crbegin() const {
|
||||||
return _impl.crbegin();
|
return impl().crbegin();
|
||||||
}
|
}
|
||||||
const_reverse_iterator crend() const {
|
const_reverse_iterator crend() const {
|
||||||
return _impl.crend();
|
return impl().crend();
|
||||||
}
|
}
|
||||||
|
|
||||||
reference front() {
|
reference front() {
|
||||||
|
@ -419,25 +375,25 @@ public:
|
||||||
|
|
||||||
iterator insert(const value_type &value) {
|
iterator insert(const value_type &value) {
|
||||||
if (empty() || compare()(value.first, front().first)) {
|
if (empty() || compare()(value.first, front().first)) {
|
||||||
_impl.push_front(value);
|
impl().push_front(value);
|
||||||
return begin();
|
return begin();
|
||||||
} else if (!compare()(value.first, back().first)) {
|
} else if (!compare()(value.first, back().first)) {
|
||||||
_impl.push_back(value);
|
impl().push_back(value);
|
||||||
return (end() - 1);
|
return (end() - 1);
|
||||||
}
|
}
|
||||||
auto where = getUpperBound(value.first);
|
auto where = getUpperBound(value.first);
|
||||||
return _impl.insert(where, value);
|
return impl().insert(where, value);
|
||||||
}
|
}
|
||||||
iterator insert(value_type &&value) {
|
iterator insert(value_type &&value) {
|
||||||
if (empty() || compare()(value.first, front().first)) {
|
if (empty() || compare()(value.first, front().first)) {
|
||||||
_impl.push_front(std::move(value));
|
impl().push_front(std::move(value));
|
||||||
return begin();
|
return begin();
|
||||||
} else if (!compare()(value.first, back().first)) {
|
} else if (!compare()(value.first, back().first)) {
|
||||||
_impl.push_back(std::move(value));
|
impl().push_back(std::move(value));
|
||||||
return (end() - 1);
|
return (end() - 1);
|
||||||
}
|
}
|
||||||
auto where = getUpperBound(value.first);
|
auto where = getUpperBound(value.first);
|
||||||
return _impl.insert(where, std::move(value));
|
return impl().insert(where, std::move(value));
|
||||||
}
|
}
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
iterator emplace(Args&&... args) {
|
iterator emplace(Args&&... args) {
|
||||||
|
@ -454,7 +410,7 @@ public:
|
||||||
if (compare()(key, where->first)) {
|
if (compare()(key, where->first)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_impl.erase(where);
|
impl().erase(where);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int removeAll(const Key &key) {
|
int removeAll(const Key &key) {
|
||||||
|
@ -467,15 +423,15 @@ public:
|
||||||
if (range.first == range.second) {
|
if (range.first == range.second) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
_impl.erase(range.first, range.second);
|
impl().erase(range.first, range.second);
|
||||||
return (range.second - range.first);
|
return (range.second - range.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator erase(const_iterator where) {
|
iterator erase(const_iterator where) {
|
||||||
return _impl.erase(where._impl);
|
return impl().erase(where._impl);
|
||||||
}
|
}
|
||||||
iterator erase(const_iterator from, const_iterator till) {
|
iterator erase(const_iterator from, const_iterator till) {
|
||||||
return _impl.erase(from._impl, till._impl);
|
return impl().erase(from._impl, till._impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator findFirst(const Key &key) {
|
iterator findFirst(const Key &key) {
|
||||||
|
@ -485,7 +441,7 @@ public:
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
auto where = getLowerBound(key);
|
auto where = getLowerBound(key);
|
||||||
return compare()(key, where->first) ? _impl.end() : where;
|
return compare()(key, where->first) ? impl().end() : where;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator findFirst(const Key &key) const {
|
const_iterator findFirst(const Key &key) const {
|
||||||
|
@ -495,7 +451,7 @@ public:
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
auto where = getLowerBound(key);
|
auto where = getLowerBound(key);
|
||||||
return compare()(key, where->first) ? _impl.end() : where;
|
return compare()(key, where->first) ? impl().end() : where;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(const Key &key) const {
|
bool contains(const Key &key) const {
|
||||||
|
@ -512,32 +468,167 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl _impl;
|
|
||||||
friend class flat_map<Key, Type, Compare>;
|
friend class flat_map<Key, Type, Compare>;
|
||||||
|
|
||||||
typename impl::iterator getLowerBound(const Key &key) {
|
struct transparent_compare : Compare {
|
||||||
return base::lower_bound(_impl, key, compare());
|
inline constexpr const Compare &initial() const noexcept {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename OtherType1,
|
||||||
|
typename OtherType2,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType1>, key_const_wrap> &&
|
||||||
|
!std::is_same_v<std::decay_t<OtherType1>, pair_type> &&
|
||||||
|
!std::is_same_v<std::decay_t<OtherType2>, key_const_wrap> &&
|
||||||
|
!std::is_same_v<std::decay_t<OtherType2>, pair_type>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType1 &&a,
|
||||||
|
OtherType2 &&b) const {
|
||||||
|
return initial()(
|
||||||
|
std::forward<OtherType1>(a),
|
||||||
|
std::forward<OtherType2>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType1,
|
||||||
|
typename OtherType2>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType1 &&a,
|
||||||
|
OtherType2 &&b) const -> std::enable_if_t<
|
||||||
|
std::is_same_v<std::decay_t<OtherType1>, key_const_wrap> &&
|
||||||
|
std::is_same_v<std::decay_t<OtherType2>, key_const_wrap>, bool> {
|
||||||
|
return initial()(
|
||||||
|
static_cast<const Key&>(a),
|
||||||
|
static_cast<const Key&>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
const key_const_wrap &a,
|
||||||
|
OtherType &&b) const {
|
||||||
|
return initial()(
|
||||||
|
static_cast<const Key&>(a),
|
||||||
|
std::forward<OtherType>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType &&a,
|
||||||
|
const key_const_wrap &b) const {
|
||||||
|
return initial()(
|
||||||
|
std::forward<OtherType>(a),
|
||||||
|
static_cast<const Key&>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType1,
|
||||||
|
typename OtherType2>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType1 &&a,
|
||||||
|
OtherType2 &&b) const -> std::enable_if_t<
|
||||||
|
std::is_same_v<std::decay_t<OtherType1>, pair_type> &&
|
||||||
|
std::is_same_v<std::decay_t<OtherType2>, pair_type>, bool> {
|
||||||
|
return initial()(
|
||||||
|
static_cast<const Key&>(a.first),
|
||||||
|
static_cast<const Key&>(b.first));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
const pair_type &a,
|
||||||
|
OtherType &&b) const {
|
||||||
|
return operator()(
|
||||||
|
static_cast<const Key&>(a.first),
|
||||||
|
std::forward<OtherType>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType &&a,
|
||||||
|
const pair_type &b) const {
|
||||||
|
return operator()(
|
||||||
|
std::forward<OtherType>(a),
|
||||||
|
static_cast<const Key&>(b.first));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
struct Data : transparent_compare {
|
||||||
|
template <typename ...Args>
|
||||||
|
Data(Args &&...args)
|
||||||
|
: elements(std::forward<Args>(args)...) {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_t elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
Data _data;
|
||||||
|
const transparent_compare &compare() const noexcept {
|
||||||
|
return _data;
|
||||||
}
|
}
|
||||||
typename impl::const_iterator getLowerBound(const Key &key) const {
|
const impl_t &impl() const noexcept {
|
||||||
return base::lower_bound(_impl, key, compare());
|
return _data.elements;
|
||||||
}
|
}
|
||||||
typename impl::iterator getUpperBound(const Key &key) {
|
impl_t &impl() noexcept {
|
||||||
return base::upper_bound(_impl, key, compare());
|
return _data.elements;
|
||||||
}
|
}
|
||||||
typename impl::const_iterator getUpperBound(const Key &key) const {
|
|
||||||
return base::upper_bound(_impl, key, compare());
|
typename impl_t::iterator getLowerBound(const Key &key) {
|
||||||
|
return std::lower_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
key,
|
||||||
|
compare());
|
||||||
|
}
|
||||||
|
typename impl_t::const_iterator getLowerBound(const Key &key) const {
|
||||||
|
return std::lower_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
key,
|
||||||
|
compare());
|
||||||
|
}
|
||||||
|
typename impl_t::iterator getUpperBound(const Key &key) {
|
||||||
|
return std::upper_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
key,
|
||||||
|
compare());
|
||||||
|
}
|
||||||
|
typename impl_t::const_iterator getUpperBound(const Key &key) const {
|
||||||
|
return std::upper_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
key,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
std::pair<
|
std::pair<
|
||||||
typename impl::iterator,
|
typename impl_t::iterator,
|
||||||
typename impl::iterator
|
typename impl_t::iterator
|
||||||
> getEqualRange(const Key &key) {
|
> getEqualRange(const Key &key) {
|
||||||
return base::equal_range(_impl, key, compare());
|
return std::equal_range(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
key,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
std::pair<
|
std::pair<
|
||||||
typename impl::const_iterator,
|
typename impl_t::const_iterator,
|
||||||
typename impl::const_iterator
|
typename impl_t::const_iterator
|
||||||
> getEqualRange(const Key &key) const {
|
> getEqualRange(const Key &key) const {
|
||||||
return base::equal_range(_impl, key, compare());
|
return std::equal_range(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
key,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -545,7 +636,6 @@ private:
|
||||||
template <typename Key, typename Type, typename Compare>
|
template <typename Key, typename Type, typename Compare>
|
||||||
class flat_map : private flat_multi_map<Key, Type, Compare> {
|
class flat_map : private flat_multi_map<Key, Type, Compare> {
|
||||||
using parent = flat_multi_map<Key, Type, Compare>;
|
using parent = flat_multi_map<Key, Type, Compare>;
|
||||||
using compare = typename parent::compare;
|
|
||||||
using pair_type = typename parent::pair_type;
|
using pair_type = typename parent::pair_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -579,30 +669,30 @@ public:
|
||||||
using parent::contains;
|
using parent::contains;
|
||||||
|
|
||||||
std::pair<iterator, bool> insert(const value_type &value) {
|
std::pair<iterator, bool> insert(const value_type &value) {
|
||||||
if (this->empty() || compare()(value.first, this->front().first)) {
|
if (this->empty() || this->compare()(value.first, this->front().first)) {
|
||||||
this->_impl.push_front(value);
|
this->impl().push_front(value);
|
||||||
return { this->begin(), true };
|
return { this->begin(), true };
|
||||||
} else if (compare()(this->back().first, value.first)) {
|
} else if (this->compare()(this->back().first, value.first)) {
|
||||||
this->_impl.push_back(value);
|
this->impl().push_back(value);
|
||||||
return { this->end() - 1, true };
|
return { this->end() - 1, true };
|
||||||
}
|
}
|
||||||
auto where = this->getLowerBound(value.first);
|
auto where = this->getLowerBound(value.first);
|
||||||
if (compare()(value.first, where->first)) {
|
if (this->compare()(value.first, where->first)) {
|
||||||
return { this->_impl.insert(where, value), true };
|
return { this->impl().insert(where, value), true };
|
||||||
}
|
}
|
||||||
return { where, false };
|
return { where, false };
|
||||||
}
|
}
|
||||||
std::pair<iterator, bool> insert(value_type &&value) {
|
std::pair<iterator, bool> insert(value_type &&value) {
|
||||||
if (this->empty() || compare()(value.first, this->front().first)) {
|
if (this->empty() || this->compare()(value.first, this->front().first)) {
|
||||||
this->_impl.push_front(std::move(value));
|
this->impl().push_front(std::move(value));
|
||||||
return { this->begin(), true };
|
return { this->begin(), true };
|
||||||
} else if (compare()(this->back().first, value.first)) {
|
} else if (this->compare()(this->back().first, value.first)) {
|
||||||
this->_impl.push_back(std::move(value));
|
this->impl().push_back(std::move(value));
|
||||||
return { this->end() - 1, true };
|
return { this->end() - 1, true };
|
||||||
}
|
}
|
||||||
auto where = this->getLowerBound(value.first);
|
auto where = this->getLowerBound(value.first);
|
||||||
if (compare()(value.first, where->first)) {
|
if (this->compare()(value.first, where->first)) {
|
||||||
return { this->_impl.insert(where, std::move(value)), true };
|
return { this->impl().insert(where, std::move(value)), true };
|
||||||
}
|
}
|
||||||
return { where, false };
|
return { where, false };
|
||||||
}
|
}
|
||||||
|
@ -618,21 +708,21 @@ public:
|
||||||
std::pair<iterator, bool> try_emplace(
|
std::pair<iterator, bool> try_emplace(
|
||||||
const Key &key,
|
const Key &key,
|
||||||
Args&&... args) {
|
Args&&... args) {
|
||||||
if (this->empty() || compare()(key, this->front().first)) {
|
if (this->empty() || this->compare()(key, this->front().first)) {
|
||||||
this->_impl.push_front(value_type(
|
this->impl().push_front(value_type(
|
||||||
key,
|
key,
|
||||||
Type(std::forward<Args>(args)...)));
|
Type(std::forward<Args>(args)...)));
|
||||||
return { this->begin(), true };
|
return { this->begin(), true };
|
||||||
} else if (compare()(this->back().first, key)) {
|
} else if (this->compare()(this->back().first, key)) {
|
||||||
this->_impl.push_back(value_type(
|
this->impl().push_back(value_type(
|
||||||
key,
|
key,
|
||||||
Type(std::forward<Args>(args)...)));
|
Type(std::forward<Args>(args)...)));
|
||||||
return { this->end() - 1, true };
|
return { this->end() - 1, true };
|
||||||
}
|
}
|
||||||
auto where = this->getLowerBound(key);
|
auto where = this->getLowerBound(key);
|
||||||
if (compare()(key, where->first)) {
|
if (this->compare()(key, where->first)) {
|
||||||
return {
|
return {
|
||||||
this->_impl.insert(
|
this->impl().insert(
|
||||||
where,
|
where,
|
||||||
value_type(
|
value_type(
|
||||||
key,
|
key,
|
||||||
|
@ -655,16 +745,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Type &operator[](const Key &key) {
|
Type &operator[](const Key &key) {
|
||||||
if (this->empty() || compare()(key, this->front().first)) {
|
if (this->empty() || this->compare()(key, this->front().first)) {
|
||||||
this->_impl.push_front({ key, Type() });
|
this->impl().push_front({ key, Type() });
|
||||||
return this->front().second;
|
return this->front().second;
|
||||||
} else if (compare()(this->back().first, key)) {
|
} else if (this->compare()(this->back().first, key)) {
|
||||||
this->_impl.push_back({ key, Type() });
|
this->impl().push_back({ key, Type() });
|
||||||
return this->back().second;
|
return this->back().second;
|
||||||
}
|
}
|
||||||
auto where = this->getLowerBound(key);
|
auto where = this->getLowerBound(key);
|
||||||
if (compare()(key, where->first)) {
|
if (this->compare()(key, where->first)) {
|
||||||
return this->_impl.insert(where, { key, Type() })->second;
|
return this->impl().insert(where, { key, Type() })->second;
|
||||||
}
|
}
|
||||||
return where->second;
|
return where->second;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "base/flat_map.h"
|
#include "base/flat_map.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
struct int_wrap {
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
struct int_wrap_comparator {
|
||||||
|
inline bool operator()(const int_wrap &a, const int_wrap &b) const {
|
||||||
|
return a.value < b.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") {
|
TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") {
|
||||||
|
@ -49,3 +58,28 @@ TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") {
|
||||||
checkSorted();
|
checkSorted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("flat_maps custom comparator", "[flat_map]") {
|
||||||
|
base::flat_map<int_wrap, string, int_wrap_comparator> v;
|
||||||
|
v.emplace({ 0 }, "a");
|
||||||
|
v.emplace({ 5 }, "b");
|
||||||
|
v.emplace({ 4 }, "d");
|
||||||
|
v.emplace({ 2 }, "e");
|
||||||
|
|
||||||
|
auto checkSorted = [&] {
|
||||||
|
auto prev = v.begin();
|
||||||
|
REQUIRE(prev != v.end());
|
||||||
|
for (auto i = prev + 1; i != v.end(); prev = i, ++i) {
|
||||||
|
REQUIRE(int_wrap_comparator()(prev->first, i->first));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REQUIRE(v.size() == 4);
|
||||||
|
checkSorted();
|
||||||
|
|
||||||
|
SECTION("adding item puts it in the right position") {
|
||||||
|
v.emplace({ 3 }, "c");
|
||||||
|
REQUIRE(v.size() == 5);
|
||||||
|
REQUIRE(v.find({ 3 }) != v.end());
|
||||||
|
checkSorted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include "base/algorithm.h"
|
#include <algorithm>
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
|
@ -31,28 +31,29 @@ class flat_set;
|
||||||
template <typename Type, typename Compare = std::less<>>
|
template <typename Type, typename Compare = std::less<>>
|
||||||
class flat_multi_set;
|
class flat_multi_set;
|
||||||
|
|
||||||
template <typename Type, typename Compare, typename iterator_impl>
|
template <typename Type, typename iterator_impl>
|
||||||
class flat_multi_set_iterator_impl;
|
class flat_multi_set_iterator_impl;
|
||||||
|
|
||||||
template <typename Type, typename Compare, typename iterator_impl>
|
template <typename Type, typename iterator_impl>
|
||||||
class flat_multi_set_iterator_impl {
|
class flat_multi_set_iterator_impl {
|
||||||
public:
|
public:
|
||||||
using iterator_category = typename iterator_impl::iterator_category;
|
using iterator_category = typename iterator_impl::iterator_category;
|
||||||
|
|
||||||
using value_type = typename flat_multi_set<Type, Compare>::value_type;
|
using value_type = Type;
|
||||||
using difference_type = typename iterator_impl::difference_type;
|
using difference_type = typename iterator_impl::difference_type;
|
||||||
using pointer = typename flat_multi_set<Type, Compare>::pointer;
|
using pointer = const Type*;
|
||||||
using reference = typename flat_multi_set<Type, Compare>::reference;
|
using reference = const Type&;
|
||||||
|
|
||||||
flat_multi_set_iterator_impl(iterator_impl impl = iterator_impl())
|
flat_multi_set_iterator_impl(
|
||||||
: _impl(impl) {
|
iterator_impl impl = iterator_impl())
|
||||||
|
: _impl(impl) {
|
||||||
}
|
}
|
||||||
template <typename other_iterator_impl>
|
template <typename other_iterator_impl>
|
||||||
flat_multi_set_iterator_impl(
|
flat_multi_set_iterator_impl(
|
||||||
const flat_multi_set_iterator_impl<
|
const flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
other_iterator_impl> &other)
|
||||||
other_iterator_impl> &other) : _impl(other._impl) {
|
: _impl(other._impl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
reference operator*() const {
|
reference operator*() const {
|
||||||
|
@ -91,10 +92,9 @@ public:
|
||||||
}
|
}
|
||||||
template <typename other_iterator_impl>
|
template <typename other_iterator_impl>
|
||||||
difference_type operator-(
|
difference_type operator-(
|
||||||
const flat_multi_set_iterator_impl<
|
const flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
other_iterator_impl> &right) const {
|
||||||
other_iterator_impl> &right) const {
|
|
||||||
return _impl - right._impl;
|
return _impl - right._impl;
|
||||||
}
|
}
|
||||||
reference operator[](difference_type offset) const {
|
reference operator[](difference_type offset) const {
|
||||||
|
@ -103,37 +103,37 @@ public:
|
||||||
|
|
||||||
template <typename other_iterator_impl>
|
template <typename other_iterator_impl>
|
||||||
bool operator==(
|
bool operator==(
|
||||||
const flat_multi_set_iterator_impl<
|
const flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
other_iterator_impl> &right) const {
|
||||||
other_iterator_impl> &right) const {
|
|
||||||
return _impl == right._impl;
|
return _impl == right._impl;
|
||||||
}
|
}
|
||||||
template <typename other_iterator_impl>
|
template <typename other_iterator_impl>
|
||||||
bool operator!=(
|
bool operator!=(
|
||||||
const flat_multi_set_iterator_impl<
|
const flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
other_iterator_impl> &right) const {
|
||||||
other_iterator_impl> &right) const {
|
|
||||||
return _impl != right._impl;
|
return _impl != right._impl;
|
||||||
}
|
}
|
||||||
template <typename other_iterator_impl>
|
template <typename other_iterator_impl>
|
||||||
bool operator<(
|
bool operator<(
|
||||||
const flat_multi_set_iterator_impl<
|
const flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
other_iterator_impl> &right) const {
|
||||||
other_iterator_impl> &right) const {
|
|
||||||
return _impl < right._impl;
|
return _impl < right._impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iterator_impl _impl;
|
iterator_impl _impl;
|
||||||
friend class flat_multi_set<Type, Compare>;
|
|
||||||
friend class flat_set<Type, Compare>;
|
template <typename OtherType, typename OtherCompare>
|
||||||
|
friend class flat_multi_set;
|
||||||
|
|
||||||
|
template <typename OtherType, typename OtherCompare>
|
||||||
|
friend class flat_set;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename OtherType,
|
typename OtherType,
|
||||||
typename OtherCompare,
|
|
||||||
typename other_iterator_impl>
|
typename other_iterator_impl>
|
||||||
friend class flat_multi_set_iterator_impl;
|
friend class flat_multi_set_iterator_impl;
|
||||||
|
|
||||||
|
@ -143,159 +143,111 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
class flat_multi_set_const_wrap {
|
||||||
|
public:
|
||||||
|
constexpr flat_multi_set_const_wrap(const Type &value)
|
||||||
|
: _value(value) {
|
||||||
|
}
|
||||||
|
constexpr flat_multi_set_const_wrap(Type &&value)
|
||||||
|
: _value(std::move(value)) {
|
||||||
|
}
|
||||||
|
inline constexpr operator const Type&() const {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
constexpr Type &wrapped() {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type _value;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Type, typename Compare>
|
template <typename Type, typename Compare>
|
||||||
class flat_multi_set {
|
class flat_multi_set {
|
||||||
class const_wrap {
|
using const_wrap = flat_multi_set_const_wrap<Type>;
|
||||||
public:
|
using impl_t = std::deque<const_wrap>;
|
||||||
constexpr const_wrap(const Type &value)
|
|
||||||
: _value(value) {
|
|
||||||
}
|
|
||||||
constexpr const_wrap(Type &&value)
|
|
||||||
: _value(std::move(value)) {
|
|
||||||
}
|
|
||||||
inline constexpr operator const Type&() const {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
constexpr Type &wrapped() {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type _value;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class compare {
|
|
||||||
public:
|
|
||||||
template <
|
|
||||||
typename OtherType1,
|
|
||||||
typename OtherType2,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType1>, const_wrap> &&
|
|
||||||
!std::is_same_v<std::decay_t<OtherType2>, const_wrap>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
OtherType1 &&a,
|
|
||||||
OtherType2 &b) const {
|
|
||||||
return Compare()(
|
|
||||||
std::forward<OtherType1>(a),
|
|
||||||
std::forward<OtherType2>(b));
|
|
||||||
}
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
const const_wrap &a,
|
|
||||||
const const_wrap &b) const {
|
|
||||||
return operator()(
|
|
||||||
static_cast<const Type&>(a),
|
|
||||||
static_cast<const Type&>(b));
|
|
||||||
}
|
|
||||||
template <
|
|
||||||
typename OtherType,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
const const_wrap &a,
|
|
||||||
OtherType &&b) const {
|
|
||||||
return operator()(
|
|
||||||
static_cast<const Type&>(a),
|
|
||||||
std::forward<OtherType>(b));
|
|
||||||
}
|
|
||||||
template <
|
|
||||||
typename OtherType,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
|
||||||
inline constexpr auto operator()(
|
|
||||||
OtherType &&a,
|
|
||||||
const const_wrap &b) const {
|
|
||||||
return operator()(
|
|
||||||
std::forward<OtherType>(a),
|
|
||||||
static_cast<const Type&>(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
using impl = std::deque<const_wrap>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = Type;
|
using value_type = Type;
|
||||||
using size_type = typename impl::size_type;
|
using size_type = typename impl_t::size_type;
|
||||||
using difference_type = typename impl::difference_type;
|
using difference_type = typename impl_t::difference_type;
|
||||||
using pointer = const Type*;
|
using pointer = const Type*;
|
||||||
using reference = const Type&;
|
using reference = const Type&;
|
||||||
|
|
||||||
using iterator = flat_multi_set_iterator_impl<
|
using iterator = flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::iterator>;
|
||||||
typename impl::iterator>;
|
|
||||||
using const_iterator = flat_multi_set_iterator_impl<
|
using const_iterator = flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::const_iterator>;
|
||||||
typename impl::const_iterator>;
|
|
||||||
using reverse_iterator = flat_multi_set_iterator_impl<
|
using reverse_iterator = flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::reverse_iterator>;
|
||||||
typename impl::reverse_iterator>;
|
|
||||||
using const_reverse_iterator = flat_multi_set_iterator_impl<
|
using const_reverse_iterator = flat_multi_set_iterator_impl<
|
||||||
Type,
|
Type,
|
||||||
Compare,
|
typename impl_t::const_reverse_iterator>;
|
||||||
typename impl::const_reverse_iterator>;
|
|
||||||
|
|
||||||
flat_multi_set() = default;
|
flat_multi_set() = default;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename Iterator,
|
typename Iterator,
|
||||||
typename = typename std::iterator_traits<Iterator>::iterator_category>
|
typename = typename std::iterator_traits<Iterator>::iterator_category>
|
||||||
flat_multi_set(Iterator first, Iterator last) : _impl(first, last) {
|
flat_multi_set(Iterator first, Iterator last)
|
||||||
base::sort(_impl, compare());
|
: _data(first, last) {
|
||||||
|
std::sort(std::begin(impl()), std::end(impl()), compare());
|
||||||
}
|
}
|
||||||
|
|
||||||
flat_multi_set(std::initializer_list<Type> iter)
|
flat_multi_set(std::initializer_list<Type> iter)
|
||||||
: flat_multi_set(iter.begin(), iter.end()) {
|
: flat_multi_set(iter.begin(), iter.end()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type size() const {
|
size_type size() const {
|
||||||
return _impl.size();
|
return impl().size();
|
||||||
}
|
}
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return _impl.empty();
|
return impl().empty();
|
||||||
}
|
}
|
||||||
void clear() {
|
void clear() {
|
||||||
_impl.clear();
|
impl().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
return _impl.begin();
|
return impl().begin();
|
||||||
}
|
}
|
||||||
iterator end() {
|
iterator end() {
|
||||||
return _impl.end();
|
return impl().end();
|
||||||
}
|
}
|
||||||
const_iterator begin() const {
|
const_iterator begin() const {
|
||||||
return _impl.begin();
|
return impl().begin();
|
||||||
}
|
}
|
||||||
const_iterator end() const {
|
const_iterator end() const {
|
||||||
return _impl.end();
|
return impl().end();
|
||||||
}
|
}
|
||||||
const_iterator cbegin() const {
|
const_iterator cbegin() const {
|
||||||
return _impl.cbegin();
|
return impl().cbegin();
|
||||||
}
|
}
|
||||||
const_iterator cend() const {
|
const_iterator cend() const {
|
||||||
return _impl.cend();
|
return impl().cend();
|
||||||
}
|
}
|
||||||
reverse_iterator rbegin() {
|
reverse_iterator rbegin() {
|
||||||
return _impl.rbegin();
|
return impl().rbegin();
|
||||||
}
|
}
|
||||||
reverse_iterator rend() {
|
reverse_iterator rend() {
|
||||||
return _impl.rend();
|
return impl().rend();
|
||||||
}
|
}
|
||||||
const_reverse_iterator rbegin() const {
|
const_reverse_iterator rbegin() const {
|
||||||
return _impl.rbegin();
|
return impl().rbegin();
|
||||||
}
|
}
|
||||||
const_reverse_iterator rend() const {
|
const_reverse_iterator rend() const {
|
||||||
return _impl.rend();
|
return impl().rend();
|
||||||
}
|
}
|
||||||
const_reverse_iterator crbegin() const {
|
const_reverse_iterator crbegin() const {
|
||||||
return _impl.crbegin();
|
return impl().crbegin();
|
||||||
}
|
}
|
||||||
const_reverse_iterator crend() const {
|
const_reverse_iterator crend() const {
|
||||||
return _impl.crend();
|
return impl().crend();
|
||||||
}
|
}
|
||||||
|
|
||||||
reference front() const {
|
reference front() const {
|
||||||
|
@ -307,25 +259,25 @@ public:
|
||||||
|
|
||||||
iterator insert(const Type &value) {
|
iterator insert(const Type &value) {
|
||||||
if (empty() || compare()(value, front())) {
|
if (empty() || compare()(value, front())) {
|
||||||
_impl.push_front(value);
|
impl().push_front(value);
|
||||||
return begin();
|
return begin();
|
||||||
} else if (!compare()(value, back())) {
|
} else if (!compare()(value, back())) {
|
||||||
_impl.push_back(value);
|
impl().push_back(value);
|
||||||
return (end() - 1);
|
return (end() - 1);
|
||||||
}
|
}
|
||||||
auto where = getUpperBound(value);
|
auto where = getUpperBound(value);
|
||||||
return _impl.insert(where, value);
|
return impl().insert(where, value);
|
||||||
}
|
}
|
||||||
iterator insert(Type &&value) {
|
iterator insert(Type &&value) {
|
||||||
if (empty() || compare()(value, front())) {
|
if (empty() || compare()(value, front())) {
|
||||||
_impl.push_front(std::move(value));
|
impl().push_front(std::move(value));
|
||||||
return begin();
|
return begin();
|
||||||
} else if (!compare()(value, back())) {
|
} else if (!compare()(value, back())) {
|
||||||
_impl.push_back(std::move(value));
|
impl().push_back(std::move(value));
|
||||||
return (end() - 1);
|
return (end() - 1);
|
||||||
}
|
}
|
||||||
auto where = getUpperBound(value);
|
auto where = getUpperBound(value);
|
||||||
return _impl.insert(where, std::move(value));
|
return impl().insert(where, std::move(value));
|
||||||
}
|
}
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
iterator emplace(Args&&... args) {
|
iterator emplace(Args&&... args) {
|
||||||
|
@ -342,7 +294,7 @@ public:
|
||||||
if (compare()(value, *where)) {
|
if (compare()(value, *where)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_impl.erase(where);
|
impl().erase(where);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int removeAll(const Type &value) {
|
int removeAll(const Type &value) {
|
||||||
|
@ -355,15 +307,15 @@ public:
|
||||||
if (range.first == range.second) {
|
if (range.first == range.second) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
_impl.erase(range.first, range.second);
|
impl().erase(range.first, range.second);
|
||||||
return (range.second - range.first);
|
return (range.second - range.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator erase(const_iterator where) {
|
iterator erase(const_iterator where) {
|
||||||
return _impl.erase(where._impl);
|
return impl().erase(where._impl);
|
||||||
}
|
}
|
||||||
iterator erase(const_iterator from, const_iterator till) {
|
iterator erase(const_iterator from, const_iterator till) {
|
||||||
return _impl.erase(from._impl, till._impl);
|
return impl().erase(from._impl, till._impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator findFirst(const Type &value) {
|
iterator findFirst(const Type &value) {
|
||||||
|
@ -373,7 +325,7 @@ public:
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
auto where = getLowerBound(value);
|
auto where = getLowerBound(value);
|
||||||
return compare()(value, *where) ? _impl.end() : where;
|
return compare()(value, *where) ? impl().end() : where;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator findFirst(const Type &value) const {
|
const_iterator findFirst(const Type &value) const {
|
||||||
|
@ -383,33 +335,33 @@ public:
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
auto where = getLowerBound(value);
|
auto where = getLowerBound(value);
|
||||||
return compare()(value, *where) ? _impl.end() : where;
|
return compare()(value, *where) ? impl().end() : where;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename OtherType,
|
typename OtherType,
|
||||||
typename = typename Compare::is_transparent>
|
typename = typename Compare::is_transparent>
|
||||||
iterator findFirst(const OtherType &value) {
|
iterator findFirst(const OtherType &value) {
|
||||||
if (empty()
|
if (empty()
|
||||||
|| compare()(value, front())
|
|| compare()(value, front())
|
||||||
|| compare()(back(), value)) {
|
|| compare()(back(), value)) {
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
auto where = getLowerBound(value);
|
auto where = getLowerBound(value);
|
||||||
return compare()(value, *where) ? _impl.end() : where;
|
return compare()(value, *where) ? impl().end() : where;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename OtherType,
|
typename OtherType,
|
||||||
typename = typename Compare::is_transparent>
|
typename = typename Compare::is_transparent>
|
||||||
const_iterator findFirst(const OtherType &value) const {
|
const_iterator findFirst(const OtherType &value) const {
|
||||||
if (empty()
|
if (empty()
|
||||||
|| compare()(value, front())
|
|| compare()(value, front())
|
||||||
|| compare()(back(), value)) {
|
|| compare()(back(), value)) {
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
auto where = getLowerBound(value);
|
auto where = getLowerBound(value);
|
||||||
return compare()(value, *where) ? _impl.end() : where;
|
return compare()(value, *where) ? impl().end() : where;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(const Type &value) const {
|
bool contains(const Type &value) const {
|
||||||
|
@ -450,8 +402,8 @@ public:
|
||||||
typename Iterator,
|
typename Iterator,
|
||||||
typename = typename std::iterator_traits<Iterator>::iterator_category>
|
typename = typename std::iterator_traits<Iterator>::iterator_category>
|
||||||
void merge(Iterator first, Iterator last) {
|
void merge(Iterator first, Iterator last) {
|
||||||
_impl.insert(_impl.end(), first, last);
|
impl().insert(impl().end(), first, last);
|
||||||
base::sort(_impl, compare());
|
std::sort(std::begin(impl()), std::end(impl()), compare());
|
||||||
}
|
}
|
||||||
|
|
||||||
void merge(const flat_multi_set<Type, Compare> &other) {
|
void merge(const flat_multi_set<Type, Compare> &other) {
|
||||||
|
@ -463,44 +415,149 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
impl _impl;
|
|
||||||
friend class flat_set<Type, Compare>;
|
friend class flat_set<Type, Compare>;
|
||||||
|
|
||||||
typename impl::iterator getLowerBound(const Type &value) {
|
struct transparent_compare : Compare {
|
||||||
return base::lower_bound(_impl, value, compare());
|
inline constexpr const Compare &initial() const noexcept {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename OtherType1,
|
||||||
|
typename OtherType2,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType1>, const_wrap> &&
|
||||||
|
!std::is_same_v<std::decay_t<OtherType2>, const_wrap>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType1 &&a,
|
||||||
|
OtherType2 &&b) const {
|
||||||
|
return initial()(
|
||||||
|
std::forward<OtherType1>(a),
|
||||||
|
std::forward<OtherType2>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType1,
|
||||||
|
typename OtherType2>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType1 &&a,
|
||||||
|
OtherType2 &&b) const -> std::enable_if_t<
|
||||||
|
std::is_same_v<std::decay_t<OtherType1>, const_wrap> &&
|
||||||
|
std::is_same_v<std::decay_t<OtherType2>, const_wrap>, bool> {
|
||||||
|
return initial()(
|
||||||
|
static_cast<const Type&>(a),
|
||||||
|
static_cast<const Type&>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
const const_wrap &a,
|
||||||
|
OtherType &&b) const {
|
||||||
|
return initial()(
|
||||||
|
static_cast<const Type&>(a),
|
||||||
|
std::forward<OtherType>(b));
|
||||||
|
}
|
||||||
|
template <
|
||||||
|
typename OtherType,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
||||||
|
inline constexpr auto operator()(
|
||||||
|
OtherType &&a,
|
||||||
|
const const_wrap &b) const {
|
||||||
|
return initial()(
|
||||||
|
std::forward<OtherType>(a),
|
||||||
|
static_cast<const Type&>(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
struct Data : transparent_compare {
|
||||||
|
template <typename ...Args>
|
||||||
|
Data(Args &&...args)
|
||||||
|
: elements(std::forward<Args>(args)...) {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_t elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
Data _data;
|
||||||
|
const transparent_compare &compare() const {
|
||||||
|
return _data;
|
||||||
}
|
}
|
||||||
typename impl::const_iterator getLowerBound(const Type &value) const {
|
const impl_t &impl() const {
|
||||||
return base::lower_bound(_impl, value, compare());
|
return _data.elements;
|
||||||
|
}
|
||||||
|
impl_t &impl() {
|
||||||
|
return _data.elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename impl_t::iterator getLowerBound(const Type &value) {
|
||||||
|
return std::lower_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
|
}
|
||||||
|
typename impl_t::const_iterator getLowerBound(const Type &value) const {
|
||||||
|
return std::lower_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
template <
|
template <
|
||||||
typename OtherType,
|
typename OtherType,
|
||||||
typename = typename Compare::is_transparent>
|
typename = typename Compare::is_transparent>
|
||||||
typename impl::iterator getLowerBound(const OtherType &value) {
|
typename impl_t::iterator getLowerBound(const OtherType &value) {
|
||||||
return base::lower_bound(_impl, value, compare());
|
return std::lower_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
template <
|
template <
|
||||||
typename OtherType,
|
typename OtherType,
|
||||||
typename = typename Compare::is_transparent>
|
typename = typename Compare::is_transparent>
|
||||||
typename impl::const_iterator getLowerBound(const OtherType &value) const {
|
typename impl_t::const_iterator getLowerBound(const OtherType &value) const {
|
||||||
return base::lower_bound(_impl, value, compare());
|
return std::lower_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
typename impl::iterator getUpperBound(const Type &value) {
|
typename impl_t::iterator getUpperBound(const Type &value) {
|
||||||
return base::upper_bound(_impl, value, compare());
|
return std::upper_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
typename impl::const_iterator getUpperBound(const Type &value) const {
|
typename impl_t::const_iterator getUpperBound(const Type &value) const {
|
||||||
return base::upper_bound(_impl, value, compare());
|
return std::upper_bound(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
std::pair<
|
std::pair<
|
||||||
typename impl::iterator,
|
typename impl_t::iterator,
|
||||||
typename impl::iterator
|
typename impl_t::iterator
|
||||||
> getEqualRange(const Type &value) {
|
> getEqualRange(const Type &value) {
|
||||||
return base::equal_range(_impl, value, compare());
|
return std::equal_range(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
std::pair<
|
std::pair<
|
||||||
typename impl::const_iterator,
|
typename impl_t::const_iterator,
|
||||||
typename impl::const_iterator
|
typename impl_t::const_iterator
|
||||||
> getEqualRange(const Type &value) const {
|
> getEqualRange(const Type &value) const {
|
||||||
return base::equal_range(_impl, value, compare());
|
return std::equal_range(
|
||||||
|
std::begin(impl()),
|
||||||
|
std::end(impl()),
|
||||||
|
value,
|
||||||
|
compare());
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -508,7 +565,6 @@ private:
|
||||||
template <typename Type, typename Compare>
|
template <typename Type, typename Compare>
|
||||||
class flat_set : private flat_multi_set<Type, Compare> {
|
class flat_set : private flat_multi_set<Type, Compare> {
|
||||||
using parent = flat_multi_set<Type, Compare>;
|
using parent = flat_multi_set<Type, Compare>;
|
||||||
using compare = typename parent::compare;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using iterator = typename parent::iterator;
|
using iterator = typename parent::iterator;
|
||||||
|
@ -553,30 +609,30 @@ public:
|
||||||
using parent::erase;
|
using parent::erase;
|
||||||
|
|
||||||
iterator insert(const Type &value) {
|
iterator insert(const Type &value) {
|
||||||
if (this->empty() || compare()(value, this->front())) {
|
if (this->empty() || this->compare()(value, this->front())) {
|
||||||
this->_impl.push_front(value);
|
this->impl().push_front(value);
|
||||||
return this->begin();
|
return this->begin();
|
||||||
} else if (compare()(this->back(), value)) {
|
} else if (this->compare()(this->back(), value)) {
|
||||||
this->_impl.push_back(value);
|
this->impl().push_back(value);
|
||||||
return (this->end() - 1);
|
return (this->end() - 1);
|
||||||
}
|
}
|
||||||
auto where = this->getLowerBound(value);
|
auto where = this->getLowerBound(value);
|
||||||
if (compare()(value, *where)) {
|
if (this->compare()(value, *where)) {
|
||||||
return this->_impl.insert(where, value);
|
return this->impl().insert(where, value);
|
||||||
}
|
}
|
||||||
return this->end();
|
return this->end();
|
||||||
}
|
}
|
||||||
iterator insert(Type &&value) {
|
iterator insert(Type &&value) {
|
||||||
if (this->empty() || compare()(value, this->front())) {
|
if (this->empty() || this->compare()(value, this->front())) {
|
||||||
this->_impl.push_front(std::move(value));
|
this->impl().push_front(std::move(value));
|
||||||
return this->begin();
|
return this->begin();
|
||||||
} else if (compare()(this->back(), value)) {
|
} else if (this->compare()(this->back(), value)) {
|
||||||
this->_impl.push_back(std::move(value));
|
this->impl().push_back(std::move(value));
|
||||||
return (this->end() - 1);
|
return (this->end() - 1);
|
||||||
}
|
}
|
||||||
auto where = this->getLowerBound(value);
|
auto where = this->getLowerBound(value);
|
||||||
if (compare()(value, *where)) {
|
if (this->compare()(value, *where)) {
|
||||||
return this->_impl.insert(where, std::move(value));
|
return this->impl().insert(where, std::move(value));
|
||||||
}
|
}
|
||||||
return this->end();
|
return this->end();
|
||||||
}
|
}
|
||||||
|
@ -612,9 +668,9 @@ public:
|
||||||
void modify(iterator which, Action action) {
|
void modify(iterator which, Action action) {
|
||||||
action(which.wrapped());
|
action(which.wrapped());
|
||||||
for (auto i = iterator(which + 1), e = end(); i != e; ++i) {
|
for (auto i = iterator(which + 1), e = end(); i != e; ++i) {
|
||||||
if (compare()(*i, *which)) {
|
if (this->compare()(*i, *which)) {
|
||||||
std::swap(i.wrapped(), which.wrapped());
|
std::swap(i.wrapped(), which.wrapped());
|
||||||
} else if (!compare()(*which, *i)) {
|
} else if (!this->compare()(*which, *i)) {
|
||||||
erase(which);
|
erase(which);
|
||||||
return;
|
return;
|
||||||
} else{
|
} else{
|
||||||
|
@ -623,9 +679,9 @@ public:
|
||||||
}
|
}
|
||||||
for (auto i = which, b = begin(); i != b;) {
|
for (auto i = which, b = begin(); i != b;) {
|
||||||
--i;
|
--i;
|
||||||
if (compare()(*which, *i)) {
|
if (this->compare()(*which, *i)) {
|
||||||
std::swap(i.wrapped(), which.wrapped());
|
std::swap(i.wrapped(), which.wrapped());
|
||||||
} else if (!compare()(*i, *which)) {
|
} else if (!this->compare()(*i, *which)) {
|
||||||
erase(which);
|
erase(which);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -652,12 +708,15 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void finalize() {
|
void finalize() {
|
||||||
this->_impl.erase(
|
this->impl().erase(
|
||||||
std::unique(
|
std::unique(
|
||||||
this->_impl.begin(),
|
std::begin(this->impl()),
|
||||||
this->_impl.end(),
|
std::end(this->impl()),
|
||||||
[](auto &&a, auto &&b) { return !compare()(a, b); }),
|
[&](auto &&a, auto &&b) {
|
||||||
this->_impl.end());
|
return !this->compare()(a, b);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
std::end(this->impl()));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,27 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "base/flat_set.h"
|
#include "base/flat_set.h"
|
||||||
|
|
||||||
|
struct int_wrap {
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
struct int_wrap_comparator {
|
||||||
|
using is_transparent = void;
|
||||||
|
inline bool operator()(const int &a, const int_wrap &b) const {
|
||||||
|
return a < b.value;
|
||||||
|
}
|
||||||
|
inline bool operator()(const int_wrap &a, const int_wrap &b) const {
|
||||||
|
return a.value < b.value;
|
||||||
|
}
|
||||||
|
inline bool operator()(const int_wrap &a, const int &b) const {
|
||||||
|
return a.value < b;
|
||||||
|
}
|
||||||
|
inline bool operator()(const int &a, const int &b) const {
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("flat_sets should keep items sorted", "[flat_set]") {
|
TEST_CASE("flat_sets should keep items sorted", "[flat_set]") {
|
||||||
|
|
||||||
base::flat_set<int> v;
|
base::flat_set<int> v;
|
||||||
v.insert(0);
|
v.insert(0);
|
||||||
v.insert(5);
|
v.insert(5);
|
||||||
|
@ -48,3 +68,30 @@ TEST_CASE("flat_sets should keep items sorted", "[flat_set]") {
|
||||||
checkSorted();
|
checkSorted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("flat_sets with custom comparators", "[flat_set]") {
|
||||||
|
base::flat_set<int_wrap, int_wrap_comparator> v;
|
||||||
|
v.insert({ 0 });
|
||||||
|
v.insert({ 5 });
|
||||||
|
v.insert({ 4 });
|
||||||
|
v.insert({ 2 });
|
||||||
|
|
||||||
|
REQUIRE(v.find(4) != v.end());
|
||||||
|
|
||||||
|
auto checkSorted = [&] {
|
||||||
|
auto prev = v.begin();
|
||||||
|
REQUIRE(prev != v.end());
|
||||||
|
for (auto i = prev + 1; i != v.end(); prev = i, ++i) {
|
||||||
|
REQUIRE(prev->value < i->value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REQUIRE(v.size() == 4);
|
||||||
|
checkSorted();
|
||||||
|
|
||||||
|
SECTION("adding item puts it in the right position") {
|
||||||
|
v.insert({ 3 });
|
||||||
|
REQUIRE(v.size() == 5);
|
||||||
|
REQUIRE(v.find(3) != v.end());
|
||||||
|
checkSorted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -593,8 +593,8 @@ void PeerListContent::addRowEntry(not_null<PeerListRow*> row) {
|
||||||
|
|
||||||
void PeerListContent::invalidatePixmapsCache() {
|
void PeerListContent::invalidatePixmapsCache() {
|
||||||
auto invalidate = [](auto &&row) { row->invalidatePixmapsCache(); };
|
auto invalidate = [](auto &&row) { row->invalidatePixmapsCache(); };
|
||||||
base::for_each(_rows, invalidate);
|
ranges::for_each(_rows, invalidate);
|
||||||
base::for_each(_searchRows, invalidate);
|
ranges::for_each(_searchRows, invalidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerListContent::addingToSearchIndex() const {
|
bool PeerListContent::addingToSearchIndex() const {
|
||||||
|
|
|
@ -648,11 +648,11 @@ void EditChatAdminsBoxController::rebuildRows() {
|
||||||
admins.insert(admins.end(), others.begin(), others.end());
|
admins.insert(admins.end(), others.begin(), others.end());
|
||||||
others.clear();
|
others.clear();
|
||||||
}
|
}
|
||||||
auto sortByName = [](auto a, auto b) {
|
auto sortByName = [](not_null<UserData*> a, auto b) {
|
||||||
return (a->name.compare(b->name, Qt::CaseInsensitive) < 0);
|
return (a->name.compare(b->name, Qt::CaseInsensitive) < 0);
|
||||||
};
|
};
|
||||||
base::sort(admins, sortByName);
|
ranges::sort(admins, sortByName);
|
||||||
base::sort(others, sortByName);
|
ranges::sort(others, sortByName);
|
||||||
|
|
||||||
auto addOne = [this](not_null<UserData*> user) {
|
auto addOne = [this](not_null<UserData*> user) {
|
||||||
if (auto row = createRow(user)) {
|
if (auto row = createRow(user)) {
|
||||||
|
@ -664,8 +664,8 @@ void EditChatAdminsBoxController::rebuildRows() {
|
||||||
addOne(creator);
|
addOne(creator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base::for_each(admins, addOne);
|
ranges::for_each(admins, addOne);
|
||||||
base::for_each(others, addOne);
|
ranges::for_each(others, addOne);
|
||||||
|
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
|
|
|
@ -538,7 +538,7 @@ void Controller::usernameChanged() {
|
||||||
_checkUsernameTimer.cancel();
|
_checkUsernameTimer.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto bad = base::find_if(username, [](QChar ch) {
|
auto bad = ranges::find_if(username, [](QChar ch) {
|
||||||
return (ch < 'A' || ch > 'Z')
|
return (ch < 'A' || ch > 'Z')
|
||||||
&& (ch < 'a' || ch > 'z')
|
&& (ch < 'a' || ch > 'z')
|
||||||
&& (ch < '0' || ch > '9')
|
&& (ch < '0' || ch > '9')
|
||||||
|
|
|
@ -51,10 +51,10 @@ public:
|
||||||
bool canAddItem(not_null<const HistoryItem*> item) const {
|
bool canAddItem(not_null<const HistoryItem*> item) const {
|
||||||
return (ComputeType(item) == _type && item->date.date() == _date);
|
return (ComputeType(item) == _type && item->date.date() == _date);
|
||||||
}
|
}
|
||||||
void addItem(HistoryItem *item) {
|
void addItem(not_null<HistoryItem*> item) {
|
||||||
Expects(canAddItem(item));
|
Expects(canAddItem(item));
|
||||||
_items.push_back(item);
|
_items.push_back(item);
|
||||||
base::sort(_items, [](HistoryItem *a, HistoryItem *b) {
|
ranges::sort(_items, [](not_null<HistoryItem*> a, auto b) {
|
||||||
return (a->id > b->id);
|
return (a->id > b->id);
|
||||||
});
|
});
|
||||||
refreshStatus();
|
refreshStatus();
|
||||||
|
@ -116,7 +116,7 @@ private:
|
||||||
void refreshStatus();
|
void refreshStatus();
|
||||||
static Type ComputeType(not_null<const HistoryItem*> item);
|
static Type ComputeType(not_null<const HistoryItem*> item);
|
||||||
|
|
||||||
std::vector<HistoryItem*> _items;
|
std::vector<not_null<HistoryItem*>> _items;
|
||||||
QDate _date;
|
QDate _date;
|
||||||
Type _type;
|
Type _type;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ base::optional<int> SparseIdsSlice::distance(
|
||||||
}
|
}
|
||||||
|
|
||||||
base::optional<MsgId> SparseIdsSlice::nearest(MsgId msgId) const {
|
base::optional<MsgId> SparseIdsSlice::nearest(MsgId msgId) const {
|
||||||
if (auto it = base::lower_bound(_ids, msgId); it != _ids.end()) {
|
if (auto it = ranges::lower_bound(_ids, msgId); it != _ids.end()) {
|
||||||
return *it;
|
return *it;
|
||||||
} else if (_ids.empty()) {
|
} else if (_ids.empty()) {
|
||||||
return base::none;
|
return base::none;
|
||||||
|
@ -342,7 +342,7 @@ void SparseIdsSliceBuilder::sliceToLimits() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto requestedSomething = false;
|
auto requestedSomething = false;
|
||||||
auto aroundIt = base::lower_bound(_ids, _key);
|
auto aroundIt = ranges::lower_bound(_ids, _key);
|
||||||
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
|
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
|
||||||
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
|
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
|
||||||
if (removeFromBegin > 0) {
|
if (removeFromBegin > 0) {
|
||||||
|
|
|
@ -60,7 +60,8 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UserPhotosSlice::UserPhotosSlice(Key key) : UserPhotosSlice(
|
UserPhotosSlice::UserPhotosSlice(Key key)
|
||||||
|
: UserPhotosSlice(
|
||||||
key,
|
key,
|
||||||
{},
|
{},
|
||||||
base::none,
|
base::none,
|
||||||
|
@ -74,15 +75,15 @@ UserPhotosSlice::UserPhotosSlice(
|
||||||
base::optional<int> fullCount,
|
base::optional<int> fullCount,
|
||||||
base::optional<int> skippedBefore,
|
base::optional<int> skippedBefore,
|
||||||
int skippedAfter)
|
int skippedAfter)
|
||||||
: _key(key)
|
: _key(key)
|
||||||
, _ids(ids)
|
, _ids(ids)
|
||||||
, _fullCount(fullCount)
|
, _fullCount(fullCount)
|
||||||
, _skippedBefore(skippedBefore)
|
, _skippedBefore(skippedBefore)
|
||||||
, _skippedAfter(skippedAfter) {
|
, _skippedAfter(skippedAfter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
base::optional<int> UserPhotosSlice::indexOf(PhotoId photoId) const {
|
base::optional<int> UserPhotosSlice::indexOf(PhotoId photoId) const {
|
||||||
auto it = base::find(_ids, photoId);
|
auto it = ranges::find(_ids, photoId);
|
||||||
if (it != _ids.end()) {
|
if (it != _ids.end()) {
|
||||||
return (it - _ids.begin());
|
return (it - _ids.begin());
|
||||||
}
|
}
|
||||||
|
@ -190,7 +191,7 @@ void UserPhotosSliceBuilder::mergeSliceData(
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserPhotosSliceBuilder::sliceToLimits() {
|
void UserPhotosSliceBuilder::sliceToLimits() {
|
||||||
auto aroundIt = base::find(_ids, _key.photoId);
|
auto aroundIt = ranges::find(_ids, _key.photoId);
|
||||||
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
|
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
|
||||||
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
|
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
|
||||||
if (removeFromEnd > 0) {
|
if (removeFromEnd > 0) {
|
||||||
|
|
|
@ -73,7 +73,7 @@ QString TopBarOverride::generateText() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TopBarOverride::computeCanDelete() const {
|
bool TopBarOverride::computeCanDelete() const {
|
||||||
return base::find_if(_items.list, [](const SelectedItem &item) {
|
return ranges::find_if(_items.list, [](const SelectedItem &item) {
|
||||||
return !item.canDelete;
|
return !item.canDelete;
|
||||||
}) == _items.list.end();
|
}) == _items.list.end();
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,10 @@ public:
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bottom() const {
|
||||||
|
return top() + height();
|
||||||
|
}
|
||||||
|
|
||||||
bool removeItem(UniversalMsgId universalId);
|
bool removeItem(UniversalMsgId universalId);
|
||||||
FoundItem findItemNearId(UniversalMsgId universalId) const;
|
FoundItem findItemNearId(UniversalMsgId universalId) const;
|
||||||
FoundItem findItemByPoint(QPoint point) const;
|
FoundItem findItemByPoint(QPoint point) const;
|
||||||
|
@ -302,12 +306,11 @@ auto ListWidget::Section::findItemByPoint(
|
||||||
auto ListWidget::Section::findItemNearId(
|
auto ListWidget::Section::findItemNearId(
|
||||||
UniversalMsgId universalId) const -> FoundItem {
|
UniversalMsgId universalId) const -> FoundItem {
|
||||||
Expects(!_items.empty());
|
Expects(!_items.empty());
|
||||||
auto itemIt = base::lower_bound(
|
auto itemIt = ranges::lower_bound(
|
||||||
_items,
|
_items,
|
||||||
universalId,
|
universalId,
|
||||||
[this](const auto &item, UniversalMsgId universalId) {
|
std::greater<>(),
|
||||||
return (item.first > universalId);
|
[](const auto &item) -> UniversalMsgId { return item.first; });
|
||||||
});
|
|
||||||
if (itemIt == _items.end()) {
|
if (itemIt == _items.end()) {
|
||||||
--itemIt;
|
--itemIt;
|
||||||
}
|
}
|
||||||
|
@ -318,36 +321,39 @@ auto ListWidget::Section::findItemNearId(
|
||||||
|
|
||||||
auto ListWidget::Section::findItemAfterTop(
|
auto ListWidget::Section::findItemAfterTop(
|
||||||
int top) -> Items::iterator {
|
int top) -> Items::iterator {
|
||||||
return base::lower_bound(
|
return ranges::lower_bound(
|
||||||
_items,
|
_items,
|
||||||
top,
|
top,
|
||||||
[this](const auto &item, int top) {
|
std::less_equal<>(),
|
||||||
|
[this](const auto &item) {
|
||||||
auto itemTop = item.second->position() / _itemsInRow;
|
auto itemTop = item.second->position() / _itemsInRow;
|
||||||
return (itemTop + item.second->height()) <= top;
|
return itemTop + item.second->height();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ListWidget::Section::findItemAfterTop(
|
auto ListWidget::Section::findItemAfterTop(
|
||||||
int top) const -> Items::const_iterator {
|
int top) const -> Items::const_iterator {
|
||||||
return base::lower_bound(
|
return ranges::lower_bound(
|
||||||
_items,
|
_items,
|
||||||
top,
|
top,
|
||||||
[this](const auto &item, int top) {
|
std::less_equal<>(),
|
||||||
auto itemTop = item.second->position() / _itemsInRow;
|
[this](const auto &item) {
|
||||||
return (itemTop + item.second->height()) <= top;
|
auto itemTop = item.second->position() / _itemsInRow;
|
||||||
});
|
return itemTop + item.second->height();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ListWidget::Section::findItemAfterBottom(
|
auto ListWidget::Section::findItemAfterBottom(
|
||||||
Items::const_iterator from,
|
Items::const_iterator from,
|
||||||
int bottom) const -> Items::const_iterator {
|
int bottom) const -> Items::const_iterator {
|
||||||
return std::lower_bound(
|
return ranges::lower_bound(
|
||||||
from,
|
from,
|
||||||
_items.end(),
|
_items.end(),
|
||||||
bottom,
|
bottom,
|
||||||
[this](const auto &item, int bottom) {
|
std::less<>(),
|
||||||
|
[this](const auto &item) {
|
||||||
auto itemTop = item.second->position() / _itemsInRow;
|
auto itemTop = item.second->position() / _itemsInRow;
|
||||||
return itemTop < bottom;
|
return itemTop;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,12 +1188,12 @@ void ListWidget::showContextMenu(
|
||||||
}
|
}
|
||||||
|
|
||||||
auto canDeleteAll = [&] {
|
auto canDeleteAll = [&] {
|
||||||
return base::find_if(_selected, [](auto &item) {
|
return ranges::find_if(_selected, [](auto &&item) {
|
||||||
return !item.second.canDelete;
|
return !item.second.canDelete;
|
||||||
}) == _selected.end();
|
}) == _selected.end();
|
||||||
};
|
};
|
||||||
auto canForwardAll = [&] {
|
auto canForwardAll = [&] {
|
||||||
return base::find_if(_selected, [](auto &item) {
|
return ranges::find_if(_selected, [](auto &&item) {
|
||||||
return !item.second.canForward;
|
return !item.second.canForward;
|
||||||
}) == _selected.end();
|
}) == _selected.end();
|
||||||
};
|
};
|
||||||
|
@ -2042,44 +2048,40 @@ void ListWidget::clearStaleLayouts() {
|
||||||
|
|
||||||
auto ListWidget::findSectionByItem(
|
auto ListWidget::findSectionByItem(
|
||||||
UniversalMsgId universalId) -> std::vector<Section>::iterator {
|
UniversalMsgId universalId) -> std::vector<Section>::iterator {
|
||||||
return base::lower_bound(
|
return ranges::lower_bound(
|
||||||
_sections,
|
_sections,
|
||||||
universalId,
|
universalId,
|
||||||
[](const Section §ion, int universalId) {
|
std::greater<>(),
|
||||||
return section.minId() > universalId;
|
[](const Section §ion) { return section.minId(); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ListWidget::findSectionAfterTop(
|
auto ListWidget::findSectionAfterTop(
|
||||||
int top) -> std::vector<Section>::iterator {
|
int top) -> std::vector<Section>::iterator {
|
||||||
return base::lower_bound(
|
return ranges::lower_bound(
|
||||||
_sections,
|
_sections,
|
||||||
top,
|
top,
|
||||||
[](const Section §ion, int top) {
|
std::less_equal<>(),
|
||||||
return (section.top() + section.height()) <= top;
|
[](const Section §ion) { return section.bottom(); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ListWidget::findSectionAfterTop(
|
auto ListWidget::findSectionAfterTop(
|
||||||
int top) const -> std::vector<Section>::const_iterator {
|
int top) const -> std::vector<Section>::const_iterator {
|
||||||
return base::lower_bound(
|
return ranges::lower_bound(
|
||||||
_sections,
|
_sections,
|
||||||
top,
|
top,
|
||||||
[](const Section §ion, int top) {
|
std::less_equal<>(),
|
||||||
return (section.top() + section.height()) <= top;
|
[](const Section §ion) { return section.bottom(); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ListWidget::findSectionAfterBottom(
|
auto ListWidget::findSectionAfterBottom(
|
||||||
std::vector<Section>::const_iterator from,
|
std::vector<Section>::const_iterator from,
|
||||||
int bottom) const -> std::vector<Section>::const_iterator {
|
int bottom) const -> std::vector<Section>::const_iterator {
|
||||||
return std::lower_bound(
|
return ranges::lower_bound(
|
||||||
from,
|
from,
|
||||||
_sections.end(),
|
_sections.end(),
|
||||||
bottom,
|
bottom,
|
||||||
[](const Section §ion, int bottom) {
|
std::less<>(),
|
||||||
return section.top() < bottom;
|
[](const Section §ion) { return section.top(); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListWidget::~ListWidget() = default;
|
ListWidget::~ListWidget() = default;
|
||||||
|
|
|
@ -341,7 +341,7 @@ DcOptions::Ids DcOptions::configEnumDcIds() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base::sort(result);
|
ranges::sort(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,7 @@ bool UnsafeShowOpenWithDropdown(const QString &filepath, QPoint menuPosition) {
|
||||||
|
|
||||||
if (!handlers.empty()) {
|
if (!handlers.empty()) {
|
||||||
HMENU menu = CreatePopupMenu();
|
HMENU menu = CreatePopupMenu();
|
||||||
base::sort(handlers, [](const OpenWithApp &a, const OpenWithApp &b) {
|
ranges::sort(handlers, [](const OpenWithApp &a, auto &b) {
|
||||||
return a.name() < b.name();
|
return a.name() < b.name();
|
||||||
});
|
});
|
||||||
for (int32 i = 0, l = handlers.size(); i < l; ++i) {
|
for (int32 i = 0, l = handlers.size(); i < l; ++i) {
|
||||||
|
|
|
@ -277,13 +277,13 @@ std::unique_ptr<PeerListState> ParticipantsBoxController::saveState() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto pos = base::find(weak->list, user);
|
auto pos = ranges::find(weak->list, user);
|
||||||
if (pos == weak->list.cend()) {
|
if (pos == weak->list.cend()) {
|
||||||
weak->list.push_back(user);
|
weak->list.push_back(user);
|
||||||
}
|
}
|
||||||
base::stable_partition(weak->list, [user](not_null<PeerData*> peer) {
|
ranges::stable_partition(
|
||||||
return (peer == user);
|
weak->list,
|
||||||
});
|
[user](auto peer) { return (peer == user); });
|
||||||
}, my->lifetime);
|
}, my->lifetime);
|
||||||
Auth().data().megagroupParticipantRemoved(_channel)
|
Auth().data().megagroupParticipantRemoved(_channel)
|
||||||
| rpl::start_with_next([weak](not_null<UserData*> user) {
|
| rpl::start_with_next([weak](not_null<UserData*> user) {
|
||||||
|
|
|
@ -326,7 +326,7 @@ inline auto combine(
|
||||||
state->latest.push_back(
|
state->latest.push_back(
|
||||||
std::move(*value));
|
std::move(*value));
|
||||||
}
|
}
|
||||||
base::take(state->accumulated);
|
details::take(state->accumulated);
|
||||||
consumer.put_next_copy(state->latest);
|
consumer.put_next_copy(state->latest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ template <typename Value, typename Error>
|
||||||
inline void type_erased_handlers<Value, Error>::terminate() {
|
inline void type_erased_handlers<Value, Error>::terminate() {
|
||||||
if (!_terminated) {
|
if (!_terminated) {
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
base::take(_lifetime).destroy();
|
details::take(_lifetime).destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include <rpl/then.h>
|
#include <rpl/then.h>
|
||||||
#include <rpl/range.h>
|
#include <rpl/range.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "base/algorithm.h"
|
|
||||||
#include "base/assertion.h"
|
#include "base/assertion.h"
|
||||||
#include "base/index_based_iterator.h"
|
#include "base/index_based_iterator.h"
|
||||||
|
|
||||||
|
@ -54,8 +53,9 @@ public:
|
||||||
if (auto strong = weak.lock()) {
|
if (auto strong = weak.lock()) {
|
||||||
auto result = [weak, consumer] {
|
auto result = [weak, consumer] {
|
||||||
if (auto strong = weak.lock()) {
|
if (auto strong = weak.lock()) {
|
||||||
auto it = base::find(
|
auto it = std::find(
|
||||||
strong->consumers,
|
strong->consumers.begin(),
|
||||||
|
strong->consumers.end(),
|
||||||
consumer);
|
consumer);
|
||||||
if (it != strong->consumers.end()) {
|
if (it != strong->consumers.end()) {
|
||||||
it->terminate();
|
it->terminate();
|
||||||
|
@ -94,13 +94,13 @@ inline event_stream<Value>::event_stream() {
|
||||||
|
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
inline event_stream<Value>::event_stream(event_stream &&other)
|
inline event_stream<Value>::event_stream(event_stream &&other)
|
||||||
: _data(base::take(other._data)) {
|
: _data(details::take(other._data)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
inline event_stream<Value> &event_stream<Value>::operator=(
|
inline event_stream<Value> &event_stream<Value>::operator=(
|
||||||
event_stream &&other) {
|
event_stream &&other) {
|
||||||
_data = base::take(other._data);
|
_data = details::take(other._data);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ inline auto event_stream<Value>::weak() const
|
||||||
|
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
inline event_stream<Value>::~event_stream() {
|
inline event_stream<Value>::~event_stream() {
|
||||||
if (auto data = base::take(_data)) {
|
if (auto data = details::take(_data)) {
|
||||||
for (auto &consumer : data->consumers) {
|
for (auto &consumer : data->consumers) {
|
||||||
consumer.put_done();
|
consumer.put_done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/lambda.h"
|
#include "base/lambda.h"
|
||||||
#include "base/algorithm.h"
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
namespace rpl {
|
namespace rpl {
|
||||||
|
namespace details {
|
||||||
|
|
||||||
|
template <typename Type>
|
||||||
|
inline Type take(Type &value) {
|
||||||
|
return std::exchange(value, Type{});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace details
|
||||||
|
|
||||||
class lifetime {
|
class lifetime {
|
||||||
public:
|
public:
|
||||||
|
@ -47,7 +54,7 @@ public:
|
||||||
auto result = new Type(std::forward<Args>(args)...);
|
auto result = new Type(std::forward<Args>(args)...);
|
||||||
add([result]() mutable {
|
add([result]() mutable {
|
||||||
static_assert(sizeof(Type) > 0, "Can't delete unknown type.");
|
static_assert(sizeof(Type) > 0, "Can't delete unknown type.");
|
||||||
delete base::take(result);
|
delete details::take(result);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +67,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
inline lifetime::lifetime(lifetime &&other)
|
inline lifetime::lifetime(lifetime &&other)
|
||||||
: _callbacks(base::take(other._callbacks)) {
|
: _callbacks(details::take(other._callbacks)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lifetime &lifetime::operator=(lifetime &&other) {
|
inline lifetime &lifetime::operator=(lifetime &&other) {
|
||||||
|
@ -80,7 +87,7 @@ inline void lifetime::add(Destroy &&destroy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lifetime::add(lifetime &&other) {
|
inline void lifetime::add(lifetime &&other) {
|
||||||
auto callbacks = base::take(other._callbacks);
|
auto callbacks = details::take(other._callbacks);
|
||||||
_callbacks.insert(
|
_callbacks.insert(
|
||||||
_callbacks.begin(),
|
_callbacks.begin(),
|
||||||
std::make_move_iterator(callbacks.begin()),
|
std::make_move_iterator(callbacks.begin()),
|
||||||
|
@ -88,7 +95,7 @@ inline void lifetime::add(lifetime &&other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lifetime::destroy() {
|
inline void lifetime::destroy() {
|
||||||
for (auto &callback : base::take(_callbacks)) {
|
for (auto &callback : details::take(_callbacks)) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InvokeCounter(InvokeCounter &&other)
|
InvokeCounter(InvokeCounter &&other)
|
||||||
: _copyCounter(base::take(other._copyCounter))
|
: _copyCounter(details::take(other._copyCounter))
|
||||||
, _moveCounter(base::take(other._moveCounter)) {
|
, _moveCounter(details::take(other._moveCounter)) {
|
||||||
if (_moveCounter) {
|
if (_moveCounter) {
|
||||||
++*_moveCounter;
|
++*_moveCounter;
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
InvokeCounter &operator=(InvokeCounter &&other) {
|
InvokeCounter &operator=(InvokeCounter &&other) {
|
||||||
_copyCounter = base::take(other._copyCounter);
|
_copyCounter = details::take(other._copyCounter);
|
||||||
_moveCounter = base::take(other._moveCounter);
|
_moveCounter = details::take(other._moveCounter);
|
||||||
if (_moveCounter) {
|
if (_moveCounter) {
|
||||||
++*_moveCounter;
|
++*_moveCounter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,14 +80,16 @@ int SparseIdsList::addRangeItemsAndCountNew(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto uniteFrom = base::lower_bound(
|
auto uniteFrom = ranges::lower_bound(
|
||||||
_slices,
|
_slices,
|
||||||
noSkipRange.from,
|
noSkipRange.from,
|
||||||
[](const Slice &slice, MsgId from) { return slice.range.till < from; });
|
std::less<>(),
|
||||||
auto uniteTill = base::upper_bound(
|
[](const Slice &slice) { return slice.range.till; });
|
||||||
|
auto uniteTill = ranges::upper_bound(
|
||||||
_slices,
|
_slices,
|
||||||
noSkipRange.till,
|
noSkipRange.till,
|
||||||
[](MsgId till, const Slice &slice) { return till < slice.range.from; });
|
std::less<>(),
|
||||||
|
[](const Slice &slice) { return slice.range.from; });
|
||||||
if (uniteFrom < uniteTill) {
|
if (uniteFrom < uniteTill) {
|
||||||
return uniteAndAdd(update, uniteFrom, uniteTill, messages, noSkipRange);
|
return uniteAndAdd(update, uniteFrom, uniteTill, messages, noSkipRange);
|
||||||
}
|
}
|
||||||
|
@ -151,10 +153,11 @@ void SparseIdsList::addSlice(
|
||||||
}
|
}
|
||||||
|
|
||||||
void SparseIdsList::removeOne(MsgId messageId) {
|
void SparseIdsList::removeOne(MsgId messageId) {
|
||||||
auto slice = base::lower_bound(
|
auto slice = ranges::lower_bound(
|
||||||
_slices,
|
_slices,
|
||||||
messageId,
|
messageId,
|
||||||
[](const Slice &slice, MsgId from) { return slice.range.till < from; });
|
std::less<>(),
|
||||||
|
[](const Slice &slice) { return slice.range.till; });
|
||||||
if (slice != _slices.end() && slice->range.from <= messageId) {
|
if (slice != _slices.end() && slice->range.from <= messageId) {
|
||||||
_slices.modify(slice, [messageId](Slice &slice) {
|
_slices.modify(slice, [messageId](Slice &slice) {
|
||||||
return slice.messages.remove(messageId);
|
return slice.messages.remove(messageId);
|
||||||
|
@ -175,12 +178,11 @@ rpl::producer<SparseIdsListResult> SparseIdsList::query(
|
||||||
SparseIdsListQuery &&query) const {
|
SparseIdsListQuery &&query) const {
|
||||||
return [this, query = std::move(query)](auto consumer) {
|
return [this, query = std::move(query)](auto consumer) {
|
||||||
auto slice = query.aroundId
|
auto slice = query.aroundId
|
||||||
? base::lower_bound(
|
? ranges::lower_bound(
|
||||||
_slices,
|
_slices,
|
||||||
query.aroundId,
|
query.aroundId,
|
||||||
[](const Slice &slice, MsgId id) {
|
std::less<>(),
|
||||||
return slice.range.till < id;
|
[](const Slice &slice) { return slice.range.till; })
|
||||||
})
|
|
||||||
: _slices.end();
|
: _slices.end();
|
||||||
if (slice != _slices.end()
|
if (slice != _slices.end()
|
||||||
&& slice->range.from <= query.aroundId) {
|
&& slice->range.from <= query.aroundId) {
|
||||||
|
@ -199,7 +201,7 @@ SparseIdsListResult SparseIdsList::queryFromSlice(
|
||||||
const SparseIdsListQuery &query,
|
const SparseIdsListQuery &query,
|
||||||
const Slice &slice) const {
|
const Slice &slice) const {
|
||||||
auto result = SparseIdsListResult {};
|
auto result = SparseIdsListResult {};
|
||||||
auto position = base::lower_bound(slice.messages, query.aroundId);
|
auto position = ranges::lower_bound(slice.messages, query.aroundId);
|
||||||
auto haveBefore = int(position - slice.messages.begin());
|
auto haveBefore = int(position - slice.messages.begin());
|
||||||
auto haveEqualOrAfter = int(slice.messages.end() - position);
|
auto haveEqualOrAfter = int(slice.messages.end() - position);
|
||||||
auto before = qMin(haveBefore, query.limitBefore);
|
auto before = qMin(haveBefore, query.limitBefore);
|
||||||
|
|
|
@ -51,7 +51,7 @@ void UserPhotos::List::addSlice(
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserPhotos::List::removeOne(PhotoId photoId) {
|
void UserPhotos::List::removeOne(PhotoId photoId) {
|
||||||
auto position = base::find(_photoIds, photoId);
|
auto position = ranges::find(_photoIds, photoId);
|
||||||
if (position == _photoIds.end()) {
|
if (position == _photoIds.end()) {
|
||||||
_count = base::none;
|
_count = base::none;
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,7 +64,7 @@ void UserPhotos::List::removeOne(PhotoId photoId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserPhotos::List::removeAfter(PhotoId photoId) {
|
void UserPhotos::List::removeAfter(PhotoId photoId) {
|
||||||
auto position = base::find(_photoIds, photoId);
|
auto position = ranges::find(_photoIds, photoId);
|
||||||
if (position == _photoIds.end()) {
|
if (position == _photoIds.end()) {
|
||||||
_count = base::none;
|
_count = base::none;
|
||||||
_photoIds.clear();
|
_photoIds.clear();
|
||||||
|
@ -90,7 +90,7 @@ rpl::producer<UserPhotosResult> UserPhotos::List::query(
|
||||||
auto result = UserPhotosResult {};
|
auto result = UserPhotosResult {};
|
||||||
result.count = _count;
|
result.count = _count;
|
||||||
|
|
||||||
auto position = base::find(_photoIds, query.key.photoId);
|
auto position = ranges::find(_photoIds, query.key.photoId);
|
||||||
if (position != _photoIds.end()) {
|
if (position != _photoIds.end()) {
|
||||||
auto haveBefore = int(position - _photoIds.begin());
|
auto haveBefore = int(position - _photoIds.begin());
|
||||||
auto haveEqualOrAfter = int(_photoIds.end() - position);
|
auto haveEqualOrAfter = int(_photoIds.end() - position);
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
|
||||||
#include <rpl/combine.h>
|
#include <rpl/combine.h>
|
||||||
|
#include <range/v3/algorithm/find.hpp>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
|
@ -156,7 +157,7 @@ rpl::producer<bool> MultiSlideTracker::atLeastOneShownValue() const {
|
||||||
return rpl::combine(
|
return rpl::combine(
|
||||||
std::move(shown),
|
std::move(shown),
|
||||||
[](const std::vector<bool> &values) {
|
[](const std::vector<bool> &values) {
|
||||||
return base::find(values, true) != values.end();
|
return ranges::find(values, true) != values.end();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ RpWidget *VerticalLayout::addChild(
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerticalLayout::childHeightUpdated(RpWidget *child) {
|
void VerticalLayout::childHeightUpdated(RpWidget *child) {
|
||||||
auto it = base::find_if(_rows, [child](const Row &row) {
|
auto it = ranges::find_if(_rows, [child](const Row &row) {
|
||||||
return (row.widget == child);
|
return (row.widget == child);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ void VerticalLayout::childHeightUpdated(RpWidget *child) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerticalLayout::removeChild(RpWidget *child) {
|
void VerticalLayout::removeChild(RpWidget *child) {
|
||||||
auto it = base::find_if(_rows, [child](const Row &row) {
|
auto it = ranges::find_if(_rows, [child](const Row &row) {
|
||||||
return (row.widget == child);
|
return (row.widget == child);
|
||||||
});
|
});
|
||||||
auto end = _rows.end();
|
auto end = _rows.end();
|
||||||
|
|
|
@ -386,17 +386,23 @@ int Completer::findEqualCharsCount(int position, const utf16string *word) {
|
||||||
|
|
||||||
std::vector<Suggestion> Completer::prepareResult() {
|
std::vector<Suggestion> Completer::prepareResult() {
|
||||||
auto firstCharOfQuery = _query[0];
|
auto firstCharOfQuery = _query[0];
|
||||||
base::stable_partition(_result, [firstCharOfQuery](Result &result) {
|
auto reorder = [&](auto &&predicate) {
|
||||||
|
std::stable_partition(
|
||||||
|
std::begin(_result),
|
||||||
|
std::end(_result),
|
||||||
|
std::forward<decltype(predicate)>(predicate));
|
||||||
|
};
|
||||||
|
reorder([firstCharOfQuery](Result &result) {
|
||||||
auto firstCharAfterColon = result.replacement->replacement[1];
|
auto firstCharAfterColon = result.replacement->replacement[1];
|
||||||
return (firstCharAfterColon == firstCharOfQuery);
|
return (firstCharAfterColon == firstCharOfQuery);
|
||||||
});
|
});
|
||||||
base::stable_partition(_result, [](Result &result) {
|
reorder([](Result &result) {
|
||||||
return (result.wordsUsed < 2);
|
return (result.wordsUsed < 2);
|
||||||
});
|
});
|
||||||
base::stable_partition(_result, [](Result &result) {
|
reorder([](Result &result) {
|
||||||
return (result.wordsUsed < 3);
|
return (result.wordsUsed < 3);
|
||||||
});
|
});
|
||||||
base::stable_partition(_result, [this](Result &result) {
|
reorder([&](Result &result) {
|
||||||
return isExactMatch(result.replacement->replacement);
|
return isExactMatch(result.replacement->replacement);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -412,13 +418,19 @@ std::vector<Suggestion> Completer::prepareResult() {
|
||||||
}
|
}
|
||||||
|
|
||||||
string_span Completer::findWordsStartingWith(utf16char ch) {
|
string_span Completer::findWordsStartingWith(utf16char ch) {
|
||||||
auto begin = base::lower_bound(_currentItemWords, ch, [](utf16string word, utf16char ch) {
|
auto begin = std::lower_bound(
|
||||||
return word[0] < ch;
|
std::begin(_currentItemWords),
|
||||||
});
|
std::end(_currentItemWords),
|
||||||
auto end = base::upper_bound(_currentItemWords, ch, [](utf16char ch, utf16string word) {
|
ch,
|
||||||
return ch < word[0];
|
[](utf16string word, utf16char ch) { return word[0] < ch; });
|
||||||
});
|
auto end = std::upper_bound(
|
||||||
return _currentItemWords.subspan(begin - _currentItemWords.begin(), end - begin);
|
std::begin(_currentItemWords),
|
||||||
|
std::end(_currentItemWords),
|
||||||
|
ch,
|
||||||
|
[](utf16char ch, utf16string word) { return ch < word[0]; });
|
||||||
|
return _currentItemWords.subspan(
|
||||||
|
begin - _currentItemWords.begin(),
|
||||||
|
end - begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
'<(src_loc)',
|
'<(src_loc)',
|
||||||
'<(submodules_loc)/GSL/include',
|
'<(submodules_loc)/GSL/include',
|
||||||
'<(submodules_loc)/variant/include',
|
'<(submodules_loc)/variant/include',
|
||||||
'<(submodules_loc)/Catch/include'
|
'<(submodules_loc)/Catch/include',
|
||||||
|
'<(libs_loc)/range-v3/include',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'<(src_loc)/base/tests_main.cpp',
|
'<(src_loc)/base/tests_main.cpp',
|
||||||
|
|
Loading…
Reference in New Issue