unit baseiter; interface uses iterimpl; type // Base iterator interfaces IIterator = interface function Next(out AValue: T): Boolean; end; IGenericIterator = IIterator; IStringIterator = IIterator; IIntegerIterator = IIterator; IFloatIterator = IIterator; IResettable = interface ['{3CC2EE46-A542-4954-BCC0-523C68B60089}'] procedure Reset; end; // -------- // Base iterator classes TIterator = class(TInterfacedObject, IIterator) private FCurrent: T; function NopGetCurrent: TObject; public function Next(out AValue: T): Boolean; virtual; abstract; procedure Reset; virtual; // IEnumerator function MoveNext: Boolean; function GetCurrent: T; property Current: T read GetCurrent; // for-in support function GetEnumerator: TIterator; function Copy: TIterator; end; TGenericIterator = TIterator; TStringIterator = TIterator; TIntegerIterator = TIterator; TFloatIterator = TIterator; // -------- // Base fiber iterator classes TBaseIterator = class(TIterator, IResettable) private FIter: TFiberIterator; protected procedure Yield(const AValue: T); procedure Iterate; virtual; //abstract; public constructor Create(AStackSize: Integer =cDefStackSize); destructor Destroy; override; function Next(out AValue: T): Boolean; override; final; procedure Reset; override; final; end; TBaseGenericIterator = TBaseIterator; TBaseStringIterator = TBaseIterator; TBaseIntegerIterator = TBaseIterator; TBaseFloatIterator = TBaseIterator; // *optional* way to stop iterator early // do not catch EStopIteration = iterimpl.EStopIteration; // -------- type TExtIterator = class(TIterator) private FIter: TIterator; public constructor Create(AIter: TIterator); function Next(out AValue: T): Boolean; override; procedure Reset; override; end; TIterateMethod = procedure of object; function CreateFiberIterator(ADoIterate: TIterateMethod; AStackSize: Integer): TFiberIterator; implementation type TMethodIterator = class(TFiberIterator) private FDoIterate: TIterateMethod; protected procedure Iterate; override; public constructor Create(ADoIterate: TIterateMethod; AStackSize: Integer); end; { TExtIterator } constructor TExtIterator.Create(AIter: TIterator); begin inherited Create; FIter := AIter; end; function TExtIterator.Next(out AValue: T): Boolean; begin Result := FIter.Next(AValue); end; procedure TExtIterator.Reset; begin FIter.Reset; end; { TIterator } function TIterator.MoveNext: Boolean; begin Result := Next(FCurrent); end; function TIterator.NopGetCurrent: TObject; begin Result := nil; end; function TIterator.GetCurrent: T; begin Result := FCurrent; end; procedure TIterator.Reset; begin // do nothing end; function TIterator.GetEnumerator: TIterator; begin Result := Self; end; function TIterator.Copy: TIterator; begin Result := TExtIterator.Create(Self); end; function CreateFiberIterator(ADoIterate: TIterateMethod; AStackSize: Integer): TFiberIterator; begin Result := TMethodIterator.Create(ADoIterate, AStackSize); end; { TMethodIterator } constructor TMethodIterator.Create(ADoIterate: TIterateMethod; AStackSize: Integer); begin inherited Create(AStackSize); FDoIterate := ADoIterate; end; procedure TMethodIterator.Iterate; begin FDoIterate; end; { TBaseIterator } constructor TBaseIterator.Create(AStackSize: Integer); begin inherited Create; FIter := CreateFiberIterator(Iterate, AStackSize); end; destructor TBaseIterator.Destroy; begin FIter.Free; inherited; end; procedure TBaseIterator.Yield(const AValue: T); begin FIter.Yield(Addr(AValue)); end; procedure TBaseIterator.Iterate; begin end; function TBaseIterator.Next(out AValue: T): Boolean; var Value: Pointer; begin Result := FIter.GetNext(Value); if Value <> nil then AValue := T(Value^); end; procedure TBaseIterator.Reset; begin FIter.Reset; end; end.