# HG changeset patch # User Chris Cannam # Date 1553005445 0 # Node ID eaad709398482af54216a3efb97652ab7bda4bd8 # Parent 08bed13d3a262bbb0572e862656378d48eea5626 Add nearest-event-matching search diff -r 08bed13d3a26 -r eaad70939848 base/EventSeries.cpp --- a/base/EventSeries.cpp Tue Mar 19 13:05:56 2019 +0000 +++ b/base/EventSeries.cpp Tue Mar 19 14:24:05 2019 +0000 @@ -401,6 +401,43 @@ return true; } +bool +EventSeries::getNearestEventMatching(sv_frame_t startSearchAt, + std::function predicate, + Direction direction, + Event &found) const +{ + auto pitr = lower_bound(m_events.begin(), m_events.end(), + Event(startSearchAt)); + + while (true) { + + if (direction == Backward) { + if (pitr == m_events.begin()) { + break; + } else { + --pitr; + } + } else { + if (pitr == m_events.end()) { + break; + } + } + + const Event &e = *pitr; + if (predicate(e)) { + found = e; + return true; + } + + if (direction == Forward) { + ++pitr; + } + } + + return false; +} + Event EventSeries::getEventByIndex(int index) const { diff -r 08bed13d3a26 -r eaad70939848 base/EventSeries.h --- a/base/EventSeries.h Tue Mar 19 13:05:56 2019 +0000 +++ b/base/EventSeries.h Tue Mar 19 14:24:05 2019 +0000 @@ -161,6 +161,23 @@ */ bool getEventFollowing(const Event &e, Event &following) const; + enum Direction { + Forward, + Backward + }; + + /** + * Return the first event for which the given predicate returns + * true, searching events with start frames increasingly far from + * the given frame in the given direction. If the direction is + * Forward then the search includes events starting at the given + * frame, otherwise it does not. + */ + bool getNearestEventMatching(sv_frame_t startSearchAt, + std::function predicate, + Direction direction, + Event &found) const; + /** * Return the event at the given numerical index in the series, * where 0 = the first event and count()-1 = the last. @@ -173,7 +190,7 @@ * return count(). */ int getIndexForEvent(const Event &e) const; - + /** * Emit to XML as a dataset element. */ diff -r 08bed13d3a26 -r eaad70939848 base/test/TestEventSeries.h --- a/base/test/TestEventSeries.h Tue Mar 19 13:05:56 2019 +0000 +++ b/base/test/TestEventSeries.h Tue Mar 19 14:24:05 2019 +0000 @@ -617,6 +617,80 @@ QCOMPARE(p, e); QCOMPARE(s.getEventFollowing(p, p), false); } + + void matchingForward() { + + EventSeries s; + Event p; + QCOMPARE(s.getNearestEventMatching + (6, [](const Event &e) { return e.getDuration() < 4; }, + EventSeries::Forward, p), false); + Event a(0, 1.0f, 18, QString("a")); + Event b(3, 2.0f, 6, QString("b")); + Event c(5, 3.0f, 2, QString("c")); + Event cc(5, 3.1f, 2, QString("cc")); + Event d(6, 4.0f, 10, QString("d")); + Event dd(6, 4.5f, 10, QString("dd")); + Event e(14, 5.0f, 3, QString("e")); + s.add(b); + s.add(c); + s.add(d); + s.add(d); // again + s.add(a); + s.add(cc); + s.add(dd); + s.add(e); + QCOMPARE(s.getNearestEventMatching + (0, [](const Event &e) { return e.getDuration() < 4; }, + EventSeries::Forward, p), true); + QCOMPARE(p, c); + QCOMPARE(s.getNearestEventMatching + (6, [](const Event &e) { return e.getDuration() < 4; }, + EventSeries::Forward, p), true); + QCOMPARE(p, e); + QCOMPARE(s.getNearestEventMatching + (6, [](const Event &e) { return e.getDuration() > 4; }, + EventSeries::Forward, p), true); + QCOMPARE(p, d); + QCOMPARE(s.getNearestEventMatching + (20, [](const Event &e) { return e.getDuration() > 4; }, + EventSeries::Forward, p), false); + } + + void matchingBackward() { + + EventSeries s; + Event p; + QCOMPARE(s.getNearestEventMatching + (6, [](const Event &e) { return e.getDuration() < 4; }, + EventSeries::Backward, p), false); + Event a(0, 1.0f, 18, QString("a")); + Event b(3, 2.0f, 6, QString("b")); + Event c(5, 3.0f, 2, QString("c")); + Event cc(5, 3.1f, 2, QString("cc")); + Event d(6, 4.0f, 10, QString("d")); + Event dd(6, 4.5f, 10, QString("dd")); + Event e(14, 5.0f, 3, QString("e")); + s.add(b); + s.add(c); + s.add(d); + s.add(d); // again + s.add(a); + s.add(cc); + s.add(dd); + s.add(e); + QCOMPARE(s.getNearestEventMatching + (0, [](const Event &e) { return e.getDuration() < 4; }, + EventSeries::Backward, p), false); + QCOMPARE(s.getNearestEventMatching + (6, [](const Event &e) { return e.getDuration() > 4; }, + EventSeries::Backward, p), true); + QCOMPARE(p, b); + QCOMPARE(s.getNearestEventMatching + (20, [](const Event &e) { return e.getDuration() > 4; }, + EventSeries::Backward, p), true); + QCOMPARE(p, dd); + } }; #endif