X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fevoral%2Fevoral%2FRange.hpp;h=9d47faf30d86e3d4971b70cf26b682be06f3cbef;hb=a6ee94ac520289f0d165c463bd5131dcbff9ee14;hp=868dccdd5f0bebf378ce99f8e077b77153f681d4;hpb=5792674ca4d02e093b4318d31a117a47ae72ecdf;p=ardour.git diff --git a/libs/evoral/evoral/Range.hpp b/libs/evoral/evoral/Range.hpp index 868dccdd5f..9d47faf30d 100644 --- a/libs/evoral/evoral/Range.hpp +++ b/libs/evoral/evoral/Range.hpp @@ -20,111 +20,136 @@ #define EVORAL_RANGE_HPP #include - +#include +#include #include "evoral/visibility.h" + + namespace Evoral { -enum LIBEVORAL_API OverlapType { +enum /*LIBEVORAL_API*/ OverlapType { OverlapNone, // no overlap - OverlapInternal, // the overlap is 100% with the object + OverlapInternal, // the overlap is 100% within the object OverlapStart, // overlap covers start, but ends within OverlapEnd, // overlap begins within and covers end OverlapExternal // overlap extends to (at least) begin+end }; template -LIBEVORAL_API OverlapType coverage (T sa, T ea, T sb, T eb) { +/*LIBEVORAL_API*/ OverlapType coverage (T sa, T ea, T sb, T eb) { /* OverlapType returned reflects how the second (B) - range overlaps the first (A). - - The diagrams show various relative placements - of A and B for each OverlapType. - - Notes: - Internal: the start points cannot coincide - External: the start and end points can coincide - Start: end points can coincide - End: start points can coincide - - XXX Logically, Internal should disallow end - point equality. - */ - - /* - |--------------------| A - |------| B - |-----------------| B - - - "B is internal to A" - - */ - - if ((sb > sa) && (eb <= ea)) { - return OverlapInternal; + * range overlaps the first (A). + * + * The diagram shows the OverlapType of each possible relative + * placement of A and B. + * + * Notes: + * Internal: the start and end points cannot coincide + * External: the start and end points can coincide + * Start: end points can coincide + * End: start points can coincide + * + * Internal disallows start and end point equality, and thus implies + * that there are two disjoint portions of A which do not overlap B. + * + * A: |---| + * B starts before A + * B: |-| None + * B: |--| Start + * B: |----| Start + * B: |------| External + * B: |--------| External + * B starts equal to A + * B: |-| Start + * B: |---| External + * B: |----| External + * B starts inside A + * B: |-| Internal + * B: |--| End + * B: |---| End + * B starts at end of A + * B: |--| End + * B starts after A + * B: |-| None + * A: |---| + */ + + + if (sa > ea) { + // seems we are sometimes called with negative length ranges + std::cerr << "a - start after end: " << sa << ", " << ea << std::endl; + return OverlapNone; } - /* - |--------------------| A - ----| B - -----------------------| B - --| B - - "B overlaps the start of A" - - */ - - if ((eb >= sa) && (eb <= ea)) { - return OverlapStart; + if (sb > eb) { + // seems we are sometimes called with negative length ranges + std::cerr << "b - start after end: " << sb << ", " << eb << std::endl; + return OverlapNone; } - /* - |---------------------| A - |----------------- B - |----------------------- B - |- B - - "B overlaps the end of A" - */ - if ((sb > sa) && (sb <= ea)) { - return OverlapEnd; - } - /* - |--------------------| A - -------------------------- B - |----------------------- B - ----------------------| B - |--------------------| B - - - "B overlaps all of A" - */ - if ((sa >= sb) && (sa <= eb) && (ea <= eb)) { - return OverlapExternal; + if (sb < sa) { // B starts before A + if (eb < sa) { + return OverlapNone; + } else if (eb == sa) { + return OverlapStart; + } else { // eb > sa + if (eb < ea) { + return OverlapStart; + } else if (eb == ea) { + return OverlapExternal; + } else { + return OverlapExternal; + } + } + } else if (sb == sa) { // B starts equal to A + if (eb < ea) { + return OverlapStart; + } else if (eb == ea) { + return OverlapExternal; + } else { // eb > ea + return OverlapExternal; + } + } else { // sb > sa + if (eb < ea) { + return OverlapInternal; + } else if (eb == ea) { + return OverlapEnd; + } else { // eb > ea + if (sb < ea) { // B starts inside A + return OverlapEnd; + } else if (sb == ea) { // B starts at end of A + return OverlapEnd; + } else { // sb > ea, B starts after A + return OverlapNone; + } + } } + std::cerr << "unknown overlap type!" << sa << ", " << ea << "; " << sb << ", " << eb << std::endl; + assert(!"unknown overlap type!"); return OverlapNone; } /** Type to describe a time range */ template -struct LIBEVORAL_API Range { +struct /*LIBEVORAL_API*/ Range { Range (T f, T t) : from (f), to (t) {} T from; ///< start of the range - T to; ///< end of the range + T to; ///< end of the range (inclusive: to lies inside the range) + bool empty() const { return from == to; } }; -template +template bool operator== (Range a, Range b) { return a.from == b.from && a.to == b.to; } template -class LIBEVORAL_API RangeList { +class /*LIBEVORAL_API*/ RangeList { public: RangeList () : _dirty (false) {} - + typedef std::list > List; List const & get () { @@ -146,7 +171,7 @@ public: return; } - restart: + restart: for (typename List::iterator i = _list.begin(); i != _list.end(); ++i) { for (typename List::iterator j = _list.begin(); j != _list.end(); ++j) { @@ -167,14 +192,14 @@ public: } private: - + List _list; bool _dirty; }; /** Type to describe the movement of a time range */ template -struct LIBEVORAL_API RangeMove { +struct /*LIBEVORAL_API*/ RangeMove { RangeMove (T f, double l, T t) : from (f), length (l), to (t) {} T from; ///< start of the range double length; ///< length of the range @@ -191,7 +216,7 @@ RangeList subtract (Range range, RangeList sub) RangeList result; result.add (range); - if (sub.empty ()) { + if (sub.empty () || range.empty()) { return result; } @@ -200,7 +225,7 @@ RangeList subtract (Range range, RangeList sub) /* 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::List::const_iterator i = s.begin(); i != s.end(); ++i) { /* Here's where we'll put the new current result after subtracting *i from it */ @@ -213,28 +238,33 @@ RangeList subtract (Range range, RangeList sub) 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, + /* The thing we're subtracting (*i) does not overlap this bit of the result (*j), 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. + /* Internal overlap of the thing we're subtracting (*i) from this bit of the result, + so we should end up with two bits of (*j) left over, from the start of (*j) to + the start of (*i), and from the end of (*i) to the end of (*j). */ - if (j->from < (i->from - 1)) { - new_result.add (Range (j->from, i->from - 1)); - } - if (j->to != i->to) { - new_result.add (Range (i->to, j->to)); - } + assert (j->from < i->from); + assert (j->to > i->to); + new_result.add (Range (j->from, i->from - 1)); + new_result.add (Range (i->to + 1, j->to)); break; case OverlapStart: - /* The bit we're subtracting overlaps the start of the bit of the result */ - new_result.add (Range (i->to, j->to - 1)); + /* The bit we're subtracting (*i) overlaps the start of the bit of the result (*j), + * so we keep only the part of of (*j) from after the end of (*i) + */ + assert (i->to < j->to); + new_result.add (Range (i->to + 1, j->to)); break; case OverlapEnd: - /* The bit we're subtracting overlaps the end of the bit of the result */ + /* The bit we're subtracting (*i) overlaps the end of the bit of the result (*j), + * so we keep only the part of of (*j) from before the start of (*i) + */ + assert (j->from < i->from); new_result.add (Range (j->from, i->from - 1)); break; case OverlapExternal: