* [uutlAlgorithm] range errors in QuickSort, avoid double-free by using IutlArray.Exchange * [uutlComparer] TutlReverseComparer: invert an arbitrary IutlComparermaster
@@ -180,21 +180,19 @@ class procedure TutlQuickSort.DoSort( | |||
aHigh: Integer); | |||
var | |||
lo, hi: Integer; | |||
p, tmp: T; | |||
p: T; | |||
begin | |||
repeat | |||
while (aLow < aHigh) do begin | |||
lo := aLow; | |||
hi := aHigh; | |||
p := aArray[(aLow + aHigh) div 2]; | |||
repeat | |||
while (aComparer.Compare(p, aArray[lo]) > 0) do | |||
while (aComparer.Compare(p, aArray[lo]) > 0) and (lo < aHigh) do | |||
lo := lo + 1; | |||
while (aComparer.Compare(p, aArray[hi]) < 0) do | |||
while (aComparer.Compare(p, aArray[hi]) < 0) and (hi > aLow) do | |||
hi := hi - 1; | |||
if (lo <= hi) then begin | |||
tmp := aArray[lo]; | |||
aArray[lo] := aArray[hi]; | |||
aArray[hi] := tmp; | |||
aArray.Exchange(lo, hi); | |||
lo := lo + 1; | |||
hi := hi - 1; | |||
end; | |||
@@ -209,7 +207,7 @@ begin | |||
DoSort(aArray, aComparer, lo, aHigh); | |||
aHigh := hi; | |||
end; | |||
until (aLow >= aHigh); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -225,14 +223,14 @@ begin | |||
if not Assigned(aArray) then | |||
raise EArgumentNilException.Create('aArray'); | |||
repeat | |||
while (aLow < aHigh) do begin | |||
lo := aLow; | |||
hi := aHigh; | |||
p := aArray[(aLow + aHigh) div 2]; | |||
repeat | |||
while (aComparer.Compare(p, aArray[lo]) > 0) do | |||
while (aComparer.Compare(p, aArray[lo]) > 0) and (lo < aHigh) do | |||
lo := lo + 1; | |||
while (aComparer.Compare(p, aArray[hi]) < 0) do | |||
while (aComparer.Compare(p, aArray[hi]) < 0) and (hi > aLow) do | |||
hi := hi - 1; | |||
if (lo <= hi) then begin | |||
tmp := aArray[lo]; | |||
@@ -252,7 +250,7 @@ begin | |||
DoSort(aArray, aComparer, lo, aHigh); | |||
aHigh := hi; | |||
end; | |||
until (aLow >= aHigh); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -111,6 +111,25 @@ type | |||
{$ENDIF} | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlReverseComparer<T> = class( | |||
TInterfacedObject, | |||
specialize IutlEqualityComparer<T>, | |||
specialize IutlComparer<T>) | |||
public type | |||
IComparer = specialize IutlComparer<T>; | |||
private | |||
fComparer: IComparer; | |||
public | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
function Compare(constref i1, i2: T): Integer; | |||
constructor Create(aComparer: IComparer); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator <(const i1, i2: TObject): Boolean; inline; | |||
operator >(const i1, i2: TObject): Boolean; inline; | |||
@@ -244,5 +263,24 @@ begin | |||
end; | |||
{$ENDIF} | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlReverseComparer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlReverseComparer.EqualityCompare(constref i1, i2: T): Boolean; | |||
begin | |||
Result:= fComparer.EqualityCompare(i1, i2); | |||
end; | |||
function TutlReverseComparer.Compare(constref i1, i2: T): Integer; | |||
begin | |||
Result:= - fComparer.Compare(i1, i2); | |||
end; | |||
constructor TutlReverseComparer.Create(aComparer: IComparer); | |||
begin | |||
inherited Create; | |||
fComparer:= aComparer; | |||
end; | |||
end. | |||
@@ -207,10 +207,16 @@ type | |||
generic TutlList<T> = class( | |||
specialize TutlCustomList<T>) | |||
private type | |||
TQuickSortImpl = specialize TutlQuickSort<T>; | |||
IComparer = TQuickSortimpl.IComparer; | |||
TReverseComp = specialize TutlReverseComparer<T>; | |||
public type | |||
TEqualityComparer = specialize TutlEqualityComparer<T>; | |||
public | |||
procedure Sort(aComparer: IComparer; const aReverse: boolean = false); | |||
constructor Create(const aOwnsItems: Boolean); | |||
end; | |||
@@ -1157,7 +1163,7 @@ begin | |||
System.Move(p1^, tmp{%H-}, SizeOf(T)); | |||
System.Move(p2^, p1^, SizeOf(T)); | |||
System.Move(tmp, p2^, SizeOf(T)); | |||
FillByte(tmp, SizeOf(tmp), 0) | |||
FillByte(tmp, SizeOf(tmp), 0); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -1278,6 +1284,14 @@ end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlList////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlList.Sort(aComparer: IComparer; const aReverse: boolean); | |||
begin | |||
if aReverse then | |||
aComparer:= TReverseComp.Create(aComparer); | |||
TQuickSortImpl.Sort(Self, aComparer); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlList.Create(const aOwnsItems: Boolean); | |||
begin | |||
@@ -92,6 +92,7 @@ type | |||
['{D3618E88-3BF7-4E63-850F-6893A334564A}'] | |||
procedure SetCount(const aValue: Integer); | |||
procedure SetItem(const aIndex: Integer; aItem: T); | |||
procedure Exchange(const aIndex1, aIndex2: Integer); | |||
property Count: Integer read GetCount write SetCount; | |||
property Items[const aIndex: Integer]: T read GetItem write SetItem; default; | |||