Blindly add a few stuff from VST
[juce-lv2.git] / juce / source / src / containers / juce_SparseSet.h
blob7490824e26147e7e121f79f498cf9a33e0f55768
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #ifndef __JUCE_SPARSESET_JUCEHEADER__
27 #define __JUCE_SPARSESET_JUCEHEADER__
29 #include "../maths/juce_Range.h"
30 #include "../threads/juce_CriticalSection.h"
33 //==============================================================================
34 /**
35 Holds a set of primitive values, storing them as a set of ranges.
37 This container acts like an array, but can efficiently hold large continguous
38 ranges of values. It's quite a specialised class, mostly useful for things
39 like keeping the set of selected rows in a listbox.
41 The type used as a template paramter must be an integer type, such as int, short,
42 int64, etc.
44 template <class Type>
45 class SparseSet
47 public:
48 //==============================================================================
49 /** Creates a new empty set. */
50 SparseSet()
54 /** Creates a copy of another SparseSet. */
55 SparseSet (const SparseSet<Type>& other)
56 : values (other.values)
60 //==============================================================================
61 /** Clears the set. */
62 void clear()
64 values.clear();
67 /** Checks whether the set is empty.
69 This is much quicker than using (size() == 0).
71 bool isEmpty() const noexcept
73 return values.size() == 0;
76 /** Returns the number of values in the set.
78 Because of the way the data is stored, this method can take longer if there
79 are a lot of items in the set. Use isEmpty() for a quick test of whether there
80 are any items.
82 Type size() const
84 Type total (0);
86 for (int i = 0; i < values.size(); i += 2)
87 total += values.getUnchecked (i + 1) - values.getUnchecked (i);
89 return total;
92 /** Returns one of the values in the set.
94 @param index the index of the value to retrieve, in the range 0 to (size() - 1).
95 @returns the value at this index, or 0 if it's out-of-range
97 Type operator[] (Type index) const
99 for (int i = 0; i < values.size(); i += 2)
101 const Type start (values.getUnchecked (i));
102 const Type len (values.getUnchecked (i + 1) - start);
104 if (index < len)
105 return start + index;
107 index -= len;
110 return Type();
113 /** Checks whether a particular value is in the set. */
114 bool contains (const Type valueToLookFor) const
116 for (int i = 0; i < values.size(); ++i)
117 if (valueToLookFor < values.getUnchecked(i))
118 return (i & 1) != 0;
120 return false;
123 //==============================================================================
124 /** Returns the number of contiguous blocks of values.
125 @see getRange
127 int getNumRanges() const noexcept
129 return values.size() >> 1;
132 /** Returns one of the contiguous ranges of values stored.
133 @param rangeIndex the index of the range to look up, between 0
134 and (getNumRanges() - 1)
135 @see getTotalRange
137 const Range<Type> getRange (const int rangeIndex) const
139 if (isPositiveAndBelow (rangeIndex, getNumRanges()))
140 return Range<Type> (values.getUnchecked (rangeIndex << 1),
141 values.getUnchecked ((rangeIndex << 1) + 1));
142 else
143 return Range<Type>();
146 /** Returns the range between the lowest and highest values in the set.
147 @see getRange
149 const Range<Type> getTotalRange() const
151 if (values.size() > 0)
153 jassert ((values.size() & 1) == 0);
154 return Range<Type> (values.getUnchecked (0),
155 values.getUnchecked (values.size() - 1));
158 return Range<Type>();
161 //==============================================================================
162 /** Adds a range of contiguous values to the set.
163 e.g. addRange (Range \<int\> (10, 14)) will add (10, 11, 12, 13) to the set.
165 void addRange (const Range<Type>& range)
167 jassert (range.getLength() >= 0);
168 if (range.getLength() > 0)
170 removeRange (range);
172 values.addUsingDefaultSort (range.getStart());
173 values.addUsingDefaultSort (range.getEnd());
175 simplify();
179 /** Removes a range of values from the set.
180 e.g. removeRange (Range\<int\> (10, 14)) will remove (10, 11, 12, 13) from the set.
182 void removeRange (const Range<Type>& rangeToRemove)
184 jassert (rangeToRemove.getLength() >= 0);
186 if (rangeToRemove.getLength() > 0
187 && values.size() > 0
188 && rangeToRemove.getStart() < values.getUnchecked (values.size() - 1)
189 && values.getUnchecked(0) < rangeToRemove.getEnd())
191 const bool onAtStart = contains (rangeToRemove.getStart() - 1);
192 const Type lastValue (jmin (rangeToRemove.getEnd(), values.getLast()));
193 const bool onAtEnd = contains (lastValue);
195 for (int i = values.size(); --i >= 0;)
197 if (values.getUnchecked(i) <= lastValue)
199 while (values.getUnchecked(i) >= rangeToRemove.getStart())
201 values.remove (i);
203 if (--i < 0)
204 break;
207 break;
211 if (onAtStart) values.addUsingDefaultSort (rangeToRemove.getStart());
212 if (onAtEnd) values.addUsingDefaultSort (lastValue);
214 simplify();
218 /** Does an XOR of the values in a given range. */
219 void invertRange (const Range<Type>& range)
221 SparseSet newItems;
222 newItems.addRange (range);
224 int i;
225 for (i = getNumRanges(); --i >= 0;)
226 newItems.removeRange (getRange (i));
228 removeRange (range);
230 for (i = newItems.getNumRanges(); --i >= 0;)
231 addRange (newItems.getRange(i));
234 /** Checks whether any part of a given range overlaps any part of this set. */
235 bool overlapsRange (const Range<Type>& range)
237 if (range.getLength() > 0)
239 for (int i = getNumRanges(); --i >= 0;)
241 if (values.getUnchecked ((i << 1) + 1) <= range.getStart())
242 return false;
244 if (values.getUnchecked (i << 1) < range.getEnd())
245 return true;
249 return false;
252 /** Checks whether the whole of a given range is contained within this one. */
253 bool containsRange (const Range<Type>& range)
255 if (range.getLength() > 0)
257 for (int i = getNumRanges(); --i >= 0;)
259 if (values.getUnchecked ((i << 1) + 1) <= range.getStart())
260 return false;
262 if (values.getUnchecked (i << 1) <= range.getStart()
263 && range.getEnd() <= values.getUnchecked ((i << 1) + 1))
264 return true;
268 return false;
271 //==============================================================================
272 bool operator== (const SparseSet<Type>& other) noexcept
274 return values == other.values;
277 bool operator!= (const SparseSet<Type>& other) noexcept
279 return values != other.values;
282 private:
283 //==============================================================================
284 // alternating start/end values of ranges of values that are present.
285 Array<Type, DummyCriticalSection> values;
287 void simplify()
289 jassert ((values.size() & 1) == 0);
291 for (int i = values.size(); --i > 0;)
292 if (values.getUnchecked(i) == values.getUnchecked (i - 1))
293 values.removeRange (--i, 2);
299 #endif // __JUCE_SPARSESET_JUCEHEADER__