Use ranges:: algorithms instead of base::

This commit is contained in:
John Preston 2017-11-20 16:23:20 +04:00
parent bc7c88c511
commit ac99318f34
28 changed files with 751 additions and 596 deletions

View file

@ -1873,11 +1873,15 @@ void ApiWrap::checkForUnreadMentions(const base::flat_set<MsgId> &possiblyReadMe
}
void ApiWrap::cancelEditChatAdmins(not_null<ChatData*> chat) {
_chatAdminsEnabledRequests.take(chat)
| requestCanceller();
_chatAdminsEnabledRequests.take(
chat
) | requestCanceller();
_chatAdminsSaveRequests.take(chat)
| base::for_each_apply(requestCanceller());
_chatAdminsSaveRequests.take(
chat
) | [&](auto &&requests) {
ranges::for_each(std::move(requests), requestCanceller());
};
_chatAdminsToSave.remove(chat);
}
@ -1975,8 +1979,8 @@ void ApiWrap::sendSaveChatAdminsRequests(not_null<ChatData*> chat) {
}
}
}
base::for_each(toRemove, removeOne);
base::for_each(toAppoint, appointOne);
ranges::for_each(toRemove, removeOne);
ranges::for_each(toAppoint, appointOne);
requestSendDelayed();
}

View file

