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