summaryrefslogtreecommitdiffstats
path: root/src/util/indexrange.cpp
blob: cde8371a3e3eceb30e3227c2da8aba4ba3ab317f (plain)
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