浏览代码

* implemented observable generics

master
Bergmann89 10 年前
父节点
当前提交
6392c680ae
共有 3 个文件被更改,包括 453 次插入 和 95 次删除
  1. +1
    -1
      uutlEventManager.pas
  2. +121
    -94
      uutlGenerics.pas
  3. +331
    -0
      uutlObservableGenerics.pas

+ 1
- 1
uutlEventManager.pas 查看文件

@@ -71,7 +71,7 @@ type
public
class function MakeMask (const aTypes: array of TutlEventType): TutlEventTypeMask;
class function CombineMasks(const aMasks: array of TutlEventTypeMask): TutlEventTypeMask;
class function MaskHasType (const aMask: TutlEventTypeMask; const aType: TutlEventType): Boolean;
class function MaskHasType (const aMask: TutlEventTypeMask; const aType: TutlEventType): Boolean; inline;
end;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 121
- 94
uutlGenerics.pas 查看文件

@@ -110,10 +110,10 @@ type
function CreateItem: PListItem; virtual;
procedure DestroyItem(const aItem: PListItem; const aFreeItem: Boolean = true); virtual;
procedure InsertIntern(const aIndex: Integer; const aItem: T); virtual;
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true);
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true); virtual;

public
property OwnsObjects: Boolean read fOwnsObjects write fOwnsObjects;
property OwnsObjects: Boolean read fOwnsObjects write fOwnsObjects;

function GetEnumerator: TEnumerator;
function GetReverseEnumerator: TEnumerator;
@@ -178,12 +178,20 @@ type
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlCustomHashSet<T> = class(specialize TutlListBase<T>)
generic TutlHashSetBase<T> = class(specialize TutlListBase<T>)
public type
IComparer = specialize IutlComparer<T>;
private
fComparer: IComparer;
protected
function SearchItem(const aMin, aMax: Integer; const aItem: T; out aIndex: Integer): Integer;
public
constructor Create(aComparer: IComparer; const aOwnsObjects: Boolean = true);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlCustomHashSet<T> = class(specialize TutlHashSetBase<T>)
public
property Items[const aIndex: Integer]: T read GetItem; default;
property Count: Integer read GetCount;
@@ -193,9 +201,6 @@ type
function IndexOf(const aItem: T): Integer;
function Remove(const aItem: T): Boolean;
procedure Delete(const aIndex: Integer);

constructor Create(aComparer: IComparer; const aOwnsObjects: Boolean = true);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -216,23 +221,23 @@ type
public
constructor Create;
end;
generic TutlCustomMap<TKey, TValue> = class(TObject)

generic TutlMapBase<TKey, TValue> = class(TObject)
public type
IComparer = specialize IutlComparer<TKey>;
TKeyValuePair = packed record
Key: TKey;
Value: TValue;
end;
private type
THashSetBase = specialize TutlCustomHashSet<TKeyValuePair>;
THashSet = class(THashSetBase)

THashSet = class(specialize TutlCustomHashSet<TKeyValuePair>)
protected
procedure DestroyItem(const aItem: PListItem; const aFreeItem: Boolean = true); override;
public
property Items[const aIndex: Integer]: TKeyValuePair read GetItem write SetItem; default;
end;

TKVPComparer = class(TInterfacedObject, THashSet.IComparer)
TKeyValuePairComparer = class(TInterfacedObject, THashSet.IComparer)
private
fComparer: IComparer;
public
@@ -299,8 +304,7 @@ type
end;

private
fComparer: IComparer;
fHashSet: THashSet;
fHashSetRef: THashSet;
fKeyWrapper: TKeyWrapper;
fKeyValuePairWrapper: TKeyValuePairWrapper;

@@ -326,7 +330,16 @@ type

function GetEnumerator: TValueEnumerator;

constructor Create(aComparer: IComparer; const aOwnsObjects: Boolean = true);
constructor Create(const aHashSet: THashSet);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlCustomMap<TKey, TValue> = class(specialize TutlMapBase<TKey, TValue>)
private
fHashSetImpl: THashSet;
public
constructor Create(const aComparer: IComparer; const aOwnsObjects: Boolean = true);
destructor Destroy; override;
end;

