Browse Source

* When parsing end-tags, compare input with element name from start-tag directly, without calling CheckName (performance).

git-svn-id: trunk@20748 -
sergei 13 years ago
parent
commit
67d6e8d6af
1 changed files with 33 additions and 5 deletions
  1. 33 5
      packages/fcl-xml/src/xmlread.pp

+ 33 - 5
packages/fcl-xml/src/xmlread.pp

@@ -191,6 +191,7 @@ type
     procedure Initialize; virtual;
     function SetEncoding(const AEncoding: string): Boolean; virtual;
     function Matches(const arg: XMLString): Boolean;
+    function MatchesLong(const arg: XMLString): Boolean;
     property SourceURI: XMLString read GetSourceURI write FSourceURI;
   end;
 
@@ -742,6 +743,34 @@ begin
   end;
 end;
 
+{ Used to check element name in end-tags, difference from Matches is that
+  buffer may be reloaded more than once. XML has no restriction on name
+  length, so a name longer than input buffer may be encountered. }
+function TXMLCharSource.MatchesLong(const arg: XMLString): Boolean;
+var
+  idx, len, chunk: Integer;
+begin
+  Result := False;
+  idx := 1;
+  len := Length(arg);
+  repeat
+    if (FBuf >= FBufEnd) and not Reload then
+      Exit;
+    if FBufEnd >= FBuf + len then
+      chunk := len
+    else
+      chunk := FBufEnd - FBuf;
+    if not CompareMem(@arg[idx], FBuf, chunk*sizeof(WideChar)) then
+      Exit;
+    Inc(FBuf, chunk);
+    Inc(idx,chunk);
+    Dec(len,chunk);
+  until len = 0;
+  Result := True;
+  if FBuf >= FBufEnd then
+    Reload;
+end;
+
 { TXMLDecodingSource }
 
 procedure TXMLDecodingSource.AfterConstruction;
@@ -3816,17 +3845,16 @@ begin
 
   FCurrNode := @FNodeStack[FNesting];  // move off the possible child
   FCurrNode^.FNodeType := ntEndElement;
-  Inc(FTokenStart.LinePos, 2);         // move over '</' chars
+  StoreLocation(FTokenStart);
   FCurrNode^.FLoc := FTokenStart;
   ElName := FCurrNode^.FQName;
 
-  CheckName;
-  if not BufEquals(FName, ElName^.Key) then
-    FatalError('Unmatching element end tag (expected "</%s>")', [ElName^.Key], FName.Length);
+  if not FSource.MatchesLong(ElName^.Key) then
+    FatalError('Unmatching element end tag (expected "</%s>")', [ElName^.Key], -1);
   if FSource.FBuf^ = '>' then    // this handles majority of cases
     FSource.NextChar
   else
-  begin
+  begin             // gives somewhat incorrect message for <a></aa>
     SkipS;
     ExpectChar('>');
   end;