* [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; | ||||