@@ -629,6 +642,20 @@ begin
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.Create(const aComparer: IComparer; const aOwnsObjects: Boolean);
begin
fHashSetImpl := THashSet.Create(TKeyValuePairComparer.Create(aComparer), aOwnsObjects);
inherited Create(fHashSetImpl);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlCustomMap.Destroy;
begin
inherited Destroy;
FreeAndNil(fHashSetImpl);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EutlEnumConvert///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1094,9 +1121,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomHashSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlHashSetBase///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomHashSet.SearchItem(const aMin, aMax: Integer; const aItem: T; out aIndex: Integer): Integer;
function TutlHashSetBase.SearchItem(const aMin, aMax: Integer; const aItem: T; out aIndex: Integer): Integer;
var
i, cmp: Integer;
begin
@@ -1115,6 +1142,22 @@ begin
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlHashSetBase.Create(aComparer: IComparer; const aOwnsObjects: Boolean);
begin
inherited Create(aOwnsObjects);
fComparer := aComparer;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlHashSetBase.Destroy;
begin
fComparer := nil;
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomHashSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomHashSet.Add(const aItem: T): Boolean;
var
@@ -1158,20 +1201,6 @@ begin
DeleteIntern(aIndex);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomHashSet.Create(aComparer: IComparer; const aOwnsObjects: Boolean);
begin
inherited Create(aOwnsObjects);
fComparer := aComparer;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlCustomHashSet.Destroy;
begin
fComparer := nil;
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlHashSet///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1181,9 +1210,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap.THashSet////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase.THashSet//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.THashSet.DestroyItem(const aItem: PListItem; const aFreeItem: Boolean);
procedure TutlMapBase.THashSet.DestroyItem(const aItem: PListItem; const aFreeItem: Boolean);
begin
// never free objects used as keys, but do finalize strings, interfaces etc.
utlFreeOrFinalize(aItem^.data.key, TypeInfo(aItem^.data.key), false);
@@ -1192,44 +1221,44 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap.TKVPComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase.TKeyValuePairComparer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKVPComparer.Compare(const i1, i2: TKeyValuePair): Integer;
function TutlMapBase.TKeyValuePairComparer.Compare(const i1, i2: TKeyValuePair): Integer;
begin
result := fComparer.Compare(i1.Key, i2.Key);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.TKVPComparer.Create(aComparer: IComparer);
constructor TutlMapBase.TKeyValuePairComparer.Create(aComparer: IComparer);
begin
inherited Create;
fComparer := aComparer;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlCustomMap.TKVPComparer.Destroy;
destructor TutlMapBase.TKeyValuePairComparer.Destroy;
begin
fComparer := nil;
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap.TValueEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase.TValueEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TValueEnumerator.GetCurrent: TValue;
function TutlMapBase.TValueEnumerator.GetCurrent: TValue;
begin
result := fHashSet[fPos].Value;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TValueEnumerator.MoveNext: Boolean;
function TutlMapBase.TValueEnumerator.MoveNext: Boolean;
begin
inc(fPos);
result := (fPos < fHashSet.Count);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.TValueEnumerator.Create(const aHashSet: THashSet);
constructor TutlMapBase.TValueEnumerator.Create(const aHashSet: THashSet);
begin
inherited Create;
fHashSet := aHashSet;
@@ -1237,22 +1266,22 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap.TKeyEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase.TKeyEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyEnumerator.GetCurrent: TKey;
function TutlMapBase.TKeyEnumerator.GetCurrent: TKey;
begin
result := fHashSet[fPos].Key;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyEnumerator.MoveNext: Boolean;
function TutlMapBase.TKeyEnumerator.MoveNext: Boolean;
begin
inc(fPos);
result := (fPos < fHashSet.Count);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.TKeyEnumerator.Create(const aHashSet: THashSet);
constructor TutlMapBase.TKeyEnumerator.Create(const aHashSet: THashSet);
begin
inherited Create;
fHashSet := aHashSet;
@@ -1260,22 +1289,22 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap.TKeyValuePairEnumerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase.TKeyValuePairEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyValuePairEnumerator.GetCurrent: TKeyValuePair;
function TutlMapBase.TKeyValuePairEnumerator.GetCurrent: TKeyValuePair;
begin
result := fHashSet[fPos];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyValuePairEnumerator.MoveNext: Boolean;
function TutlMapBase.TKeyValuePairEnumerator.MoveNext: Boolean;
begin
inc(fPos);
result := (fPos < fHashSet.Count);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.TKeyValuePairEnumerator.Create(const aHashSet: THashSet);
constructor TutlMapBase.TKeyValuePairEnumerator.Create(const aHashSet: THashSet);
begin
inherited Create;
fHashSet := aHashSet;
@@ -1283,185 +1312,183 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap.TKeyWrapper/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase.TKeyWrapper///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyWrapper.GetItem(const aIndex: Integer): TKey;
function TutlMapBase.TKeyWrapper.GetItem(const aIndex: Integer): TKey;
begin
result := fHashSet[aIndex].Key;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyWrapper.GetCount: Integer;
function TutlMapBase.TKeyWrapper.GetCount: Integer;
begin
result := fHashSet.Count;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyWrapper.GetEnumerator: TKeyEnumerator;
function TutlMapBase.TKeyWrapper.GetEnumerator: TKeyEnumerator;
begin
result := TKeyEnumerator.Create(fHashSet);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.TKeyWrapper.Create(const aHashSet: THashSet);
constructor TutlMapBase.TKeyWrapper.Create(const aHashSet: THashSet);
begin
inherited Create;
fHashSet := aHashSet;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap.TKeyValuePairWrapper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase.TKeyValuePairWrapper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyValuePairWrapper.GetItem(const aIndex: Integer): TKeyValuePair;
function TutlMapBase.TKeyValuePairWrapper.GetItem(const aIndex: Integer): TKeyValuePair;
begin
result := fHashSet[aIndex];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyValuePairWrapper.GetCount: Integer;
function TutlMapBase.TKeyValuePairWrapper.GetCount: Integer;
begin
result := fHashSet.Count;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.TKeyValuePairWrapper.GetEnumerator: TKeyValuePairEnumerator;
function TutlMapBase.TKeyValuePairWrapper.GetEnumerator: TKeyValuePairEnumerator;
begin
result := TKeyValuePairEnumerator.Create(fHashSet);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.TKeyValuePairWrapper.Create(const aHashSet: THashSet);
constructor TutlMapBase.TKeyValuePairWrapper.Create(const aHashSet: THashSet);
begin
inherited Create;
fHashSet := aHashSet;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlCustomMap/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlMapBase///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.GetValues(const aKey: TKey): TValue;
function TutlMapBase.GetValues(const aKey: TKey): TValue;
var
i: Integer;
kvp: TKeyValuePair;
begin
kvp.Key := aKey;
i := fHashSet.IndexOf(kvp);
i := fHashSetRef.IndexOf(kvp);
if (i < 0) then
FillByte(result{%H-}, SizeOf(result), 0)
else
result := fHashSet[i].Value;
result := fHashSetRef[i].Value;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.GetValueAt(const aIndex: Integer): TValue;
function TutlMapBase.GetValueAt(const aIndex: Integer): TValue;
begin
result := fHashSet[aIndex].Value;
result := fHashSetRef[aIndex].Value;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.GetCount: Integer;
function TutlMapBase.GetCount: Integer;
begin
result := fHashSet.Count;
result := fHashSetRef.Count;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetValues(const aKey: TKey; aValue: TValue);
procedure TutlMapBase.SetValues(const aKey: TKey; aValue: TValue);
var
i: Integer;
kvp: TKeyValuePair;
begin
kvp.Key := aKey;
kvp.Value := aValue;
i := fHashSet.IndexOf(kvp);
i := fHashSetRef.IndexOf(kvp);
if (i < 0) then
raise EutlMap.Create('key not found');
fHashSet[i] := kvp;
fHashSetRef[i] := kvp;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.SetValueAt(const aIndex: Integer; aValue: TValue);
procedure TutlMapBase.SetValueAt(const aIndex: Integer; aValue: TValue);
var
kvp: TKeyValuePair;
begin
kvp := fHashSet[aIndex];
kvp := fHashSetRef[aIndex];
kvp.Value := aValue;
fHashSet[aIndex] := kvp;
fHashSetRef[aIndex] := kvp;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.Add(const aKey: TKey; const aValue: TValue);
procedure TutlMapBase.Add(const aKey: TKey; const aValue: TValue);
var
kvp: TKeyValuePair;
begin
kvp.Key := aKey;
kvp.Value := aValue;
if not fHashSet.Add(kvp) then
if not fHashSetRef.Add(kvp) then
raise EutlMapKeyAlreadyExists.Create();
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.IndexOf(const aKey: TKey): Integer;
function TutlMapBase.IndexOf(const aKey: TKey): Integer;
var
kvp: TKeyValuePair;
begin
kvp.Key := aKey;
result := fHashSet.IndexOf(kvp);
result := fHashSetRef.IndexOf(kvp);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.Contains(const aKey: TKey): Boolean;
function TutlMapBase.Contains(const aKey: TKey): Boolean;
var
kvp: TKeyValuePair;
begin
kvp.Key := aKey;
result := (fHashSet.IndexOf(kvp) >= 0);
result := (fHashSetRef.IndexOf(kvp) >= 0);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.Delete(const aKey: TKey);
procedure TutlMapBase.Delete(const aKey: TKey);
var
kvp: TKeyValuePair;
begin
kvp.Key := aKey;
if not fHashSet.Remove(kvp) then
if not fHashSetRef.Remove(kvp) then
raise EutlMapKeyNotFound.Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.DeleteAt(const aIndex: Integer);
procedure TutlMapBase.DeleteAt(const aIndex: Integer);
begin
fHashSet.Delete(aIndex);
fHashSetRef.Delete(aIndex);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlCustomMap.Clear;
procedure TutlMapBase.Clear;
begin
fHashSet.Clear;
fHashSetRef.Clear;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlCustomMap.GetEnumerator: TValueEnumerator;
function TutlMapBase.GetEnumerator: TValueEnumerator;
begin
result := TValueEnumerator.Create(fHashSet);
result := TValueEnumerator.Create(fHashSetRef);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlCustomMap.Create(aComparer: IComparer; const aOwnsObjects: Boolean);
constructor TutlMapBase.Create(const aHashSet: THashSet);
begin
inherited Create;
fComparer := aComparer;
fHashSet := THashSet.Create(TKVPComparer.Create(fComparer), aOwnsObjects);
fKeyWrapper := TKeyWrapper.Create(fHashSet);
fKeyValuePairWrapper := TKeyValuePairWrapper.Create(fHashSet);
fHashSetRef := aHashSet;
fKeyWrapper := TKeyWrapper.Create(fHashSetRef);
fKeyValuePairWrapper := TKeyValuePairWrapper.Create(fHashSetRef);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlCustomMap.Destroy;
destructor TutlMapBase.Destroy;
begin
FreeAndNil(fKeyValuePairWrapper);
FreeAndNil(fKeyWrapper);
FreeAndNil(fHashSet);
fComparer := nil;
fHashSetRef := nil;
inherited Destroy;
end;



