|
- unit uutlEnumerator;
-
- {$mode objfpc}{$H+}
-
- interface
-
- uses
- Classes, SysUtils,
- uutlTypes, uutlInterfaces
- {$IFDEF UTL_ADVANCED_ENUMERATORS}
- , uutlAlgorithm
- {$ENDIF}
- ;
-
- type
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlEnumerator<T> = class(
- TInterfacedObject
- , specialize IEnumerator<T>
- , specialize IutlEnumerator<T>)
-
- public type
- TStatus = (
- stCreated,
- stReseted,
- stMoving,
- stFinished
- );
-
- {$IFDEF UTL_ENUMERATORS}
- TArray = specialize TutlArray<T>;
- IutlEnumerator = specialize IutlEnumerator<T>;
- IEqualityComparer = specialize IutlEqualityComparer<T>;
- {$IFDEF UTL_ADVANCED_ENUMERATORS}
- IComparer = specialize IutlComparer<T>;
- IFilter = specialize IutlFilter<T>;
- {$ENDIF}
- {$ENDIF}
-
- strict private
- fStatus: TStatus;
- fAutoReset: Boolean;
-
- protected
- function InternalMoveNext: Boolean; virtual; abstract;
- procedure InternalReset; virtual; abstract;
-
- public { IEnumerator }
- function GetCurrent: T; virtual; abstract;
- function MoveNext: Boolean;
- procedure Reset;
-
- {$IFDEF UTL_ENUMERATORS}
- public { IutlEnumerator }
- function GetEnumerator: IutlEnumerator; virtual;
-
- function Count (): Integer; virtual;
- function Any (): Boolean; virtual;
- function ToArray (): TArray; virtual;
- function Contains (constref aElement: T; aComparer: IEqualityComparer): Boolean; virtual;
-
- function Skip (aCount: Integer): IutlEnumerator; virtual;
- function Take (aCount: Integer): IutlEnumerator; virtual;
- function Concat (aEnumerator: IutlEnumerator): IutlEnumerator; virtual;
- function Reverse (): IutlEnumerator; virtual;
- {$IFDEF UTL_ADVANCED_ENUMERATORS}
- function Sort (aComparer: IComparer): IutlEnumerator; virtual;
- function Where (aFilter: IFilter): IutlEnumerator; virtual;
- function Distinct (aComparer: IComparer): IutlEnumerator; virtual;
- function Intersect(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator; virtual;
- function Union (aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator; virtual;
- function Without (aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator; virtual;
- {$ENDIF}
- {$ENDIF}
-
- public
- property Status: TStatus read fStatus;
- property AutoReset: Boolean read fAutoReset write fAutoReset;
-
- constructor Create;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlMemoryEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- public type
- PT = ^T;
-
- strict private
- fMemory: PT;
- fReversed: Boolean;
- fCurrent: Integer;
- fFirst: Integer;
- fLast: Integer;
-
- protected
- property Memory: PT read fMemory write fMemory;
- property Reversed: Boolean read fReversed write fReversed;
- property Current: Integer read fCurrent write fCurrent;
- property First: Integer read fFirst write fFirst;
- property Last: Integer read fLast write fLast;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: T; override;
-
- {$IFDEF UTL_ADVANCED_ENUMERATORS}
- public { IutlEnumerator }
- function Count (): Integer; override;
- function Any (): Boolean; override;
- function ToArray (): TArray; override;
- {$ENDIF}
-
- public
- constructor Create(
- const aMemory: PT;
- const aCount: Integer); overload;
- constructor Create(
- const aMemory: PT;
- const aReversed: Boolean;
- const aFirst: Integer;
- const aLast: Integer); overload;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- generic TutlArrayEnumerator<T> = class(
- specialize TutlMemoryEnumerator<T>)
-
- {$IFNDEF UTL_ENUMERATORS}
- public type
- TArray = specialize TutlArray<T>;
- {$ENDIF}
-
- strict private
- fData: TArray;
-
- public { IEnumerator }
- procedure InternalReset; override;
-
- public
- property Data: TArray read fData write fData;
-
- constructor Create; overload;
- constructor Create(const aData: TArray); overload;
- constructor Create(const aData: TArray; const aReversed: Boolean); overload;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ENUMERATORS}
- generic TutlReverseEnumerator<T> = class(
- specialize TutlArrayEnumerator<T>)
-
- strict private
- fEnumerator: IutlEnumerator;
-
- public { IEnumerator }
- procedure InternalReset; override;
-
- public
- constructor Create(aEnumerator: IutlEnumerator); reintroduce;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- generic TutlSortEnumerator<T> = class(
- specialize TutlArrayEnumerator<T>)
-
- strict private
- fEnumerator: IutlEnumerator;
- fComparer: IComparer;
-
- public { IEnumerator }
- procedure InternalReset; override;
-
- public
- constructor Create(aEnumerator: IutlEnumerator; aComparer: IComparer); reintroduce;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- generic TutlDistinctEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- strict private
- fEnumerator: IutlEnumerator;
- fComparer: IComparer;
- fCurrent: T;
- fData: array of T;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: T; override;
-
- public
- constructor Create(aEnumerator: IutlEnumerator; aComparer: IComparer); reintroduce;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- generic TutlIntersectWithoutEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- strict private
- fWithoutMode: Boolean;
- fEnumerator: IutlEnumerator;
- fOther: IutlEnumerator;
- fComparer: IComparer;
- fData: array of T;
- fCurrent: T;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: T; override;
-
- public
- constructor Create(
- const aWithoutMode: Boolean;
- aEnumerator: IutlEnumerator;
- aOther: IutlEnumerator;
- aComparer: IComparer); reintroduce;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ENUMERATORS}
- generic TutlSkipTakeEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- strict private
- fEnumerator: IutlEnumerator;
- 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;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: T; override;
-
- public
- constructor Create(aEnumerator: IutlEnumerator; const aSkip: Integer; const aTake: Integer);
- destructor Destroy; override;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- generic TutlWhereEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- strict private
- fEnumerator: IutlEnumerator;
- fFilter: IFilter;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: T; override;
-
- public
- constructor Create(aEnumerator: IutlEnumerator; aFilter: IFilter);
- destructor Destroy; override;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- 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;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: Tout; override;
-
- public
- constructor Create(aEnumerator: IInEnumerator; aSelector: ISelector);
- destructor Destroy; override;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- generic TutlSelectManyEnumerator<Tin, Tout> = class(
- specialize TutlEnumerator<Tout>)
-
- public type
- IInEnumerator = specialize IutlEnumerator<Tin>;
- IOutEnumerator = specialize IutlEnumerator<Tout>;
- ISelector = specialize IutlSelector<Tin, IOutEnumerator>;
-
- strict private
- fEnumerator: IInEnumerator;
- fSelector: ISelector;
- fCurrent: IOutEnumerator;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: Tout; override;
-
- public
- constructor Create(aEnumerator: IInEnumerator; aSelector: ISelector);
- destructor Destroy; override;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- generic TutlZipEnumerator<T, S> = class(
- specialize TutlEnumerator<specialize TutlPair<T, S>>)
-
- public type
- IEnumeratorT = specialize IutlEnumerator<T>;
- IEnumeratorS = specialize IutlEnumerator<S>;
- TPair = specialize TutlPair<T, S>;
-
- strict private
- fEnumeratorT: IEnumeratorT;
- fEnumeratorS: IEnumeratorS;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: TPair; override;
-
- public
- constructor Create(aEnumeratorT: IEnumeratorT; aEnumeratorS: IEnumeratorS);
- destructor Destroy; override;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ENUMERATORS}
- generic TutlConcatEnumerator<T> = class(
- specialize TutlEnumerator<T>)
-
- public type
- TEnumerators = array of IutlEnumerator;
-
- strict private
- fEnumerators: TEnumerators;
- fCurrent: Integer;
-
- protected { TutlEnumerator }
- function InternalMoveNext: Boolean; override;
- procedure InternalReset; override;
-
- public { IEnumerator }
- function GetCurrent: T; override;
-
- public
- constructor Create(aEnumerators: TEnumerators);
- destructor Destroy; override;
- end;
- {$ENDIF}
-
- implementation
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.MoveNext: Boolean;
- begin
- if (fStatus = stCreated)
- or ( fAutoReset
- and (fStatus = stFinished))
- then
- Reset;
- result := InternalMoveNext;
- if not result then
- fStatus := stFinished
- else if (fStatus = stReseted) then
- fStatus := stMoving;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlEnumerator.Reset;
- begin
- InternalReset;
- fStatus := stReseted;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ENUMERATORS}
- function TutlEnumerator.GetEnumerator: IutlEnumerator;
- begin
- result := self;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Count: Integer;
- begin
- result := 0;
- Reset;
- while MoveNext do
- inc(result);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Any: Boolean;
- begin
- Reset;
- result := MoveNext;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.ToArray: TArray;
- var
- i: Integer;
- begin
- i := 0;
- SetLength(result, i);
- Reset;
- while MoveNext do begin
- inc(i);
- SetLength(result, i);
- result[i-1] := GetCurrent;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Contains(constref aElement: T; aComparer: IEqualityComparer): Boolean;
- begin
- Reset;
- result := false;
- while MoveNext and not result do
- result := aComparer.EqualityCompare(aElement, GetCurrent);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Skip(aCount: Integer): IutlEnumerator;
- begin
- result := specialize TutlSkipTakeEnumerator<T>.Create(self, aCount, -1);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Take(aCount: Integer): IutlEnumerator;
- begin
- result := specialize TutlSkipTakeEnumerator<T>.Create(self, -1, aCount);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Concat(aEnumerator: IutlEnumerator): IutlEnumerator;
- type
- TConcatEnumerator = specialize TutlConcatEnumerator<T>;
- begin
- result := TConcatEnumerator.Create(TConcatEnumerator.TEnumerators.Create(self, aEnumerator));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Reverse: IutlEnumerator;
- begin
- result := specialize TutlReverseEnumerator<T>.Create(self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ADVANCED_ENUMERATORS}
- function TutlEnumerator.Sort(aComparer: IComparer): IutlEnumerator;
- begin
- result := specialize TutlSortEnumerator<T>.Create(self, aComparer);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Where(aFilter: IFilter): IutlEnumerator;
- begin
- result := specialize TutlWhereEnumerator<T>.Create(self, aFilter);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Distinct(aComparer: IComparer): IutlEnumerator;
- begin
- result := specialize TutlDistinctEnumerator<T>.Create(self, aComparer);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Intersect(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator;
- begin
- result := specialize TutlIntersectWithoutEnumerator<T>.Create(false, self, aEnumerator, aComparer);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Union(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator;
- begin
- result := Concat(aEnumerator).Distinct(aComparer);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlEnumerator.Without(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator;
- begin
- result := specialize TutlIntersectWithoutEnumerator<T>.Create(true, self, aEnumerator, aComparer);
- end;
- {$ENDIF}
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlEnumerator.Create;
- begin
- inherited Create;
- fStatus := stCreated;
- fAutoReset := false;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlMemoryEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.InternalMoveNext: Boolean;
- begin
- if fReversed
- then dec(fCurrent)
- else inc(fCurrent);
- result := (fFirst <= fCurrent) and (fCurrent <= fLast);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlMemoryEnumerator.InternalReset;
- begin
- if fReversed
- then fCurrent := fLast + 1
- else fCurrent := fFirst - 1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.{%H-}GetCurrent: T;
- begin
- if not Assigned(fMemory) or (fCurrent < fFirst) or (fCurrent > fLast) then
- raise EInvalidOperation.Create('enumerator is not initialized');
- result := (fMemory + fCurrent)^;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ADVANCED_ENUMERATORS}
- function TutlMemoryEnumerator.Count: Integer;
- begin
- Reset;
- result := fLast - fFirst + 1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.Any: Boolean;
- begin
- Reset;
- result := fFirst <= fLast;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlMemoryEnumerator.ToArray: TArray;
- var
- i: Integer;
- begin
- Reset;
- SetLength(result, fLast - fFirst + 1);
- if fReversed then begin
- for i := fFirst to fLast do
- result[i-fFirst] := fMemory[i];
- end else
- System.Move(fMemory^, result[0], SizeOf(T) * Length(result));
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlMemoryEnumerator.Create(const aMemory: PT; const aCount: Integer);
- begin
- Create(aMemory, false, 0, aCount - 1);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlMemoryEnumerator.Create(
- const aMemory: PT;
- const aReversed: Boolean;
- const aFirst: Integer;
- const aLast: Integer);
- begin
- fMemory := aMemory;
- fReversed := aReversed;
- fFirst := aFirst;
- fLast := aLast;
- inherited Create;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlArrayEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlArrayEnumerator.InternalReset;
- begin
- Memory := @fData[0];
- First := low(fData);
- Last := high(fData);
- inherited InternalReset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlArrayEnumerator.Create;
- begin
- inherited Create(nil, false, 0, -1);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlArrayEnumerator.Create(const aData: TArray);
- begin
- Create(aData, false);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlArrayEnumerator.Create(const aData: TArray; const aReversed: Boolean);
- begin
- fData := aData;
- inherited Create(@fData[0], aReversed, low(fData), high(fData));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlReverseEnumerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ENUMERATORS}
- procedure TutlReverseEnumerator.InternalReset;
- begin
- Data := fEnumerator.ToArray;
- Reversed := true;
- inherited InternalReset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlReverseEnumerator.Create(aEnumerator: IutlEnumerator);
- begin
- inherited Create;
- fEnumerator := aEnumerator;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlSortEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- procedure TutlSortEnumerator.InternalReset;
- type
- TBinarySearch = specialize TutlBinarySearch<T>;
- var
- c, i: Integer;
- tmp: T;
- arr: TArray;
- begin
- c := 0;
- SetLength(arr, c);
- fEnumerator.Reset;
- while fEnumerator.MoveNext do begin
- tmp := fEnumerator.GetCurrent;
- TBinarySearch.Search(arr[0], c, fComparer, tmp, i);
- inc(c);
- SetLength(arr, c);
- Move(arr[i], arr[i+1], SizeOf(T) * (Length(arr) - i - 1));
- FillByte(arr[i], SizeOf(T), 0);
- arr[i] := tmp;
- end;
- Data := arr;
- First := low(arr);
- Last := high(arr);
- inherited InternalReset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlSortEnumerator.Create(aEnumerator: IutlEnumerator; aComparer: IComparer);
- begin
- inherited Create;
- fEnumerator := aEnumerator;
- fComparer := aComparer;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlDistinctEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- function TutlDistinctEnumerator.InternalMoveNext: Boolean;
- type
- TBinarySearch = specialize TutlBinarySearch<T>;
- var
- i: Integer;
- begin
- result := false;
- while not result and fEnumerator.MoveNext do begin
- fCurrent := fEnumerator.GetCurrent;
- result := not TBinarySearch.Search(fData[0], Length(fData), fComparer, fCurrent, i);
- if result then begin
- SetLength(fData, Length(fData) + 1);
- Move(fData[i], fData[i+1], SizeOf(T) * (Length(fData) - i - 1));
- FillByte(fData[i], SizeOf(T), 0);
- fData[i] := fCurrent;
- end;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlDistinctEnumerator.InternalReset;
- begin
- SetLength(fData, 0);
- fEnumerator.Reset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlDistinctEnumerator.GetCurrent: T;
- begin
- result := fCurrent;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlDistinctEnumerator.Create(aEnumerator: IutlEnumerator; aComparer: IComparer);
- begin
- inherited Create;
- fEnumerator := aEnumerator;
- fComparer := aComparer;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlIntersectWithoutEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- function TutlIntersectWithoutEnumerator.InternalMoveNext: Boolean;
- type
- TBinarySearch = specialize TutlBinarySearch<T>;
- var
- i: Integer;
- begin
- result := false;
- while not result and fEnumerator.MoveNext do begin
- fCurrent := fEnumerator.GetCurrent;
- result := TBinarySearch.Search(fData[0], Length(fData), fComparer, fCurrent, i);
- if fWithoutMode then
- result := not result;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlIntersectWithoutEnumerator.InternalReset;
- begin
- fEnumerator.Reset;
- fData := fOther.Distinct(fComparer).Sort(fComparer).ToArray();
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlIntersectWithoutEnumerator.GetCurrent: T;
- begin
- result := fCurrent;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlIntersectWithoutEnumerator.Create(
- const aWithoutMode: Boolean;
- aEnumerator: IutlEnumerator;
- aOther: IutlEnumerator;
- aComparer: IComparer);
- begin
- inherited Create;
- fWithoutMode := aWithoutMode;
- fEnumerator := aEnumerator;
- fOther := aOther;
- fComparer := aComparer;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlSkipTakeEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ENUMERATORS}
- function TutlSkipTakeEnumerator.InternalMoveNext: 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.InternalReset;
- begin
- fEnumerator.Reset;
- fCurrentSkip := fSkip;
- fCurrentTake := fTake;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlSkipTakeEnumerator.GetCurrent: T;
- begin
- result := fEnumerator.Current;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlSkipTakeEnumerator.Create(aEnumerator: IutlEnumerator; const aSkip: Integer; const aTake: Integer);
- begin
- if not Assigned(aEnumerator) then
- raise EArgumentNilException.Create('aEnumerator');
- inherited Create;
- fEnumerator := aEnumerator;
- fSkip := aSkip;
- fTake := aTake;
- fCurrentSkip := aSkip;
- fCurrentTake := aTake;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlSkipTakeEnumerator.Destroy;
- begin
- fEnumerator := nil;
- inherited Destroy;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlWhereEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- function TutlWhereEnumerator.InternalMoveNext: Boolean;
- begin
- repeat
- result := fEnumerator.MoveNext;
- until not result or fFilter.Filter(fEnumerator.Current);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlWhereEnumerator.InternalReset;
- begin
- fEnumerator.Reset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlWhereEnumerator.GetCurrent: T;
- begin
- result := fEnumerator.Current;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlWhereEnumerator.Create(aEnumerator: IutlEnumerator; aFilter: IFilter);
- begin
- if not Assigned(aEnumerator) then
- raise EArgumentNilException.Create('aEnumerator');
- if not Assigned(aFilter) then
- raise EArgumentNilException.Create('aFilter');
- inherited Create;
- fEnumerator := aEnumerator;
- fFilter := aFilter;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlWhereEnumerator.Destroy;
- begin
- fEnumerator := nil;
- fFilter := nil;
- inherited Destroy;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlSelectEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- function TutlSelectEnumerator.InternalMoveNext: Boolean;
- begin
- result := fEnumerator.MoveNext;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlSelectEnumerator.InternalReset;
- begin
- fEnumerator.Reset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlSelectEnumerator.GetCurrent: Tout;
- begin
- result := fSelector.Select(fEnumerator.Current);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlSelectEnumerator.Create(aEnumerator: IInEnumerator; aSelector: ISelector);
- begin
- if not Assigned(aEnumerator) then
- raise EArgumentNilException.Create('aEnumerator');
- if not Assigned(aSelector) then
- raise EArgumentNilException.Create('aSelector');
- inherited Create;
- fEnumerator := aEnumerator;
- fSelector := aSelector;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlSelectEnumerator.Destroy;
- begin
- fEnumerator := nil;
- fSelector := nil;
- inherited Destroy;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlSelectManyEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- function TutlSelectManyEnumerator.InternalMoveNext: Boolean;
- begin
- result := false;
- while not result do begin
- while not Assigned(fCurrent) do begin
- if not fEnumerator.MoveNext then
- exit;
- fCurrent := fSelector.Select(fEnumerator.Current);
- if Assigned(fCurrent) then
- fCurrent.Reset;
- end;
- result := fCurrent.MoveNext;
- if not result then
- fCurrent := nil;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlSelectManyEnumerator.InternalReset;
- begin
- fEnumerator.Reset;
- fCurrent := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlSelectManyEnumerator.GetCurrent: Tout;
- begin
- if not Assigned(fCurrent) then
- raise EInvalidOperation.Create('enumerator is not initialized');
- result := fCurrent.GetCurrent;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlSelectManyEnumerator.Create(aEnumerator: IInEnumerator; aSelector: ISelector);
- begin
- inherited Create;
- fEnumerator := aEnumerator;
- fSelector := aSelector;
- fCurrent := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlSelectManyEnumerator.Destroy;
- begin
- fCurrent := nil;
- fEnumerator := nil;
- fSelector := nil;
- inherited Destroy;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
- function TutlZipEnumerator.InternalMoveNext: Boolean;
- begin
- result := fEnumeratorT.MoveNext and fEnumeratorS.MoveNext;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlZipEnumerator.InternalReset;
- begin
- fEnumeratorT.Reset;
- fEnumeratorS.Reset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlZipEnumerator.GetCurrent: TPair;
- begin
- result.First := fEnumeratorT.GetCurrent;
- result.Second := fEnumeratorS.GetCurrent;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlZipEnumerator.Create(aEnumeratorT: IEnumeratorT; aEnumeratorS: IEnumeratorS);
- begin
- inherited Create;
- fEnumeratorT := aEnumeratorT;
- fEnumeratorS := aEnumeratorS;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlZipEnumerator.Destroy;
- begin
- fEnumeratorT := nil;
- fEnumeratorS := nil;
- inherited Destroy;
- end;
- {$ENDIF}
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TutlConcatEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- {$IFDEF UTL_ENUMERATORS}
- function TutlConcatEnumerator.InternalMoveNext: Boolean;
- begin
- if (fCurrent < 0) then begin
- fCurrent := 0;
- fEnumerators[fCurrent].Reset;
- end;
- result := false;
- while not result and (fCurrent <= high(fEnumerators)) and not fEnumerators[fCurrent].MoveNext do begin
- inc(fCurrent);
- if (fCurrent > high(fEnumerators)) then
- exit;
- fEnumerators[fCurrent].Reset;
- end;
- result := (fCurrent <= high(fEnumerators));
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TutlConcatEnumerator.InternalReset;
- begin
- fCurrent := -1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TutlConcatEnumerator.{%H-}GetCurrent: T;
- begin
- if (fCurrent < low(fEnumerators)) or (fCurrent > high(fEnumerators)) then
- raise EInvalidOperation.Create('enumerator is not initialized');
- result := fEnumerators[fCurrent].Current;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TutlConcatEnumerator.Create(aEnumerators: TEnumerators);
- begin
- inherited Create;
- fCurrent := -1;
- fEnumerators := aEnumerators;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TutlConcatEnumerator.Destroy;
- var
- i: Integer;
- begin
- for i := low(fEnumerators) to high(fEnumerators) do
- fEnumerators [i] := nil;
- SetLength(fEnumerators, 0);
- inherited Destroy;
- end;
- {$ENDIF}
-
- end.
|