unit uutlEnumerator; {$mode objfpc}{$H+} interface uses Classes, SysUtils, uutlTypes, uutlInterfaces {$IFDEF UTL_ADVANCED_ENUMERATORS} , uutlAlgorithm {$ENDIF} ; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// generic TutlEnumerator = class( TInterfacedObject , specialize IEnumerator , specialize IutlEnumerator) public type TStatus = ( stCreated, stReseted, stMoving, stFinished ); {$IFDEF UTL_ENUMERATORS} TArray = specialize TutlArray; IutlEnumerator = specialize IutlEnumerator; IEqualityComparer = specialize IutlEqualityComparer; {$IFDEF UTL_ADVANCED_ENUMERATORS} IComparer = specialize IutlComparer; IFilter = specialize IutlFilter; {$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 = class( specialize TutlEnumerator) 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 = class( specialize TutlMemoryEnumerator) {$IFNDEF UTL_ENUMERATORS} public type TArray = specialize TutlArray; {$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 = class( specialize TutlArrayEnumerator) 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 = class( specialize TutlArrayEnumerator) 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 = class( specialize TutlEnumerator) 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 = class( specialize TutlEnumerator) 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 = class( specialize TutlEnumerator) 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 = class( specialize TutlEnumerator) 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 = class( specialize TutlEnumerator) public type IInEnumerator = specialize IutlEnumerator; ISelector = specialize IutlSelector; 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 = class( specialize TutlEnumerator) public type IInEnumerator = specialize IutlEnumerator; IOutEnumerator = specialize IutlEnumerator; ISelector = specialize IutlSelector; 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 = class( specialize TutlEnumerator>) public type IEnumeratorT = specialize IutlEnumerator; IEnumeratorS = specialize IutlEnumerator; TPair = specialize TutlPair; 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 = class( specialize TutlEnumerator) 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.Create(self, aCount, -1); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlEnumerator.Take(aCount: Integer): IutlEnumerator; begin result := specialize TutlSkipTakeEnumerator.Create(self, -1, aCount); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlEnumerator.Concat(aEnumerator: IutlEnumerator): IutlEnumerator; type TConcatEnumerator = specialize TutlConcatEnumerator; begin result := TConcatEnumerator.Create(TConcatEnumerator.TEnumerators.Create(self, aEnumerator)); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlEnumerator.Reverse: IutlEnumerator; begin result := specialize TutlReverseEnumerator.Create(self); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// {$IFDEF UTL_ADVANCED_ENUMERATORS} function TutlEnumerator.Sort(aComparer: IComparer): IutlEnumerator; begin result := specialize TutlSortEnumerator.Create(self, aComparer); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlEnumerator.Where(aFilter: IFilter): IutlEnumerator; begin result := specialize TutlWhereEnumerator.Create(self, aFilter); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlEnumerator.Distinct(aComparer: IComparer): IutlEnumerator; begin result := specialize TutlDistinctEnumerator.Create(self, aComparer); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TutlEnumerator.Intersect(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator; begin result := specialize TutlIntersectWithoutEnumerator.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.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; 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; 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; 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.