static internal void AdjustLineInfo( char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo ) { int lastNewLinePos = -1; int i = startPos; while ( i < endPos ) { switch ( chars[i] ) { case '\n': lineInfo.lineNo++; lastNewLinePos = i; break; case '\r': if ( isNormalized ) { break; } lineInfo.lineNo++; lastNewLinePos = i; if ( i + 1 < endPos && chars[i+1] == '\n' ) { i++; lastNewLinePos++; } break; } i++; } if ( lastNewLinePos >= 0 ) { lineInfo.linePos = endPos - lastNewLinePos; } }
private async Task< Tuple<string, string> > ParseExternalIdAsync(Token idTokenType, Token declType) { Tuple<string, string> tuple; string publicId; string systemId; LineInfo keywordLineInfo = new LineInfo( LineNo, LinePos - 6 ); publicId = null; systemId = null; if ( await GetTokenAsync( true ).ConfigureAwait(false) != Token.Literal ) { ThrowUnexpectedToken( curPos, "\"", "'" ); } if ( idTokenType == Token.SYSTEM ) { systemId = GetValue(); if ( systemId.IndexOf( '#' ) >= 0 ) { Throw( curPos - systemId.Length - 1, Res.Xml_FragmentId, new string[] { systemId.Substring( systemId.IndexOf( '#' ) ), systemId } ); } if ( declType == Token.DOCTYPE && !freeFloatingDtd ) { literalLineInfo.linePos++; readerAdapter.OnSystemId( systemId, keywordLineInfo, literalLineInfo ); } } else { Debug.Assert( idTokenType == Token.PUBLIC ); publicId = GetValue(); // verify if it contains chars valid for public ids int i; if ( ( i = xmlCharType.IsPublicId( publicId ) ) >= 0 ) { ThrowInvalidChar( curPos - 1 - publicId.Length + i, publicId, i ); } if ( declType == Token.DOCTYPE && !freeFloatingDtd ) { literalLineInfo.linePos++; readerAdapter.OnPublicId( publicId, keywordLineInfo, literalLineInfo ); if ( await GetTokenAsync( false ).ConfigureAwait(false) == Token.Literal ) { if ( !whitespaceSeen ) { Throw( Res.Xml_ExpectingWhiteSpace, new string( literalQuoteChar, 1 ), (int)literalLineInfo.lineNo, (int)literalLineInfo.linePos ); } systemId = GetValue(); literalLineInfo.linePos++; readerAdapter.OnSystemId( systemId, keywordLineInfo, literalLineInfo ); } else { ThrowUnexpectedToken( curPos, "\"", "'" ); } } else { if ( await GetTokenAsync( false ).ConfigureAwait(false) == Token.Literal ) { if ( !whitespaceSeen ) { Throw( Res.Xml_ExpectingWhiteSpace, new string( literalQuoteChar, 1 ), (int)literalLineInfo.lineNo, (int)literalLineInfo.linePos ); } systemId = GetValue(); } else if ( declType != Token.NOTATION ) { ThrowUnexpectedToken( curPos, "\"", "'" ); } } } tuple = new Tuple<string, string>(publicId, systemId); return tuple; }
private Task ParseEndElementAsync_CheckEndTag(int nameLen, NodeData startTagNode, LineInfo endTagLineInfo) { int pos; char[] chars; for (; ; ) { pos = ps.charPos + nameLen; chars = ps.chars; if (pos == ps.charsUsed) { parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData; return AsyncHelper.DoneTask; } bool tagMismatch = false; unsafe { #if SILVERLIGHT if ( xmlCharType.IsNCNameSingleChar( chars[pos] ) || #else // Optimization due to the lack of inlining when a method uses byte* if (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCNameSC) != 0) || #endif (chars[pos] == ':') #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar( chars[pos] ) #endif ) { tagMismatch = true; } } if (tagMismatch) { return ThrowTagMismatchAsync(startTagNode); } // eat whitespaces if (chars[pos] != '>') { char tmpCh; while (xmlCharType.IsWhiteSpace(tmpCh = chars[pos])) { pos++; switch (tmpCh) { case (char)0xA: OnNewLine(pos); continue; case (char)0xD: if (chars[pos] == (char)0xA) { pos++; } else if (pos == ps.charsUsed && !ps.isEof) { break; } OnNewLine(pos); continue; } } } if (chars[pos] == '>') { break; } else if (pos == ps.charsUsed) { parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData; return AsyncHelper.DoneTask; } else { ThrowUnexpectedToken(pos, ">"); } Debug.Assert(false, "We should never get to this point."); } Debug.Assert(index > 0); index--; curNode = nodes[index]; // set the element data Debug.Assert(curNode == startTagNode); startTagNode.lineInfo = endTagLineInfo; startTagNode.type = XmlNodeType.EndElement; ps.charPos = pos + 1; // set next parsing function nextParsingFunction = (index > 0) ? parsingFunction : ParsingFunction.DocumentContent; parsingFunction = ParsingFunction.PopElementContext; parseEndElement_NextFunc = ParseEndElementParseFunction.Done; return AsyncHelper.DoneTask; }
internal void AdjustLineInfo(int valueOffset, bool isNormalized, ref LineInfo lineInfo) { if (valueOffset == 0) { return; } if (valueStartPos != -1) { XmlTextReader.AdjustLineInfo(chars, valueStartPos, valueStartPos + valueOffset, isNormalized, ref lineInfo); } else { char[] chars = value.Substring(0, valueOffset).ToCharArray(); XmlTextReader.AdjustLineInfo(chars, 0, chars.Length, isNormalized, ref lineInfo); } }
internal static unsafe void AdjustLineInfo(char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) { Debug.Assert(startPos >= 0); Debug.Assert(endPos < chars.Length); Debug.Assert(startPos <= endPos); fixed (char* pChars = &chars[startPos]) { AdjustLineInfo(pChars, endPos - startPos, isNormalized, ref lineInfo); } }
internal static unsafe void AdjustLineInfo(char* pChars, int length, bool isNormalized, ref LineInfo lineInfo) { int lastNewLinePos = -1; for (int i = 0; i < length; i++) { switch (pChars[i]) { case '\n': lineInfo.lineNo++; lastNewLinePos = i; break; case '\r': if (isNormalized) { break; } lineInfo.lineNo++; lastNewLinePos = i; if (i + 1 < length && pChars[i + 1] == '\n') { i++; lastNewLinePos++; } break; } } if (lastNewLinePos >= 0) { lineInfo.linePos = length - lastNewLinePos; } }
private Task ParseEndElementAsync_CheckNameAndParse() { NodeData startTagNode = _nodes[_index - 1]; int prefLen = startTagNode.prefix.Length; int locLen = startTagNode.localName.Length; int nameLen; char[] chars = _ps.chars; if (startTagNode.prefix.Length == 0) { if (!XmlConvert.StrEqual(chars, _ps.charPos, locLen, startTagNode.localName)) { return ThrowTagMismatchAsync(startTagNode); } nameLen = locLen; } else { int colonPos = _ps.charPos + prefLen; if (!XmlConvert.StrEqual(chars, _ps.charPos, prefLen, startTagNode.prefix) || chars[colonPos] != ':' || !XmlConvert.StrEqual(chars, colonPos + 1, locLen, startTagNode.localName)) { return ThrowTagMismatchAsync(startTagNode); } nameLen = locLen + prefLen + 1; } LineInfo endTagLineInfo = new LineInfo(_ps.lineNo, _ps.LinePos); return ParseEndElementAsync_Finish(nameLen, startTagNode, endTagLineInfo); }
// parses the element end tag private void ParseEndElement() { // check if the end tag name equals start tag name NodeData startTagNode = _nodes[_index - 1]; int prefLen = startTagNode.prefix.Length; int locLen = startTagNode.localName.Length; while (_ps.charsUsed - _ps.charPos < prefLen + locLen + 1) { if (ReadData() == 0) { break; } } int nameLen; char[] chars = _ps.chars; if (startTagNode.prefix.Length == 0) { if (!XmlConvert.StrEqual(chars, _ps.charPos, locLen, startTagNode.localName)) { ThrowTagMismatch(startTagNode); } nameLen = locLen; } else { int colonPos = _ps.charPos + prefLen; if (!XmlConvert.StrEqual(chars, _ps.charPos, prefLen, startTagNode.prefix) || chars[colonPos] != ':' || !XmlConvert.StrEqual(chars, colonPos + 1, locLen, startTagNode.localName)) { ThrowTagMismatch(startTagNode); } nameLen = locLen + prefLen + 1; } LineInfo endTagLineInfo = new LineInfo(_ps.lineNo, _ps.LinePos); int pos; for (;;) { pos = _ps.charPos + nameLen; chars = _ps.chars; if (pos == _ps.charsUsed) { goto ReadData; } unsafe { if (_xmlCharType.IsNCNameSingleChar(chars[pos]) || (chars[pos] == ':') #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(chars[pos]) #endif ) { ThrowTagMismatch(startTagNode); } } // eat whitespaces if (chars[pos] != '>') { char tmpCh; while (_xmlCharType.IsWhiteSpace(tmpCh = chars[pos])) { pos++; switch (tmpCh) { case (char)0xA: OnNewLine(pos); continue; case (char)0xD: if (chars[pos] == (char)0xA) { pos++; } else if (pos == _ps.charsUsed && !_ps.isEof) { break; } OnNewLine(pos); continue; } } } if (chars[pos] == '>') { break; } else if (pos == _ps.charsUsed) { goto ReadData; } else { ThrowUnexpectedToken(pos, ">"); } Debug.Assert(false, "We should never get to this point."); ReadData: if (ReadData() == 0) { ThrowUnclosedElements(); } } Debug.Assert(_index > 0); _index--; _curNode = _nodes[_index]; // set the element data Debug.Assert(_curNode == startTagNode); startTagNode.lineInfo = endTagLineInfo; startTagNode.type = XmlNodeType.EndElement; _ps.charPos = pos + 1; // set next parsing function _nextParsingFunction = (_index > 0) ? _parsingFunction : ParsingFunction.DocumentContent; _parsingFunction = ParsingFunction.PopElementContext; }
void IDtdParserAdapter.OnSystemId(string systemId, LineInfo keywordLineInfo, LineInfo systemLiteralLineInfo) { _reader.DtdParserProxy_OnSystemId(systemId, keywordLineInfo, systemLiteralLineInfo); }
void IDtdParserAdapter.OnPublicId(string publicId, LineInfo keywordLineInfo, LineInfo publicLiteralLineInfo) { _reader.DtdParserProxy_OnPublicId(publicId, keywordLineInfo, publicLiteralLineInfo); }
void IDtdParserAdapter.OnPublicId( string publicId, LineInfo keywordLineInfo, LineInfo publicLiteralLineInfo ) { reader.DtdParserProxy_OnPublicId( publicId, keywordLineInfo, publicLiteralLineInfo ); }
void IDtdParserAdapter.OnSystemId( string systemId, LineInfo keywordLineInfo, LineInfo systemLiteralLineInfo ) { reader.DtdParserProxy_OnSystemId( systemId, keywordLineInfo, systemLiteralLineInfo ); }
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; }
internal void DtdParserProxy_OnSystemId(string systemId, LineInfo keywordLineInfo, LineInfo systemLiteralLineInfo) { NodeData attr = AddAttributeNoChecks("SYSTEM", _index + 1); attr.SetValue(systemId); attr.lineInfo = keywordLineInfo; attr.lineInfo2 = systemLiteralLineInfo; }
private Task ParseEndElementAsync_Finish(int nameLen, NodeData startTagNode, LineInfo endTagLineInfo) { Task task = ParseEndElementAsync_CheckEndTag(nameLen, startTagNode, endTagLineInfo); while (true) { if (!task.IsSuccess()) { return ParseEndElementAsync_Finish(task, nameLen, startTagNode, endTagLineInfo); } switch (_parseEndElement_NextFunc) { case ParseEndElementParseFunction.CheckEndTag: task = ParseEndElementAsync_CheckEndTag(nameLen, startTagNode, endTagLineInfo); break; case ParseEndElementParseFunction.ReadData: task = ParseEndElementAsync_ReadData(); break; case ParseEndElementParseFunction.Done: return task; } } }
internal void DtdParserProxy_OnPublicId(string publicId, LineInfo keywordLineInfo, LineInfo publicLiteralLineInfo) { NodeData attr = AddAttributeNoChecks("PUBLIC", _index + 1); attr.SetValue(publicId); attr.lineInfo = keywordLineInfo; attr.lineInfo2 = publicLiteralLineInfo; }
private async Task ParseEndElementAsync_Finish(Task task, int nameLen, NodeData startTagNode, LineInfo endTagLineInfo) { while (true) { await task.ConfigureAwait(false); switch (_parseEndElement_NextFunc) { case ParseEndElementParseFunction.CheckEndTag: task = ParseEndElementAsync_CheckEndTag(nameLen, startTagNode, endTagLineInfo); break; case ParseEndElementParseFunction.ReadData: task = ParseEndElementAsync_ReadData(); break; case ParseEndElementParseFunction.Done: return; } } }
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 Task ParseEndElementAsync_CheckEndTag(int nameLen, NodeData startTagNode, LineInfo endTagLineInfo) { int pos; char[] chars; for (; ;) { pos = _ps.charPos + nameLen; chars = _ps.chars; if (pos == _ps.charsUsed) { _parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData; return Task.CompletedTask; } bool tagMismatch = false; unsafe { if (_xmlCharType.IsNCNameSingleChar(chars[pos]) || (chars[pos] == ':') #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(chars[pos]) #endif ) { tagMismatch = true; } } if (tagMismatch) { return ThrowTagMismatchAsync(startTagNode); } // eat whitespaces if (chars[pos] != '>') { char tmpCh; while (_xmlCharType.IsWhiteSpace(tmpCh = chars[pos])) { pos++; switch (tmpCh) { case (char)0xA: OnNewLine(pos); continue; case (char)0xD: if (chars[pos] == (char)0xA) { pos++; } else if (pos == _ps.charsUsed && !_ps.isEof) { break; } OnNewLine(pos); continue; } } } if (chars[pos] == '>') { break; } else if (pos == _ps.charsUsed) { _parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData; return Task.CompletedTask; } else { ThrowUnexpectedToken(pos, ">"); } Debug.Assert(false, "We should never get to this point."); } Debug.Assert(_index > 0); _index--; _curNode = _nodes[_index]; // set the element data Debug.Assert(_curNode == startTagNode); startTagNode.lineInfo = endTagLineInfo; startTagNode.type = XmlNodeType.EndElement; _ps.charPos = pos + 1; // set next parsing function _nextParsingFunction = (_index > 0) ? _parsingFunction : ParsingFunction.DocumentContent; _parsingFunction = ParsingFunction.PopElementContext; _parseEndElement_NextFunc = ParseEndElementParseFunction.Done; return Task.CompletedTask; }
internal static unsafe void AdjustLineInfo(string str, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) { Debug.Assert(startPos >= 0); Debug.Assert(endPos < str.Length); Debug.Assert(startPos <= endPos); fixed (char* pChars = str) { AdjustLineInfo(pChars + startPos, endPos - startPos, isNormalized, ref lineInfo); } }
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 void ParseExternalId(Token idTokenType, Token declType, out string publicId, out string systemId) { LineInfo keywordLineInfo = new LineInfo(LineNo, LinePos - 6); publicId = null; systemId = null; if (GetToken(true) != Token.Literal) { ThrowUnexpectedToken(_curPos, "\"", "'"); } if (idTokenType == Token.SYSTEM) { systemId = GetValue(); if (systemId.IndexOf('#') >= 0) { Throw(_curPos - systemId.Length - 1, SR.Xml_FragmentId, new string[] { systemId.Substring(systemId.IndexOf('#')), systemId }); } if (declType == Token.DOCTYPE && !_freeFloatingDtd) { _literalLineInfo.linePos++; _readerAdapter.OnSystemId(systemId, keywordLineInfo, _literalLineInfo); } } else { Debug.Assert(idTokenType == Token.PUBLIC); publicId = GetValue(); // verify if it contains chars valid for public ids int i; if ((i = _xmlCharType.IsPublicId(publicId)) >= 0) { ThrowInvalidChar(_curPos - 1 - publicId.Length + i, publicId, i); } if (declType == Token.DOCTYPE && !_freeFloatingDtd) { _literalLineInfo.linePos++; _readerAdapter.OnPublicId(publicId, keywordLineInfo, _literalLineInfo); if (GetToken(false) == Token.Literal) { if (!_whitespaceSeen) { Throw(SR.Xml_ExpectingWhiteSpace, new string(_literalQuoteChar, 1), (int)_literalLineInfo.lineNo, (int)_literalLineInfo.linePos); } systemId = GetValue(); _literalLineInfo.linePos++; _readerAdapter.OnSystemId(systemId, keywordLineInfo, _literalLineInfo); } else { ThrowUnexpectedToken(_curPos, "\"", "'"); } } else { if (GetToken(false) == Token.Literal) { if (!_whitespaceSeen) { Throw(SR.Xml_ExpectingWhiteSpace, new string(_literalQuoteChar, 1), (int)_literalLineInfo.lineNo, (int)_literalLineInfo.linePos); } systemId = GetValue(); } else if (declType != Token.NOTATION) { ThrowUnexpectedToken(_curPos, "\"", "'"); } } } }
protected override void Render(HtmlTextWriter writer) { int nRet = 0; string strError = ""; List<LineInfo> infos = new List<LineInfo>(); int nPageNo = this.StartIndex / this.PageMaxLines; if (this.DatabaseMode == false) { // return: // -1 出错 // 0 成功 // 1 尚未登录 nRet = this.LoadReaderXml(out strError); if (nRet == -1) { writer.Write(strError); return; } if (nRet == 1) { sessioninfo.LoginCallStack.Push(this.Page.Request.RawUrl); this.Page.Response.Redirect("login.aspx", true); return; } XmlNodeList nodes = ReaderDom.DocumentElement.SelectNodes("borrowHistory/borrow"); SetResultInfo(nodes.Count); for (int i = this.StartIndex; i < this.StartIndex + this.PageMaxLines; i++) { if (i >= nodes.Count) { infos.Add(new LineInfo()); } else { XmlNode node = nodes[i]; infos.Add(new LineInfo(node as XmlElement)); } } } else { List<ChargingItemWrapper> results = null; // return: // -2 尚未登录 // -1 出错 // 其它 符合条件的事项总数 nRet = GetChargingHistory(nPageNo, this.PageMaxLines, out results, out strError); if (nRet == -1) { writer.Write(strError); return; } if (nRet == -2) { sessioninfo.LoginCallStack.Push(this.Page.Request.RawUrl); this.Page.Response.Redirect("login.aspx", true); return; } SetResultInfo(nRet); if (results != null) // 2016/10/30 { for (int i = 0; i < this.PageMaxLines; i++) { if (i >= results.Count) { infos.Add(new LineInfo()); } else { ChargingItemWrapper wrapper = results[i]; LineInfo info = new LineInfo(wrapper); infos.Add(info); } } } } if (infos.Count != 0) { //OpacApplication app = (OpacApplication)this.Page.Application["app"]; //SessionInfo sessioninfo = (SessionInfo)this.Page.Session["sessioninfo"]; // 显示本页中的浏览行 { int i = 0; foreach (LineInfo info in infos) { StringBuilder text = new StringBuilder(); string strBarcodeLink = "<a href='book.aspx?barcode=" + info.strBarcode + "&forcelogin=userid' target='_blank'>" + info.strBarcode + "</a>"; string strItemBarcode = info.strBarcode; if (info.strAction == "read") { if (string.IsNullOrEmpty(strItemBarcode) == true) strItemBarcode = "@biblioRecPath:" + info.strBiblioRecPath; strBarcodeLink = "<a href='book.aspx?barcode=" + strItemBarcode + "&forcelogin=userid' target='_blank'>" + strItemBarcode + "</a>"; } string strTrClass = " class='dark content " + info.strAction + "' "; if ((i % 2) == 1) strTrClass = " class='light content " + info.strAction + "' "; text.Append("<tr " + strTrClass + ">"); text.Append("<td class='no'>" + (i + this.StartIndex + 1).ToString() + "</td>"); text.Append("<td class='action'>" + HttpUtility.HtmlEncode(GetActionName(info.strAction)) + "</td>"); text.Append("<td class='barcode'>" + strBarcodeLink + "</td>"); text.Append("<td class='summary pending' >" + HttpUtility.HtmlEncode(strItemBarcode) + "</td>"); info.strBorrowPeriod = app.GetDisplayTimePeriodStringEx(info.strBorrowPeriod); if (info.IsEmpty() == true) text.Append("<td class='borrowinfo'>" + "</td>"); else { if (info.strAction == "read") text.Append("<td class='borrowinfo'>" + "<div class='returndate'>" + this.GetString("操作日期") + ":" + info.strReturnDate + "</div>" + "</td>"); else text.Append("<td class='borrowinfo'>" + "<div class='borrowno'>" + this.GetString("续借次") + " :" + info.strNo + "</div>" + "<div class='borrowdate'>" + this.GetString("借阅日期") + ":" + info.strBorrowDate + "</div>" + "<div class='borrowperiod'>" + this.GetString("期限") + ": " + info.strBorrowPeriod + "</div>" + "<div class='returndate'>" + this.GetString("还书日期") + ":" + info.strReturnDate + "</div>" + "</td>"); } text.Append("<td class='renewcomment'>" + HttpUtility.HtmlEncode(info.strRenewComment) + "</td>"); if (this.DatabaseMode == false || info.IsEmpty()) text.Append("<td class='operator'>" + info.strOperator + "</td>"); else { if (info.strAction == "read") text.Append("<td class='operator'>" + HttpUtility.HtmlEncode(info.strOperator) + "</td>"); else text.Append("<td class='operator'>" + "<div class='borrowoperator'>" + this.GetString("借") + ": " + HttpUtility.HtmlEncode(info.strBorrowOperator) + "</div>" + "<div class='returnoperator'>" + this.GetString("还") + ": " + HttpUtility.HtmlEncode(info.strOperator) + "</div>" + "</td>"); } text.Append("</tr>"); PlaceHolder line = (PlaceHolder)this.FindControl("line" + Convert.ToString(i)); if (line == null) { PlaceHolder insertpoint = (PlaceHolder)this.FindControl("insertpoint"); PlaceHolder content = (PlaceHolder)this.FindControl("content"); line = this.NewContentLine(content, i, insertpoint); } LiteralControl contentcontrol = (LiteralControl)this.FindControl("line" + Convert.ToString(i) + "_content"); contentcontrol.Text = text.ToString(); i++; } // end of for } this.LineCount = Math.Max(this.LineCount, this.PageMaxLines); } else { // 显示空行 for (int i = 0; i < this.PageMaxLines; i++) { PlaceHolder line = (PlaceHolder)this.FindControl("line" + Convert.ToString(i)); if (line == null) continue; } } base.Render(writer); }