1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#include "util/indexrange.h"
#include <ostream>
#include <sstream>
namespace mixxx {
IndexRange IndexRange::splitAndShrinkFront(SINT frontLength) {
DEBUG_ASSERT(frontLength >= 0);
DEBUG_ASSERT(frontLength <= length());
if (start() <= end()) {
auto startRange = forward(first, frontLength);
DEBUG_ASSERT(startRange.length() == frontLength);
first += frontLength;
DEBUG_ASSERT(start() == startRange.end()); // adjacent
return startRange;
} else {
auto startRange = backward(first, frontLength);
DEBUG_ASSERT(startRange.length() == frontLength);
first -= frontLength;
DEBUG_ASSERT(start() == startRange.end()); // adjacent
return startRange;
}
}
IndexRange IndexRange::splitAndShrinkBack(SINT backLength) {
DEBUG_ASSERT(backLength >= 0);
DEBUG_ASSERT(backLength <= length());
if (start() <= end()) {
auto endRange = between(end() - backLength, end());
DEBUG_ASSERT(endRange.length() == backLength);
second -= backLength;
DEBUG_ASSERT(end() == endRange.start()); // adjacent
return endRange;
} else {
auto endRange = between(end() + backLength, end());
DEBUG_ASSERT(endRange.length() == backLength);
second += backLength;
DEBUG_ASSERT(end() == endRange.start()); // adjacent
return endRange;
}
}
bool IndexRange::isSubrangeOf(IndexRange outerIndexRange) const {
if (outerIndexRange.start() <= outerIndexRange.end()) {
if (start() <= end()) {
return (outerIndexRange.start() <= start() &&
outerIndexRange.end() >= end());
}
DEBUG_ASSERT(!"Cannot compare ranges with different orientations");
return false;
}
if (start() >= end()) {
return (outerIndexRange.start() >= start() &&
outerIndexRange.end() <= end());
}
DEBUG_ASSERT(!"Cannot compare ranges with different orientations");
return false;
}
std::optional<IndexRange> intersect2(IndexRange lhs, IndexRange rhs) {
if (lhs.start() < lhs.end()) {
if (rhs.start() <= rhs.end()) {
const SINT start = std::max(lhs.start(), rhs.start());
const SINT end = std::min(lhs.end(), rhs.end());
if (start <= end) {
return IndexRange::between(start, end);
}
} else {
DEBUG_ASSERT(!"Cannot intersect index ranges with different orientations");
return std::nullopt;
}
} else if (lhs.start() > lhs.end()) {
if (rhs.start() >= rhs.end()) {
const SINT start = std::min(lhs.start(), rhs.start());
const SINT end = std::max(lhs.end(), rhs.end());
if (start >= end) {
return IndexRange::between(start, end);
}
} else {
DEBUG_ASSERT(!"Cannot intersect index ranges with different orientations");
return std::nullopt;
}
} else {
// Single point = empty range
DEBUG_ASSERT(lhs.empty());
DEBUG_ASSERT(lhs.start() == lhs.end());
// Check if this point is located within the other range
// and then return it
if (rhs.start() <= rhs.end()) {
if (lhs.start() >= rhs.start() && lhs.end() <= rhs.end()) {
return lhs;
}
} else {
if (lhs.start() <= rhs.start() && lhs.end() >= rhs.end()) {
return lhs;
}
}
}
// disconnected
return std::nullopt;
}
std::ostream& operator<<(std::ostream& os, IndexRange arg) {
return os << '[' << arg.start() << " -> " << arg.end() << ')';
}
QDebug operator<<(QDebug dbg, IndexRange arg) {
std::ostringstream oss;
oss << arg;
return dbg << oss.str().c_str();
}
} // namespace mixxx
|