+ 331
- 0
uutlObservableGenerics.pas 查看文件

@@ -0,0 +1,331 @@
unit uutlObservableGenerics;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils,
uutlGenerics;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlEventList<T> = class(specialize TutlHashSetBase<T>)
private type
TComparer = class(TInterfacedObject, IComparer)
public
function Compare(const i1, i2: T): Integer;
end;

public
function RegisterEvent(const aEvent: T): Boolean;
function UnregisterEvent(const aEvent: T): Boolean;

constructor Create;
end;
TutlNotifyEventList = specialize TutlEventList<TNotifyEvent>;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableCustomList<T> = class(specialize TutlCustomList<T>)
public type
TEvent = procedure(aSender: TObject; const aIndex: Integer; const aItem: T) of object;
TEventList = specialize TutlEventList<TEvent>;
private
fOnAddItem: TEventList;
fOnRemoveItem: TEventList;
protected
procedure InsertIntern(const aIndex: Integer; const aItem: T); override;
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true); override;
public
property OnAddItem: TEventList read fOnAddItem;
property OnRemoveItem: TEventList read fOnRemoveItem;

constructor Create(aEqualityComparer: IEqualityComparer; const aOwnsObjects: Boolean = true);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableList<T> = class(specialize TutlObservableCustomList<T>)
public type
TEqualityComparer = specialize TutlEqualityComparer<T>;
public
constructor Create(const aOwnsObjects: Boolean = true);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableCustomHashSet<T> = class(specialize TutlCustomHashSet<T>)
public type
TEvent = procedure(aSender: TObject; const aItem: T) of object;
TEventList = specialize TutlEventList<TEvent>;
private
fOnAddItem: TEventList;
fOnRemoveItem: TEventList;
protected
procedure InsertIntern(const aIndex: Integer; const aItem: T); override;
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true); override;
public
property OnAddItem: TEventList read fOnAddItem;
property OnRemoveItem: TEventList read fOnRemoveItem;

