mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Rename beast sources for consistency
This commit is contained in:
292
modules/beast_core/containers/SparseSet.h
Normal file
292
modules/beast_core/containers/SparseSet.h
Normal file
@@ -0,0 +1,292 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
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.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SPARSESET_H_INCLUDED
|
||||
#define BEAST_SPARSESET_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Holds a set of primitive values, storing them as a set of ranges.
|
||||
|
||||
This container acts like an array, but can efficiently hold large contiguous
|
||||
ranges of values. It's quite a specialised class, mostly useful for things
|
||||
like keeping the set of selected rows in a listbox.
|
||||
|
||||
The type used as a template paramter must be an integer type, such as int, short,
|
||||
int64, etc.
|
||||
*/
|
||||
template <class Type>
|
||||
class SparseSet
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a new empty set. */
|
||||
SparseSet()
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a copy of another SparseSet. */
|
||||
SparseSet (const SparseSet<Type>& other)
|
||||
: values (other.values)
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Clears the set. */
|
||||
void clear()
|
||||
{
|
||||
values.clear();
|
||||
}
|
||||
|
||||
/** Checks whether the set is empty.
|
||||
|
||||
This is much quicker than using (size() == 0).
|
||||
*/
|
||||
bool isEmpty() const noexcept
|
||||
{
|
||||
return values.size() == 0;
|
||||
}
|
||||
|
||||
/** Returns the number of values in the set.
|
||||
|
||||
Because of the way the data is stored, this method can take longer if there
|
||||
are a lot of items in the set. Use isEmpty() for a quick test of whether there
|
||||
are any items.
|
||||
*/
|
||||
Type size() const
|
||||
{
|
||||
Type total (0);
|
||||
|
||||
for (int i = 0; i < values.size(); i += 2)
|
||||
total += values.getUnchecked (i + 1) - values.getUnchecked (i);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/** Returns one of the values in the set.
|
||||
|
||||
@param index the index of the value to retrieve, in the range 0 to (size() - 1).
|
||||
@returns the value at this index, or 0 if it's out-of-range
|
||||
*/
|
||||
Type operator[] (Type index) const
|
||||
{
|
||||
for (int i = 0; i < values.size(); i += 2)
|
||||
{
|
||||
const Type start (values.getUnchecked (i));
|
||||
const Type len (values.getUnchecked (i + 1) - start);
|
||||
|
||||
if (index < len)
|
||||
return start + index;
|
||||
|
||||
index -= len;
|
||||
}
|
||||
|
||||
return Type();
|
||||
}
|
||||
|
||||
/** Checks whether a particular value is in the set. */
|
||||
bool contains (const Type valueToLookFor) const
|
||||
{
|
||||
for (int i = 0; i < values.size(); ++i)
|
||||
if (valueToLookFor < values.getUnchecked(i))
|
||||
return (i & 1) != 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of contiguous blocks of values.
|
||||
@see getRange
|
||||
*/
|
||||
int getNumRanges() const noexcept
|
||||
{
|
||||
return values.size() >> 1;
|
||||
}
|
||||
|
||||
/** Returns one of the contiguous ranges of values stored.
|
||||
@param rangeIndex the index of the range to look up, between 0
|
||||
and (getNumRanges() - 1)
|
||||
@see getTotalRange
|
||||
*/
|
||||
const Range<Type> getRange (const int rangeIndex) const
|
||||
{
|
||||
if (isPositiveAndBelow (rangeIndex, getNumRanges()))
|
||||
return Range<Type> (values.getUnchecked (rangeIndex << 1),
|
||||
values.getUnchecked ((rangeIndex << 1) + 1));
|
||||
|
||||
return Range<Type>();
|
||||
}
|
||||
|
||||
/** Returns the range between the lowest and highest values in the set.
|
||||
@see getRange
|
||||
*/
|
||||
Range<Type> getTotalRange() const
|
||||
{
|
||||
if (values.size() > 0)
|
||||
{
|
||||
bassert ((values.size() & 1) == 0);
|
||||
return Range<Type> (values.getUnchecked (0),
|
||||
values.getUnchecked (values.size() - 1));
|
||||
}
|
||||
|
||||
return Range<Type>();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a range of contiguous values to the set.
|
||||
e.g. addRange (Range \<int\> (10, 14)) will add (10, 11, 12, 13) to the set.
|
||||
*/
|
||||
void addRange (const Range<Type> range)
|
||||
{
|
||||
bassert (range.getLength() >= 0);
|
||||
if (range.getLength() > 0)
|
||||
{
|
||||
removeRange (range);
|
||||
|
||||
values.addUsingDefaultSort (range.getStart());
|
||||
values.addUsingDefaultSort (range.getEnd());
|
||||
|
||||
simplify();
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes a range of values from the set.
|
||||
e.g. removeRange (Range\<int\> (10, 14)) will remove (10, 11, 12, 13) from the set.
|
||||
*/
|
||||
void removeRange (const Range<Type> rangeToRemove)
|
||||
{
|
||||
bassert (rangeToRemove.getLength() >= 0);
|
||||
|
||||
if (rangeToRemove.getLength() > 0
|
||||
&& values.size() > 0
|
||||
&& rangeToRemove.getStart() < values.getUnchecked (values.size() - 1)
|
||||
&& values.getUnchecked(0) < rangeToRemove.getEnd())
|
||||
{
|
||||
const bool onAtStart = contains (rangeToRemove.getStart() - 1);
|
||||
const Type lastValue (bmin (rangeToRemove.getEnd(), values.getLast()));
|
||||
const bool onAtEnd = contains (lastValue);
|
||||
|
||||
for (int i = values.size(); --i >= 0;)
|
||||
{
|
||||
if (values.getUnchecked(i) <= lastValue)
|
||||
{
|
||||
while (values.getUnchecked(i) >= rangeToRemove.getStart())
|
||||
{
|
||||
values.remove (i);
|
||||
|
||||
if (--i < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (onAtStart) values.addUsingDefaultSort (rangeToRemove.getStart());
|
||||
if (onAtEnd) values.addUsingDefaultSort (lastValue);
|
||||
|
||||
simplify();
|
||||
}
|
||||
}
|
||||
|
||||
/** Does an XOR of the values in a given range. */
|
||||
void invertRange (const Range<Type> range)
|
||||
{
|
||||
SparseSet newItems;
|
||||
newItems.addRange (range);
|
||||
|
||||
for (int i = getNumRanges(); --i >= 0;)
|
||||
newItems.removeRange (getRange (i));
|
||||
|
||||
removeRange (range);
|
||||
|
||||
for (int i = newItems.getNumRanges(); --i >= 0;)
|
||||
addRange (newItems.getRange(i));
|
||||
}
|
||||
|
||||
/** Checks whether any part of a given range overlaps any part of this set. */
|
||||
bool overlapsRange (const Range<Type> range)
|
||||
{
|
||||
if (range.getLength() > 0)
|
||||
{
|
||||
for (int i = getNumRanges(); --i >= 0;)
|
||||
{
|
||||
if (values.getUnchecked ((i << 1) + 1) <= range.getStart())
|
||||
return false;
|
||||
|
||||
if (values.getUnchecked (i << 1) < range.getEnd())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Checks whether the whole of a given range is contained within this one. */
|
||||
bool containsRange (const Range<Type> range)
|
||||
{
|
||||
if (range.getLength() > 0)
|
||||
{
|
||||
for (int i = getNumRanges(); --i >= 0;)
|
||||
{
|
||||
if (values.getUnchecked ((i << 1) + 1) <= range.getStart())
|
||||
return false;
|
||||
|
||||
if (values.getUnchecked (i << 1) <= range.getStart()
|
||||
&& range.getEnd() <= values.getUnchecked ((i << 1) + 1))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool operator== (const SparseSet<Type>& other) noexcept
|
||||
{
|
||||
return values == other.values;
|
||||
}
|
||||
|
||||
bool operator!= (const SparseSet<Type>& other) noexcept
|
||||
{
|
||||
return values != other.values;
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
// alternating start/end values of ranges of values that are present.
|
||||
Array<Type, DummyCriticalSection> values;
|
||||
|
||||
void simplify()
|
||||
{
|
||||
bassert ((values.size() & 1) == 0);
|
||||
|
||||
for (int i = values.size(); --i > 0;)
|
||||
if (values.getUnchecked(i) == values.getUnchecked (i - 1))
|
||||
values.removeRange (--i, 2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // BEAST_SPARSESET_H_INCLUDED
|
||||
Reference in New Issue
Block a user