procedure TGedFile.LoadFromFile(
const Filename:
string );
var
LValue: TDataRecord;
LCurrent: TNode;
LCurrentIdx: Integer;
LLines: TStringList;
LLine:
string;
begin
LCurrent := Self;
LCurrentIdx := 0;
LLines := TStringList.Create;
try
LLines.LoadFromFile( Filename );
for LLine
in LLines
do
begin
LValue := ParseLine( LLine );
while LCurrentIdx <> LValue.Level
do
begin
if LCurrentIdx < LValue.Level
then
begin
LCurrent := LCurrent.LastChild;
Inc( LCurrentIdx );
end
else
begin
LCurrent := LCurrent.Parent;
Dec( LCurrentIdx );
end;
end;
if LValue.DataIsReference
then
LCurrent := TRefNode.Create( LCurrent, TNodeType.Create( LValue.NodeTypeStr ), LValue.Data, FReferenceDict )
else
LCurrent := TDataNode.Create( LCurrent, TNodeType.Create( LValue.NodeTypeStr ), LValue.Data );
Inc( LCurrentIdx );
if not LValue.Reference.IsEmpty
then
FReferenceDict.Add( LValue.Reference, LCurrent );
end;
finally
LLines.Free;
end;
end;
function TGedFile.ParseLine(
const ALine:
string ): TDataRecord;
var
LValues: TArray<
string>;
LPrefix:
string;
begin
LValues := ALine.Split( ['
'], 3 );
Result.Level := LValues[0].ToInteger;
// Reference gefunden?
if LValues[1].StartsWith( '
@' )
then
begin
Result.Reference := LValues[1];
Result.NodeTypeStr := LValues[2];
end
else
begin
Result.Reference := '
';
Result.NodeTypeStr := LValues[1];
SetLength( LValues, 2 );
end;
LPrefix :=
string.Join( '
', LValues );
Result.Data := ALine.Substring( LPrefix.Length + 1 );
Result.DataIsReference := Result.Data.StartsWith( '
@' );
end;