|
- unit uutlEnumerator;
-
- {$mode objfpc}{$H+}
-
- interface
-
- uses
- Classes, SysUtils,
- uutlInterfaces;
-
- type
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlEnumerator<T> = class(
- TInterfacedObject,
- specialize IutlEnumerator<T>)
-
- public type
- IEnumerator = specialize IutlEnumerator<T>;
- IFilter = specialize IutlFilter<T>;
- TArray = specialize TGenericArray<T>;
-
- public { IEnumerator }
- function GetCurrent: T; virtual; abstract;
- function MoveNext: Boolean; virtual; abstract;
- procedure Reset; virtual; abstract;
-
- public { IutlEnumerator }
- function GetEnumerator: IEnumerator; virtual;
-
- function Count: Integer; virtual;
-
- function Reverse: IEnumerator; virtual;
- function Skip (const aCount: Integer): IEnumerator; virtual;
- function Take (const aCount: Integer): IEnumerator; virtual;
- function Where(const aFilter: IFilter): IEnumerator; virtual;
-
- function ToArray: TArray; virtual;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlMemoryEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- public type
- PT = ^T;
-
- strict private
- fReverse: Boolean;
- fMemory: PT;
- fCurrent: Integer;
- fCount: Integer;
-
- public { IEnumerator }
- function GetCurrent: T; override;
- function MoveNext: Boolean; override;
- procedure Reset; override;
-
- public { IutlEnumerator }
- function Count: Integer; override;
- function Reverse: IEnumerator; override;
-
- public
- constructor Create(const aMemory: PT; const aCount: Integer); overload;
- constructor Create(const aMemory: PT; const aCount: Integer; const aReverse: Boolean); overload;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlArrayEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- strict private
- fArray: TArray;
- fReverse: Boolean;
- fCurrent: Integer;
- fFirst: Integer;
- fLast: Integer;
-
- public { IEnumerator }
- function GetCurrent: T; override;
- function MoveNext: Boolean; override;
- procedure Reset; override;
-
- public { IutlEnumerator }
- function Count: Integer; override;
-
- function Reverse: IEnumerator; override;
- function Skip(const aCount: Integer): IEnumerator; override;
- function Take(const aCount: Integer): IEnumerator; override;
-
- function ToArray: TArray; override;
-
- public
- constructor Create(
- const aArray: TArray); overload;
- constructor Create(
- const aArray: TArray;
- const aReverse: Boolean;
- const aFirst: Integer;
- const aLast: Integer); overload;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlSkipTakeEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- strict private
- fEnumerator: IEnumerator;
- fSkip: Integer; // greater than 0: skip X; lower than 0: skip none
- fTake: Integer; // greater than 0: take X; lower than 0: take all
- fCurrentSkip: Integer;
- fCurrentTake: Integer;
-
- public { IEnumerator }
- function GetCurrent: T; override;
- function MoveNext: Boolean; override;
- procedure Reset; override;
-
- public
- constructor Create(const aEnumerator: IEnumerator; const aSkip: Integer; const aTake: Integer);
- destructor Destroy; override;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlWhereEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- strict private
- fEnumerator: IEnumerator;
- fFilter: IFilter;
-
- public { IEnumerator }
- function GetCurrent: T; override;
- function MoveNext: Boolean; override;
- procedure Reset; override;
-
- public
- constructor Create(const aEnumerator: IEnumerator; const aFilter: IFilter);
- destructor Destroy; override;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlSelectEnumerator<Tin, Tout> = class(
- specialize TutlEnumerator<Tout>)
-
- public type
- IInEnumerator = specialize IutlEnumerator<Tin>;
- ISelector = specialize IutlSelector<Tin, Tout>;
-
- strict private
- fEnumerator: IInEnumerator;
- fSelector: ISelector;
-
- public { IEnumerator }
- function GetCurrent: Tout; override;
- function MoveNext: Boolean; override;
- procedure Reset; override;
-
- public
- constructor Create(const aEnumerator: IInEnumerator; const aSelector: ISelector);
- destructor Destroy; override;
- end;
-
- implementation
-
- uses
- uutlExceptions;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.GetEnumerator: IEnumerator;
- begin
- result := self;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Reverse: IEnumerator;
- var
- arr: TArray;
- begin
- arr := ToArray;
- result := specialize TutlArrayEnumerator<T>.Create(arr, true, low(arr), high(arr));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Skip(const aCount: Integer): IEnumerator;
- begin
- result := specialize TutlSkipTakeEnumerator<T>.Create(self, aCount, -1);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Take(const aCount: Integer): IEnumerator;
- begin
- result := specialize TutlSkipTakeEnumerator<T>.Create(self, -1, aCount);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Where(const aFilter: IFilter): IEnumerator;
- begin
- result := specialize TutlWhereEnumerator<T>.Create(self, aFilter);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.ToArray: TArray;
- var
- i: Integer;
- arr: array of T;
- begin
- i := 0;
- SetLength(arr, i);
- Reset;
- while MoveNext do begin
- inc(i);
- SetLength(arr, i);
- arr[i-1] := GetCurrent;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Count: Integer;
- begin
- result := 0;
- Reset;
- while MoveNext do
- inc(result);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlMemoryEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.GetCurrent: T;
- var
- p: PT;
- begin
- if (fCurrent < 0) or (fCurrent >= fCount) then
- raise EutlInvalidOperation.Create('enumerator is not initialized');
- p := fMemory;
- if fReverse
- then inc(p, fCount - fCurrent - 1)
- else inc(p, fCurrent);
- result := p^;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.MoveNext: Boolean;
- begin
- inc(fCurrent);
- result := (fCurrent < fCount);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlMemoryEnumerator.Reset;
- begin
- fCurrent := -1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.Count: Integer;
- begin
- result := fCount;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.Reverse: IEnumerator;
- begin
- result := TutlMemoryEnumerator.Create(fMemory, fCount, not fReverse);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlMemoryEnumerator.Create(const aMemory: PT; const aCount: Integer);
- begin
- Create(aMemory, aCount, false);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlMemoryEnumerator.Create(const aMemory: PT; const aCount: Integer; const aReverse: Boolean);
- begin
- inherited Create;
- fMemory := aMemory;
- fCount := aCount;
- fReverse := aReverse;
- fCurrent := -1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlArrayEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlArrayEnumerator.GetCurrent: T;
- begin
- if (fCurrent < fFirst) or (fCurrent > fLast) then
- raise EutlInvalidOperation.Create('enumerator is not initialized');
- result := fArray[fCurrent];
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlArrayEnumerator.MoveNext: Boolean;
- begin
- if fReverse
- then dec(fCurrent)
- else inc(fCurrent);
- result := (fFirst <= fCurrent) and (fCurrent <= fLast);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlArrayEnumerator.Reset;
- begin
- if fReverse
- then fCurrent := fLast + 1
- else fCurrent := fFirst - 1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlArrayEnumerator.Count: Integer;
- begin
- result := fLast - fFirst + 1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlArrayEnumerator.Reverse: IEnumerator;
- begin
- result := specialize TutlArrayEnumerator<T>.Create(fArray, not fReverse, fFirst, fLast);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlArrayEnumerator.Skip(const aCount: Integer): IEnumerator;
- begin
- if fReverse
- then result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fFirst, fLast - aCount)
- else result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fFirst + aCount, fLast);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlArrayEnumerator.Take(const aCount: Integer): IEnumerator;
- begin
- if fReverse
- then result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fLast - aCount + 1, fLast)
- else result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fFirst, fFirst + aCount - 1);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlArrayEnumerator.ToArray: TArray;
- var
- i: Integer;
- begin
- SetLength(result, fLast - fFirst + 1);
- if fReverse then begin
- for i := fFirst to fLast do
- result[i-fFirst] := fArray[i];
- end else
- System.Move(fArray[fFirst], result[0], Length(result));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlArrayEnumerator.Create(const aArray: TArray);
- begin
- Create(aArray, false, low(aArray), high(aArray));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlArrayEnumerator.Create(
- const aArray: TArray;
- const aReverse: Boolean;
- const aFirst: Integer;
- const aLast: Integer);
- begin
- inherited Create;
- fArray := aArray;
- fReverse := aReverse;
- fFirst := aFirst;
- fLast := aLast;
-
- if (fFirst < low(fArray)) then
- fFirst := low(fArray);
- if (fLast > high(fArray)) then
- fLast := high(fArray);
-
- if fReverse
- then fCurrent := fLast + 1
- else fCurrent := fFirst - 1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlSkipTakeEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlSkipTakeEnumerator.GetCurrent: T;
- begin
- result := fEnumerator.Current;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlSkipTakeEnumerator.MoveNext: Boolean;
- begin
- while (fCurrentSkip > 0) and fEnumerator.MoveNext do
- dec(fCurrentSkip);
- result :=
- (fCurrentSkip <= 0)
- and (fCurrentTake <> 0)
- and fEnumerator.MoveNext;
-
- if (fCurrentTake > 0) then
- dec(fCurrentTake);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlSkipTakeEnumerator.Reset;
- begin
- fEnumerator.Reset;
- fCurrentSkip := fSkip;
- fCurrentTake := fTake;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlSkipTakeEnumerator.Create(const aEnumerator: IEnumerator; const aSkip: Integer; const aTake: Integer);
- begin
- if not Assigned(aEnumerator) then
- raise EutlArgumentNil.Create('aEnumerator');
- inherited Create;
- fEnumerator := aEnumerator;
- fSkip := aSkip;
- fTake := aTake;
- fCurrentSkip := aSkip;
- fCurrentTake := aTake;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlSkipTakeEnumerator.Destroy;
- begin
- fEnumerator := nil;
- inherited Destroy;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlWhereEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlWhereEnumerator.GetCurrent: T;
- begin
- result := fEnumerator.Current;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlWhereEnumerator.MoveNext: Boolean;
- begin
- repeat
- result := fEnumerator.MoveNext;
- until not result or fFilter.Filter(fEnumerator.Current);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlWhereEnumerator.Reset;
- begin
- fEnumerator.Reset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlWhereEnumerator.Create(const aEnumerator: IEnumerator; const aFilter: IFilter);
- begin
- if not Assigned(aEnumerator) then
- raise EutlArgumentNil.Create('aEnumerator');
- if not Assigned(aFilter) then
- raise EutlArgumentNil.Create('aFilter');
- inherited Create;
- fEnumerator := aEnumerator;
- fFilter := aFilter;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlWhereEnumerator.Destroy;
- begin
- fEnumerator := nil;
- fFilter := nil;
- inherited Destroy;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlSelectEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlSelectEnumerator.GetCurrent: Tout;
- begin
- result := fSelector.Select(fEnumerator.Current);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlSelectEnumerator.MoveNext: Boolean;
- begin
- result := fEnumerator.MoveNext;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlSelectEnumerator.Reset;
- begin
- fEnumerator.Reset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlSelectEnumerator.Create(const aEnumerator: IInEnumerator; const aSelector: ISelector);
- begin
- if not Assigned(aEnumerator) then
- raise EutlArgumentNil.Create('aEnumerator');
- if not Assigned(aSelector) then
- raise EutlArgumentNil.Create('aSelector');
- inherited Create;
- fEnumerator := aEnumerator;
- fSelector := aSelector;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlSelectEnumerator.Destroy;
- begin
- fEnumerator := nil;
- fSelector := nil;
- inherited Destroy;
- end;
-
- end.
|