Простой текстовый итератор. Пример использования record в Delphi

Задача: осуществить перебор строковых значений в исходной строке, разделённых символом-разделителем, с учётом символа-кавычки.
Решение:
unit dnStringIterator;
interface
type
TStringValuesIterator = record
type
TCallBack = reference to procedure (const AValue: string);
TOptions = set of (ioTrimValues, ioDequoteValues);
private
FSourceString: string;
FDelimiter, FQuoteChar: Char;
FCheckQuotes: Boolean;
FOptions: TOptions;
FOffset, FLength: Integer;
FCurrent: string;
public
constructor Init(const ASourceString: string; ADelimiter: Char; AQuoteChar: Char = #0; AOptions: TOptions = []);
function GetEnumerator: TStringValuesIterator;
function MoveNext: Boolean;
procedure Run(ACallBack: TCallBack); inline;
property Current: string read FCurrent;
end;
implementation
uses
SysUtils;
{ TStringValuesIterator }
constructor TStringValuesIterator.Init(const ASourceString: string; ADelimiter, AQuoteChar: Char; AOptions: TOptions);
begin
FSourceString := ASourceString;
FDelimiter := ADelimiter;
FQuoteChar := AQuoteChar;
FOffset := 1;
FLength := Length(FSourceString);
FOptions := AOptions;
FCurrent := '';
FCheckQuotes := FQuoteChar <> #0;
// нельзя, чтобы символ разделитель совпадал с символом-кавычкой:
Assert(not FCheckQuotes or (FDelimiter <> FQuoteChar));
// нельзя использовать ioDeqouteValues, если не указан QuoteChar
Assert(FCheckQuotes or not (ioDequoteValues in FOptions));
end;
function TStringValuesIterator.GetEnumerator: TStringValuesIterator;
begin
Result := Self;
end;
function TStringValuesIterator.MoveNext: Boolean;
var
IsInQuote: Boolean;
CurPos: Integer;
Ch: Char;
begin
Result := (FLength > 0) and (FOffset
Примеры использования
С явным объявлением дополнительной переменной:
var
svi: TStringValuesIterator;
begin
svi.Init(TestString, ',');
while svi.MoveNext do
Memo1.Lines.Add(svi.Current);
end;
Без явного объявления дополнительной переменной, используя with:
begin
with TStringValuesIterator.Init(TestString, ',') do
while MoveNext do
Memo1.Lines.Add(Current);
end;
Используя анонимную процедуру:
begin
TStringValuesIterator.Init(TestString, ',').Run(
procedure (const AValue: string)
begin
Memo1.Lines.Add(AValue);
end
);
end;
Используя for-in синтаксис:
var
Tmp: string;
begin
for Tmp in TStringValuesIterator.Init(TestString, ',') do
Memo1.Lines.Add(Tmp);
end;

Ответить
Хотите присоединиться к обсуждению?Не стесняйтесь вносить свой вклад!