@ -32,109 +32,4 @@ inline constexpr size_t array_size(const Type(&)[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

View file

@ -21,8 +21,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include <deque>
#include <algorithm>
#include "base/optional.h"
#include "base/algorithm.h"
namespace base {
@ -39,18 +39,41 @@ template <
class flat_multi_map;
template <
typename Me,
typename Key,
typename Type,
typename Compare,
typename iterator_impl,
typename pointer_impl,
typename reference_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 <
typename Me,
typename Key,
typename Type,
typename Compare,
typename iterator_impl,
typename pointer_impl,
typename reference_impl>
@ -58,12 +81,13 @@ class flat_multi_map_iterator_base_impl {
public:
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 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 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())
: _impl(impl) {
@ -81,43 +105,44 @@ public:
const_pointer operator->() const {
return std::addressof(**this);
}
flat_multi_map_iterator_base_impl &operator++() {
Me &operator++() {
++_impl;
return *this;
return static_cast<Me&>(*this);
}
flat_multi_map_iterator_base_impl operator++(int) {
Me operator++(int) {
return _impl++;
}
flat_multi_map_iterator_base_impl &operator--() {
Me &operator--() {
--_impl;
return *this;
return static_cast<Me&>(*this);
}
flat_multi_map_iterator_base_impl operator--(int) {
Me operator--(int) {
return _impl--;
}
flat_multi_map_iterator_base_impl &operator+=(difference_type offset) {
Me &operator+=(difference_type 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;
}
flat_multi_map_iterator_base_impl &operator-=(difference_type offset) {
Me &operator-=(difference_type 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;
}
template <
typename other_me,
typename other_iterator_impl,
typename other_pointer_impl,
typename other_reference_impl>
difference_type operator-(
const flat_multi_map_iterator_base_impl<
other_me,
Key,
Type,
Compare,
other_iterator_impl,
other_pointer_impl,
other_reference_impl> &right) const {
@ -131,42 +156,45 @@ public:
}
template <
typename other_me,
typename other_iterator_impl,
typename other_pointer_impl,
typename other_reference_impl>
bool operator==(
const flat_multi_map_iterator_base_impl<
other_me,
Key,
Type,
Compare,
other_iterator_impl,
other_pointer_impl,
other_reference_impl> &right) const {
return _impl == right._impl;
}
template <
typename other_me,
typename other_iterator_impl,
typename other_pointer_impl,
typename other_reference_impl>
bool operator!=(
const flat_multi_map_iterator_base_impl<
other_me,
Key,
Type,
Compare,
other_iterator_impl,
other_pointer_impl,
other_reference_impl> &right) const {
return _impl != right._impl;
}
template <
typename other_me,
typename other_iterator_impl,
typename other_pointer_impl,
typename other_reference_impl>
bool operator<(
const flat_multi_map_iterator_base_impl<
other_me,
Key,
Type,
Compare,
other_iterator_impl,
other_pointer_impl,
other_reference_impl> &right) const {
@ -175,12 +203,17 @@ public:
private:
iterator_impl _impl;
friend class flat_multi_map<Key, Type, Compare>;
template <
typename OtherKey,
typename OtherType,
typename OtherCompare,
typename OtherCompare>
friend class flat_multi_map;
template <
typename OtherMe,
typename OtherKey,
typename OtherType,
typename other_iterator_impl,
typename other_pointer_impl,
typename other_reference_impl>
@ -190,131 +223,50 @@ private:
template <typename Key, typename Type, typename Compare>
class flat_multi_map {
class key_const_wrap {
public:
constexpr key_const_wrap(const Key &value) : _value(value) {
}
constexpr key_const_wrap(Key &&value) : _value(std::move(value)) {
}
inline constexpr operator const Key&() const {
return _value;
}
public:
class iterator;
class const_iterator;
class reverse_iterator;
class const_reverse_iterator;
private:
Key _value;
};
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>;
private:
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 iterator_base = flat_multi_map_iterator_base_impl<
iterator,
Key,
Type,
Compare,
typename impl::iterator,
typename impl_t::iterator,
pair_type*,
pair_type&>;
using const_iterator_base = flat_multi_map_iterator_base_impl<
const_iterator,
Key,
Type,
Compare,
typename impl::const_iterator,
typename impl_t::const_iterator,
const pair_type*,
const pair_type&>;
using reverse_iterator_base = flat_multi_map_iterator_base_impl<
reverse_iterator,
Key,
Type,
Compare,
typename impl::reverse_iterator,
typename impl_t::reverse_iterator,
pair_type*,
pair_type&>;
using const_reverse_iterator_base = flat_multi_map_iterator_base_impl<
const_reverse_iterator,
Key,
Type,
Compare,
typename impl::const_reverse_iterator,
typename impl_t::const_reverse_iterator,
const pair_type*,
const pair_type&>;
public:
using value_type = pair_type;
using size_type = typename impl::size_type;
using difference_type = typename impl::difference_type;
using size_type = typename impl_t::size_type;
using difference_type = typename impl_t::difference_type;
using pointer = pair_type*;
using const_pointer = const pair_type*;
using reference = pair_type&;
@ -324,6 +276,7 @@ public:
class iterator : public iterator_base {
public:
using iterator_base::iterator_base;
iterator() = default;
iterator(const iterator_base &other) : iterator_base(other) {
}
friend class const_iterator;
@ -332,6 +285,7 @@ public:
class const_iterator : public const_iterator_base {
public:
using const_iterator_base::const_iterator_base;
const_iterator() = default;
const_iterator(const_iterator_base other) : const_iterator_base(other) {
}
const_iterator(const iterator &other) : const_iterator_base(other._impl) {
@ -342,6 +296,7 @@ public:
class reverse_iterator : public reverse_iterator_base {
public:
using reverse_iterator_base::reverse_iterator_base;
reverse_iterator() = default;
reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) {
}
friend class const_reverse_iterator;
@ -350,6 +305,7 @@ public:
class const_reverse_iterator : public const_reverse_iterator_base {
public:
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 &other) : const_reverse_iterator_base(other._impl) {
@ -358,50 +314,50 @@ public:
};
size_type size() const {
return _impl.size();
return impl().size();
}
bool empty() const {
return _impl.empty();
return impl().empty();
}
void clear() {
_impl.clear();
impl().clear();
}
iterator begin() {
return _impl.begin();
return impl().begin();
}
iterator end() {
return _impl.end();
return impl().end();
}
const_iterator begin() const {
return _impl.begin();
return impl().begin();
}
const_iterator end() const {
return _impl.end();
return impl().end();
}
const_iterator cbegin() const {
return _impl.cbegin();
return impl().cbegin();
}
const_iterator cend() const {
return _impl.cend();
return impl().cend();
}
reverse_iterator rbegin() {
return _impl.rbegin();
return impl().rbegin();
}
reverse_iterator rend() {
return _impl.rend();
return impl().rend();
}
const_reverse_iterator rbegin() const {
return _impl.rbegin();
return impl().rbegin();
}
const_reverse_iterator rend() const {
return _impl.rend();
return impl().rend();
}
const_reverse_iterator crbegin() const {
return _impl.crbegin();
return impl().crbegin();
}
const_reverse_iterator crend() const {
return _impl.crend();
return impl().crend();
}
reference front() {
@ -419,25 +375,25 @@ public:
iterator insert(const value_type &value) {
if (empty() || compare()(value.first, front().first)) {
_impl.push_front(value);
impl().push_front(value);
return begin();
} else if (!compare()(value.first, back().first)) {
_impl.push_back(value);
impl().push_back(value);
return (end() - 1);
}
auto where = getUpperBound(value.first);
return _impl.insert(where, value);
return impl().insert(where, value);
}
iterator insert(value_type &&value) {
if (empty() || compare()(value.first, front().first)) {
_impl.push_front(std::move(value));
impl().push_front(std::move(value));
return begin();
} else if (!compare()(value.first, back().first)) {
_impl.push_back(std::move(value));
impl().push_back(std::move(value));
return (end() - 1);
}
auto where = getUpperBound(value.first);
return _impl.insert(where, std::move(value));
return impl().insert(where, std::move(value));
}
template <typename... Args>
iterator emplace(Args&&... args) {
@ -454,7 +410,7 @@ public:
if (compare()(key, where->first)) {
return false;
}
_impl.erase(where);
impl().erase(where);
return true;
}
int removeAll(const Key &key) {
@ -467,15 +423,15 @@ public:
if (range.first == range.second) {
return 0;
}
_impl.erase(range.first, range.second);
impl().erase(range.first, range.second);
return (range.second - range.first);
}
iterator erase(const_iterator where) {
return _impl.erase(where._impl);
return impl().erase(where._impl);
}
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) {
@ -485,7 +441,7 @@ public:
return end();
}
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 {
@ -495,7 +451,7 @@ public:
return end();
}
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 {
@ -512,32 +468,167 @@ public:
}
private:
impl _impl;
friend class flat_map<Key, Type, Compare>;
typename impl::iterator getLowerBound(const Key &key) {
return base::lower_bound(_impl, key, compare());
struct transparent_compare : 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 {
return base::lower_bound(_impl, key, compare());
const impl_t &impl() const noexcept {
return _data.elements;
}
typename impl::iterator getUpperBound(const Key &key) {
return base::upper_bound(_impl, key, compare());
impl_t &impl() noexcept {
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<
typename impl::iterator,
typename impl::iterator
typename impl_t::iterator,
typename impl_t::iterator
> 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<
typename impl::const_iterator,
typename impl::const_iterator
typename impl_t::const_iterator,
typename impl_t::const_iterator
> 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>
class flat_map : private 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;
public:
@ -579,30 +669,30 @@ public:
using parent::contains;
std::pair<iterator, bool> insert(const value_type &value) {
if (this->empty() || compare()(value.first, this->front().first)) {
this->_impl.push_front(value);
if (this->empty() || this->compare()(value.first, this->front().first)) {
this->impl().push_front(value);
return { this->begin(), true };
} else if (compare()(this->back().first, value.first)) {
this->_impl.push_back(value);
} else if (this->compare()(this->back().first, value.first)) {
this->impl().push_back(value);
return { this->end() - 1, true };
}
auto where = this->getLowerBound(value.first);
if (compare()(value.first, where->first)) {
return { this->_impl.insert(where, value), true };
if (this->compare()(value.first, where->first)) {
return { this->impl().insert(where, value), true };
}
return { where, false };
}
std::pair<iterator, bool> insert(value_type &&value) {
if (this->empty() || compare()(value.first, this->front().first)) {
this->_impl.push_front(std::move(value));
if (this->empty() || this->compare()(value.first, this->front().first)) {
this->impl().push_front(std::move(value));
return { this->begin(), true };
} else if (compare()(this->back().first, value.first)) {
this->_impl.push_back(std::move(value));
} else if (this->compare()(this->back().first, value.first)) {
this->impl().push_back(std::move(value));
return { this->end() - 1, true };
}
auto where = this->getLowerBound(value.first);
if (compare()(value.first, where->first)) {
return { this->_impl.insert(where, std::move(value)), true };
if (this->compare()(value.first, where->first)) {
return { this->impl().insert(where, std::move(value)), true };
}
return { where, false };
}
@ -618,21 +708,21 @@ public:
std::pair<iterator, bool> try_emplace(
const Key &key,
Args&&... args) {
if (this->empty() || compare()(key, this->front().first)) {
this->_impl.push_front(value_type(
if (this->empty() || this->compare()(key, this->front().first)) {
this->impl().push_front(value_type(
key,
Type(std::forward<Args>(args)...)));
return { this->begin(), true };
} else if (compare()(this->back().first, key)) {
this->_impl.push_back(value_type(
} else if (this->compare()(this->back().first, key)) {
this->impl().push_back(value_type(
key,
Type(std::forward<Args>(args)...)));
return { this->end() - 1, true };
}
auto where = this->getLowerBound(key);
if (compare()(key, where->first)) {
if (this->compare()(key, where->first)) {
return {
this->_impl.insert(
this->impl().insert(
where,
value_type(
key,
@ -655,16 +745,16 @@ public:
}
Type &operator[](const Key &key) {
if (this->empty() || compare()(key, this->front().first)) {
this->_impl.push_front({ key, Type() });
if (this->empty() || this->compare()(key, this->front().first)) {
this->impl().push_front({ key, Type() });
return this->front().second;
} else if (compare()(this->back().first, key)) {
this->_impl.push_back({ key, Type() });
} else if (this->compare()(this->back().first, key)) {
this->impl().push_back({ key, Type() });
return this->back().second;
}
auto where = this->getLowerBound(key);
if (compare()(key, where->first)) {
return this->_impl.insert(where, { key, Type() })->second;
if (this->compare()(key, where->first)) {
return this->impl().insert(where, { key, Type() })->second;
}
return where->second;
}

View file

@ -23,6 +23,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "base/flat_map.h"
#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;
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();
}
}
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();
}
}

View file

@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include <deque>
#include "base/algorithm.h"
#include <algorithm>
namespace base {
@ -31,28 +31,29 @@ class flat_set;
template <typename Type, typename Compare = std::less<>>
class flat_multi_set;
template <typename Type, typename Compare, typename iterator_impl>
template <typename Type, typename 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 {
public:
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 pointer = typename flat_multi_set<Type, Compare>::pointer;
using reference = typename flat_multi_set<Type, Compare>::reference;
using pointer = const Type*;
using reference = const Type&;
flat_multi_set_iterator_impl(iterator_impl impl = iterator_impl())
: _impl(impl) {
flat_multi_set_iterator_impl(
iterator_impl impl = iterator_impl())
: _impl(impl) {
}
template <typename other_iterator_impl>
flat_multi_set_iterator_impl(
const flat_multi_set_iterator_impl<
Type,
Compare,
other_iterator_impl> &other) : _impl(other._impl) {
const flat_multi_set_iterator_impl<
Type,
other_iterator_impl> &other)
: _impl(other._impl) {
}
reference operator*() const {
@ -91,10 +92,9 @@ public:
}
template <typename other_iterator_impl>
difference_type operator-(
const flat_multi_set_iterator_impl<
Type,
Compare,
other_iterator_impl> &right) const {
const flat_multi_set_iterator_impl<
Type,
other_iterator_impl> &right) const {
return _impl - right._impl;
}
reference operator[](difference_type offset) const {
@ -103,37 +103,37 @@ public:
template <typename other_iterator_impl>
bool operator==(
const flat_multi_set_iterator_impl<
Type,
Compare,
other_iterator_impl> &right) const {
const flat_multi_set_iterator_impl<
Type,
other_iterator_impl> &right) const {
return _impl == right._impl;
}
template <typename other_iterator_impl>
bool operator!=(
const flat_multi_set_iterator_impl<
Type,
Compare,
other_iterator_impl> &right) const {
const flat_multi_set_iterator_impl<
Type,
other_iterator_impl> &right) const {
return _impl != right._impl;
}
template <typename other_iterator_impl>
bool operator<(
const flat_multi_set_iterator_impl<
Type,
Compare,
other_iterator_impl> &right) const {
const flat_multi_set_iterator_impl<
Type,
other_iterator_impl> &right) const {
return _impl < right._impl;
}
private:
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 <
typename OtherType,
typename OtherCompare,
typename other_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>
class flat_multi_set {
class const_wrap {
public:
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>;
using const_wrap = flat_multi_set_const_wrap<Type>;
using impl_t = std::deque<const_wrap>;
public:
using value_type = Type;
using size_type = typename impl::size_type;
using difference_type = typename impl::difference_type;
using size_type = typename impl_t::size_type;
using difference_type = typename impl_t::difference_type;
using pointer = const Type*;
using reference = const Type&;
using iterator = flat_multi_set_iterator_impl<
Type,
Compare,
typename impl::iterator>;
typename impl_t::iterator>;
using const_iterator = flat_multi_set_iterator_impl<
Type,
Compare,
typename impl::const_iterator>;
typename impl_t::const_iterator>;
using reverse_iterator = flat_multi_set_iterator_impl<
Type,
Compare,
typename impl::reverse_iterator>;
typename impl_t::reverse_iterator>;
using const_reverse_iterator = flat_multi_set_iterator_impl<
Type,
Compare,
typename impl::const_reverse_iterator>;
typename impl_t::const_reverse_iterator>;
flat_multi_set() = default;
template <
typename Iterator,
typename = typename std::iterator_traits<Iterator>::iterator_category>
flat_multi_set(Iterator first, Iterator last) : _impl(first, last) {
base::sort(_impl, compare());
flat_multi_set(Iterator first, Iterator last)
: _data(first, last) {
std::sort(std::begin(impl()), std::end(impl()), compare());
}
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 {
return _impl.size();
return impl().size();
}
bool empty() const {
return _impl.empty();
return impl().empty();
}
void clear() {
_impl.clear();
impl().clear();
}
iterator begin() {
return _impl.begin();
return impl().begin();
}
iterator end() {
return _impl.end();
return impl().end();
}
const_iterator begin() const {
return _impl.begin();
return impl().begin();
}
const_iterator end() const {
return _impl.end();
return impl().end();
}
const_iterator cbegin() const {
return _impl.cbegin();
return impl().cbegin();
}
const_iterator cend() const {
return _impl.cend();
return impl().cend();
}
reverse_iterator rbegin() {
return _impl.rbegin();
return impl().rbegin();
}
reverse_iterator rend() {
return _impl.rend();
return impl().rend();
}
const_reverse_iterator rbegin() const {
return _impl.rbegin();
return impl().rbegin();
}
const_reverse_iterator rend() const {
return _impl.rend();
return impl().rend();
}
const_reverse_iterator crbegin() const {
return _impl.crbegin();
return impl().crbegin();
}
const_reverse_iterator crend() const {
return _impl.crend();
return impl().crend();
}
reference front() const {
@ -307,25 +259,25 @@ public:
iterator insert(const Type &value) {
if (empty() || compare()(value, front())) {
_impl.push_front(value);
impl().push_front(value);
return begin();
} else if (!compare()(value, back())) {
_impl.push_back(value);
impl().push_back(value);
return (end() - 1);
}
auto where = getUpperBound(value);
return _impl.insert(where, value);
return impl().insert(where, value);
}
iterator insert(Type &&value) {
if (empty() || compare()(value, front())) {
_impl.push_front(std::move(value));
impl().push_front(std::move(value));
return begin();
} else if (!compare()(value, back())) {
_impl.push_back(std::move(value));
impl().push_back(std::move(value));
return (end() - 1);
}
auto where = getUpperBound(value);
return _impl.insert(where, std::move(value));
return impl().insert(where, std::move(value));
}
template <typename... Args>
iterator emplace(Args&&... args) {
@ -342,7 +294,7 @@ public:
if (compare()(value, *where)) {
return false;
}
_impl.erase(where);
impl().erase(where);
return true;
}
int removeAll(const Type &value) {
@ -355,15 +307,15 @@ public:
if (range.first == range.second) {
return 0;
}
_impl.erase(range.first, range.second);
impl().erase(range.first, range.second);
return (range.second - range.first);
}
iterator erase(const_iterator where) {
return _impl.erase(where._impl);
return impl().erase(where._impl);
}
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) {
@ -373,7 +325,7 @@ public:
return end();
}
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 {
@ -383,33 +335,33 @@ public:
return end();
}
auto where = getLowerBound(value);
return compare()(value, *where) ? _impl.end() : where;
return compare()(value, *where) ? impl().end() : where;
}
template <
typename OtherType,
typename = typename Compare::is_transparent>
iterator findFirst(const OtherType &value) {
iterator findFirst(const OtherType &value) {
if (empty()
|| compare()(value, front())
|| compare()(back(), value)) {
return end();
}
auto where = getLowerBound(value);
return compare()(value, *where) ? _impl.end() : where;
return compare()(value, *where) ? impl().end() : where;
}
template <
typename OtherType,
typename = typename Compare::is_transparent>
const_iterator findFirst(const OtherType &value) const {
const_iterator findFirst(const OtherType &value) const {
if (empty()
|| compare()(value, front())
|| compare()(back(), value)) {
return end();
}
auto where = getLowerBound(value);
return compare()(value, *where) ? _impl.end() : where;
return compare()(value, *where) ? impl().end() : where;
}
bool contains(const Type &value) const {
@ -450,8 +402,8 @@ public:
typename Iterator,
typename = typename std::iterator_traits<Iterator>::iterator_category>
void merge(Iterator first, Iterator last) {
_impl.insert(_impl.end(), first, last);
base::sort(_impl, compare());
impl().insert(impl().end(), first, last);
std::sort(std::begin(impl()), std::end(impl()), compare());
}
void merge(const flat_multi_set<Type, Compare> &other) {
@ -463,44 +415,149 @@ public:
}
private:
impl _impl;
friend class flat_set<Type, Compare>;
typename impl::iterator getLowerBound(const Type &value) {
return base::lower_bound(_impl, value, compare());
struct transparent_compare : 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 {
return base::lower_bound(_impl, value, compare());
const impl_t &impl() const {
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 <
typename OtherType,
typename = typename Compare::is_transparent>
typename impl::iterator getLowerBound(const OtherType &value) {
return base::lower_bound(_impl, value, compare());
typename impl_t::iterator getLowerBound(const OtherType &value) {
return std::lower_bound(
std::begin(impl()),
std::end(impl()),
value,
compare());
}
template <
typename OtherType,
typename = typename Compare::is_transparent>
typename impl::const_iterator getLowerBound(const OtherType &value) const {
return base::lower_bound(_impl, value, compare());
typename impl_t::const_iterator getLowerBound(const OtherType &value) const {
return std::lower_bound(
std::begin(impl()),
std::end(impl()),
value,
compare());
}
typename impl::iterator getUpperBound(const Type &value) {
return base::upper_bound(_impl, value, compare());
typename impl_t::iterator getUpperBound(const Type &value) {
return std::upper_bound(
std::begin(impl()),
std::end(impl()),
value,
compare());
}
typename impl::const_iterator getUpperBound(const Type &value) const {
return base::upper_bound(_impl, value, compare());
typename impl_t::const_iterator getUpperBound(const Type &value) const {
return std::upper_bound(
std::begin(impl()),
std::end(impl()),
value,
compare());
}
std::pair<
typename impl::iterator,
typename impl::iterator
typename impl_t::iterator,
typename impl_t::iterator
> 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<
typename impl::const_iterator,
typename impl::const_iterator
typename impl_t::const_iterator,
typename impl_t::const_iterator
> 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>
class flat_set : private flat_multi_set<Type, Compare> {
using parent = flat_multi_set<Type, Compare>;
using compare = typename parent::compare;
public:
using iterator = typename parent::iterator;
@ -553,30 +609,30 @@ public:
using parent::erase;
iterator insert(const Type &value) {
if (this->empty() || compare()(value, this->front())) {
this->_impl.push_front(value);
if (this->empty() || this->compare()(value, this->front())) {
this->impl().push_front(value);
return this->begin();
} else if (compare()(this->back(), value)) {
this->_impl.push_back(value);
} else if (this->compare()(this->back(), value)) {
this->impl().push_back(value);
return (this->end() - 1);
}
auto where = this->getLowerBound(value);
if (compare()(value, *where)) {
return this->_impl.insert(where, value);
if (this->compare()(value, *where)) {
return this->impl().insert(where, value);
}
return this->end();
}
iterator insert(Type &&value) {
if (this->empty() || compare()(value, this->front())) {
this->_impl.push_front(std::move(value));
if (this->empty() || this->compare()(value, this->front())) {
this->impl().push_front(std::move(value));
return this->begin();
} else if (compare()(this->back(), value)) {
this->_impl.push_back(std::move(value));
} else if (this->compare()(this->back(), value)) {
this->impl().push_back(std::move(value));
return (this->end() - 1);
}
auto where = this->getLowerBound(value);
if (compare()(value, *where)) {
return this->_impl.insert(where, std::move(value));
if (this->compare()(value, *where)) {
return this->impl().insert(where, std::move(value));
}
return this->end();
}
@ -612,9 +668,9 @@ public:
void modify(iterator which, Action action) {
action(which.wrapped());
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());
} else if (!compare()(*which, *i)) {
} else if (!this->compare()(*which, *i)) {
erase(which);
return;
} else{
@ -623,9 +679,9 @@ public:
}
for (auto i = which, b = begin(); i != b;) {
--i;
if (compare()(*which, *i)) {
if (this->compare()(*which, *i)) {
std::swap(i.wrapped(), which.wrapped());
} else if (!compare()(*i, *which)) {
} else if (!this->compare()(*i, *which)) {
erase(which);
return;
} else {
@ -652,12 +708,15 @@ public:
private:
void finalize() {
this->_impl.erase(
this->impl().erase(
std::unique(
this->_impl.begin(),
this->_impl.end(),
[](auto &&a, auto &&b) { return !compare()(a, b); }),
this->_impl.end());
std::begin(this->impl()),
std::end(this->impl()),
[&](auto &&a, auto &&b) {
return !this->compare()(a, b);
}
),
std::end(this->impl()));
}
};

View file

@ -22,7 +22,27 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#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]") {
base::flat_set<int> v;
v.insert(0);
v.insert(5);
@ -48,3 +68,30 @@ TEST_CASE("flat_sets should keep items sorted", "[flat_set]") {
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();
}
}

View file

@ -593,8 +593,8 @@ void PeerListContent::addRowEntry(not_null<PeerListRow*> row) {
void PeerListContent::invalidatePixmapsCache() {
auto invalidate = [](auto &&row) { row->invalidatePixmapsCache(); };
base::for_each(_rows, invalidate);
base::for_each(_searchRows, invalidate);
ranges::for_each(_rows, invalidate);
ranges::for_each(_searchRows, invalidate);
}
bool PeerListContent::addingToSearchIndex() const {

View file

@ -648,11 +648,11 @@ void EditChatAdminsBoxController::rebuildRows() {
admins.insert(admins.end(), others.begin(), others.end());
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);
};
base::sort(admins, sortByName);
base::sort(others, sortByName);
ranges::sort(admins, sortByName);
ranges::sort(others, sortByName);
auto addOne = [this](not_null<UserData*> user) {
if (auto row = createRow(user)) {
@ -664,8 +664,8 @@ void EditChatAdminsBoxController::rebuildRows() {
addOne(creator);
}
}
base::for_each(admins, addOne);
base::for_each(others, addOne);
ranges::for_each(admins, addOne);
ranges::for_each(others, addOne);
delegate()->peerListRefreshRows();
}

View file

@ -538,7 +538,7 @@ void Controller::usernameChanged() {
_checkUsernameTimer.cancel();
return;
}
auto bad = base::find_if(username, [](QChar ch) {
auto bad = ranges::find_if(username, [](QChar ch) {
return (ch < 'A' || ch > 'Z')
&& (ch < 'a' || ch > 'z')
&& (ch < '0' || ch > '9')

View file

@ -51,10 +51,10 @@ public:
bool canAddItem(not_null<const HistoryItem*> item) const {
return (ComputeType(item) == _type && item->date.date() == _date);
}
void addItem(HistoryItem *item) {
void addItem(not_null<HistoryItem*> item) {
Expects(canAddItem(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);
});
refreshStatus();
@ -116,7 +116,7 @@ private:
void refreshStatus();
static Type ComputeType(not_null<const HistoryItem*> item);
std::vector<HistoryItem*> _items;
std::vector<not_null<HistoryItem*>> _items;
QDate _date;
Type _type;

View file

@ -62,7 +62,7 @@ base::optional<int> SparseIdsSlice::distance(
}
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;
} else if (_ids.empty()) {
return base::none;
@ -342,7 +342,7 @@ void SparseIdsSliceBuilder::sliceToLimits() {
return;
}
auto requestedSomething = false;
auto aroundIt = base::lower_bound(_ids, _key);
auto aroundIt = ranges::lower_bound(_ids, _key);
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
if (removeFromBegin > 0) {

View file

@ -60,7 +60,8 @@ private:
};
UserPhotosSlice::UserPhotosSlice(Key key) : UserPhotosSlice(
UserPhotosSlice::UserPhotosSlice(Key key)
: UserPhotosSlice(
key,
{},
base::none,
@ -74,15 +75,15 @@ UserPhotosSlice::UserPhotosSlice(
base::optional<int> fullCount,
base::optional<int> skippedBefore,
int skippedAfter)
: _key(key)
, _ids(ids)
, _fullCount(fullCount)
, _skippedBefore(skippedBefore)
, _skippedAfter(skippedAfter) {
: _key(key)
, _ids(ids)
, _fullCount(fullCount)
, _skippedBefore(skippedBefore)
, _skippedAfter(skippedAfter) {
}
base::optional<int> UserPhotosSlice::indexOf(PhotoId photoId) const {
auto it = base::find(_ids, photoId);
auto it = ranges::find(_ids, photoId);
if (it != _ids.end()) {
return (it - _ids.begin());
}
@ -190,7 +191,7 @@ void UserPhotosSliceBuilder::mergeSliceData(
}
void UserPhotosSliceBuilder::sliceToLimits() {
auto aroundIt = base::find(_ids, _key.photoId);
auto aroundIt = ranges::find(_ids, _key.photoId);
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
if (removeFromEnd > 0) {

View file

@ -73,7 +73,7 @@ QString TopBarOverride::generateText() 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;
}) == _items.list.end();
}

View file

@ -104,6 +104,10 @@ public:
return _height;
}
int bottom() const {
return top() + height();
}
bool removeItem(UniversalMsgId universalId);
FoundItem findItemNearId(UniversalMsgId universalId) const;
FoundItem findItemByPoint(QPoint point) const;
@ -302,12 +306,11 @@ auto ListWidget::Section::findItemByPoint(
auto ListWidget::Section::findItemNearId(
UniversalMsgId universalId) const -> FoundItem {
Expects(!_items.empty());
auto itemIt = base::lower_bound(
auto itemIt = ranges::lower_bound(
_items,
universalId,
[this](const auto &item, UniversalMsgId universalId) {
return (item.first > universalId);
});
std::greater<>(),
[](const auto &item) -> UniversalMsgId { return item.first; });
if (itemIt == _items.end()) {
--itemIt;
}
@ -318,36 +321,39 @@ auto ListWidget::Section::findItemNearId(
auto ListWidget::Section::findItemAfterTop(
int top) -> Items::iterator {
return base::lower_bound(
return ranges::lower_bound(
_items,
top,
[this](const auto &item, int top) {
std::less_equal<>(),
[this](const auto &item) {
auto itemTop = item.second->position() / _itemsInRow;
return (itemTop + item.second->height()) <= top;
return itemTop + item.second->height();
});
}
auto ListWidget::Section::findItemAfterTop(
int top) const -> Items::const_iterator {
return base::lower_bound(
return ranges::lower_bound(
_items,
top,
[this](const auto &item, int top) {
auto itemTop = item.second->position() / _itemsInRow;
return (itemTop + item.second->height()) <= top;
});
std::less_equal<>(),
[this](const auto &item) {
auto itemTop = item.second->position() / _itemsInRow;
return itemTop + item.second->height();
});
}
auto ListWidget::Section::findItemAfterBottom(
Items::const_iterator from,
int bottom) const -> Items::const_iterator {
return std::lower_bound(
return ranges::lower_bound(
from,
_items.end(),
bottom,
[this](const auto &item, int bottom) {
std::less<>(),
[this](const auto &item) {
auto itemTop = item.second->position() / _itemsInRow;
return itemTop < bottom;
return itemTop;
});
}
@ -1182,12 +1188,12 @@ void ListWidget::showContextMenu(
}
auto canDeleteAll = [&] {
return base::find_if(_selected, [](auto &item) {
return ranges::find_if(_selected, [](auto &&item) {
return !item.second.canDelete;
}) == _selected.end();
};
auto canForwardAll = [&] {
return base::find_if(_selected, [](auto &item) {
return ranges::find_if(_selected, [](auto &&item) {
return !item.second.canForward;
}) == _selected.end();
};
@ -2042,44 +2048,40 @@ void ListWidget::clearStaleLayouts() {
auto ListWidget::findSectionByItem(
UniversalMsgId universalId) -> std::vector<Section>::iterator {
return base::lower_bound(
return ranges::lower_bound(
_sections,
universalId,
[](const Section &section, int universalId) {
return section.minId() > universalId;
});
std::greater<>(),
[](const Section &section) { return section.minId(); });
}
auto ListWidget::findSectionAfterTop(
int top) -> std::vector<Section>::iterator {
return base::lower_bound(
return ranges::lower_bound(
_sections,
top,
[](const Section &section, int top) {
return (section.top() + section.height()) <= top;
});
std::less_equal<>(),
[](const Section &section) { return section.bottom(); });
}
auto ListWidget::findSectionAfterTop(
int top) const -> std::vector<Section>::const_iterator {
return base::lower_bound(
return ranges::lower_bound(
_sections,
top,
[](const Section &section, int top) {
return (section.top() + section.height()) <= top;
});
std::less_equal<>(),
[](const Section &section) { return section.bottom(); });
}
auto ListWidget::findSectionAfterBottom(
std::vector<Section>::const_iterator from,
int bottom) const -> std::vector<Section>::const_iterator {
return std::lower_bound(
return ranges::lower_bound(
from,
_sections.end(),
bottom,
[](const Section &section, int bottom) {
return section.top() < bottom;
});
std::less<>(),
[](const Section &section) { return section.top(); });
}
ListWidget::~ListWidget() = default;

View file

@ -341,7 +341,7 @@ DcOptions::Ids DcOptions::configEnumDcIds() const {
}
}
}
base::sort(result);
ranges::sort(result);
return result;
}

View file

@ -181,7 +181,7 @@ bool UnsafeShowOpenWithDropdown(const QString &filepath, QPoint menuPosition) {
if (!handlers.empty()) {
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();
});
for (int32 i = 0, l = handlers.size(); i < l; ++i) {

View file

@ -277,13 +277,13 @@ std::unique_ptr<PeerListState> ParticipantsBoxController::saveState() {
return;
}
}
auto pos = base::find(weak->list, user);
auto pos = ranges::find(weak->list, user);
if (pos == weak->list.cend()) {
weak->list.push_back(user);
}
base::stable_partition(weak->list, [user](not_null<PeerData*> peer) {
return (peer == user);
});
ranges::stable_partition(
weak->list,
[user](auto peer) { return (peer == user); });
}, my->lifetime);
Auth().data().megagroupParticipantRemoved(_channel)
| rpl::start_with_next([weak](not_null<UserData*> user) {

View file

@ -326,7 +326,7 @@ inline auto combine(
state->latest.push_back(
std::move(*value));
}
base::take(state->accumulated);
details::take(state->accumulated);
consumer.put_next_copy(state->latest);
}
}

View file

@ -128,7 +128,7 @@ template <typename Value, typename Error>
inline void type_erased_handlers<Value, Error>::terminate() {
if (!_terminated) {
_terminated = true;
base::take(_lifetime).destroy();
details::take(_lifetime).destroy();
}
}

View file

@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include <rpl/then.h>
#include <rpl/range.h>
#include <algorithm>
#include "base/algorithm.h"
#include "base/assertion.h"
#include "base/index_based_iterator.h"
@ -54,8 +53,9 @@ public:
if (auto strong = weak.lock()) {
auto result = [weak, consumer] {
if (auto strong = weak.lock()) {
auto it = base::find(
strong->consumers,
auto it = std::find(
strong->consumers.begin(),
strong->consumers.end(),
consumer);
if (it != strong->consumers.end()) {
it->terminate();
@ -94,13 +94,13 @@ inline event_stream<Value>::event_stream() {
template <typename Value>
inline event_stream<Value>::event_stream(event_stream &&other)
: _data(base::take(other._data)) {
: _data(details::take(other._data)) {
}
template <typename Value>
inline event_stream<Value> &event_stream<Value>::operator=(
event_stream &&other) {
_data = base::take(other._data);
_data = details::take(other._data);
return *this;
}
@ -164,7 +164,7 @@ inline auto event_stream<Value>::weak() const
template <typename Value>
inline event_stream<Value>::~event_stream() {
if (auto data = base::take(_data)) {
if (auto data = details::take(_data)) {
for (auto &consumer : data->consumers) {
consumer.put_done();
}

View file

@ -21,10 +21,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
#include "base/lambda.h"
#include "base/algorithm.h"
#include <deque>
namespace rpl {
namespace details {
template <typename Type>
inline Type take(Type &value) {
return std::exchange(value, Type{});
}
} // namespace details
class lifetime {
public:
@ -47,7 +54,7 @@ public:
auto result = new Type(std::forward<Args>(args)...);
add([result]() mutable {
static_assert(sizeof(Type) > 0, "Can't delete unknown type.");
delete base::take(result);
delete details::take(result);
});
return result;
}
@ -60,7 +67,7 @@ private:
};
inline lifetime::lifetime(lifetime &&other)
: _callbacks(base::take(other._callbacks)) {
: _callbacks(details::take(other._callbacks)) {
}
inline lifetime &lifetime::operator=(lifetime &&other) {
@ -80,7 +87,7 @@ inline void lifetime::add(Destroy &&destroy) {
}
inline void lifetime::add(lifetime &&other) {
auto callbacks = base::take(other._callbacks);
auto callbacks = details::take(other._callbacks);
_callbacks.insert(
_callbacks.begin(),
std::make_move_iterator(callbacks.begin()),
@ -88,7 +95,7 @@ inline void lifetime::add(lifetime &&other) {
}
inline void lifetime::destroy() {
for (auto &callback : base::take(_callbacks)) {
for (auto &callback : details::take(_callbacks)) {
callback();
}
}

View file

@ -57,8 +57,8 @@ public:
}
}
InvokeCounter(InvokeCounter &&other)
: _copyCounter(base::take(other._copyCounter))
, _moveCounter(base::take(other._moveCounter)) {
: _copyCounter(details::take(other._copyCounter))
, _moveCounter(details::take(other._moveCounter)) {
if (_moveCounter) {
++*_moveCounter;
}
@ -72,8 +72,8 @@ public:
return *this;
}
InvokeCounter &operator=(InvokeCounter &&other) {
_copyCounter = base::take(other._copyCounter);
_moveCounter = base::take(other._moveCounter);
_copyCounter = details::take(other._copyCounter);
_moveCounter = details::take(other._moveCounter);
if (_moveCounter) {
++*_moveCounter;
}
@ -213,7 +213,7 @@ TEST_CASE("basic operators tests", "[rpl::operators]") {
}
REQUIRE(*sum == "1 1 3 ");
}
SECTION("filter tuple test") {
auto sum = std::make_shared<std::string>("");
{

View file

@ -80,14 +80,16 @@ int SparseIdsList::addRangeItemsAndCountNew(
return 0;
}
auto uniteFrom = base::lower_bound(
auto uniteFrom = ranges::lower_bound(
_slices,
noSkipRange.from,
[](const Slice &slice, MsgId from) { return slice.range.till < from; });
auto uniteTill = base::upper_bound(
std::less<>(),
[](const Slice &slice) { return slice.range.till; });
auto uniteTill = ranges::upper_bound(
_slices,
noSkipRange.till,
[](MsgId till, const Slice &slice) { return till < slice.range.from; });
std::less<>(),
[](const Slice &slice) { return slice.range.from; });
if (uniteFrom < uniteTill) {
return uniteAndAdd(update, uniteFrom, uniteTill, messages, noSkipRange);
}
@ -151,10 +153,11 @@ void SparseIdsList::addSlice(
}
void SparseIdsList::removeOne(MsgId messageId) {
auto slice = base::lower_bound(
auto slice = ranges::lower_bound(
_slices,
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) {
_slices.modify(slice, [messageId](Slice &slice) {
return slice.messages.remove(messageId);
@ -175,12 +178,11 @@ rpl::producer<SparseIdsListResult> SparseIdsList::query(
SparseIdsListQuery &&query) const {
return [this, query = std::move(query)](auto consumer) {
auto slice = query.aroundId
? base::lower_bound(
? ranges::lower_bound(
_slices,
query.aroundId,
[](const Slice &slice, MsgId id) {
return slice.range.till < id;
})
std::less<>(),
[](const Slice &slice) { return slice.range.till; })
: _slices.end();
if (slice != _slices.end()
&& slice->range.from <= query.aroundId) {
@ -199,7 +201,7 @@ SparseIdsListResult SparseIdsList::queryFromSlice(
const SparseIdsListQuery &query,
const Slice &slice) const {
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 haveEqualOrAfter = int(slice.messages.end() - position);
auto before = qMin(haveBefore, query.limitBefore);

View file

@ -51,7 +51,7 @@ void UserPhotos::List::addSlice(
}
void UserPhotos::List::removeOne(PhotoId photoId) {
auto position = base::find(_photoIds, photoId);
auto position = ranges::find(_photoIds, photoId);
if (position == _photoIds.end()) {
_count = base::none;
} else {
@ -64,7 +64,7 @@ void UserPhotos::List::removeOne(PhotoId photoId) {
}
void UserPhotos::List::removeAfter(PhotoId photoId) {
auto position = base::find(_photoIds, photoId);
auto position = ranges::find(_photoIds, photoId);
if (position == _photoIds.end()) {
_count = base::none;
_photoIds.clear();
@ -90,7 +90,7 @@ rpl::producer<UserPhotosResult> UserPhotos::List::query(
auto result = UserPhotosResult {};
result.count = _count;
auto position = base::find(_photoIds, query.key.photoId);
auto position = ranges::find(_photoIds, query.key.photoId);
if (position != _photoIds.end()) {
auto haveBefore = int(position - _photoIds.begin());
auto haveEqualOrAfter = int(_photoIds.end() - position);

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/wrap/slide_wrap.h"
#include <rpl/combine.h>
#include <range/v3/algorithm/find.hpp>
namespace Ui {
@ -156,7 +157,7 @@ rpl::producer<bool> MultiSlideTracker::atLeastOneShownValue() const {
return rpl::combine(
std::move(shown),
[](const std::vector<bool> &values) {
return base::find(values, true) != values.end();
return ranges::find(values, true) != values.end();
});
}

View file

@ -131,7 +131,7 @@ RpWidget *VerticalLayout::addChild(
}
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);
});
@ -158,7 +158,7 @@ void VerticalLayout::childHeightUpdated(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);
});
auto end = _rows.end();

View file

@ -386,17 +386,23 @@ int Completer::findEqualCharsCount(int position, const utf16string *word) {
std::vector<Suggestion> Completer::prepareResult() {
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];
return (firstCharAfterColon == firstCharOfQuery);
});
base::stable_partition(_result, [](Result &result) {
reorder([](Result &result) {
return (result.wordsUsed < 2);
});
base::stable_partition(_result, [](Result &result) {
reorder([](Result &result) {
return (result.wordsUsed < 3);
});
base::stable_partition(_result, [this](Result &result) {
reorder([&](Result &result) {
return isExactMatch(result.replacement->replacement);
});
@ -412,13 +418,19 @@ std::vector<Suggestion> Completer::prepareResult() {
}
string_span Completer::findWordsStartingWith(utf16char ch) {
auto begin = base::lower_bound(_currentItemWords, ch, [](utf16string word, utf16char ch) {
return word[0] < ch;
});
auto end = base::upper_bound(_currentItemWords, ch, [](utf16char ch, utf16string word) {
return ch < word[0];
});
return _currentItemWords.subspan(begin - _currentItemWords.begin(), end - begin);
auto begin = std::lower_bound(
std::begin(_currentItemWords),
std::end(_currentItemWords),
ch,
[](utf16string word, utf16char ch) { return word[0] < ch; });
auto end = std::upper_bound(
std::begin(_currentItemWords),
std::end(_currentItemWords),
ch,
[](utf16char ch, utf16string word) { return ch < word[0]; });
return _currentItemWords.subspan(
begin - _currentItemWords.begin(),
end - begin);
}
} // namespace

View file

@ -26,7 +26,8 @@
'<(src_loc)',
'<(submodules_loc)/GSL/include',
'<(submodules_loc)/variant/include',
'<(submodules_loc)/Catch/include'
'<(submodules_loc)/Catch/include',
'<(libs_loc)/range-v3/include',
],
'sources': [
'<(src_loc)/base/tests_main.cpp',