Loading...
Searching...
No Matches
juce_SparseSet.h
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
template <class Type>
class SparseSet
{
public:
//==============================================================================
SparseSet() = default;
SparseSet (const SparseSet&) = default;
SparseSet& operator= (const SparseSet&) = default;
SparseSet (SparseSet&& other) noexcept : ranges (std::move (other.ranges)) {}
SparseSet& operator= (SparseSet&& other) noexcept { ranges = std::move (other.ranges); return *this; }
//==============================================================================
void clear() { ranges.clear(); }
bool isEmpty() const noexcept { return ranges.isEmpty(); }
Type size() const noexcept
{
Type total = {};
for (auto& r : ranges)
total += r.getLength();
return total;
}
Type operator[] (Type index) const noexcept
{
Type total = {};
for (auto& r : ranges)
{
auto end = total + r.getLength();
if (index < end)
return r.getStart() + (index - total);
total = end;
}
return {};
}
bool contains (Type valueToLookFor) const noexcept
{
for (auto& r : ranges)
{
if (r.getStart() > valueToLookFor)
break;
if (r.getEnd() > valueToLookFor)
return true;
}
return false;
}
//==============================================================================
int getNumRanges() const noexcept { return ranges.size(); }
Range<Type> getRange (int rangeIndex) const noexcept { return ranges[rangeIndex]; }
Range<Type> getTotalRange() const noexcept
{
if (ranges.isEmpty())
return {};
return { ranges.getFirst().getStart(),
ranges.getLast().getEnd() };
}
//==============================================================================
void addRange (Range<Type> range)
{
if (! range.isEmpty())
{
removeRange (range);
ranges.add (range);
std::sort (ranges.begin(), ranges.end(),
[] (Range<Type> a, Range<Type> b) { return a.getStart() < b.getStart(); });
simplify();
}
}
void removeRange (Range<Type> rangeToRemove)
{
if (getTotalRange().intersects (rangeToRemove) && ! rangeToRemove.isEmpty())
{
for (int i = ranges.size(); --i >= 0;)
{
auto& r = ranges.getReference (i);
if (r.getEnd() <= rangeToRemove.getStart())
break;
if (r.getStart() >= rangeToRemove.getEnd())
continue;
if (rangeToRemove.contains (r))
{
ranges.remove (i);
}
else if (r.contains (rangeToRemove))
{
auto r1 = r.withEnd (rangeToRemove.getStart());
auto r2 = r.withStart (rangeToRemove.getEnd());
// this should be covered in if (rangeToRemove.contains (r))
jassert (! r1.isEmpty() || ! r2.isEmpty());
r = r1;
if (r.isEmpty())
r = r2;
if (! r1.isEmpty() && ! r2.isEmpty())
ranges.insert (i + 1, r2);
}
else if (rangeToRemove.getEnd() > r.getEnd())
{
r.setEnd (rangeToRemove.getStart());
}
else
{
r.setStart (rangeToRemove.getEnd());
}
}
}
}
void invertRange (Range<Type> range)
{
SparseSet newItems;
newItems.addRange (range);
for (auto& r : ranges)
newItems.removeRange (r);
removeRange (range);
for (auto& r : newItems.ranges)
addRange (r);
}
bool overlapsRange (Range<Type> range) const noexcept
{
if (! range.isEmpty())
for (auto& r : ranges)
if (r.intersects (range))
return true;
return false;
}
bool containsRange (Range<Type> range) const noexcept
{
if (! range.isEmpty())
for (auto& r : ranges)
if (r.contains (range))
return true;
return false;
}
const Array<Range<Type>>& getRanges() const noexcept { return ranges; }
//==============================================================================
bool operator== (const SparseSet& other) const noexcept { return ranges == other.ranges; }
bool operator!= (const SparseSet& other) const noexcept { return ranges != other.ranges; }
private:
//==============================================================================
Array<Range<Type>> ranges;
void simplify()
{
for (int i = ranges.size(); --i > 0;)
{
auto& r1 = ranges.getReference (i - 1);
auto& r2 = ranges.getReference (i);
if (r1.getEnd() == r2.getStart())
{
r1.setEnd (r2.getEnd());
ranges.remove (i);
}
}
}
};
} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::Range
Definition juce_Range.h:40
juce::Range::getStart
constexpr ValueType getStart() const noexcept
Definition juce_Range.h:80
juce::Range::isEmpty
constexpr bool isEmpty() const noexcept
Definition juce_Range.h:89
juce::Range::getEnd
constexpr ValueType getEnd() const noexcept
Definition juce_Range.h:86
juce::Range::contains
constexpr bool contains(const ValueType position) const noexcept
Definition juce_Range.h:214
juce::SparseSet
Definition juce_SparseSet.h:41
juce::SparseSet::getRange
Range< Type > getRange(int rangeIndex) const noexcept
Definition juce_SparseSet.h:125
juce::SparseSet::invertRange
void invertRange(Range< Type > range)
Definition juce_SparseSet.h:205
juce::SparseSet::clear
void clear()
Definition juce_SparseSet.h:54
juce::SparseSet::overlapsRange
bool overlapsRange(Range< Type > range) const noexcept
Definition juce_SparseSet.h:220
juce::SparseSet::size
Type size() const noexcept
Definition juce_SparseSet.h:67
juce::SparseSet::addRange
void addRange(Range< Type > range)
Definition juce_SparseSet.h:143
juce::SparseSet::isEmpty
bool isEmpty() const noexcept
Definition juce_SparseSet.h:59
juce::SparseSet::operator[]
Type operator[](Type index) const noexcept
Definition juce_SparseSet.h:82
juce::SparseSet::contains
bool contains(Type valueToLookFor) const noexcept
Definition juce_SparseSet.h:100
juce::SparseSet::getNumRanges
int getNumRanges() const noexcept
Definition juce_SparseSet.h:118
juce::SparseSet::getRanges
const Array< Range< Type > > & getRanges() const noexcept
Definition juce_SparseSet.h:242
juce::SparseSet::getTotalRange
Range< Type > getTotalRange() const noexcept
Definition juce_SparseSet.h:130
juce::SparseSet::containsRange
bool containsRange(Range< Type > range) const noexcept
Definition juce_SparseSet.h:231
juce::SparseSet::removeRange
void removeRange(Range< Type > rangeToRemove)
Definition juce_SparseSet.h:158