Skip to content

Commit abffaf8

Browse files
Remove XmlConvert.StrEqual and use Span<char>.StartsWith() instead. (#74955)
* Use Span.SequenceEqual instead if manual loop over char array. * Remove StrEqual. Replace with StartsWith as suggested. * Remove not needed brackets + fix tests * Use switch expression for "verison", "encoding" and "standalone" * Use ranges + one more switch expression * Remove StartsWith helper method from ParsingState * Address range feedback * Add test for XmlTextReader.ReadChars * Fix test Co-authored-by: Traian Zaprianov <Traian.Zaprianov@docuware.com>
1 parent d10cc5a commit abffaf8

5 files changed

Lines changed: 315 additions & 88 deletions

File tree

src/libraries/System.Private.Xml/src/System/Xml/Core/XmlTextReaderImpl.cs

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3643,7 +3643,7 @@ private bool ParseXmlDeclaration(bool isTextDecl)
36433643
}
36443644
}
36453645

3646-
if (!XmlConvert.StrEqual(_ps.chars, _ps.charPos, 5, XmlDeclarationBeginning) ||
3646+
if (!_ps.chars.AsSpan(_ps.charPos).StartsWith(XmlDeclarationBeginning) ||
36473647
XmlCharType.IsNameSingleChar(_ps.chars![_ps.charPos + 5]))
36483648
{
36493649
goto NoXmlDecl;
@@ -3741,10 +3741,10 @@ private bool ParseXmlDeclaration(bool isTextDecl)
37413741
int nameEndPos = ParseName();
37423742

37433743
NodeData? attr = null;
3744-
switch (_ps.chars[_ps.charPos])
3744+
switch (_ps.chars.AsSpan(_ps.charPos, nameEndPos - _ps.charPos))
37453745
{
3746-
case 'v':
3747-
if (XmlConvert.StrEqual(_ps.chars, _ps.charPos, nameEndPos - _ps.charPos, "version") && xmlDeclState == 0)
3746+
case "version":
3747+
if (xmlDeclState == 0)
37483748
{
37493749
if (!isTextDecl)
37503750
{
@@ -3753,9 +3753,8 @@ private bool ParseXmlDeclaration(bool isTextDecl)
37533753
break;
37543754
}
37553755
goto default;
3756-
case 'e':
3757-
if (XmlConvert.StrEqual(_ps.chars, _ps.charPos, nameEndPos - _ps.charPos, "encoding") &&
3758-
(xmlDeclState == 1 || (isTextDecl && xmlDeclState == 0)))
3756+
case "encoding":
3757+
if (xmlDeclState == 1 || (isTextDecl && xmlDeclState == 0))
37593758
{
37603759
if (!isTextDecl)
37613760
{
@@ -3765,9 +3764,8 @@ private bool ParseXmlDeclaration(bool isTextDecl)
37653764
break;
37663765
}
37673766
goto default;
3768-
case 's':
3769-
if (XmlConvert.StrEqual(_ps.chars, _ps.charPos, nameEndPos - _ps.charPos, "standalone") &&
3770-
(xmlDeclState == 1 || xmlDeclState == 2) && !isTextDecl)
3767+
case "standalone":
3768+
if ((xmlDeclState == 1 || xmlDeclState == 2) && !isTextDecl)
37713769
{
37723770
attr = AddAttributeNoChecks("standalone", 1);
37733771
xmlDeclState = 2;
@@ -3835,7 +3833,7 @@ private bool ParseXmlDeclaration(bool isTextDecl)
38353833
// version
38363834
case 0:
38373835
// VersionNum ::= '1.0' (XML Fourth Edition and earlier)
3838-
if (XmlConvert.StrEqual(_ps.chars, _ps.charPos, pos - _ps.charPos, "1.0"))
3836+
if (_ps.chars.AsSpan(_ps.charPos).StartsWith("1.0"))
38393837
{
38403838
if (!isTextDecl)
38413839
{
@@ -3861,18 +3859,18 @@ private bool ParseXmlDeclaration(bool isTextDecl)
38613859
xmlDeclState = 2;
38623860
break;
38633861
case 2:
3864-
if (XmlConvert.StrEqual(_ps.chars, _ps.charPos, pos - _ps.charPos, "yes"))
3865-
{
3866-
_standalone = true;
3867-
}
3868-
else if (XmlConvert.StrEqual(_ps.chars, _ps.charPos, pos - _ps.charPos, "no"))
3869-
{
3870-
_standalone = false;
3871-
}
3872-
else
3862+
switch (_ps.chars.AsSpan(_ps.charPos, pos - _ps.charPos))
38733863
{
3874-
Debug.Assert(!isTextDecl);
3875-
Throw(SR.Xml_InvalidXmlDecl, _ps.LineNo, _ps.LinePos - 1);
3864+
case "yes":
3865+
_standalone = true;
3866+
break;
3867+
case "no":
3868+
_standalone = false;
3869+
break;
3870+
default:
3871+
Debug.Assert(!isTextDecl);
3872+
Throw(SR.Xml_InvalidXmlDecl, _ps.LineNo, _ps.LinePos - 1);
3873+
break;
38763874
}
38773875
if (!isTextDecl)
38783876
{
@@ -3997,7 +3995,7 @@ private bool ParseDocumentContent()
39973995
{
39983996
goto ReadData;
39993997
}
4000-
if (XmlConvert.StrEqual(chars, pos, 6, "CDATA["))
3998+
if (chars.AsSpan(pos).StartsWith("CDATA["))
40013999
{
40024000
_ps.charPos = pos + 6;
40034001
ParseCData();
@@ -4217,7 +4215,7 @@ private bool ParseElementContent()
42174215
{
42184216
goto ReadData;
42194217
}
4220-
if (XmlConvert.StrEqual(chars, pos, 6, "CDATA["))
4218+
if (chars.AsSpan(pos).StartsWith("CDATA["))
42214219
{
42224220
_ps.charPos = pos + 6;
42234221
ParseCData();
@@ -4424,7 +4422,7 @@ private void ParseElement()
44244422
{
44254423
int startPos = _ps.charPos;
44264424
int prefixLen = colonPos - startPos;
4427-
if (prefixLen == _lastPrefix.Length && XmlConvert.StrEqual(chars, startPos, prefixLen, _lastPrefix))
4425+
if (prefixLen == _lastPrefix.Length && chars.AsSpan(startPos).StartsWith(_lastPrefix))
44284426
{
44294427
_curNode.SetNamedNode(XmlNodeType.Element,
44304428
_nameTable.Add(chars, colonPos + 1, pos - colonPos - 1),
@@ -4600,7 +4598,7 @@ private void ParseEndElement()
46004598
char[] chars = _ps.chars;
46014599
if (startTagNode.prefix.Length == 0)
46024600
{
4603-
if (!XmlConvert.StrEqual(chars, _ps.charPos, locLen, startTagNode.localName))
4601+
if (!chars.AsSpan(_ps.charPos).StartsWith(startTagNode.localName))
46044602
{
46054603
ThrowTagMismatch(startTagNode);
46064604
}
@@ -4609,9 +4607,9 @@ private void ParseEndElement()
46094607
else
46104608
{
46114609
int colonPos = _ps.charPos + prefLen;
4612-
if (!XmlConvert.StrEqual(chars, _ps.charPos, prefLen, startTagNode.prefix) ||
4610+
if (!chars.AsSpan(_ps.charPos).StartsWith(startTagNode.prefix) ||
46134611
chars[colonPos] != ':' ||
4614-
!XmlConvert.StrEqual(chars, colonPos + 1, locLen, startTagNode.localName))
4612+
!chars.AsSpan(colonPos + 1).StartsWith(startTagNode.localName))
46154613
{
46164614
ThrowTagMismatch(startTagNode);
46174615
}
@@ -6732,7 +6730,7 @@ private bool ParseDoctypeDecl()
67326730
}
67336731
}
67346732

6735-
if (!XmlConvert.StrEqual(_ps.chars, _ps.charPos, 7, "DOCTYPE"))
6733+
if (!_ps.chars.AsSpan(_ps.charPos).StartsWith("DOCTYPE"))
67366734
{
67376735
ThrowUnexpectedToken((!_rootElementParsed && _dtdInfo == null) ? "DOCTYPE" : "<!--");
67386736
}
@@ -6814,7 +6812,7 @@ private void SkipDtd()
68146812
}
68156813
}
68166814
// check 'PUBLIC'
6817-
if (!XmlConvert.StrEqual(_ps.chars, _ps.charPos, 6, "PUBLIC"))
6815+
if (!_ps.chars.AsSpan(_ps.charPos).StartsWith("PUBLIC"))
68186816
{
68196817
ThrowUnexpectedToken("PUBLIC");
68206818
}
@@ -6851,7 +6849,7 @@ private void SkipDtd()
68516849
}
68526850
}
68536851
// check 'SYSTEM'
6854-
if (!XmlConvert.StrEqual(_ps.chars, _ps.charPos, 6, "SYSTEM"))
6852+
if (!_ps.chars.AsSpan(_ps.charPos).StartsWith("SYSTEM"))
68556853
{
68566854
ThrowUnexpectedToken("SYSTEM");
68576855
}
@@ -7725,7 +7723,7 @@ private NodeData AddAttribute(int endNamePos, int colonPos)
77257723
_attrNeedNamespaceLookup = true;
77267724
int startPos = _ps.charPos;
77277725
int prefixLen = colonPos - startPos;
7728-
if (prefixLen == _lastPrefix.Length && XmlConvert.StrEqual(_ps.chars, startPos, prefixLen, _lastPrefix))
7726+
if (prefixLen == _lastPrefix.Length && _ps.chars.AsSpan(_ps.charPos).StartsWith(_lastPrefix))
77297727
{
77307728
return AddAttribute(_nameTable.Add(_ps.chars, colonPos + 1, endNamePos - colonPos - 1),
77317729
_lastPrefix,
@@ -8274,23 +8272,23 @@ private int IncrementalRead()
82748272
case IncrementalReadState.PI:
82758273
if (ParsePIValue(out startPos, out pos))
82768274
{
8277-
Debug.Assert(XmlConvert.StrEqual(_ps.chars, _ps.charPos - 2, 2, "?>"));
8275+
Debug.Assert(_ps.chars.AsSpan(_ps.charPos - 2).StartsWith("?>"));
82788276
_ps.charPos -= 2;
82798277
_incReadState = IncrementalReadState.Text;
82808278
}
82818279
goto Append;
82828280
case IncrementalReadState.Comment:
82838281
if (ParseCDataOrComment(XmlNodeType.Comment, out startPos, out pos))
82848282
{
8285-
Debug.Assert(XmlConvert.StrEqual(_ps.chars, _ps.charPos - 3, 3, "-->"));
8283+
Debug.Assert(_ps.chars.AsSpan(_ps.charPos - 3).StartsWith("-->"));
82868284
_ps.charPos -= 3;
82878285
_incReadState = IncrementalReadState.Text;
82888286
}
82898287
goto Append;
82908288
case IncrementalReadState.CDATA:
82918289
if (ParseCDataOrComment(XmlNodeType.CDATA, out startPos, out pos))
82928290
{
8293-
Debug.Assert(XmlConvert.StrEqual(_ps.chars, _ps.charPos - 3, 3, "]]>"));
8291+
Debug.Assert(_ps.chars.AsSpan(_ps.charPos - 3).StartsWith("]]>"));
82948292
_ps.charPos -= 3;
82958293
_incReadState = IncrementalReadState.Text;
82968294
}
@@ -8410,7 +8408,7 @@ private int IncrementalRead()
84108408
{
84118409
goto ReadData;
84128410
}
8413-
if (XmlConvert.StrEqual(chars, pos + 2, 7, "[CDATA["))
8411+
if (chars.AsSpan(pos + 2).StartsWith("[CDATA["))
84148412
{
84158413
pos += 9;
84168414
_incReadState = IncrementalReadState.CDATA;
@@ -8429,7 +8427,8 @@ private int IncrementalRead()
84298427

84308428
// ParseQName can flush the buffer, so we need to update the startPos, pos and chars after calling it
84318429
int endPos = ParseQName(true, 2, out _);
8432-
if (XmlConvert.StrEqual(chars, _ps.charPos + 2, endPos - _ps.charPos - 2, _curNode.GetNameWPrefix(_nameTable)) &&
8430+
string checkName = _curNode.GetNameWPrefix(_nameTable);
8431+
if ((endPos - _ps.charPos - 2) == checkName.Length && chars.AsSpan(_ps.charPos + 2).StartsWith(checkName) &&
84338432
(_ps.chars[endPos] == '>' || XmlCharType.IsWhiteSpace(_ps.chars[endPos])))
84348433
{
84358434
if (--_incReadDepth > 0)
@@ -8468,7 +8467,7 @@ private int IncrementalRead()
84688467

84698468
// ParseQName can flush the buffer, so we need to update the startPos, pos and chars after calling it
84708469
int endPos = ParseQName(true, 1, out _);
8471-
if (XmlConvert.StrEqual(_ps.chars, _ps.charPos + 1, endPos - _ps.charPos - 1, _curNode.localName) &&
8470+
if (endPos - _ps.charPos - 1 == _curNode.localName.Length && _ps.chars.AsSpan(_ps.charPos + 1).StartsWith(_curNode.localName) &&
84728471
(_ps.chars[endPos] == '>' || _ps.chars[endPos] == '/' || XmlCharType.IsWhiteSpace(_ps.chars[endPos])))
84738472
{
84748473
_incReadDepth++;

0 commit comments

Comments
 (0)