constructor Create(aComparer: IComparer; const aOwnsObjects: Boolean = true);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableHashSet<T> = class(specialize TutlObservableCustomHashSet<T>)
public type
TComparer = specialize TutlComparer<T>;
public
constructor Create(const aOwnsObjects: Boolean = true);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableCustomMap<TKey, TValue> = class(specialize TutlMapBase<TKey, TValue>)
public type
TEvent = procedure(aSender: TObject; const aKey: TKey; const aValue: TValue) of object;
TEventList = specialize TutlEventList<TEvent>;
TObservableHashSet = class(THashSet)
private
fOwner: TObject;
fOnAddItem: TEventList;
fOnRemoveItem: TEventList;
protected
procedure InsertIntern(const aIndex: Integer; const aItem: TKeyValuePair); override;
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean = true); override;
public
property OnAddItem: TEventList read fOnAddItem write fOnAddItem;
property OnRemoveItem: TEventList read fOnRemoveItem write fOnRemoveItem;
constructor Create(const aOwner: TObject; const aComparer: IComparer; const aOwnsObjects: Boolean = true);
end;

private
fHashSetImpl: TObservableHashSet;
fOnAddItem: TEventList;
fOnRemoveItem: TEventList;
public
property OnAddItem: TEventList read fOnAddItem;
property OnRemoveItem: TEventList read fOnRemoveItem;

constructor Create(const aComparer: IComparer; const aOwnsObjects: Boolean = true);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlObservableMap<TKey, TValue> = class(specialize TutlObservableCustomMap<TKey, TValue>)
public type
TComparer = specialize TutlComparer<TKey>;
public
constructor Create(const aOwnsObjects: Boolean = true);
end;

implementation

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlEventList/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlEventList.TComparer.Compare(const i1, i2: T): Integer;
var
m1, m2: TMethod;
begin
m1 := TMethod(i1);
m2 := TMethod(i2);
if (m1.Data < m2.Data) then
result := -1
else if (m1.Data > m2.Data) then
result := 1
else if (m1.Code < m2.Code) then
result := -1
else if (m1.Code > m2.Code) then
result := 1
else
result := 0;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlEventList.RegisterEvent(const aEvent: T): Boolean;
var
i: Integer;
begin
result := (SearchItem(0, List.Count-1, aEvent, i) < 0);
if result then
InsertIntern(i, aEvent);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlEventList.UnregisterEvent(const aEvent: T): Boolean;
var
i, tmp: Integer;
begin
i := SearchItem(0, List.Count-1, aEvent, tmp);
result := (i >= 0);
if result then
DeleteIntern(i);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlEventList.Create;
begin
inherited Create(TComparer.Create, true);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomList//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomList.InsertIntern(const aIndex: Integer; const aItem: T);
var
e: TEvent;
begin
inherited InsertIntern(aIndex, aItem);
if Assigned(fOnAddItem) then
for e in fOnAddItem do
e(self, aIndex, aItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomList.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
var
e: TEvent;
begin
if Assigned(fOnRemoveItem) then
for e in fOnRemoveItem do
e(self, aIndex, GetItem(aIndex));
inherited DeleteIntern(aIndex, aFreeItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomList.Create(aEqualityComparer: IEqualityComparer; const aOwnsObjects: Boolean);
begin
inherited Create(aEqualityComparer, aOwnsObjects);
fOnAddItem := TEventList.Create;
fOnRemoveItem := TEventList.Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlObservableCustomList.Destroy;
begin
FreeAndNil(fOnRemoveItem);
FreeAndNil(fOnAddItem);
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableList////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableList.Create(const aOwnsObjects: Boolean);
begin
inherited Create(TEqualityComparer.Create, aOwnsObjects);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomHashSet///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.InsertIntern(const aIndex: Integer; const aItem: T);
var
e: TEvent;
begin
inherited InsertIntern(aIndex, aItem);
if Assigned(fOnAddItem) then
for e in fOnAddItem do
e(self, aItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomHashSet.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
var
e: TEvent;
begin
if Assigned(fOnRemoveItem) then
for e in fOnRemoveItem do
e(self, GetItem(aIndex));
inherited DeleteIntern(aIndex, aFreeItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomHashSet.Create(aComparer: IComparer; const aOwnsObjects: Boolean);
begin
inherited Create(aComparer, aOwnsObjects);
fOnAddItem := TEventList.Create;
fOnRemoveItem := TEventList.Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlObservableCustomHashSet.Destroy;
begin
inherited Destroy; // calls clear -> Free EventLists after
FreeAndNil(fOnAddItem);
FreeAndNil(fOnRemoveItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableHashSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableHashSet.Create(const aOwnsObjects: Boolean);
begin
inherited Create(TComparer.Create, aOwnsObjects);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableCustomMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.TObservableHashSet.InsertIntern(const aIndex: Integer; const aItem: TKeyValuePair);
var
e: TEvent;
begin
inherited InsertIntern(aIndex, aItem);
if Assigned(fOnAddItem) then begin
for e in fOnAddItem do
e(fOwner, aItem.Key, aItem.Value);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlObservableCustomMap.TObservableHashSet.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean);
var
e: TEvent;
tmp: TKeyValuePair;
begin
if Assigned(fOnRemoveItem) then begin
tmp := GetItem(aIndex);
for e in fOnRemoveItem do
e(fOwner, tmp.Key, tmp.Value);
end;
inherited DeleteIntern(aIndex, aFreeItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomMap.TObservableHashSet.Create(const aOwner: TObject; const aComparer: IComparer; const aOwnsObjects: Boolean);
begin
inherited Create(aComparer, aOwnsObjects);
fOwner := aOwner;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableCustomMap.Create(const aComparer: IComparer; const aOwnsObjects: Boolean);
begin
fOnAddItem := TEventList.Create;
fOnRemoveItem := TEventList.Create;
fHashSetImpl := TObservableHashSet.Create(self, aComparer, aOwnsObjects);
fHashSetImpl.OnAddItem := fOnAddItem;
fHashSetImpl.OnRemoveItem := fOnRemoveItem;
inherited Create(fHashSetImpl);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlObservableCustomMap.Destroy;
begin
inherited Destroy;
FreeAndNil(fHashSetImpl);
FreeAndNil(fOnAddItem);
FreeAndNil(fOnRemoveItem);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlObservableMap/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlObservableMap.Create(const aOwnsObjects: Boolean);
begin
inherited Create(TComparer.Create, aOwnsObjects);
end;

end.


正在加载...
取消
保存