فهرست منبع

* 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 -
sergei 14 سال پیش
والد
کامیت
9ca12c0377
1فایلهای تغییر یافته به همراه63 افزوده شده و 82 حذف شده
  1. 63 82
      packages/fcl-xml/src/xmlread.pp

+ 63 - 82
packages/fcl-xml/src/xmlread.pp

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