Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
unit Lyna.Generators;
interface
uses
SysUtils, Rtti, TypInfo;
type
TRange = record
strict private
FStart, FStep, FLen: Integer;
public
constructor Create(AStart, AEnd, AStep: Integer);
function Reverse: TRange; inline;
function ToArray: TArray<Integer>;
type
TEnumerator = class
private
FStart, FStep, FLen, FCurrent: Integer;
function GetCurrent: Integer;
public
constructor Create(AStart, AStep, ALen: Integer);
function MoveNext: Boolean; inline;
property Current: Integer read GetCurrent;
end;
function GetEnumerator: TEnumerator;
end;
function Range(ACount: Integer): TRange; overload;
function Range(AStart, AEnd: Integer): TRange; overload;
function Range(AStart, AEnd, AStep: Integer): TRange; overload;
implementation
function Range(ACount: Integer): TRange;
begin
Result := TRange.Create(0, ACount-1, 1);
end;
function Range(AStart, AEnd: Integer): TRange;
begin
Result := TRange.Create(AStart, AEnd, 1);
end;
function Range(AStart, AEnd, AStep: Integer): TRange;
begin
Result := TRange.Create(AStart,AEnd, AStep);
end;
function GetLength(AStart, AEnd, AStep: Integer): Integer;
begin
Result := 0;
if AStart < AEnd then
begin
Result := (AEnd-AStart) div AStep + 1;
end;
end;
{ TRange }
constructor TRange.Create(AStart, AEnd, AStep: Integer);
begin
FStart := AStart;
FStep := AStep;
if FStep > 0 then
FLen := GetLength(FStart, AEnd, FStep)
else if FStep < 0 then
FLen := GetLength(AEnd, FStart, -FStep)
else
FLen := 0;
end;
function TRange.Reverse: TRange;
begin
FStart := FStart + (FLen-1) * FStep;
FStep := -FStep;
Result := Self;
end;
function TRange.ToArray: TArray<Integer>;
var
i, value: Integer;
begin
SetLength(Result, FLen);
i := 0;
for value in Self do
begin
Result[i] := value;
Inc(i);
end;
end;
function TRange.GetEnumerator: TEnumerator;
begin
Result := TRange.TEnumerator.Create(FStart, FStep, FLen);
end;
{ TRange.TEnumerator }
constructor TRange.TEnumerator.Create(AStart, AStep, ALen: Integer);
begin
FStart := AStart;
FStep := AStep;
FLen := ALen;
FCurrent := -1;
end;
function TRange.TEnumerator.GetCurrent: Integer;
begin
Result := FStart + FCurrent * FStep;
end;
function TRange.TEnumerator.MoveNext: Boolean;
begin
Inc(FCurrent);
Result := FCurrent < FLen;
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment