فهرست منبع

[collections] IList<T> and IObjectList<T> with Linq inherited search

Exilon 5 سال پیش
والد
کامیت
f502e41fed
1فایلهای تغییر یافته به همراه511 افزوده شده و 0 حذف شده
  1. 511 0
      Quick.Collections.pas

+ 511 - 0
Quick.Collections.pas

@@ -0,0 +1,511 @@
+{ ***************************************************************************
+
+  Copyright (c) 2016-2020 Kike Pérez
+
+  Unit        : Quick.Collections
+  Description : Generic Collections
+  Author      : Kike Pérez
+  Version     : 1.2
+  Created     : 07/03/2020
+  Modified    : 20/03/2020
+
+  This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+ ***************************************************************************
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ *************************************************************************** }
+
+unit Quick.Collections;
+
+{$i QuickLib.inc}
+
+interface
+
+uses
+  System.SysUtils,
+  TypInfo,
+  System.Types,
+  System.Generics.Defaults,
+  System.Generics.Collections,
+  Quick.Linq;
+
+type
+
+  IListBase<T> = interface
+  ['{9A9B2DB9-14E4-49DD-A628-F84F50539F41}']
+    function GetList: TArray<T>;
+    function GetCapacity: Integer;
+    procedure SetCapacity(Value: Integer); overload;
+    function GetCount : Integer;
+    procedure SetCount(Value: Integer);
+    function GetItem(Index: Integer): T;
+    procedure SetItem(Index: Integer; const Value: T);
+    function GetEnumerator : TEnumerator<T>;
+    function Add(const Value: T): Integer;
+    procedure AddRange(const Values: array of T); overload;
+    procedure AddRange(const Collection: IEnumerable<T>); overload;
+    procedure AddRange(const Collection: TEnumerable<T>); overload;
+    procedure Insert(Index: Integer; const Value: T);
+    procedure InsertRange(Index: Integer; const Values: array of T; Count: Integer); overload;
+    procedure InsertRange(Index: Integer; const Values: array of T); overload;
+    procedure InsertRange(Index: Integer; const Collection: IEnumerable<T>); overload;
+    procedure InsertRange(Index: Integer; const Collection: TEnumerable<T>); overload;
+    function Remove(const Value: T): Integer;
+    function RemoveItem(const Value: T; Direction: TDirection): Integer;
+    procedure Delete(Index: Integer);
+    procedure DeleteRange(AIndex, ACount: Integer);
+    function ExtractItem(const Value: T; Direction: TDirection): T;
+    function Extract(const Value: T): T;
+    function ExtractAt(Index: Integer): T;
+    procedure Exchange(Index1, Index2: Integer);
+    procedure Move(CurIndex, NewIndex: Integer);
+    function First: T;
+    function Last: T;
+    procedure Clear;
+    function Contains(const Value: T): Boolean;
+    function IndexOf(const Value: T): Integer;
+    function IndexOfItem(const Value: T; Direction: TDirection): Integer;
+    function LastIndexOf(const Value: T): Integer;
+    procedure Reverse;
+    procedure Sort; overload;
+    procedure Sort(const AComparer: IComparer<T>); overload;
+    function BinarySearch(const Item: T; out Index: Integer): Boolean; overload;
+    function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer<T>): Boolean; overload;
+    procedure TrimExcess;
+    function ToArray: TArray<T>;
+    procedure FromList(const aList : TList<T>);
+    function ToList : TList<T>;
+    property Capacity: Integer read GetCapacity write SetCapacity;
+    property Count: Integer read GetCount write SetCount;
+    property Items[Index: Integer]: T read GetItem write SetItem; default;
+    property List: TArray<T> read GetList;
+    function Any : Boolean; overload;
+  end;
+
+  IList<T> = interface(IListBase<T>)
+  ['{78952BD5-7D15-42BB-ADCB-2F835DF879A0}']
+    function Any(const aMatchString : string; aUseRegEx : Boolean) : Boolean; overload;
+    function Where(const aMatchString : string; aUseRegEx : Boolean) : ILinqArray<T>; overload;
+    function Where(const aWhereClause : string; aWhereValues : array of const) : ILinqQuery<T>; overload;
+    function Where(const aWhereClause: string): ILinqQuery<T>; overload;
+    {$IFNDEF FPC}
+    function Where(aPredicate : TPredicate<T>) : ILinqQuery<T>; overload;
+    {$ENDIF}
+  end;
+
+  IObjectList<T : class> = interface(IListBase<T>)
+  ['{7380847B-9F94-4FB8-8B73-DC8ACAFF1729}']
+    function Any(const aWhereClause : string; aValues : array of const) : Boolean; overload;
+    function Where(const aWhereClause : string; aWhereValues : array of const) : ILinqQuery<T>; overload;
+    function Where(const aWhereClause: string): ILinqQuery<T>; overload;
+    function Where(aPredicate : TPredicate<T>): ILinqQuery<T>; overload;
+  end;
+
+  TXList<T> = class(TInterfacedObject,IList<T>)
+  private type
+    arrayofT = array of T;
+  private
+    fList : TList<T>;
+    function GetList: TArray<T>;
+    function GetCapacity: Integer;
+    procedure SetCapacity(Value: Integer); overload;
+    function GetCount : Integer;
+    procedure SetCount(Value: Integer);
+    function GetItem(Index: Integer): T;
+    procedure SetItem(Index: Integer; const Value: T);
+    function GetEnumerator : TEnumerator<T>;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    function Add(const Value: T): Integer; inline;
+    procedure AddRange(const Values: array of T); overload;
+    procedure AddRange(const Collection: IEnumerable<T>); overload; inline;
+    procedure AddRange(const Collection: TEnumerable<T>); overload;
+    procedure Insert(Index: Integer; const Value: T); inline;
+    procedure InsertRange(Index: Integer; const Values: array of T; Count: Integer); overload;
+    procedure InsertRange(Index: Integer; const Values: array of T); overload;
+    procedure InsertRange(Index: Integer; const Collection: IEnumerable<T>); overload;
+    procedure InsertRange(Index: Integer; const Collection: TEnumerable<T>); overload;
+    function Remove(const Value: T): Integer; inline;
+    function RemoveItem(const Value: T; Direction: TDirection): Integer; inline;
+    procedure Delete(Index: Integer); inline;
+    procedure DeleteRange(AIndex, ACount: Integer); inline;
+    function ExtractItem(const Value: T; Direction: TDirection): T; inline;
+    function Extract(const Value: T): T; inline;
+    function ExtractAt(Index: Integer): T; inline;
+    procedure Exchange(Index1, Index2: Integer); inline;
+    procedure Move(CurIndex, NewIndex: Integer); inline;
+    function First: T; inline;
+    function Last: T; inline;
+    procedure Clear; inline;
+    function Contains(const Value: T): Boolean; inline;
+    function IndexOf(const Value: T): Integer; inline;
+    function IndexOfItem(const Value: T; Direction: TDirection): Integer; inline;
+    function LastIndexOf(const Value: T): Integer; inline;
+    procedure Reverse; inline;
+    procedure Sort; overload; inline;
+    procedure Sort(const AComparer: IComparer<T>); overload; inline;
+    function BinarySearch(const Item: T; out Index: Integer): Boolean; overload; inline;
+    function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer<T>): Boolean; overload; inline;
+    procedure TrimExcess; inline;
+    function ToArray: TArray<T>; inline;
+    property Capacity: Integer read GetCapacity write SetCapacity;
+    property Count: Integer read GetCount write SetCount;
+    property Items[Index: Integer]: T read GetItem write SetItem; default;
+    property List: arrayofT read GetList;
+    procedure FromList(const aList : TList<T>);
+    function ToList : TList<T>;
+    function Any : Boolean; overload; virtual;
+    function Where(const aWhereClause : string; aWhereValues : array of const) : ILinqQuery<T>; overload;
+    function Where(const aWhereClause: string): ILinqQuery<T>; overload;
+    function Any(const aMatchString : string; aUseRegEx : Boolean) : Boolean; overload;
+    function Where(const aMatchString : string; aUseRegEx : Boolean) : ILinqArray<T>; overload;
+    {$IFNDEF FPC}
+    function Where(aPredicate : TPredicate<T>) : ILinqQuery<T>; overload;
+    {$ENDIF}
+  end;
+
+  TXObjectList<T : class> = class(TXList<T>,IObjectList<T>)
+  private
+    fOwnsObjects : Boolean;
+    procedure InternalOnNotify(Sender: TObject; const Item: T; Action: TCollectionNotification);
+  public
+    constructor Create(aOwnedObjects : Boolean = True);
+    destructor Destroy; override;
+    function Any(const aWhereClause : string; aValues : array of const) : Boolean; overload;
+    function Where(const aWhereClause : string; aWhereValues : array of const) : ILinqQuery<T>; overload;
+    function Where(const aWhereClause: string): ILinqQuery<T>; overload;
+    function Where(aPredicate : TPredicate<T>): ILinqQuery<T>; overload;
+  end;
+
+  ECollectionError = class(Exception);
+  ECollectionNotSupported = class(Exception);
+
+implementation
+
+
+
+{ TXList<T> }
+
+constructor TXList<T>.Create;
+begin
+  fList := TList<T>.Create;
+end;
+
+destructor TXList<T>.Destroy;
+begin
+  fList.Free;
+  inherited;
+end;
+
+function TXList<T>.Add(const Value: T): Integer;
+begin
+  Result := fList.Add(Value);
+end;
+
+procedure TXList<T>.AddRange(const Values: array of T);
+begin
+  fList.AddRange(Values);
+end;
+
+procedure TXList<T>.AddRange(const Collection: IEnumerable<T>);
+begin
+  fList.AddRange(Collection);
+end;
+
+procedure TXList<T>.AddRange(const Collection: TEnumerable<T>);
+begin
+  fList.AddRange(Collection);
+end;
+
+function TXList<T>.Any(const aMatchString: string;
+  aUseRegEx: Boolean): Boolean;
+begin
+
+end;
+
+function TXList<T>.Any: Boolean;
+begin
+  Result := fList.Count > 0;
+end;
+
+function TXList<T>.BinarySearch(const Item: T; out Index: Integer): Boolean;
+begin
+  Result := fList.BinarySearch(Item,Index);
+end;
+
+function TXList<T>.BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer<T>): Boolean;
+begin
+  Result := fList.BinarySearch(Item,Index,AComparer);
+end;
+
+procedure TXList<T>.Clear;
+begin
+  fList.Clear;
+end;
+
+function TXList<T>.Contains(const Value: T): Boolean;
+begin
+  Result := fList.Contains(Value);
+end;
+
+procedure TXList<T>.Delete(Index: Integer);
+begin
+  fList.Delete(Index);
+end;
+
+procedure TXList<T>.DeleteRange(AIndex, ACount: Integer);
+begin
+  fList.DeleteRange(aIndex,aCount);
+end;
+
+procedure TXList<T>.Exchange(Index1, Index2: Integer);
+begin
+  fList.Exchange(Index1,Index2);
+end;
+
+function TXList<T>.Extract(const Value: T): T;
+begin
+  Result := fList.Extract(Value);
+end;
+
+function TXList<T>.ExtractAt(Index: Integer): T;
+begin
+  Result := fList.ExtractAt(Index);
+end;
+
+function TXList<T>.ExtractItem(const Value: T; Direction: TDirection): T;
+begin
+  Result := fList.ExtractItem(Value,Direction);
+end;
+
+function TXList<T>.First: T;
+begin
+  Result := fList.First;
+end;
+
+procedure TXList<T>.FromList(const aList: TList<T>);
+var
+  value : T;
+begin
+  for value in aList do fList.Add(value);
+end;
+
+function TXList<T>.GetCapacity: Integer;
+begin
+  Result := fList.Capacity;
+end;
+
+function TXList<T>.GetCount: Integer;
+begin
+  Result := fList.Count;
+end;
+
+function TXList<T>.GetEnumerator: TEnumerator<T>;
+begin
+  Result := fList.GetEnumerator;
+end;
+
+function TXList<T>.GetItem(Index: Integer): T;
+begin
+  Result := fList.Items[Index];
+end;
+
+function TXList<T>.GetList: TArray<T>;
+begin
+  Result := fList.ToArray;
+end;
+
+function TXList<T>.IndexOf(const Value: T): Integer;
+begin
+  Result := fList.IndexOf(Value);
+end;
+
+function TXList<T>.IndexOfItem(const Value: T; Direction: TDirection): Integer;
+begin
+  Result := fList.IndexOfItem(Value,Direction);
+end;
+
+procedure TXList<T>.Insert(Index: Integer; const Value: T);
+begin
+  fList.Insert(Index,Value);
+end;
+
+procedure TXList<T>.InsertRange(Index: Integer; const Collection: IEnumerable<T>);
+begin
+  fList.InsertRange(Index,Collection);
+end;
+
+procedure TXList<T>.InsertRange(Index: Integer; const Collection: TEnumerable<T>);
+begin
+  fList.InsertRange(index,Collection);
+end;
+
+procedure TXList<T>.InsertRange(Index: Integer; const Values: array of T; Count: Integer);
+begin
+  fList.InsertRange(Index,Values,Count);
+end;
+
+procedure TXList<T>.InsertRange(Index: Integer; const Values: array of T);
+begin
+  fList.InsertRange(index,Values);
+end;
+
+function TXList<T>.Last: T;
+begin
+  Result := fList.Last;
+end;
+
+function TXList<T>.LastIndexOf(const Value: T): Integer;
+begin
+  Result := fList.LastIndexOf(Value);
+end;
+
+procedure TXList<T>.Move(CurIndex, NewIndex: Integer);
+begin
+  fList.Move(CurIndex,NewIndex);
+end;
+
+function TXList<T>.Remove(const Value: T): Integer;
+begin
+  Result := fList.Remove(Value);
+end;
+
+function TXList<T>.RemoveItem(const Value: T; Direction: TDirection): Integer;
+begin
+  Result := fList.RemoveItem(Value,Direction);
+end;
+
+procedure TXList<T>.Reverse;
+begin
+  fList.Reverse;
+end;
+
+procedure TXList<T>.SetCapacity(Value: Integer);
+begin
+  fList.Capacity := Value;
+end;
+
+procedure TXList<T>.SetCount(Value: Integer);
+begin
+  fList.Count := Value;
+end;
+
+procedure TXList<T>.SetItem(Index: Integer; const Value: T);
+begin
+  fList.Items[Index] := Value;
+end;
+
+procedure TXList<T>.Sort(const AComparer: IComparer<T>);
+begin
+  fList.Sort(AComparer);
+end;
+
+procedure TXList<T>.Sort;
+begin
+  fList.Sort;
+end;
+
+function TXList<T>.ToArray: TArray<T>;
+begin
+  Result := fList.ToArray;
+end;
+
+function TXList<T>.ToList: TList<T>;
+var
+  value : T;
+begin
+  Result := TList<T>.Create;
+  for value in fList do Result.Add(value);    
+end;
+
+procedure TXList<T>.TrimExcess;
+begin
+  fList.TrimExcess;
+end;
+
+function TXList<T>.Where(const aMatchString: string; aUseRegEx: Boolean): ILinqArray<T>;
+begin
+  Result := TLinqArray<T>.Create(fList.ToArray);
+  Result.Where(aMatchString, aUseRegEx);
+end;
+
+function TXList<T>.Where(const aWhereClause: string; aWhereValues: array of const): ILinqQuery<T>;
+begin
+  if PTypeInfo(typeInfo(T)).Kind <> tkClass then raise ECollectionNotSupported.Create('TXList<T>.Where only supports classes. Use MatchString overload method instead!');
+  Result := TLinqQuery<TObject>.Create(TObjectList<TObject>(Self.fList)).Where(aWhereClause,aWhereValues) as ILinqQuery<T>;
+end;
+
+function TXList<T>.Where(const aWhereClause: string): ILinqQuery<T>;
+begin
+  if PTypeInfo(typeInfo(T)).Kind <> tkClass then raise ECollectionNotSupported.Create('TXList<T>.Where only supports classes. Use MatchString overload method instead!');
+  Result := TLinqQuery<TObject>.Create(TObjectList<TObject>(Self.fList)).Where(aWhereClause) as ILinqQuery<T>;
+end;
+
+function TXList<T>.Where(aPredicate: TPredicate<T>): ILinqQuery<T>;
+begin
+  if PTypeInfo(typeInfo(T)).Kind <> tkClass then raise ECollectionNotSupported.Create('TXList<T>.Where only supports classes. Use MatchString overload method instead!');
+  Result := TLinqQuery<TObject>.Create(TObjectList<TObject>(Self.fList)).Where(TPredicate<TObject>(aPredicate)) as ILinqQuery<T>;
+end;
+
+{ TXObjectList<T> }
+
+function TXObjectList<T>.Any(const aWhereClause: string; aValues: array of const): Boolean;
+var
+  query : ILinqQuery<T>;
+begin
+  query := TLinqQuery<T>.Create(Self.fList);
+  Result := query.Where(aWhereClause,aValues).Count > 0;
+end;
+
+constructor TXObjectList<T>.Create(aOwnedObjects: Boolean);
+begin
+  inherited Create;
+  fOwnsObjects := aOwnedObjects;
+  fList.OnNotify := InternalOnNotify;
+end;
+
+destructor TXObjectList<T>.Destroy;
+begin
+
+  inherited;
+end;
+
+procedure TXObjectList<T>.InternalOnNotify(Sender: TObject; const Item: T; Action: TCollectionNotification);
+begin
+  if (fOwnsObjects) and (Action = TCollectionNotification.cnRemoved) then
+  begin
+    if Assigned(Item) then Item.DisposeOf;
+    //if PTypeInfo(typeInfo(T)).Kind = tkClass then
+    //PObject(@Item).DisposeOf;
+  end;
+end;
+
+function TXObjectList<T>.Where(const aWhereClause: string): ILinqQuery<T>;
+begin
+    Result := TLinqQuery<T>.Create(Self.fList).Where(aWhereClause);
+end;
+
+function TXObjectList<T>.Where(const aWhereClause: string; aWhereValues: array of const): ILinqQuery<T>;
+begin
+  Result := TLinqQuery<T>.Create(Self.fList).Where(aWhereClause,aWhereValues);
+end;
+
+function TXObjectList<T>.Where(aPredicate: TPredicate<T>): ILinqQuery<T>;
+begin
+  Result := TLinqQuery<T>.Create(Self.fList).Where(aPredicate);
+end;
+
+end.