From d7cc7775f37abd4163da08876528af10dd661109 Mon Sep 17 00:00:00 2001 From: Colin Fletcher Date: Mon, 1 Dec 2014 20:03:22 +0000 Subject: [PATCH] Rework Evoral::coverage() to pass unit tests Rewrite Evoral::coverage() to (hopefully) do what it's supposed to. Return OverlapNone for invalid ranges: if either of the ranges passed to Evoral::coverage() have negative length (i.e. start > end), return OverlapNone - it seems reasonable to say that a negative-length range can't overlap anything. Also return OverlapNone from the fallthrough case, though this should never happen. --- libs/evoral/evoral/Range.hpp | 132 ++++++++++++++++++++++++++++------- 1 file changed, 108 insertions(+), 24 deletions(-) diff --git a/libs/evoral/evoral/Range.hpp b/libs/evoral/evoral/Range.hpp index 689dc439b4..0019604bb0 100644 --- a/libs/evoral/evoral/Range.hpp +++ b/libs/evoral/evoral/Range.hpp @@ -20,9 +20,39 @@ #define EVORAL_RANGE_HPP #include - +#include +#include #include "evoral/visibility.h" + + +/* + +a: |---| +b starts before: + |-| + |--| + |----| + |------| + |--------| +a: |---| +b starts equal: + |-| + |---| + |----| +a: |---| +b starts inside: + |-| + |--| + |---| +a: |---| +b starts at end: + |--| +a: |---| +b starts after: + |-| +*/ + namespace Evoral { enum /*LIBEVORAL_API*/ OverlapType { @@ -42,29 +72,96 @@ template of A and B for each OverlapType. Notes: - Internal: the start points cannot coincide + 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 - XXX Logically, Internal should disallow end - point equality. + Internal disallows start and end point equality, and thus implies + that there are two disjoint portions of A which do not overlap B. */ + // assert(sa <= ea); // seems we are sometimes called with 0-length ranges + if (sa > ea) { + std::cerr << "a - start after end: " << sa << ", " << ea << std::endl; + return OverlapNone; + } + + // assert(sb <= eb); + if (sb > eb) { + std::cerr << "b - start after end: " << sb << ", " << eb << std::endl; + return OverlapNone; + } + + if (sb < sa) { + if (eb < sa) { + return OverlapNone; + } else if (eb == sa) { + return OverlapStart; + } else { + if (eb < ea) { + return OverlapStart; + } else if (eb == ea) { + return OverlapExternal; + } else { + return OverlapExternal; + } + } + } else if (sb == sa) { + 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) { + return OverlapEnd; + } else if (sb == ea) { + return OverlapEnd; + } else { + return OverlapNone; + } + } + } + + + std::cerr << "unknown overlap type!" << sa << ", " << ea << "; " << sb << ", " << eb << std::endl; + // assert(!"unknown overlap type!"); + return OverlapNone; + +#if 0 /* |--------------------| A |------| B |-----------------| B - "B is internal to A" - */ - if ((sb > sa) && (eb <= ea)) { + if ((sb > sa) && (eb < ea)) { return OverlapInternal; } + /* + |--------------------| A + -------------------------- B + |----------------------- B + ----------------------| B + |--------------------| B + + "B overlaps all of A" + */ + if ((sb <= sa) && (eb >= ea)) { + return OverlapExternal; + } + /* |--------------------| A ----| B @@ -72,10 +169,9 @@ template --| B "B overlaps the start of A" - */ - if ((eb >= sa) && (eb <= ea)) { + if ((sb <= sa) && (eb >= sa) && (eb <= ea)) { return OverlapStart; } /* @@ -85,26 +181,14 @@ template |- B "B overlaps the end of A" - */ - if ((sb > sa) && (sb <= ea)) { + if ((sb > sa) && (sb < ea) && (eb >= ea)) { return OverlapEnd; } - /* - |--------------------| A - -------------------------- B - |----------------------- B - ----------------------| B - |--------------------| B - - - "B overlaps all of A" - */ - if ((sa >= sb) && (sa <= eb) && (ea <= eb)) { - return OverlapExternal; - } + // assert(eb < sa || sb > ea); return OverlapNone; +#endif } /** Type to describe a time range */