From 67d6e8d6af7252aa8c61898ddf9681c63172bf47 Mon Sep 17 00:00:00 2001 From: sergei Date: Sat, 7 Apr 2012 17:02:41 +0000 Subject: [PATCH] * When parsing end-tags, compare input with element name from start-tag directly, without calling CheckName (performance). git-svn-id: trunk@20748 - --- packages/fcl-xml/src/xmlread.pp | 38 ++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/fcl-xml/src/xmlread.pp b/packages/fcl-xml/src/xmlread.pp index 871e904128..69cd8df864 100644 --- a/packages/fcl-xml/src/xmlread.pp +++ b/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 '")', [ElName^.Key], FName.Length); + if not FSource.MatchesLong(ElName^.Key) then + FatalError('Unmatching element end tag (expected "")', [ElName^.Key], -1); if FSource.FBuf^ = '>' then // this handles majority of cases FSource.NextChar else - begin + begin // gives somewhat incorrect message for SkipS; ExpectChar('>'); end;