1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-14 00:14:18 +00:00
JUCE/src/containers/juce_ElementComparator.h

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__