Skip to content

Commit

Permalink
Merge #843(kitsune): Drop findIndirect() algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
KitsuneRal authored Dec 4, 2024
2 parents 75d559d + f3615df commit 4c97d1d
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Quotient/events/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ using namespace Quotient;
void AbstractEventMetaType::addDerived(const AbstractEventMetaType* newType)
{
if (const auto existing =
findIndirect(_derivedTypes, newType->matrixId, &AbstractEventMetaType::matrixId);
std::ranges::find(_derivedTypes, newType->matrixId, &AbstractEventMetaType::matrixId);
existing != _derivedTypes.cend()) {
if (*existing == newType)
return;
Expand Down
35 changes: 0 additions & 35 deletions Quotient/ranges_extras.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,6 @@

namespace Quotient {

//! Same as std::projected but Proj is checked against the reference under the iterator
template <std::indirectly_readable IterT,
std::indirectly_regular_unary_invocable<std::iter_reference_t<IterT>> ProjT>
using IndirectlyProjected = std::projected<std::iter_reference_t<IterT>, ProjT>;

//! Same as std::indirectly_comparable but uses IndirectlyProjected<> instead of std::projected<>
template <typename IterT, typename ValT, typename ProjT, typename CompT = std::ranges::equal_to>
concept IndirectlyProjectedComparable =
std::indirect_binary_predicate<CompT, IndirectlyProjected<IterT, ProjT>, const ValT*>;

//! \brief Find a value in a container of (smart) pointers
//!
//! This is a replica of std::ranges::find that automatically applies dereferencing projection
//! before applying the provided projection. Quotient has a few containers with pointers or wrappers
//! for other types - think of timeline items or `event_ptr_tt<>`s. This is meant to streamline
//! searching for events that match a specific simple criterion; e.g., to find an event with a given
//! id in a container you can now write `findIndirect(events, eventId, &RoomEvent::id);` instead
//! of having to supply your own lambda to dereference the timeline item and check the event id.
template <std::input_iterator IterT, typename ValT, typename ProjT = std::identity>
requires IndirectlyProjectedComparable<IterT, ValT, ProjT>
inline constexpr auto findIndirect(IterT from, IterT to, const ValT& value, ProjT proj = {})
{
return std::ranges::find(from, to, value, [p = std::move(proj)](auto& itemPtr) {
return std::invoke(p, *itemPtr);
});
}

//! The overload of findIndirect for ranges
template <typename RangeT, typename ValT, typename ProjT = std::identity>
requires IndirectlyProjectedComparable<std::ranges::iterator_t<RangeT>, ValT, ProjT>
inline constexpr auto findIndirect(RangeT&& range, const ValT& value, ProjT proj = {})
{
return findIndirect(std::ranges::begin(range), std::ranges::end(range), value, std::move(proj));
}

//! \brief An indexOf() alternative for any range
//!
//! Unlike QList::indexOf(), returns `range.size()` if \p value is not found
Expand Down
14 changes: 7 additions & 7 deletions Quotient/room.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,12 +1102,12 @@ Room::rev_iter_t Room::findInTimeline(const QString& evtId) const

Room::PendingEvents::iterator Room::findPendingEvent(const QString& txnId)
{
return findIndirect(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
return std::ranges::find(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
}

Room::PendingEvents::const_iterator Room::findPendingEvent(const QString& txnId) const
{
return findIndirect(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
return std::ranges::find(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
}

const Room::RelatedEvents Room::relatedEvents(
Expand Down Expand Up @@ -2815,18 +2815,19 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events)
et.start();

{
using namespace std::ranges;
// Pre-process redactions and edits so that events that get
// redacted/replaced in the same batch landed in the timeline already
// treated.
// NB: We have to store redacting/replacing events to the timeline too -
// see #220.
auto it = std::ranges::find_if(events, isEditing);
for (const auto& eptr : std::ranges::subrange(it, events.end())) {
auto it = find_if(events, isEditing);
for (const auto& eptr : subrange(it, events.end())) {
if (auto* r = eventCast<RedactionEvent>(eptr)) {
// Try to find the target in the timeline, then in the batch.
if (processRedaction(*r))
continue;
if (auto targetIt = findIndirect(events, r->redactedEvent(), &RoomEvent::id);
if (auto targetIt = find(events, r->redactedEvent(), &RoomEvent::id);
targetIt != events.end())
*targetIt = makeRedacted(**targetIt, *r);
else
Expand All @@ -2839,8 +2840,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events)
msg && !msg->replacedEvent().isEmpty()) {
if (processReplacement(*msg))
continue;
if (auto targetIt =
findIndirect(events.begin(), it, msg->replacedEvent(), &RoomEvent::id);
if (auto targetIt = find(events.begin(), it, msg->replacedEvent(), &RoomEvent::id);
targetIt != it)
*targetIt = makeReplaced(**targetIt, *msg);
else // FIXME: hide the replacing event when target arrives later
Expand Down

0 comments on commit 4c97d1d

Please sign in to comment.