mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-13 18:16:35 +01:00
Hopefully less bad version of Evoral::RangeList::subtract,
with more tests. git-svn-id: svn://localhost/ardour2/branches/3.0@12514 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
19becdf7e0
commit
a6786a6dd2
3 changed files with 120 additions and 17 deletions
|
|
@ -139,7 +139,6 @@ public:
|
||||||
return _list.empty ();
|
return _list.empty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
void coalesce () {
|
void coalesce () {
|
||||||
if (!_dirty) {
|
if (!_dirty) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -164,6 +163,8 @@ private:
|
||||||
|
|
||||||
_dirty = false;
|
_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
List _list;
|
List _list;
|
||||||
bool _dirty;
|
bool _dirty;
|
||||||
|
|
@ -178,37 +179,71 @@ struct RangeMove {
|
||||||
T to; ///< new start of the range
|
T to; ///< new start of the range
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Subtract the ranges in `sub' from that in `range',
|
||||||
|
* returning the result.
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
RangeList<T> subtract (Range<T> range, RangeList<T> sub)
|
RangeList<T> subtract (Range<T> range, RangeList<T> sub)
|
||||||
{
|
{
|
||||||
|
/* Start with the input range */
|
||||||
RangeList<T> result;
|
RangeList<T> result;
|
||||||
|
result.add (range);
|
||||||
|
|
||||||
if (sub.empty ()) {
|
if (sub.empty ()) {
|
||||||
result.add (range);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
T x = range.from;
|
|
||||||
|
|
||||||
typename RangeList<T>::List s = sub.get ();
|
typename RangeList<T>::List s = sub.get ();
|
||||||
|
|
||||||
|
/* The basic idea here is to keep a list of the result ranges, and subtract
|
||||||
|
the bits of `sub' from them one by one.
|
||||||
|
*/
|
||||||
|
|
||||||
for (typename RangeList<T>::List::const_iterator i = s.begin(); i != s.end(); ++i) {
|
for (typename RangeList<T>::List::const_iterator i = s.begin(); i != s.end(); ++i) {
|
||||||
|
|
||||||
if (coverage (range.from, range.to, i->from, i->to) == OverlapNone) {
|
/* Here's where we'll put the new current result after subtracting *i from it */
|
||||||
continue;
|
RangeList<T> new_result;
|
||||||
|
|
||||||
|
typename RangeList<T>::List r = result.get ();
|
||||||
|
|
||||||
|
/* Work on all parts of the current result using this range *i */
|
||||||
|
for (typename RangeList<T>::List::const_iterator j = r.begin(); j != r.end(); ++j) {
|
||||||
|
|
||||||
|
switch (coverage (j->from, j->to, i->from, i->to)) {
|
||||||
|
case OverlapNone:
|
||||||
|
/* The thing we're subtracting does not overlap this bit of the result,
|
||||||
|
so pass it through.
|
||||||
|
*/
|
||||||
|
new_result.add (*j);
|
||||||
|
break;
|
||||||
|
case OverlapInternal:
|
||||||
|
/* Internal overlap of the thing we're subtracting from this bit of the result,
|
||||||
|
so we might end up with two bits left over.
|
||||||
|
*/
|
||||||
|
if (j->from < (i->from - 1)) {
|
||||||
|
new_result.add (Range<T> (j->from, i->from - 1));
|
||||||
|
}
|
||||||
|
if (j->to != i->to) {
|
||||||
|
new_result.add (Range<T> (i->to, j->to));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OverlapStart:
|
||||||
|
/* The bit we're subtracting overlaps the start of the bit of the result */
|
||||||
|
new_result.add (Range<T> (i->to, j->to - 1));
|
||||||
|
break;
|
||||||
|
case OverlapEnd:
|
||||||
|
/* The bit we're subtracting overlaps the end of the bit of the result */
|
||||||
|
new_result.add (Range<T> (j->from, i->from - 1));
|
||||||
|
break;
|
||||||
|
case OverlapExternal:
|
||||||
|
/* total overlap of the bit we're subtracting with the result bit, so the
|
||||||
|
result bit is completely removed; do nothing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Range<T> clamped (std::max (range.from, i->from), std::min (range.to, i->to));
|
new_result.coalesce ();
|
||||||
|
result = new_result;
|
||||||
if (clamped.from != x) {
|
|
||||||
result.add (Range<T> (x, clamped.from - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
x = clamped.to;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s.back().to < range.to) {
|
|
||||||
result.add (Range<T> (x, range.to));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "RangeTest.hpp"
|
#include "RangeTest.hpp"
|
||||||
#include "evoral/Range.hpp"
|
#include "evoral/Range.hpp"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE_REGISTRATION (RangeTest);
|
CPPUNIT_TEST_SUITE_REGISTRATION (RangeTest);
|
||||||
|
|
||||||
|
|
@ -24,6 +25,7 @@ RangeTest::coalesceTest ()
|
||||||
CPPUNIT_ASSERT_EQUAL (8, i->to);
|
CPPUNIT_ASSERT_EQUAL (8, i->to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Basic subtraction of a few smaller ranges from a larger one */
|
||||||
void
|
void
|
||||||
RangeTest::subtractTest1 ()
|
RangeTest::subtractTest1 ()
|
||||||
{
|
{
|
||||||
|
|
@ -51,6 +53,7 @@ RangeTest::subtractTest1 ()
|
||||||
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test subtraction of a range B from a range A, where A and B do not overlap */
|
||||||
void
|
void
|
||||||
RangeTest::subtractTest2 ()
|
RangeTest::subtractTest2 ()
|
||||||
{
|
{
|
||||||
|
|
@ -69,6 +72,7 @@ RangeTest::subtractTest2 ()
|
||||||
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test subtraction of B from A, where B entirely overlaps A */
|
||||||
void
|
void
|
||||||
RangeTest::subtractTest3 ()
|
RangeTest::subtractTest3 ()
|
||||||
{
|
{
|
||||||
|
|
@ -82,3 +86,62 @@ RangeTest::subtractTest3 ()
|
||||||
RangeList<int>::List s = sheila.get ();
|
RangeList<int>::List s = sheila.get ();
|
||||||
CPPUNIT_ASSERT_EQUAL (size_t (0), s.size ());
|
CPPUNIT_ASSERT_EQUAL (size_t (0), s.size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A bit like subtractTest1, except some of the ranges
|
||||||
|
we are subtracting overlap.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RangeTest::subtractTest4 ()
|
||||||
|
{
|
||||||
|
Range<int> fred (0, 10);
|
||||||
|
|
||||||
|
RangeList<int> jim;
|
||||||
|
jim.add (Range<int> (2, 4));
|
||||||
|
jim.add (Range<int> (7, 8));
|
||||||
|
jim.add (Range<int> (8, 9));
|
||||||
|
|
||||||
|
RangeList<int> sheila = subtract (fred, jim);
|
||||||
|
|
||||||
|
RangeList<int>::List s = sheila.get ();
|
||||||
|
CPPUNIT_ASSERT_EQUAL (size_t (3), s.size ());
|
||||||
|
|
||||||
|
RangeList<int>::List::iterator i = s.begin ();
|
||||||
|
CPPUNIT_ASSERT_EQUAL (0, i->from);
|
||||||
|
CPPUNIT_ASSERT_EQUAL (1, i->to);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
CPPUNIT_ASSERT_EQUAL (4, i->from);
|
||||||
|
CPPUNIT_ASSERT_EQUAL (6, i->to);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
CPPUNIT_ASSERT_EQUAL (9, i->from);
|
||||||
|
CPPUNIT_ASSERT_EQUAL (10, i->to);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A bit like subtractTest1, except some of the ranges
|
||||||
|
we are subtracting overlap the start / end of the
|
||||||
|
initial range.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RangeTest::subtractTest5 ()
|
||||||
|
{
|
||||||
|
Range<int> fred (1, 12);
|
||||||
|
|
||||||
|
RangeList<int> jim;
|
||||||
|
jim.add (Range<int> (0, 4));
|
||||||
|
jim.add (Range<int> (6, 7));
|
||||||
|
jim.add (Range<int> (9, 42));
|
||||||
|
|
||||||
|
RangeList<int> sheila = subtract (fred, jim);
|
||||||
|
|
||||||
|
RangeList<int>::List s = sheila.get ();
|
||||||
|
CPPUNIT_ASSERT_EQUAL (size_t (2), s.size ());
|
||||||
|
|
||||||
|
RangeList<int>::List::iterator i = s.begin ();
|
||||||
|
CPPUNIT_ASSERT_EQUAL (4, i->from);
|
||||||
|
CPPUNIT_ASSERT_EQUAL (5, i->to);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
CPPUNIT_ASSERT_EQUAL (7, i->from);
|
||||||
|
CPPUNIT_ASSERT_EQUAL (8, i->to);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ class RangeTest : public CppUnit::TestFixture
|
||||||
CPPUNIT_TEST_SUITE (RangeTest);
|
CPPUNIT_TEST_SUITE (RangeTest);
|
||||||
CPPUNIT_TEST (coalesceTest);
|
CPPUNIT_TEST (coalesceTest);
|
||||||
CPPUNIT_TEST (subtractTest1);
|
CPPUNIT_TEST (subtractTest1);
|
||||||
|
CPPUNIT_TEST (subtractTest2);
|
||||||
CPPUNIT_TEST (subtractTest3);
|
CPPUNIT_TEST (subtractTest3);
|
||||||
|
CPPUNIT_TEST (subtractTest4);
|
||||||
|
CPPUNIT_TEST (subtractTest5);
|
||||||
CPPUNIT_TEST_SUITE_END ();
|
CPPUNIT_TEST_SUITE_END ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -14,6 +17,8 @@ public:
|
||||||
void subtractTest1 ();
|
void subtractTest1 ();
|
||||||
void subtractTest2 ();
|
void subtractTest2 ();
|
||||||
void subtractTest3 ();
|
void subtractTest3 ();
|
||||||
|
void subtractTest4 ();
|
||||||
|
void subtractTest5 ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue