mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-14 00:14:18 +00:00
287 lines
10 KiB
C++
287 lines
10 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
|
Copyright 2004-10 by Raw Material Software Ltd.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
JUCE can be redistributed and/or modified under the terms of the GNU General
|
|
Public License (Version 2), as published by the Free Software Foundation.
|
|
A copy of the license is included in the JUCE distribution, or can be found
|
|
online at www.gnu.org/licenses.
|
|
|
|
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
To release a closed-source product which uses JUCE, commercial licenses are
|
|
available: visit www.rawmaterialsoftware.com/juce for more information.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__
|
|
#define __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__
|
|
|
|
|
|
//==============================================================================
|
|
/**
|
|
Sorts a range of elements in an array.
|
|
|
|
The comparator object that is passed-in must define a public method with the following
|
|
signature:
|
|
@code
|
|
int compareElements (ElementType first, ElementType second);
|
|
@endcode
|
|
|
|
..and this method must return:
|
|
- a value of < 0 if the first comes before the second
|
|
- a value of 0 if the two objects are equivalent
|
|
- a value of > 0 if the second comes before the first
|
|
|
|
To improve performance, the compareElements() method can be declared as static or const.
|
|
|
|
@param comparator an object which defines a compareElements() method
|
|
@param array the array to sort
|
|
@param firstElement the index of the first element of the range to be sorted
|
|
@param lastElement the index of the last element in the range that needs
|
|
sorting (this is inclusive)
|
|
@param retainOrderOfEquivalentItems if true, the order of items that the
|
|
comparator deems the same will be maintained - this will be
|
|
a slower algorithm than if they are allowed to be moved around.
|
|
|
|
@see sortArrayRetainingOrder
|
|
*/
|
|
template <class ElementType, class ElementComparator>
|
|
static void sortArray (ElementComparator& comparator,
|
|
ElementType* const array,
|
|
int firstElement,
|
|
int lastElement,
|
|
const bool retainOrderOfEquivalentItems)
|
|
{
|
|
(void) comparator; // if you pass in an object with a static compareElements() method, this
|
|
// avoids getting warning messages about the parameter being unused
|
|
|
|
if (lastElement > firstElement)
|
|
{
|
|
if (retainOrderOfEquivalentItems)
|
|
{
|
|
for (int i = firstElement; i < lastElement; ++i)
|
|
{
|
|
if (comparator.compareElements (array[i], array [i + 1]) > 0)
|
|
{
|
|
const ElementType temp = array [i];
|
|
array [i] = array[i + 1];
|
|
array [i + 1] = temp;
|
|
|
|
if (i > firstElement)
|
|
i -= 2;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int fromStack[30], toStack[30];
|
|
int stackIndex = 0;
|
|
|
|
for (;;)
|
|
{
|
|
const int size = (lastElement - firstElement) + 1;
|
|
|
|
if (size <= 8)
|
|
{
|
|
int j = lastElement;
|
|
int maxIndex;
|
|
|
|
while (j > firstElement)
|
|
{
|
|
maxIndex = firstElement;
|
|
for (int k = firstElement + 1; k <= j; ++k)
|
|
if (comparator.compareElements (array[k], array [maxIndex]) > 0)
|
|
maxIndex = k;
|
|
|
|
const ElementType temp = array [maxIndex];
|
|
array [maxIndex] = array[j];
|
|
array [j] = temp;
|
|
|
|
--j;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const int mid = firstElement + (size >> 1);
|
|
ElementType temp = array [mid];
|
|
array [mid] = array [firstElement];
|
|
array [firstElement] = temp;
|
|
|
|
int i = firstElement;
|
|
int j = lastElement + 1;
|
|
|
|
for (;;)
|
|
{
|
|
while (++i <= lastElement
|
|
&& comparator.compareElements (array[i], array [firstElement]) <= 0)
|
|
{}
|
|
|
|
while (--j > firstElement
|
|
&& comparator.compareElements (array[j], array [firstElement]) >= 0)
|
|
{}
|
|
|
|
if (j < i)
|
|
break;
|
|
|
|
temp = array[i];
|
|
array[i] = array[j];
|
|
array[j] = temp;
|
|
}
|
|
|
|
temp = array [firstElement];
|
|
array [firstElement] = array[j];
|
|
array [j] = temp;
|
|
|
|
if (j - 1 - firstElement >= lastElement - i)
|
|
{
|
|
if (firstElement + 1 < j)
|
|
{
|
|
fromStack [stackIndex] = firstElement;
|
|
toStack [stackIndex] = j - 1;
|
|
++stackIndex;
|
|
}
|
|
|
|
if (i < lastElement)
|
|
{
|
|
firstElement = i;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (i < lastElement)
|
|
{
|
|
fromStack [stackIndex] = i;
|
|
toStack [stackIndex] = lastElement;
|
|
++stackIndex;
|
|
}
|
|
|
|
if (firstElement + 1 < j)
|
|
{
|
|
lastElement = j - 1;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (--stackIndex < 0)
|
|
break;
|
|
|
|
jassert (stackIndex < numElementsInArray (fromStack));
|
|
|
|
firstElement = fromStack [stackIndex];
|
|
lastElement = toStack [stackIndex];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
/**
|
|
Searches a sorted array of elements, looking for the index at which a specified value
|
|
should be inserted for it to be in the correct order.
|
|
|
|
The comparator object that is passed-in must define a public method with the following
|
|
signature:
|
|
@code
|
|
int compareElements (ElementType first, ElementType second);
|
|
@endcode
|
|
|
|
..and this method must return:
|
|
- a value of < 0 if the first comes before the second
|
|
- a value of 0 if the two objects are equivalent
|
|
- a value of > 0 if the second comes before the first
|
|
|
|
To improve performance, the compareElements() method can be declared as static or const.
|
|
|
|
@param comparator an object which defines a compareElements() method
|
|
@param array the array to search
|
|
@param newElement the value that is going to be inserted
|
|
@param firstElement the index of the first element to search
|
|
@param lastElement the index of the last element in the range (this is non-inclusive)
|
|
*/
|
|
template <class ElementType, class ElementComparator>
|
|
static int findInsertIndexInSortedArray (ElementComparator& comparator,
|
|
ElementType* const array,
|
|
const ElementType newElement,
|
|
int firstElement,
|
|
int lastElement)
|
|
{
|
|
jassert (firstElement <= lastElement);
|
|
|
|
(void) comparator; // if you pass in an object with a static compareElements() method, this
|
|
// avoids getting warning messages about the parameter being unused
|
|
|
|
while (firstElement < lastElement)
|
|
{
|
|
if (comparator.compareElements (newElement, array [firstElement]) == 0)
|
|
{
|
|
++firstElement;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
const int halfway = (firstElement + lastElement) >> 1;
|
|
|
|
if (halfway == firstElement)
|
|
{
|
|
if (comparator.compareElements (newElement, array [halfway]) >= 0)
|
|
++firstElement;
|
|
|
|
break;
|
|
}
|
|
else if (comparator.compareElements (newElement, array [halfway]) >= 0)
|
|
{
|
|
firstElement = halfway;
|
|
}
|
|
else
|
|
{
|
|
lastElement = halfway;
|
|
}
|
|
}
|
|
}
|
|
|
|
return firstElement;
|
|
}
|
|
|
|
//==============================================================================
|
|
/**
|
|
A simple ElementComparator class that can be used to sort an array of
|
|
objects that support the '<' operator.
|
|
|
|
This will work for primitive types and objects that implement operator<().
|
|
|
|
Example: @code
|
|
Array <int> myArray;
|
|
DefaultElementComparator<int> sorter;
|
|
myArray.sort (sorter);
|
|
@endcode
|
|
|
|
@see ElementComparator
|
|
*/
|
|
template <class ElementType>
|
|
class DefaultElementComparator
|
|
{
|
|
private:
|
|
typedef PARAMETER_TYPE (ElementType) ParameterType;
|
|
|
|
public:
|
|
static int compareElements (ParameterType first, ParameterType second)
|
|
{
|
|
return (first < second) ? -1 : ((second < first) ? 1 : 0);
|
|
}
|
|
};
|
|
|
|
|
|
#endif // __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__
|