private void ParseAttributeValueSlow(int curPos, char quoteChar, NodeData attr) { int pos = curPos; char[] chars = _ps.chars; int attributeBaseEntityId = _ps.entityId; int valueChunkStartPos = 0; LineInfo valueChunkLineInfo = new LineInfo(_ps.lineNo, _ps.LinePos); NodeData lastChunk = null; Debug.Assert(_stringBuilder.Length == 0); for (;;) { // parse the rest of the attribute value unsafe { while (_xmlCharType.IsAttributeValueChar(chars[pos])) { pos++; } } if (pos - _ps.charPos > 0) { _stringBuilder.Append(chars, _ps.charPos, pos - _ps.charPos); _ps.charPos = pos; } if (chars[pos] == quoteChar && attributeBaseEntityId == _ps.entityId) { break; } else { switch (chars[pos]) { // eol case (char)0xA: pos++; OnNewLine(pos); if (_normalize) { _stringBuilder.Append((char)0x20); // CDATA normalization of 0xA _ps.charPos++; } continue; case (char)0xD: if (chars[pos + 1] == (char)0xA) { pos += 2; if (_normalize) { _stringBuilder.Append(_ps.eolNormalized ? "\u0020\u0020" : "\u0020"); // CDATA normalization of 0xD 0xA _ps.charPos = pos; } } else if (pos + 1 < _ps.charsUsed || _ps.isEof) { pos++; if (_normalize) { _stringBuilder.Append((char)0x20); // CDATA normalization of 0xD and 0xD 0xA _ps.charPos = pos; } } else { goto ReadData; } OnNewLine(pos); continue; // tab case (char)0x9: pos++; if (_normalize) { _stringBuilder.Append((char)0x20); // CDATA normalization of 0x9 _ps.charPos++; } continue; case '"': case '\'': case '>': pos++; continue; // attribute values cannot contain '<' case '<': Throw(pos, SR.Xml_BadAttributeChar, XmlException.BuildCharExceptionArgs('<', '\0')); break; // entity referece case '&': if (pos - _ps.charPos > 0) { _stringBuilder.Append(chars, _ps.charPos, pos - _ps.charPos); } _ps.charPos = pos; int enclosingEntityId = _ps.entityId; LineInfo entityLineInfo = new LineInfo(_ps.lineNo, _ps.LinePos + 1); switch (HandleEntityReference(true, EntityExpandType.All, out pos)) { case EntityType.CharacterDec: case EntityType.CharacterHex: case EntityType.CharacterNamed: break; case EntityType.Unexpanded: if (_parsingMode == ParsingMode.Full && _ps.entityId == attributeBaseEntityId) { // construct text value chunk int valueChunkLen = _stringBuilder.Length - valueChunkStartPos; if (valueChunkLen > 0) { NodeData textChunk = new NodeData(); textChunk.lineInfo = valueChunkLineInfo; textChunk.depth = attr.depth + 1; textChunk.SetValueNode(XmlNodeType.Text, _stringBuilder.ToString(valueChunkStartPos, valueChunkLen)); AddAttributeChunkToList(attr, textChunk, ref lastChunk); } // parse entity name _ps.charPos++; string entityName = ParseEntityName(); // construct entity reference chunk NodeData entityChunk = new NodeData(); entityChunk.lineInfo = entityLineInfo; entityChunk.depth = attr.depth + 1; entityChunk.SetNamedNode(XmlNodeType.EntityReference, entityName); AddAttributeChunkToList(attr, entityChunk, ref lastChunk); // append entity ref to the attribute value _stringBuilder.Append('&'); _stringBuilder.Append(entityName); _stringBuilder.Append(';'); // update info for the next attribute value chunk valueChunkStartPos = _stringBuilder.Length; valueChunkLineInfo.Set(_ps.LineNo, _ps.LinePos); _fullAttrCleanup = true; } else { _ps.charPos++; ParseEntityName(); } pos = _ps.charPos; break; case EntityType.ExpandedInAttribute: if (_parsingMode == ParsingMode.Full && enclosingEntityId == attributeBaseEntityId) { // construct text value chunk int valueChunkLen = _stringBuilder.Length - valueChunkStartPos; if (valueChunkLen > 0) { NodeData textChunk = new NodeData(); textChunk.lineInfo = valueChunkLineInfo; textChunk.depth = attr.depth + 1; textChunk.SetValueNode(XmlNodeType.Text, _stringBuilder.ToString(valueChunkStartPos, valueChunkLen)); AddAttributeChunkToList(attr, textChunk, ref lastChunk); } // construct entity reference chunk NodeData entityChunk = new NodeData(); entityChunk.lineInfo = entityLineInfo; entityChunk.depth = attr.depth + 1; entityChunk.SetNamedNode(XmlNodeType.EntityReference, _ps.entity.Name); AddAttributeChunkToList(attr, entityChunk, ref lastChunk); _fullAttrCleanup = true; // Note: info for the next attribute value chunk will be updated once we // get out of the expanded entity } pos = _ps.charPos; break; default: pos = _ps.charPos; break; } chars = _ps.chars; continue; default: // end of buffer if (pos == _ps.charsUsed) { goto ReadData; } // surrogate chars else { char ch = chars[pos]; if (XmlCharType.IsHighSurrogate(ch)) { if (pos + 1 == _ps.charsUsed) { goto ReadData; } pos++; if (XmlCharType.IsLowSurrogate(chars[pos])) { pos++; continue; } } ThrowInvalidChar(chars, _ps.charsUsed, pos); break; } } } ReadData: // read new characters into the buffer if (ReadData() == 0) { if (_ps.charsUsed - _ps.charPos > 0) { if (_ps.chars[_ps.charPos] != (char)0xD) { Debug.Assert(false, "We should never get to this point."); Throw(SR.Xml_UnexpectedEOF1); } Debug.Assert(_ps.isEof); } else { if (!InEntity) { if (_fragmentType == XmlNodeType.Attribute) { if (attributeBaseEntityId != _ps.entityId) { Throw(SR.Xml_EntityRefNesting); } break; } Throw(SR.Xml_UnclosedQuote); } if (HandleEntityEnd(true)) { // no EndEntity reporting while parsing attributes Debug.Assert(false); Throw(SR.Xml_InternalError); } // update info for the next attribute value chunk if (attributeBaseEntityId == _ps.entityId) { valueChunkStartPos = _stringBuilder.Length; valueChunkLineInfo.Set(_ps.LineNo, _ps.LinePos); } } } pos = _ps.charPos; chars = _ps.chars; } if (attr.nextAttrValueChunk != null) { // construct last text value chunk int valueChunkLen = _stringBuilder.Length - valueChunkStartPos; if (valueChunkLen > 0) { NodeData textChunk = new NodeData(); textChunk.lineInfo = valueChunkLineInfo; textChunk.depth = attr.depth + 1; textChunk.SetValueNode(XmlNodeType.Text, _stringBuilder.ToString(valueChunkStartPos, valueChunkLen)); AddAttributeChunkToList(attr, textChunk, ref lastChunk); } } _ps.charPos = pos + 1; attr.SetValue(_stringBuilder.ToString()); _stringBuilder.Length = 0; }
private void ParseAttributeValueSlow(int curPos, char quoteChar, NodeData attr) { int pos = curPos; char[] chars = _ps.chars; int attributeBaseEntityId = _ps.entityId; Debug.Assert(_stringBuilder.Length == 0); for (; ;) { // parse the rest of the attribute value while (_xmlCharType.IsAttributeValueChar(chars[pos])) { pos++; } if (pos - _ps.charPos > 0) { _stringBuilder.Append(chars, _ps.charPos, pos - _ps.charPos); _ps.charPos = pos; } if (chars[pos] == quoteChar && attributeBaseEntityId == _ps.entityId) { break; } else { switch (chars[pos]) { // eol case (char)0xA: pos++; OnNewLine(pos); if (_normalize) { _stringBuilder.Append((char)0x20); // CDATA normalization of 0xA _ps.charPos++; } continue; case (char)0xD: if (chars[pos + 1] == (char)0xA) { pos += 2; if (_normalize) { _stringBuilder.Append(_ps.eolNormalized ? "\u0020\u0020" : "\u0020"); // CDATA normalization of 0xD 0xA _ps.charPos = pos; } } else if (pos + 1 < _ps.charsUsed || _ps.isEof) { pos++; if (_normalize) { _stringBuilder.Append((char)0x20); // CDATA normalization of 0xD and 0xD 0xA _ps.charPos = pos; } } else { goto ReadData; } OnNewLine(pos); continue; // tab case (char)0x9: pos++; if (_normalize) { _stringBuilder.Append((char)0x20); // CDATA normalization of 0x9 _ps.charPos++; } continue; case '"': case '\'': case '>': pos++; continue; // attribute values cannot contain '<' case '<': Throw(pos, SR.Xml_BadAttributeChar, XmlException.BuildCharExceptionArgs('<', '\0')); break; // entity referece case '&': if (pos - _ps.charPos > 0) { _stringBuilder.Append(chars, _ps.charPos, pos - _ps.charPos); } _ps.charPos = pos; switch (HandleEntityReference(true, EntityExpandType.All, out pos)) { case EntityType.CharacterDec: case EntityType.CharacterHex: case EntityType.CharacterNamed: break; default: pos = _ps.charPos; break; } chars = _ps.chars; continue; default: // end of buffer if (pos == _ps.charsUsed) { goto ReadData; } // surrogate chars else { char ch = chars[pos]; if (XmlCharType.IsHighSurrogate(ch)) { if (pos + 1 == _ps.charsUsed) { goto ReadData; } pos++; if (XmlCharType.IsLowSurrogate(chars[pos])) { pos++; continue; } } ThrowInvalidChar(chars, _ps.charsUsed, pos); break; } } } ReadData: // read new characters into the buffer if (ReadData() == 0) { if (_ps.charsUsed - _ps.charPos > 0) { if (_ps.chars[_ps.charPos] != (char)0xD) { Debug.Assert(false, "We should never get to this point."); Throw(SR.Xml_UnexpectedEOF1); } Debug.Assert(_ps.isEof); } else { if (!InEntity) { if (_fragmentType == XmlNodeType.Attribute) { if (attributeBaseEntityId != _ps.entityId) { Throw(SR.Xml_EntityRefNesting); } break; } Throw(SR.Xml_UnclosedQuote); } HandleEntityEnd(true); } } pos = _ps.charPos; chars = _ps.chars; } _ps.charPos = pos + 1; attr.SetValue(_stringBuilder.ToString()); _stringBuilder.Length = 0; }
private void OnNamespaceDecl( NodeData attr ) { if ( !supportNamespaces ) { return; } string ns = attr.GetAtomizedValue( nameTable ); if ( ns.Length == 0 ) { Throw( Res.Xml_BadNamespaceDecl, attr.lineInfo2.lineNo, attr.lineInfo2.linePos - 1 ); } attr.SetValue( ns ); AddNamespace( attr.localName, ns, attr ); }
private void OnDefaultNamespaceDecl( NodeData attr ) { if ( !supportNamespaces ) { return; } string ns = attr.GetAtomizedValue( nameTable ); attr.SetValue( ns ); attr.ns = nameTable.Add( XmlReservedNs.NsXmlNs ); if ( !curNode.xmlContextPushed ) { PushXmlContext(); } xmlContext.defaultNamespace = ns; AddNamespace( string.Empty, ns, attr ); }
private void ParseAttributeValueSlow(int curPos, char quoteChar, NodeData attr) { int pos = curPos; char[] chars = ps.chars; int valueChunkStartPos = 0; LineInfo valueChunkLineInfo = new LineInfo(ps.lineNo, ps.LinePos); NodeData lastChunk = null; Debug.Assert(stringBuilder.Length == 0); for (; ; ) { // parse the rest of the attribute value while (chars[pos] > XmlCharType.MaxAsciiChar || (xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue) != 0) { pos++; } if (pos - ps.charPos > 0) { stringBuilder.Append(chars, ps.charPos, pos - ps.charPos); ps.charPos = pos; } if (chars[pos] == quoteChar) { break; } else { switch (chars[pos]) { // eol case (char)0xA: pos++; OnNewLine(pos); if (normalize) { stringBuilder.Append((char)0x20); // CDATA normalization of 0xA ps.charPos++; } continue; case (char)0xD: if (chars[pos + 1] == (char)0xA) { pos += 2; if (normalize) { stringBuilder.Append(ps.eolNormalized ? "\u0020\u0020" : "\u0020"); // CDATA normalization of 0xD 0xA ps.charPos = pos; } } else if (pos + 1 < ps.charsUsed || ps.isEof) { pos++; if (normalize) { stringBuilder.Append((char)0x20); // CDATA normalization of 0xD and 0xD 0xA ps.charPos = pos; } } else { goto ReadData; } OnNewLine(pos); continue; // tab case (char)0x9: pos++; if (normalize) { stringBuilder.Append((char)0x20); // CDATA normalization of 0x9 ps.charPos++; } continue; case '"': case '\'': case '>': pos++; continue; // attribute values cannot contain '<' case '<': Throw(pos, Res.Xml_BadAttributeChar, XmlException.BuildCharExceptionStr('<')); break; // entity referece case '&': if (pos - ps.charPos > 0) { stringBuilder.Append(chars, ps.charPos, pos - ps.charPos); } ps.charPos = pos; LineInfo entityLineInfo = new LineInfo(ps.lineNo, ps.LinePos + 1); switch (HandleEntityReference(true, EntityExpandType.All, out pos)) { case EntityType.CharacterDec: case EntityType.CharacterHex: case EntityType.CharacterNamed: break; case EntityType.Unexpanded: Debug.Assert(false, "The document contains an entity reference"); throw new NotSupportedException(); case EntityType.ExpandedInAttribute: Debug.Assert(false, "The document contains an entity reference"); throw new NotSupportedException(); default: pos = ps.charPos; break; } chars = ps.chars; continue; default: // end of buffer if (pos == ps.charsUsed) { goto ReadData; } // surrogate chars else { char ch = chars[pos]; if (ch >= SurHighStart && ch <= SurHighEnd) { if (pos + 1 == ps.charsUsed) { goto ReadData; } pos++; if (chars[pos] >= SurLowStart && chars[pos] <= SurLowEnd) { pos++; continue; } } ThrowInvalidChar(pos, ch); break; } } } ReadData: // read new characters into the buffer if (ReadData() == 0) { if (ps.charsUsed - ps.charPos > 0) { if (ps.chars[ps.charPos] != (char)0xD) { Debug.Assert(false, "We should never get to this point."); Throw(Res.Xml_UnexpectedEOF1); } Debug.Assert(ps.isEof); } else { if (fragmentType == XmlNodeType.Attribute) { break; } Throw(Res.Xml_UnclosedQuote); } } pos = ps.charPos; chars = ps.chars; } if (attr.nextAttrValueChunk != null) { // construct last text value chunk int valueChunkLen = stringBuilder.Length - valueChunkStartPos; if (valueChunkLen > 0) { NodeData textChunk = new NodeData(); textChunk.lineInfo = valueChunkLineInfo; textChunk.depth = attr.depth + 1; textChunk.SetValueNode(XmlNodeType.Text, stringBuilder.ToString(valueChunkStartPos, valueChunkLen)); AddAttributeChunkToList(attr, textChunk, ref lastChunk); } } ps.charPos = pos + 1; attr.SetValue(stringBuilder.ToString()); stringBuilder.Length = 0; }
private async Task ParseAttributeValueSlowAsync( int curPos, char quoteChar, NodeData attr ) { int pos = curPos; char[] chars = ps.chars; int attributeBaseEntityId = ps.entityId; #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) int valueChunkStartPos = 0; LineInfo valueChunkLineInfo = new LineInfo(ps.lineNo, ps.LinePos); NodeData lastChunk = null; #endif Debug.Assert( stringBuilder.Length == 0 ); for (;;) { // parse the rest of the attribute value #if SILVERLIGHT while (xmlCharType.IsAttributeValueChar(chars[pos])) { pos++; } #else // Optimization due to the lack of inlining when a method uses byte* unsafe { while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue) != 0)) { pos++; } } #endif if ( pos - ps.charPos > 0 ) { stringBuilder.Append( chars, ps.charPos, pos - ps.charPos ); ps.charPos = pos; } if ( chars[pos] == quoteChar && attributeBaseEntityId == ps.entityId ) { break; } else { switch ( chars[pos] ) { // eol case (char)0xA: pos++; OnNewLine( pos ); if ( normalize ) { stringBuilder.Append( (char)0x20 ); // CDATA normalization of 0xA ps.charPos++; } continue; case (char)0xD: if ( chars[pos+1] == (char)0xA ) { pos += 2; if ( normalize ) { stringBuilder.Append( ps.eolNormalized ? "\u0020\u0020" : "\u0020" ); // CDATA normalization of 0xD 0xA ps.charPos = pos; } } else if ( pos+1 < ps.charsUsed || ps.isEof ) { pos++; if ( normalize ) { stringBuilder.Append( (char)0x20 ); // CDATA normalization of 0xD and 0xD 0xA ps.charPos = pos; } } else { goto ReadData; } OnNewLine( pos ); continue; // tab case (char)0x9: pos++; if ( normalize ) { stringBuilder.Append( (char)0x20 ); // CDATA normalization of 0x9 ps.charPos++; } continue; case '"': case '\'': case '>': pos++; continue; // attribute values cannot contain '<' case '<': Throw( pos, Res.Xml_BadAttributeChar, XmlException.BuildCharExceptionArgs( '<', '\0' ) ); break; // entity referece case '&': if ( pos - ps.charPos > 0 ) { stringBuilder.Append( chars, ps.charPos, pos - ps.charPos ); } ps.charPos = pos; #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) int enclosingEntityId = ps.entityId; LineInfo entityLineInfo = new LineInfo( ps.lineNo, ps.LinePos + 1 ); #endif var tuple_8 = await HandleEntityReferenceAsync( true, EntityExpandType.All).ConfigureAwait(false); pos = tuple_8.Item1; switch ( tuple_8.Item2 ) { case EntityType.CharacterDec: case EntityType.CharacterHex: case EntityType.CharacterNamed: break; #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) case EntityType.Unexpanded: if ( parsingMode == ParsingMode.Full && ps.entityId == attributeBaseEntityId ) { // construct text value chunk int valueChunkLen = stringBuilder.Length - valueChunkStartPos; if ( valueChunkLen > 0 ) { NodeData textChunk = new NodeData(); textChunk.lineInfo = valueChunkLineInfo; textChunk.depth = attr.depth + 1; textChunk.SetValueNode( XmlNodeType.Text, stringBuilder.ToString( valueChunkStartPos, valueChunkLen ) ); AddAttributeChunkToList( attr, textChunk, ref lastChunk ); } // parse entity name ps.charPos++; string entityName = await ParseEntityNameAsync().ConfigureAwait(false); // construct entity reference chunk NodeData entityChunk = new NodeData(); entityChunk.lineInfo = entityLineInfo; entityChunk.depth = attr.depth + 1; entityChunk.SetNamedNode( XmlNodeType.EntityReference, entityName ); AddAttributeChunkToList( attr, entityChunk, ref lastChunk ); // append entity ref to the attribute value stringBuilder.Append( '&' ); stringBuilder.Append( entityName ); stringBuilder.Append( ';' ); // update info for the next attribute value chunk valueChunkStartPos = stringBuilder.Length; valueChunkLineInfo.Set( ps.LineNo, ps.LinePos ); fullAttrCleanup = true; } else { ps.charPos++; await ParseEntityNameAsync().ConfigureAwait(false); } pos = ps.charPos; break; case EntityType.ExpandedInAttribute: if ( parsingMode == ParsingMode.Full && enclosingEntityId == attributeBaseEntityId ) { // construct text value chunk int valueChunkLen = stringBuilder.Length - valueChunkStartPos; if ( valueChunkLen > 0 ) { NodeData textChunk = new NodeData(); textChunk.lineInfo = valueChunkLineInfo; textChunk.depth = attr.depth + 1; textChunk.SetValueNode( XmlNodeType.Text, stringBuilder.ToString( valueChunkStartPos, valueChunkLen ) ); AddAttributeChunkToList( attr, textChunk, ref lastChunk ); } // construct entity reference chunk NodeData entityChunk = new NodeData(); entityChunk.lineInfo = entityLineInfo; entityChunk.depth = attr.depth + 1; entityChunk.SetNamedNode( XmlNodeType.EntityReference, ps.entity.Name ); AddAttributeChunkToList( attr, entityChunk, ref lastChunk ); fullAttrCleanup = true; // Note: info for the next attribute value chunk will be updated once we // get out of the expanded entity } pos = ps.charPos; break; #endif default: pos = ps.charPos; break; } chars = ps.chars; continue; default: // end of buffer if ( pos == ps.charsUsed ) { goto ReadData; } // surrogate chars else { char ch = chars[pos]; if ( XmlCharType.IsHighSurrogate(ch) ) { if ( pos + 1 == ps.charsUsed ) { goto ReadData; } pos++; if ( XmlCharType.IsLowSurrogate( chars[pos] ) ) { pos++; continue; } } ThrowInvalidChar( chars, ps.charsUsed, pos ); break; } } } ReadData: // read new characters into the buffer if ( await ReadDataAsync().ConfigureAwait(false) == 0 ) { if ( ps.charsUsed - ps.charPos > 0 ) { if ( ps.chars[ps.charPos] != (char)0xD ) { Debug.Assert( false, "We should never get to this point." ); Throw( Res.Xml_UnexpectedEOF1 ); } Debug.Assert( ps.isEof ); } else { if ( !InEntity ) { if ( fragmentType == XmlNodeType.Attribute ) { if ( attributeBaseEntityId != ps.entityId ) { Throw( Res.Xml_EntityRefNesting ); } break; } Throw( Res.Xml_UnclosedQuote ); } #if SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) HandleEntityEnd( true ); #else if ( HandleEntityEnd( true ) ) { // no EndEntity reporting while parsing attributes Debug.Assert( false ); Throw( Res.Xml_InternalError ); } // update info for the next attribute value chunk if ( attributeBaseEntityId == ps.entityId ) { valueChunkStartPos = stringBuilder.Length; valueChunkLineInfo.Set( ps.LineNo, ps.LinePos ); } #endif } } pos = ps.charPos; chars = ps.chars; } #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) if ( attr.nextAttrValueChunk != null ) { // construct last text value chunk int valueChunkLen = stringBuilder.Length - valueChunkStartPos; if ( valueChunkLen > 0 ) { NodeData textChunk = new NodeData(); textChunk.lineInfo = valueChunkLineInfo; textChunk.depth = attr.depth + 1; textChunk.SetValueNode( XmlNodeType.Text, stringBuilder.ToString( valueChunkStartPos, valueChunkLen ) ); AddAttributeChunkToList( attr, textChunk, ref lastChunk ); } } #endif ps.charPos = pos + 1; attr.SetValue( stringBuilder.ToString() ); stringBuilder.Length = 0; }