Your IP : 216.73.216.48
/*
This file is part of the kcal library.
Copyright (c) 2006 David Jarvie <software@astrojar.org.uk>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/**
@file
This file is part of the API for handling calendar data and
defines the Sortable List class.
@author David Jarvie \<software@astrojar.org.uk\>.
*/
#ifndef KCAL_SORTABLELIST_H
#define KCAL_SORTABLELIST_H
#include <QtCore/QList>
#include <QtCore/QtAlgorithms>
namespace KCal {
//@cond PRIVATE
template <class T>
void qSortUnique( QList<T> &list )
{
if ( list.count() <= 1 ) {
return;
}
qSort( list );
typename QList<T>::iterator prev = list.begin();
for ( typename QList<T>::iterator it = prev + 1; it != list.end(); ++it ) {
if ( *it == *prev ) {
// Found two equal values. Search for any further equal values and remove
// them all together for efficiency.
while ( ++it != list.end() && *it == *prev ) ;
prev = it = list.erase( prev + 1, it );
if ( it == list.end() ) {
break;
}
} else {
prev = it;
}
}
}
//@endcond
/**
@brief A QList which can be sorted
For a QList is capable of being sorted, SortedList provides additional
optimized methods which can be used when the list is sorted and has no
duplicate entries.
Because SortableList has no data members, an object may be referred to
interchangeably as either a QList or SortableList. Just bear in mind that
the results of the SortableList methods are undefined when the list is
unsorted or contains duplicate entries.
To sort the list and remove duplicate entries, thereby allowing use of
other SortableList methods, use sortUnique(). Once sortUnique() has been
called, use findSorted(), containsSorted() and removeSorted() in preference
to QList::indexOf(), QList::contains() and QList::removeAll(). Use findLE(),
findLT(), findGE(), findGT() to find the index to the nearest value in the
list which is <=, <, >= or > a given value. To add a value to the list,
use insertSorted() in preference to insert(), append(), prepend(),
operator<<() or operator+=().
@author David Jarvie \<software@astrojar.org.uk\>.
*/
template <class T>
class SortableList : public QList<T>
{
public:
/**
Constructs an empty sortable list.
*/
SortableList() {}
/**
Constructs a sortable list by copying another one.
@param list is the list to copy.
*/
SortableList( const QList<T> &list ) : QList<T>( list ) {} // implicit conversion
/**
Return whether the list contains value @p value. The list must be sorted;
if not, the result is undefined.
When the list is sorted, use this optimised method in preference to
QList<T>::contains().
@param value is the value to find.
@return true if list contains @p value; false otherwise.
*/
bool containsSorted( const T &value ) const { return findSorted( value ) >= 0; }
/**
Search the list for the item equal to @p value. The list must be sorted;
if not, the result is undefined.
When the list is sorted, use this optimised method in preference to
QList<T>::indexOf().
@param value is the value to find.
@param start is the start index for search (default is from beginning).
@return index to item in list, or -1 if @p value not found in the list.
*/
int findSorted( const T &value, int start = 0 ) const;
/**
Search the list for the last item <= @p value. The list must be sorted;
if not, the result is undefined.
@param value is the value to find.
@param start is the start index for search (default is from beginning).
@return index to item in list, or -1 if @p value < first value in the list.
*/
int findLE( const T &value, int start = 0 ) const;
/**
Search the list for the last item < @p value. The list must be sorted;
if not, the result is undefined.
@param value is the value to find.
@param start is the start index for search (default is from beginning).
@return index to item in list, or -1 if @p value <= first value in the list.
*/
int findLT( const T &value, int start = 0 ) const;
/**
Search the list for the first item >= @p value. The list must be sorted;
if not, the result is undefined.
@param value is the value to find.
@param start is the start index for search (default is from beginning).
@return index to item in list, or -1 if @p value > last value in the list.
*/
int findGE( const T &value, int start = 0 ) const;
/**
Search the list for the first item > @p value. The list must be sorted;
if not, the result is undefined.
@param value is the value to find.
@param start is the start index for search (default is from beginning).
@return index to item in list, or -1 if @p value >= last value in the list.
*/
int findGT( const T &value, int start = 0 ) const;
/**
Insert a value in the list, in correct sorted order. If the same value
is already in the list, no change is made.
The list must already be sorted before calling this method; otherwise
the result is undefined.
@param value is the value to insert.
@return index to inserted item in list, or to the pre-existing entry
equal to @p value.
*/
int insertSorted( const T &value );
/**
Remove value @p value from the list. The list must be sorted.
When the list is sorted, use this optimised method in preference to
QList<T>::removeAll().
@param value is the value to remove.
@param start is the start index for search (default is from beginning).
@return index to removed value, or -1 if not found.
*/
int removeSorted( const T &value, int start = 0 );
/**
Sort the list. Any duplicate values are removed.
*/
void sortUnique() { qSortUnique( *this ); }
};
template <class T>
int SortableList<T>::findSorted( const T &value, int start ) const
{
// Do a binary search to find the item == value
int st = start - 1;
int end = QList<T>::count();
while ( end - st > 1 ) {
int i = ( st + end ) / 2;
if ( value < QList<T>::at(i) ) {
end = i;
} else {
st = i;
}
}
return ( end > start && value == QList<T>::at(st) ) ? st : -1;
}
template <class T>
int SortableList<T>::findLE( const T &value, int start ) const
{
// Do a binary search to find the last item <= value
int st = start - 1;
int end = QList<T>::count();
while ( end - st > 1 ) {
int i = ( st + end ) / 2;
if ( value < QList<T>::at(i) ) {
end = i;
} else {
st = i;
}
}
return ( end > start ) ? st : -1;
}
template <class T>
int SortableList<T>::findLT( const T &value, int start ) const
{
// Do a binary search to find the last item < value
int st = start - 1;
int end = QList<T>::count();
while ( end - st > 1 ) {
int i = ( st + end ) / 2;
if ( value <= QList<T>::at(i) ) {
end = i;
} else {
st = i;
}
}
return ( end > start ) ? st : -1;
}
template <class T>
int SortableList<T>::findGE( const T &value, int start ) const
{
// Do a binary search to find the first item >= value
int st = start - 1;
int end = QList<T>::count();
while ( end - st > 1 ) {
int i = ( st + end ) / 2;
if ( value <= QList<T>::at(i) ) {
end = i;
} else {
st = i;
}
}
++st;
return ( st == QList<T>::count() ) ? -1 : st;
}
template <class T>
int SortableList<T>::findGT( const T &value, int start ) const
{
// Do a binary search to find the first item > value
int st = start - 1;
int end = QList<T>::count();
while ( end - st > 1 ) {
int i = ( st + end ) / 2;
if ( value < QList<T>::at(i) ) {
end = i;
} else {
st = i;
}
}
++st;
return ( st == QList<T>::count() ) ? -1 : st;
}
template <class T>
int SortableList<T>::insertSorted( const T &value )
{
int i = findLE( value );
if ( i < 0 || QList<T>::at(i) != value ) {
QList<T>::insert( ++i, value );
}
return i;
}
template <class T>
int SortableList<T>::removeSorted( const T &value, int start )
{
int i = findSorted( value, start );
if ( i >= 0 ) {
QList<T>::removeAt( i );
}
return i;
}
} // namespace KCal
#endif