* xmlread.pp, remove FCursorStack and resort back to a single cursor node. But this time it is simply a local variable.

git-svn-id: trunk@16962 -
This commit is contained in:
sergei 2011-02-21 16:11:38 +00:00
parent 547a1b289c
commit 9ca12c0377

View File

@ -254,7 +254,6 @@ type
end; end;
TNodeDataDynArray = array of TNodeData; TNodeDataDynArray = array of TNodeData;
TDOMNodeDynArray = array of TDOMNode_WithChildren;
TValidatorDynArray = array of TElementValidator; TValidatorDynArray = array of TElementValidator;
TXMLReadState = (rsProlog, rsDTD, rsAfterDTD, rsRoot, rsEpilog); TXMLReadState = (rsProlog, rsDTD, rsAfterDTD, rsRoot, rsEpilog);
@ -348,7 +347,6 @@ type
FPrefixedAttrs: Integer; FPrefixedAttrs: Integer;
FSpecifiedAttrs: Integer; FSpecifiedAttrs: Integer;
FNodeStack: TNodeDataDynArray; FNodeStack: TNodeDataDynArray;
FCursorStack: TDOMNodeDynArray;
FValidators: TValidatorDynArray; FValidators: TValidatorDynArray;
FAttrChunks: TFPList; FAttrChunks: TFPList;
FFreeAttrChunk: PNodeData; FFreeAttrChunk: PNodeData;
@ -378,20 +376,20 @@ type
procedure ExpectAttValue(attrData: PNodeData; NonCDATA: Boolean); // [10] procedure ExpectAttValue(attrData: PNodeData; NonCDATA: Boolean); // [10]
procedure ParseComment(discard: Boolean); // [15] procedure ParseComment(discard: Boolean); // [15]
procedure ParsePI; // [16] procedure ParsePI; // [16]
procedure CreatePINode; function CreatePINode: TDOMNode;
procedure ParseXmlOrTextDecl(TextDecl: Boolean); procedure ParseXmlOrTextDecl(TextDecl: Boolean);
procedure ExpectEq; procedure ExpectEq;
procedure ParseDoctypeDecl; // [28] procedure ParseDoctypeDecl; // [28]
procedure ParseMarkupDecl; // [29] procedure ParseMarkupDecl; // [29]
procedure ParseStartTag; // [39] procedure ParseStartTag; // [39]
procedure ParseEndTag; // [42] procedure ParseEndTag; // [42]
procedure DoStartElement; function DoStartElement: TDOMElement;
procedure HandleEntityStart; procedure HandleEntityStart;
procedure HandleEntityEnd; procedure HandleEntityEnd;
procedure ResolveEntity; procedure ResolveEntity;
procedure DoStartEntity; procedure DoStartEntity;
procedure ParseAttribute(ElDef: TElementDecl); procedure ParseAttribute(ElDef: TElementDecl);
procedure ParseContent; // [43] procedure ParseContent(parent: TDOMNode_WithChildren); // [43]
function Read: Boolean; function Read: Boolean;
function ResolvePredefined: Boolean; function ResolvePredefined: Boolean;
function EntityCheck(NoExternals: Boolean = False): TEntityDecl; function EntityCheck(NoExternals: Boolean = False): TEntityDecl;
@ -422,12 +420,8 @@ type
procedure ValidationErrorWithName(const Msg: string; LineOffs: Integer = -1); procedure ValidationErrorWithName(const Msg: string; LineOffs: Integer = -1);
procedure DTDReloadHook; procedure DTDReloadHook;
procedure ConvertSource(SrcIn: TXMLInputSource; out SrcOut: TXMLCharSource); procedure ConvertSource(SrcIn: TXMLInputSource; out SrcOut: TXMLCharSource);
// Some SAX-alike stuff (at a very early stage) function DoCDSect(ch: PWideChar; Count: Integer): TDOMNode;
procedure DoText(ch: PWideChar; Count: Integer; Whitespace: Boolean=False);
procedure DoComment(ch: PWideChar; Count: Integer);
procedure DoCDSect(ch: PWideChar; Count: Integer);
procedure DoNotationDecl(const aName, aPubID, aSysID: WideString); procedure DoNotationDecl(const aName, aPubID, aSysID: WideString);
procedure DoEntityReference;
public public
doc: TDOMDocument; doc: TDOMDocument;
constructor Create; overload; constructor Create; overload;
@ -1248,7 +1242,6 @@ begin
FNamePages := @NamePages; FNamePages := @NamePages;
SetLength(FNodeStack, 16); SetLength(FNodeStack, 16);
SetLength(FValidators, 16); SetLength(FValidators, 16);
SetLength(FCursorStack, 16);
end; end;
constructor TXMLReader.Create(AParser: TDOMParser); constructor TXMLReader.Create(AParser: TDOMParser);
@ -1324,14 +1317,14 @@ begin
FState := rsProlog; FState := rsProlog;
FNesting := 0; FNesting := 0;
FCurrNode := @FNodeStack[0]; FCurrNode := @FNodeStack[0];
FCursorStack[0] := doc;
FFragmentMode := False; FFragmentMode := False;
NSPrepare; NSPrepare;
Initialize(ASource); Initialize(ASource);
if FSource.FXMLVersion <> xmlVersionUnknown then if FSource.FXMLVersion <> xmlVersionUnknown then
TDOMTopNodeEx(TDOMNode(doc)).FXMLVersion := FSource.FXMLVersion; TDOMTopNodeEx(TDOMNode(doc)).FXMLVersion := FSource.FXMLVersion;
TDOMTopNodeEx(TDOMNode(doc)).FXMLEncoding := FSource.FXMLEncoding; TDOMTopNodeEx(TDOMNode(doc)).FXMLEncoding := FSource.FXMLEncoding;
ParseContent; FNext := xtText;
ParseContent(doc);
if FState < rsRoot then if FState < rsRoot then
FatalError('Root element is missing'); FatalError('Root element is missing');
@ -1352,7 +1345,6 @@ begin
FState := rsRoot; FState := rsRoot;
FNesting := 0; FNesting := 0;
FCurrNode := @FNodeStack[0]; FCurrNode := @FNodeStack[0];
FCursorStack[0] := AOwner as TDOMNode_WithChildren;
FFragmentMode := True; FFragmentMode := True;
FXML11 := doc.InheritsFrom(TXMLDocument) and (TXMLDocument(doc).XMLVersion = '1.1'); FXML11 := doc.InheritsFrom(TXMLDocument) and (TXMLDocument(doc).XMLVersion = '1.1');
NSPrepare; NSPrepare;
@ -1369,7 +1361,8 @@ begin
TDOMTopNodeEx(AOwner).FXMLVersion := FSource.FXMLVersion; TDOMTopNodeEx(AOwner).FXMLVersion := FSource.FXMLVersion;
TDOMTopNodeEx(AOwner).FXMLEncoding := FSource.FXMLEncoding; TDOMTopNodeEx(AOwner).FXMLEncoding := FSource.FXMLEncoding;
end; end;
ParseContent; FNext := xtText;
ParseContent(aOwner as TDOMNode_WithChildren);
end; end;
function TXMLReader.CheckName(aFlags: TCheckNameFlags): Boolean; function TXMLReader.CheckName(aFlags: TCheckNameFlags): Boolean;
@ -1929,17 +1922,13 @@ begin
FNameTable.FindOrAdd(FName.Buffer, FName.Length)); FNameTable.FindOrAdd(FName.Buffer, FName.Length));
end; end;
procedure TXMLReader.CreatePINode; function TXMLReader.CreatePINode: TDOMNode;
var var
NameStr, ValueStr: WideString; NameStr, ValueStr: WideString;
PINode: TDOMProcessingInstruction;
begin begin
SetString(NameStr, FName.Buffer, FName.Length); SetString(NameStr, FName.Buffer, FName.Length);
SetString(ValueStr, FValue.Buffer, FValue.Length); SetString(ValueStr, FValue.Buffer, FValue.Length);
// SAX: ContentHandler.ProcessingInstruction(Name, Value); result := Doc.CreateProcessingInstruction(NameStr, ValueStr);
PINode := Doc.CreateProcessingInstruction(NameStr, ValueStr);
FCursorStack[FNesting].InternalAppend(PINode);
end; end;
const const
@ -2550,7 +2539,7 @@ begin
if FSource.FBuf^ = '?' then if FSource.FBuf^ = '?' then
begin begin
ParsePI; ParsePI;
CreatePINode; doc.AppendChild(CreatePINode);
end end
else else
begin begin
@ -2764,11 +2753,6 @@ begin
end; end;
end; end;
procedure TXMLReader.DoEntityReference;
begin
FCursorStack[FNesting].AppendChild(doc.CreateEntityReference(FCurrNode^.FQName^.Key));
end;
procedure TXMLReader.HandleEntityStart; procedure TXMLReader.HandleEntityStart;
begin begin
{ FNesting+1 is available due to overallocation in AllocNodeData() } { FNesting+1 is available due to overallocation in AllocNodeData() }
@ -2782,7 +2766,6 @@ end;
procedure TXMLReader.HandleEntityEnd; procedure TXMLReader.HandleEntityEnd;
begin begin
FValidators[FNesting-1] := FValidators[FNesting]; FValidators[FNesting-1] := FValidators[FNesting];
FCursorStack[FNesting-1] := FCursorStack[FNesting];
ContextPop(True); ContextPop(True);
PopVC; PopVC;
FCurrNode := @FNodeStack[FNesting+1]; FCurrNode := @FNodeStack[FNesting+1];
@ -2817,31 +2800,27 @@ begin
{ Compensate for an extra entry in node stack } { Compensate for an extra entry in node stack }
FValidators[FNesting] := FValidators[FNesting-1]; FValidators[FNesting] := FValidators[FNesting-1];
FCursorStack[FNesting] := FCursorStack[FNesting-1];
UpdateConstraints; UpdateConstraints;
FNext := xtText; FNext := xtText;
end; end;
procedure TXMLReader.DoStartElement; function TXMLReader.DoStartElement: TDOMElement;
var var
NewElem: TDOMElement;
Attr: TDOMAttr; Attr: TDOMAttr;
i: Integer; i: Integer;
begin begin
with FCurrNode^.FQName^ do with FCurrNode^.FQName^ do
NewElem := doc.CreateElementBuf(PWideChar(Key), Length(Key)); Result := doc.CreateElementBuf(PWideChar(Key), Length(Key));
FCursorStack[FNesting-1].InternalAppend(NewElem);
FCursorStack[FNesting] := NewElem;
if Assigned(FCurrNode^.FNsUri) then if Assigned(FCurrNode^.FNsUri) then
NewElem.SetNSI(FCurrNode^.FNsUri^.Key, FCurrNode^.FColonPos+1); Result.SetNSI(FCurrNode^.FNsUri^.Key, FCurrNode^.FColonPos+1);
for i := 1 to FAttrCount do for i := 1 to FAttrCount do
begin begin
Attr := LoadAttribute(doc, @FNodeStack[FNesting+i]); Attr := LoadAttribute(doc, @FNodeStack[FNesting+i]);
NewElem.SetAttributeNode(Attr); Result.SetAttributeNode(Attr);
// Attach element to ID map entry if necessary // Attach element to ID map entry if necessary
if Assigned(FNodeStack[FNesting+i].FIDEntry) then if Assigned(FNodeStack[FNesting+i].FIDEntry) then
FNodeStack[FNesting+i].FIDEntry^.Data := NewElem; FNodeStack[FNesting+i].FIDEntry^.Data := Result;
end; end;
end; end;
@ -2898,33 +2877,57 @@ const
ntText ntText
); );
procedure TXMLReader.ParseContent; procedure TXMLReader.ParseContent(parent: TDOMNode_WithChildren);
var
cursor: TDOMNode_WithChildren;
element: TDOMElement;
begin begin
FNext := xtText; cursor := parent;
while Read do while Read do
begin begin
if FValidate then if FValidate then
ValidateCurrentNode; ValidateCurrentNode;
case FCurrNode^.FNodeType of case FCurrNode^.FNodeType of
ntText, ntWhitespace: ntText:
DoText(FValue.Buffer, FValue.Length, FCurrNode^.FNodeType = ntWhitespace); cursor.InternalAppend(doc.CreateTextNodeBuf(FValue.Buffer, FValue.Length, False));
ntWhitespace:
if FPreserveWhitespace then
cursor.InternalAppend(doc.CreateTextNodeBuf(FValue.Buffer, FValue.Length, FCurrContentType = ctChildren))
else
Continue;
ntCDATA: ntCDATA:
DoCDSect(FValue.Buffer, FValue.Length); cursor.InternalAppend(DoCDSect(FValue.Buffer, FValue.Length));
ntProcessingInstruction: ntProcessingInstruction:
CreatePINode; cursor.InternalAppend(CreatePINode);
ntComment: ntComment:
DoComment(FCurrNode^.FValueStart, FCurrNode^.FValueLength); if FIgnoreComments then
Continue
else
cursor.InternalAppend(doc.CreateCommentBuf(FCurrNode^.FValueStart, FCurrNode^.FValueLength));
ntElement: ntElement:
DoStartElement;
ntEndElement:
;
ntDocumentType:
begin begin
if not FCanonical then element := DoStartElement;
doc.AppendChild(TDOMDocumentType.Create(doc, FDocType)); cursor.InternalAppend(element);
cursor := element;
Continue;
end; end;
ntEndElement:
cursor := TDOMNode_WithChildren(cursor.ParentNode);
ntDocumentType:
if FCanonical then
Continue
else
cursor.InternalAppend(TDOMDocumentType.Create(doc, FDocType));
ntEntityReference: ntEntityReference:
DoEntityReference; cursor.InternalAppend(doc.CreateEntityReference(FCurrNode^.FQName^.Key));
end; end;
end; end;
end; end;
@ -3080,6 +3083,12 @@ begin
end; end;
if FValue.Length <> 0 then if FValue.Length <> 0 then
begin begin
if FState <> rsRoot then
if nonWs then
FatalError('Illegal at document level', -1)
else
Break;
SetNodeInfoWithValue(textNodeTypes[nonWs]); SetNodeInfoWithValue(textNodeTypes[nonWs]);
FNext := tok; FNext := tok;
Result := True; Result := True;
@ -3538,42 +3547,15 @@ begin
DoErrorPos(esError, 'Notation ''%s'' is not declared', [Value], Loc); DoErrorPos(esError, 'Notation ''%s'' is not declared', [Value], Loc);
end; end;
procedure TXMLReader.DoText(ch: PWideChar; Count: Integer; Whitespace: Boolean);
var
TextNode: TDOMText;
begin
if FState <> rsRoot then
if not Whitespace then
FatalError('Illegal at document level', -1)
else
Exit;
if (Whitespace and (not FPreserveWhitespace)) or (Count = 0) then function TXMLReader.DoCDSect(ch: PWideChar; Count: Integer): TDOMNode;
Exit;
TextNode := Doc.CreateTextNodeBuf(ch, Count, Whitespace and (FCurrContentType = ctChildren));
FCursorStack[FNesting].InternalAppend(TextNode);
end;
procedure TXMLReader.DoComment(ch: PWideChar; Count: Integer);
var
Node: TDOMComment;
begin
if (not FIgnoreComments) and (FState <> rsDTD) then
begin
Node := Doc.CreateCommentBuf(ch, Count);
FCursorStack[FNesting].InternalAppend(Node);
end;
end;
procedure TXMLReader.DoCDSect(ch: PWideChar; Count: Integer);
var var
s: WideString; s: WideString;
begin begin
Assert(not FCDSectionsAsText, 'Should not be called when CDSectionsAsText=True'); Assert(not FCDSectionsAsText, 'Should not be called when CDSectionsAsText=True');
SetString(s, ch, Count); SetString(s, ch, Count);
FCursorStack[FNesting].InternalAppend(doc.CreateCDATASection(s)); result := doc.CreateCDATASection(s);
end; end;
procedure TXMLReader.DoNotationDecl(const aName, aPubID, aSysID: WideString); procedure TXMLReader.DoNotationDecl(const aName, aPubID, aSysID: WideString);
@ -3695,9 +3677,8 @@ begin
FCurrNode^.FNsUri := nil; FCurrNode^.FNsUri := nil;
FCurrNode^.FIDEntry := nil; FCurrNode^.FIDEntry := nil;
if FNesting >= Length(FCursorStack) then if FNesting >= Length(FValidators) then
begin begin
SetLength(FCursorStack, FNesting * 2);
SetLength(FValidators, FNesting * 2); SetLength(FValidators, FNesting * 2);
end; end;