From 39f4b97ea54f64ee9b91db074e4242b1b155f2d8 Mon Sep 17 00:00:00 2001 From: svenbarth <pascaldragon@googlemail.com> Date: Sun, 24 Nov 2019 00:04:35 +0000 Subject: [PATCH] + add test for a problem reported by Michael van Canneyt which is fixed by the previous revision git-svn-id: trunk@43569 - --- .gitattributes | 1 + tests/tbs/tb0664.pp | 915 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 916 insertions(+) create mode 100644 tests/tbs/tb0664.pp diff --git a/.gitattributes b/.gitattributes index 9c1064101b..394643fce2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12971,6 +12971,7 @@ tests/tbs/tb0660.pp svneol=native#text/pascal tests/tbs/tb0661.pp svneol=native#text/plain tests/tbs/tb0662.pp svneol=native#text/pascal tests/tbs/tb0663.pp svneol=native#text/plain +tests/tbs/tb0664.pp svneol=native#text/pascal tests/tbs/ub0060.pp svneol=native#text/plain tests/tbs/ub0069.pp svneol=native#text/plain tests/tbs/ub0119.pp svneol=native#text/plain diff --git a/tests/tbs/tb0664.pp b/tests/tbs/tb0664.pp new file mode 100644 index 0000000000..386258ccb2 --- /dev/null +++ b/tests/tbs/tb0664.pp @@ -0,0 +1,915 @@ +unit tb0664; + +{$mode delphi} + +interface + +uses Generics.Defaults, Generics.Collections, SysUtils; + + +type + + TuList<T> = class + {$IFDEF FPC} + type + TArrayT = Array of T; + {$ENDIF} + private + function GetCapacity: integer; + procedure SetCapacity(const Value: integer); + + protected + {$IFDEF FPC} + FData: TArrayT; + {$ELSE} + FData: TArray<T>; + {$ENDIF} + FCount : integer; + function GetItem(Index: Integer): T; + procedure SetItem(Index: Integer; const Value: T); + public + constructor Create; overload; + constructor Create(const aCapacity: integer); overload; + function Add(const item: T): integer; + property Count: integer read FCount; + property Items[Index: Integer]: T read GetItem write SetItem; default; + procedure Clear; virtual; + {$IFDEF FPC} + function ToArray: TArrayT; + {$ELSE} + function ToArray: TArray<T>; + {$ENDIF} + procedure TrimExcess; + property Capacity: integer read GetCapacity write SetCapacity; + end; + + ListHelper = record + public + class procedure Reverse<T>(const List: TuList<T>); static; + class function ToArray<T>(const List: TuList<T>): TArray<T>; static; + class procedure Sort<T>(const List: TuList<T>); overload; static; + class procedure Sort<T>(const List: TuList<T>; AComparer: IComparer<T>); overload; static; + class procedure StableSort<T>(const List: TuList<T>; AComparer: IComparer<T>); overload; static; + class function BinarySearch<T>(const List: TuList<T>; const Item: T): Integer; overload; static; + class function BinarySearch<T>(const List: TuList<T>; const Item: T; AComparer: IComparer<T>): SizeInt; overload; static; + class procedure Insert<T>(const List: TuList<T>; const index: integer; const Item: T); static; + class procedure Delete<T>(const List: TuList<T>; const index: integer); static; + class procedure InsertRange<T>(const List: TuList<T>; const index: integer; const Items: TArray<T>); static; + class procedure DeleteRange<T>(const List: TuList<T>; const index: integer; const dCount: integer); static; + + class procedure Remove<T>(const List: TuList<T>; const obj: T; AComparer: IComparer<T>); static; + class procedure AddManyInts(const List: TuList<UInt32>; const obj: UInt32; const aCount: Int32); static; + class procedure AddArrayByte(const List: TuList<UInt32>; const Source: TArray<Byte>; const aCount: Int32); static; + end; + + TuObjectList = class(TuList<TObject>) + private + FDontFree: Boolean; + public + constructor Create(const aCapacity: integer; const OwnsObjects: boolean); + destructor Destroy; override; + procedure Clear; override; + procedure Insert(Index: Integer; const Value: TObject); + procedure Delete(Index: Integer); + procedure DeleteAndNotFree(Index: Integer); + procedure RemoveRange(Index, Count: Integer); + procedure SetCount(const a: integer); + + function IndexOfPointer(const Value: TObject): Integer; + procedure RemovePointer(const obj: TObject); + procedure SetButDontDestroy(const i: integer; const r: TObject); + + property DontFree: Boolean read FDontFree write FDontFree; + end; + + {TuVListEnumerator<T> = class(TEnumerator<T>) + private + FList: TObject; //silly generics don't allow forward decl + Position: integer; + protected + function DoGetCurrent: T; override; + function DoMoveNext: Boolean; override; + public + constructor Create(const aList: TObject); + end;} + + TuVList<T: class> = class(TuObjectList) + protected + function GetItemTyped(Index: Integer): T; + procedure SetItemTyped(Index: Integer; const Value: T); + protected + FComparer: IComparer<T>; + public + constructor Create(const aCapacity: integer; const OwnsObjects: boolean); overload; + constructor Create(const aComparer: IComparer<T>); overload; + property ItemTyped[Index: Integer]: T read GetItemTyped write SetItemTyped; default; + //function GetEnumerator: TEnumerator<T>; + function ToArray: TArray<T>; + procedure Sort; overload; + procedure Sort(aComparer: IComparer<T>); overload; + procedure StableSort(aComparer: IComparer<T>); + function BinarySearch(const Item: T): Integer; overload; + function BinarySearch(const Item: T; aComparer: IComparer<T>): Integer; overload; + + end; + + {$ifdef blubb} + TuStack<T> = class + private + FData: TArray<T>; + FCount: integer; + public + procedure Push(const v: T); + function Pop: T; + function Peek: T; + function Count: integer; + procedure Clear; + end; + + TuOStack<T: class> = class + private + FData: TArray<T>; + FCount: integer; + public + procedure Push(const v: T); + procedure Pop; + function Peek: T; + function Count: integer; + procedure Clear; + end; + + +{ //can't create an instance in XE6 android + TKeyComparer<K, V> = class(TInterfacedObject, IComparer<TPair<K, V>>) + function Compare(const Left, Right: TPair<K, V>): Integer; + end; } + + TuSortedList<K, V> = class + type + TPairKV = TPair<K, V>; + private + List: TuList<TPairKV>; + function GetItems(const key: K): V; + procedure SetItems(const key: K; const value: V); + protected + FComparer: IComparer<K>; + + public + constructor Create; overload; + constructor Create(const aComparer: IComparer<K>); overload; + destructor Destroy; override; + + procedure Add(const key: K; const value: V); + procedure Remove(const key: K); + function ContainsKey(const key: K): boolean; + function IndexOfKey(const key: K): integer; + + function TryGetValue(const key: K; out value: V): boolean; + + property Items[const key: K]: V read GetItems write SetItems; default; + + function Count: integer; + + function Values(const index: integer): V; + function Keys(const index: integer): K; + end; + {$endif} + + procedure TrueFree(const obj: TObject); inline; + procedure FreeObj(var obj); inline; + +procedure RaiseArgEx; +function GetNextCapacity(const c: integer): integer; + +implementation + +//uses b; + +procedure TrueFree(const obj: TObject); +begin +{$ifdef AUTOREFCOUNT} +begin + obj.DisposeOf; +end; +{$else} +begin + obj.Free; +end; +{$endif} +end; + +procedure FreeObj(var obj); +{$ifdef AUTOREFCOUNT} +begin + if (Pointer(obj) <> nil) then TObject(obj).DisposeOf; + + TObject(obj) := nil; +end; +{$else} +var + Temp: TObject; +begin + Temp := TObject(Obj); + Pointer(Obj) := nil; + Temp.Free; +end; +{$endif} + +procedure RaiseArgEx; +begin + raise EArgumentOutOfRangeException.Create('Index out of bounds'); +end; + +function GetNextCapacity(const c: integer): integer; +begin + if (c = 0) then exit(4); + + if c < 1000 then exit (c * 2); + exit(c + 1000); +end; + +{$RANGECHECKS OFF} +procedure FillDWord(var Dest; Count, Value: UInt32); +{$IFDEF CPUX86} +asm + XCHG EDX, ECX + PUSH EDI + MOV EDI, EAX + MOV EAX, EDX + REP STOSD + POP EDI +end; +{$ELSE} +type + IntArray = array[0..0] of integer; + PIntArray = ^IntArray; +var + i: integer; + Arr: PIntArray; +begin + Arr := PIntArray(@Dest); + for i := 0 to Count - 1 do Arr[i] := Value; + +end; +{$ENDIF CPUX86} + +{ TuList<T> } +constructor TuList<T>.Create; +begin + inherited Create; +end; + + +constructor TuList<T>.Create(const aCapacity: integer); +begin + inherited Create; + Capacity := aCapacity; +end; + + +{$RANGECHECKS OFF} +function TuList<T>.Add(const item: T): integer; +begin + if FCount >= Length(FData) then + begin + SetLength(FData, GetNextCapacity(FCount)); + end; + FData[FCount] := item; + Result := FCount; + inc(FCount); +end; + +procedure TuList<T>.Clear; +begin + FData := nil; + FCount := 0; +end; + +function TuList<T>.GetItem(Index: Integer): T; +begin + {$R-} + if (Index >= Count) or (Index < 0)then RaiseArgEx; + Result := FData[Index]; + {$R+} +end; + +procedure TuList<T>.SetItem(Index: Integer; const Value: T); +begin + {$R-} + if (Index >= Count) or (Index < 0)then RaiseArgEx; + FData[Index] := Value; + {$R+} +end; + +{$IFDEF FPC} +function TuList<T>.ToArray: TArrayT; +{$ELSE} +function TuList<T>.ToArray: TArray<T>; +{$ENDIF} +begin + SetLength(FData, FCount); + Result := FData; //we won't return a deep copy. +end; + +procedure TuList<T>.TrimExcess; +begin + SetLength(FData, FCount); +end; + +function TuList<T>.GetCapacity: integer; +begin + Result := Length(FData); +end; + +procedure TuList<T>.SetCapacity(const Value: integer); +begin + if Value > FCount then SetLength(FData, value) else SetLength(FData, FCount); +end; + +{ TuVList<T> } + +function TuVList<T>.BinarySearch(const Item: T): Integer; +begin + Result := ListHelper.BinarySearch<T>(TuList<T>(self), Item, FComparer); +end; + +function TuVList<T>.BinarySearch(const Item: T; + aComparer: IComparer<T>): Integer; +begin + Result := ListHelper.BinarySearch<T>(TuList<T>(self), Item, aComparer); +end; + +constructor TuVList<T>.Create(const aCapacity: integer; + const OwnsObjects: boolean); +var + Tmp: T; +begin + inherited Create(aCapacity, OwnsObjects); +// Tmp := Default(T); +// if Supports(TObject(Tmp), IComparable<T>) then FComparer := TComparableComparer<T>.Create(); + +end; + +constructor TuVList<T>.Create(const aComparer: IComparer<T>); +begin + inherited Create(4, true); + FComparer := aComparer; +end; + +{function TuVList<T>.GetEnumerator: TEnumerator<T>; +begin + Result := TuVListEnumerator<T>.Create(self); +end;} + +function TuVList<T>.GetItemTyped(Index: Integer): T; +begin + {$R-} + if (Index >= Count) or (Index < 0)then RaiseArgEx; + Result := T(FData[Index]); + {$R+} +end; + +procedure TuVList<T>.SetItemTyped(Index: Integer; const Value: T); +begin + {$R-} + if (Index >= Count) or (Index < 0)then RaiseArgEx; + if not DontFree then TrueFree(FData[Index]); + FData[Index] := Value; + {$R+} +end; + +procedure TuVList<T>.Sort(aComparer: IComparer<T>); +begin + ListHelper.Sort<T>(TuList<T>(self), aComparer); +end; + +procedure TuVList<T>.StableSort(aComparer: IComparer<T>); +var + CastData: TArray<T>; +begin + TrimExcess; + CastData := TArray<T>(FData); +// MergeSort.Sort<T>(CastData, aComparer); +end; + +procedure TuVList<T>.Sort; +begin + ListHelper.Sort<T>(TuList<T>(self), FComparer); +end; + +function TuVList<T>.ToArray: TArray<T>; +var + i: integer; +begin + Result := nil; + SetLength(Result, FCount); + for i := 0 to FCount - 1 do Result[i] := T(FData[i]); + +end; + +{ ListHelper } + +class function ListHelper.BinarySearch<T>(const List: TuList<T>; const Item: T): Integer; +begin + Result := BinarySearch<T>(List, Item, TComparer<T>.Default); +end; + +class function ListHelper.BinarySearch<T>(const List: TuList<T>; const Item: T; + AComparer: IComparer<T>): SizeInt; +var + b: boolean; +begin + if AComparer = nil then AComparer := TComparer<T>.Default; + + b := {$IFDEF FPC}TArrayHelper<T>.BinarySearch{$ELSE}TArray.BinarySearch<T>{$ENDIF}(List.FData, Item, Result, AComparer, 0, List.Count); + if not b then Result := not Result; +end; + +class procedure ListHelper.Delete<T>(const List: TuList<T>; + const index: integer); +begin + if (index > List.Count) or (index < 0) then RaiseArgEx; + {$IFDEF FPC} + List[index] := Default(T); //clear strings or interfaces. + {$ELSE} + {$if (CompilerVersion = 33.0) and (Defined(MACOS32) or Defined(IOS))} //see https://quality.embarcadero.com/browse/RSB-2792 We don't do it for the future since it should be fixed after RIO (and likely in a RIO ServicePack.) + Finalize(List.FData[Index]); + {$else} + List[index] := Default(T); //clear strings or interfaces. + {$ifend} + {$ENDIF} + if index + 1 < List.Count then + begin + Move(List.FData[index + 1], List.FData[index], SizeOf(T) * (List.Count - (index + 1))); + FillChar(List.FData[List.FCount - 1], SizeOf(T), 0); //avoid having those records finalized + end; + + dec(List.FCount); +end; + +class procedure ListHelper.DeleteRange<T>(const List: TuList<T>; const index, + dCount: integer); +var + i: integer; + remaining, ToClean: integer; +begin + if dCount = 0 then exit; + + if (index > List.Count) or (index < 0) or (dCount < 0) or (dCount + index > List.Count) then RaiseArgEx; + for i := 0 to dCount - 1 do List[index + i] := Default(T); //clear strings or interfaces. + if index + dCount < List.Count then + begin + remaining := List.Count - (index + dcount); + Move(List.FData[index + dCount], List.FData[index], SizeOf(T) * remaining); + ToClean := remaining; if ToClean > dCount then ToClean := dCount; + + FillChar(List.FData[List.FCount - ToClean], ToClean * SizeOf(T), 0); //avoid having those records finalized + end; + + dec(List.FCount, dCount); +end; + +class procedure ListHelper.Insert<T>(const List: TuList<T>; + const index: integer; const Item: T); +begin + if (index > List.Count) or (index < 0) then RaiseArgEx; + if List.Count >= Length(List.FData) then + begin + SetLength(List.FData, GetNextCapacity(List.FCount)); + end; + + if index < List.Count then + begin + Move(List.FData[index], List.FData[index + 1], SizeOf(T) * (List.Count - index)); + FillChar(List.FData[index], SizeOf(T), 0); //avoid having those records finalized + end; + + List.FData[index] := item; + inc(List.FCount); +end; + +class procedure ListHelper.InsertRange<T>(const List: TuList<T>; + const index: integer; const Items: TArray<T>); +var + i: integer; +begin + if Length(Items) = 0 then exit; + + if (index > List.Count) or (index < 0) then RaiseArgEx; + if List.Count + Length(Items) > Length(List.FData) then + begin + SetLength(List.FData, GetNextCapacity(List.FCount + Length(Items))); + end; + + if index < List.Count then + begin + Move(List.FData[index], List.FData[index + Length(Items)], SizeOf(T) * (List.Count - index)); + FillChar(List.FData[index], Length(Items) * SizeOf(T), 0); //avoid having those records finalized + end; + + for i := 0 to Length(Items) - 1 do List.FData[index + i] := Items[i]; + inc(List.FCount, Length(Items)); +end; + +class procedure ListHelper.AddManyInts(const List: TuList<UInt32>; const obj: UInt32; const aCount: Int32); +begin + if (aCount <= 0) then exit; + + if List.Count + aCount > Length(List.FData) then + begin + SetLength(List.FData, GetNextCapacity(List.FCount + aCount)); + end; + + FillDWord(List.FData[List.Count], aCount, Obj); + inc(List.FCount, aCount); +end; + +class procedure ListHelper.AddArrayByte(const List: TuList<UInt32>; const Source: TArray<Byte>; const aCount: Int32); +begin + if (aCount <= 0) then exit; + + if List.Count + aCount > Length(List.FData) then + begin + SetLength(List.FData, GetNextCapacity(List.FCount + aCount)); + end; + + System.Move(Source[0], List.FData[List.Count], aCount * SizeOf(UInt32)); + inc(List.FCount, aCount); +end; + + +class procedure ListHelper.Remove<T>(const List: TuList<T>; const obj: T; AComparer: IComparer<T>); +var + i: Integer; +begin + if (AComparer = nil) then AComparer := TComparer<T>.Default; + + for i := 0 to List.Count - 1 do + begin + if AComparer.Compare(List[i], obj) = 0 then + begin + Delete<T>(List, i); + exit; + end; + + end; +end; + +class procedure ListHelper.Reverse<T>(const List: TuList<T>); +var + i, k: integer; + Tmp: T; +begin + k := List.Count - 1; + for i := 0 to (List.Count div 2) - 1 do + begin + Tmp := List[i]; + List[i] := List[k]; + List[k] := Tmp; + dec(k); + end; +end; + +class procedure ListHelper.Sort<T>(const List: TuList<T>; + AComparer: IComparer<T>); +begin + if AComparer = nil then AComparer := TComparer<T>.Default; + {$IFDEF FPC}TArrayHelper<T>.Sort{$ELSE}TArray.Sort<T>{$ENDIF}(List.FData, AComparer, 0, List.Count); +end; + +class procedure ListHelper.Sort<T>(const List: TuList<T>); +begin + {$IFDEF FPC}TArrayHelper<T>.Sort{$ELSE}TArray.Sort<T>{$ENDIF}(List.FData, TComparer<T>.Default, 0, List.Count); +end; + +class procedure ListHelper.StableSort<T>(const List: TuList<T>; + AComparer: IComparer<T>); +begin + if AComparer = nil then AComparer := TComparer<T>.Default; + List.TrimExcess; +// MergeSort.Sort<T>(List.FData, AComparer); +end; + +class function ListHelper.ToArray<T>(const List: TuList<T>): TArray<T>; +var + i: Integer; +begin + SetLength(Result, List.Count); + for i := 0 to Length(Result) - 1 do + begin + Result[i] := List[i]; + end; + +end; + +{ TuObjectList } + +procedure TuObjectList.Clear; +var + i: integer; +begin + if not DontFree then for i := 0 to FCount - 1 do TrueFree(FData[i]); + inherited; +end; + +constructor TuObjectList.Create(const aCapacity: integer; + const OwnsObjects: boolean); +begin + inherited Create; + SetLength(FData, aCapacity); + DontFree := not OwnsObjects; +end; + +procedure TuObjectList.Delete(Index: Integer); +begin + if not DontFree then TrueFree(Self[Index]); + ListHelper.Delete<TObject>(self, Index); + +end; + +procedure TuObjectList.DeleteAndNotFree(Index: Integer); +begin + ListHelper.Delete<TObject>(self, Index); + +end; + +procedure TuObjectList.RemoveRange(Index, Count: Integer); +var + i: integer; +begin + if not DontFree then for i := Index to Index + Count - 1 do TrueFree(Self[i]); + ListHelper.DeleteRange<TObject>(self, Index, Count); + +end; + +destructor TuObjectList.Destroy; +begin + if not DontFree then Clear; + + inherited; +end; + +function TuObjectList.IndexOfPointer(const Value: TObject): Integer; +var + i: Integer; +begin + for i := 0 to Count - 1 do + if Items[i] = Value then + Exit(i); + Result := -1; +end; +procedure TuObjectList.Insert(Index: Integer; const Value: TObject); +begin + ListHelper.Insert<TObject>(self, Index, Value); +end; + +procedure TuObjectList.RemovePointer(const obj: TObject); +var + i: integer; +begin + i := IndexOfPointer(obj); + if i >= 0 then Delete(i); +end; + +procedure TuObjectList.SetButDontDestroy(const i: integer; const r: TObject); +begin + SetItem(i, r); +end; + +procedure TuObjectList.SetCount(const a: integer); +begin + FCount := a; + Capacity := a; +end; + +{ TuVListEnumerator<T> } +{$ifdef blubb} + +constructor TuVListEnumerator<T>.Create(const aList: TObject); +begin + inherited Create; + FList := aList; + Position := -1; +end; + +function TuVListEnumerator<T>.DoGetCurrent: T; +begin + Result := TuList<T>(FList)[Position]; +end; + +function TuVListEnumerator<T>.DoMoveNext: Boolean; +begin + if Position >= (TuList<T>(FList)).Count then exit(false); + + inc(Position); + Result := Position < (TuList<T>(FList)).Count; +end; + +{ TuStack<T> } + +procedure TuStack<T>.Clear; +begin + FData := nil; + FCount := 0; +end; + +function TuStack<T>.Count: integer; +begin + Result := FCount; +end; + +function TuStack<T>.Peek: T; +begin + if (FCount <= 0) then RaiseArgEx; + Result := FData[FCount - 1]; +end; + +function TuStack<T>.Pop: T; +begin + if (FCount <= 0) then RaiseArgEx; + dec(FCount); + Result := FData[FCount]; + FData[FCount] := Default(T); +end; + +procedure TuStack<T>.Push(const v: T); +begin + if FCount >= Length(FData) then + begin + SetLength(FData, GetNextCapacity(FCount)); + end; + FData[FCount] := v; + inc(FCount); +end; + +{ TuStack<T> } + +procedure TuOStack<T>.Clear; +begin + FData := nil; + FCount := 0; +end; + +function TuOStack<T>.Count: integer; +begin + Result := FCount; +end; + +function TuOStack<T>.Peek: T; +begin + if (FCount <= 0) then RaiseArgEx; + Result := FData[FCount - 1]; +end; + +procedure TuOStack<T>.Pop; +begin + if (FCount <= 0) then RaiseArgEx; + dec(FCount); + TrueFree(FData[Count]); + FData[FCount] := Default(T); +end; + +procedure TuOStack<T>.Push(const v: T); +begin + if FCount >= Length(FData) then + begin + SetLength(FData, GetNextCapacity(FCount)); + end; + FData[FCount] := v; + inc(FCount); +end; + +{ TuSortedList<K, V> } + +constructor TuSortedList<K, V>.Create; +begin + Create(TComparer<K>.Default); +end; + +constructor TuSortedList<K, V>.Create(const aComparer: IComparer<K>); +begin + List := TuList<TPairKV>.Create; + FComparer := aComparer; +end; + +destructor TuSortedList<K, V>.Destroy; +begin + FreeObj(List); + + inherited; +end; + +procedure TuSortedList<K, V>.Add(const key: K; const value: V); +var + index: integer; +begin + index := IndexOfKey(key); + if index >= 0 then RaiseArgEx; + + index := not index; + ListHelper.Insert<TPairKV>(List, index, TPairKV.Create(key, value)); +end; + +procedure TuSortedList<K, V>.Remove(const key: K); +var + index: integer; +begin + index := IndexOfKey(key); + if index < 0 then RaiseArgEx; + + ListHelper.Delete<TPairKV>(List, index); +end; + +function TuSortedList<K, V>.IndexOfKey(const key: K): integer; +//begin +// fails in android /iosdevice XE6 Result := ListHelper.BinarySearch<TPairKV>(List, TPairKV.Create(key, Default(V)), TKeyComparer<K, V>.Create); +var + L, H: Integer; + mid, cmp: Integer; + found: boolean; +begin + found := false; + if Count = 0 then exit(not 0); + + L := 0; + H := Count - 1; + while L <= H do + begin + mid := L + (H - L) shr 1; + cmp := FComparer.Compare(List[mid].Key, key); + if cmp < 0 then + L := mid + 1 + else + begin + H := mid - 1; + if cmp = 0 then + begin + found := true; + end; + end; + end; + + Result := L; + if (not found) then Result := not Result; + +end; + +function TuSortedList<K, V>.GetItems(const key: K): V; +begin + Result := List[IndexOfKey(key)].Value; +end; + +function TuSortedList<K, V>.Keys(const index: integer): K; +begin + Result := List[index].Key; +end; + +procedure TuSortedList<K, V>.SetItems(const key: K; const value: V); +var + index: integer; +begin + index := IndexOfKey(key); + if (index >= 0) then List[index] := TPairKV.Create(key, value) + else Add(key, value); +end; + +function TuSortedList<K, V>.TryGetValue(const key: K; out value: V): boolean; +var + i: integer; +begin + i := IndexOfKey(key); + if (i < 0) then + begin + value := Default(V); + exit(false); + end; + + value := List[i].Value; + Result := true; +end; + +function TuSortedList<K, V>.Values(const index: integer): V; +begin + Result := List[index].Value; +end; + +function TuSortedList<K, V>.ContainsKey(const key: K): boolean; +begin + Result := IndexOfKey(key) >= 0; +end; + +function TuSortedList<K, V>.Count: integer; +begin + Result := List.Count; +end; +{$endif} + +(* +{ TKeyComparer<K, V> } + +function TKeyComparer<K, V>.Compare(const Left, Right: TPairKV): Integer; +begin + Result := TComparer<K>.Default.Compare(Left.Key, Right.Key); +end;*) + +end.