Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / Core / XmlTextReaderImpl.cs / 1305376 / XmlTextReaderImpl.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.IO; using System.Text; using System.Security; using System.Threading; using System.Xml.Schema; using System.Collections; using System.Diagnostics; using System.Globalization; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.Versioning; #if SILVERLIGHT using System.Reflection; #endif #if SILVERLIGHT using BufferBuilder=System.Xml.BufferBuilder; #else using BufferBuilder = System.Text.StringBuilder; #endif namespace System.Xml { internal partial class XmlTextReaderImpl : XmlReader, IXmlLineInfo, IXmlNamespaceResolver { // // Private helper types // // ParsingFunction = what should the reader do when the next Read() is called enum ParsingFunction { ElementContent = 0, NoData, #if !SILVERLIGHT OpenUrl, #endif SwitchToInteractive, SwitchToInteractiveXmlDecl, DocumentContent, MoveToElementContent, PopElementContext, PopEmptyElementContext, ResetAttributesRootLevel, Error, Eof, ReaderClosed, EntityReference, InIncrementalRead, #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) FragmentAttribute, ReportEndEntity, AfterResolveEntityInContent, AfterResolveEmptyEntityInContent, #endif XmlDeclarationFragment, GoToEof, PartialTextValue, // these two states must be last; see InAttributeValueIterator property InReadAttributeValue, InReadValueChunk, InReadContentAsBinary, InReadElementContentAsBinary, } enum ParsingMode { Full, SkipNode, SkipContent, } enum EntityType { CharacterDec, CharacterHex, CharacterNamed, Expanded, Skipped, FakeExpanded, #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) Unexpanded, ExpandedInAttribute, #endif } enum EntityExpandType { All, OnlyGeneral, #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) OnlyCharacter, #endif } enum IncrementalReadState { // Following values are used in ReadText, ReadBase64 and ReadBinHex (V1 streaming methods) Text, StartTag, PI, CDATA, Comment, Attributes, AttributeValue, ReadData, EndElement, End, // Following values are used in ReadTextChunk, ReadContentAsBase64 and ReadBinHexChunk (V2 streaming methods) ReadValueChunk_OnCachedValue, ReadValueChunk_OnPartialValue, ReadContentAsBinary_OnCachedValue, ReadContentAsBinary_OnPartialValue, ReadContentAsBinary_End, } // // Fields // // XmlCharType instance XmlCharType xmlCharType = XmlCharType.Instance; // current parsing state (aka. scanner data) ParsingState ps; // parsing function = what to do in the next Read() (3-items-long stack, usually used just 2 level) ParsingFunction parsingFunction; ParsingFunction nextParsingFunction; ParsingFunction nextNextParsingFunction; // stack of nodes NodeData[] nodes; // current node NodeData curNode; // current index int index = 0; // attributes info int curAttrIndex = -1; int attrCount; int attrHashtable; int attrDuplWalkCount; bool attrNeedNamespaceLookup; bool fullAttrCleanup; NodeData[] attrDuplSortingArray; // name table XmlNameTable nameTable; bool nameTableFromSettings; // resolver XmlResolver xmlResolver; #if !SILVERLIGHT // Needed only for XmlTextReader constructors that takes url // this is only for constructors that takes url string url = string.Empty; CompressedStack compressedStack; #endif // settings bool normalize; bool supportNamespaces = true; WhitespaceHandling whitespaceHandling; DtdProcessing dtdProcessing = DtdProcessing.Parse; #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) EntityHandling entityHandling; #endif bool ignorePIs; bool ignoreComments; bool checkCharacters; int lineNumberOffset; int linePositionOffset; bool closeInput; long maxCharactersInDocument; long maxCharactersFromEntities; // this flag enables XmlTextReader backwards compatibility; // when false, the reader has been created via XmlReader.Create bool v1Compat; // namespace handling XmlNamespaceManager namespaceManager; string lastPrefix = string.Empty; // xml context (xml:space, xml:lang, default namespace) XmlContext xmlContext; // stack of parsing states (=stack of entities) private ParsingState[] parsingStatesStack; private int parsingStatesStackTop = -1; // current node base uri and encoding string reportedBaseUri; Encoding reportedEncoding; // DTD IDtdInfo dtdInfo; // fragment parsing XmlNodeType fragmentType = XmlNodeType.Document; XmlParserContext fragmentParserContext; #if !SILVERLIGHT // Needed only for XmlTextReader bool fragment; #endif // incremental read IncrementalReadDecoder incReadDecoder; IncrementalReadState incReadState; LineInfo incReadLineInfo; BinHexDecoder binHexDecoder; Base64Decoder base64Decoder; #if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex) int incReadDepth; int incReadLeftStartPos; int incReadLeftEndPos; IncrementalReadCharsDecoder readCharsDecoder; #endif // ReadAttributeValue helpers #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) int attributeValueBaseEntityId; bool emptyEntityInAttributeResolved; #endif // Validation helpers #if !SILVERLIGHT // No validation in Silverlight IValidationEventHandling validationEventHandling; OnDefaultAttributeUseDelegate onDefaultAttributeUse; #endif #if !SILVERLIGHT // Needed only for XmlTextReader and XmlValidatingReader bool validatingReaderCompatFlag; #endif // misc bool addDefaultAttributesAndNormalize; BufferBuilder stringBuilder; bool rootElementParsed; bool standalone; int nextEntityId = 1; ParsingMode parsingMode; ReadState readState = ReadState.Initial; #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities, ResetState) IDtdEntityInfo lastEntity; bool afterResetState; #endif int documentStartBytePos; int readValueOffset; // Counters for security settings long charactersInDocument; long charactersFromEntities; // All entities that are currently being processed DictionarycurrentEntities; // DOM helpers #if !SILVERLIGHT // Needed only for XmlTextReader (when used from XmlDocument) bool disableUndeclaredEntityCheck; #endif // Outer XmlReader exposed to the user - either XmlTextReader or XmlTextReaderImpl (when created via XmlReader.Create). // Virtual methods called from within XmlTextReaderImpl must be called on the outer reader so in case the user overrides // some of the XmlTextReader methods we will call the overriden version. XmlReader outerReader; // // Atomized string constants // private string Xml; private string XmlNs; // // Constants // private const int MaxBytesToMove = 128; private const int ApproxXmlDeclLength = 80; private const int NodesInitialSize = 8; private const int InitialAttributesCount = 4; private const int InitialParsingStateStackSize = 2; private const int InitialParsingStatesDepth = 2; private const int DtdChidrenInitialSize = 2; private const int MaxByteSequenceLen = 6; // max bytes per character private const int MaxAttrDuplWalkCount = 250; private const int MinWhitespaceLookahedCount = 4096; private const string XmlDeclarationBegining = "" ) ); InitFragmentReader( XmlNodeType.XmlDeclaration, context, true ); } // Initializes a new instance of the XmlTextReaderImpl class with the specified url and XmlNameTable. // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader #if !SILVERLIGHT [ResourceConsumption(ResourceScope.Machine)] [ResourceExposure(ResourceScope.Machine)] #endif public XmlTextReaderImpl( string url ) : this( url, new NameTable() ) { } #if !SILVERLIGHT [ResourceConsumption(ResourceScope.Machine)] [ResourceExposure(ResourceScope.Machine)] #endif public XmlTextReaderImpl( string url, XmlNameTable nt ): this( nt ) { if ( url == null ) { throw new ArgumentNullException( "url" ); } if ( url.Length == 0 ) { throw new ArgumentException( Res.GetString( Res.Xml_EmptyUrl ), "url" ); } namespaceManager = new XmlNamespaceManager( nt ); compressedStack = CompressedStack.Capture(); this.url = url; ps.baseUri = xmlResolver.ResolveUri( null, url ); ps.baseUriStr = ps.baseUri.ToString(); reportedBaseUri = ps.baseUriStr; parsingFunction = ParsingFunction.OpenUrl; } #endif // Initializes a new instance of the XmlTextReaderImpl class with the specified arguments. // This constructor is used when creating XmlTextReaderImpl via XmlReader.Create internal XmlTextReaderImpl( Stream stream, byte[] bytes, int byteCount, XmlReaderSettings settings, Uri baseUri, string baseUriStr, XmlParserContext context, bool closeInput ) : this( settings.GetXmlResolver(), settings, context ) { Encoding enc = null; // get BaseUri and Encoding from XmlParserContext if ( context != null ) { if ( context.BaseURI != null && context.BaseURI.Length > 0 && !UriEqual( baseUri, baseUriStr, context.BaseURI, settings.GetXmlResolver() ) ) { if ( baseUriStr.Length > 0 ) { Throw( Res.Xml_DoubleBaseUri ); } Debug.Assert( baseUri == null ); baseUriStr = context.BaseURI; } enc = context.Encoding; } // init ParsingState InitStreamInput( baseUri, baseUriStr, stream, bytes, byteCount, enc ); this.closeInput = closeInput; reportedBaseUri = ps.baseUriStr; reportedEncoding = ps.encoding; // parse DTD if ( context != null && context.HasDtdInfo ) { ProcessDtdFromParserContext(context); } } // Initializes a new instance of the XmlTextReaderImpl class with the specified arguments. // This constructor is used when creating XmlTextReaderImpl via XmlReader.Create internal XmlTextReaderImpl( TextReader input, XmlReaderSettings settings, string baseUriStr, XmlParserContext context ) : this( settings.GetXmlResolver(), settings, context ) { // get BaseUri from XmlParserContext if ( context != null ) { Debug.Assert( baseUriStr == string.Empty, "BaseURI can come either from XmlParserContext or from the constructor argument, not from both" ); if ( context.BaseURI != null ) { baseUriStr = context.BaseURI; } } // init ParsingState InitTextReaderInput( baseUriStr, input ); this.closeInput = settings.CloseInput; reportedBaseUri = ps.baseUriStr; reportedEncoding = ps.encoding; // parse DTD if ( context != null && context.HasDtdInfo ) { ProcessDtdFromParserContext( context); } } #if !SILVERLIGHT // Initializes a new instance of the XmlTextReaderImpl class for fragment parsing. // This constructor is used by XmlBinaryReader for nested text XML internal XmlTextReaderImpl( string xmlFragment, XmlParserContext context, XmlReaderSettings settings ) : this( null, settings, context ) { InitStringInput( string.Empty, Encoding.Unicode, xmlFragment ); reportedBaseUri = ps.baseUriStr; reportedEncoding = ps.encoding; } #endif // // XmlReader members // // Returns the current settings of the reader public override XmlReaderSettings Settings { get { XmlReaderSettings settings = new XmlReaderSettings(); if (nameTableFromSettings) { settings.NameTable = nameTable; } switch (fragmentType) { case XmlNodeType.None: settings.ConformanceLevel = ConformanceLevel.Auto; break; case XmlNodeType.Element: settings.ConformanceLevel = ConformanceLevel.Fragment; break; case XmlNodeType.Document: settings.ConformanceLevel = ConformanceLevel.Document; break; default: Debug.Assert(false); goto case XmlNodeType.None; } settings.CheckCharacters = checkCharacters; settings.LineNumberOffset = lineNumberOffset; settings.LinePositionOffset = linePositionOffset; settings.IgnoreWhitespace = (whitespaceHandling == WhitespaceHandling.Significant); settings.IgnoreProcessingInstructions = ignorePIs; settings.IgnoreComments = ignoreComments; settings.DtdProcessing = dtdProcessing; settings.MaxCharactersInDocument = maxCharactersInDocument; settings.MaxCharactersFromEntities = maxCharactersFromEntities; settings.ReadOnly = true; return settings; } } // Returns the type of the current node. public override XmlNodeType NodeType { get { return curNode.type; } } // Returns the name of the current node, including prefix. public override string Name { get { return curNode.GetNameWPrefix( nameTable ); } } // Returns local name of the current node (without prefix) public override string LocalName { get { return curNode.localName; } } // Returns namespace name of the current node. public override string NamespaceURI { get { return curNode.ns; } } // Returns prefix associated with the current node. public override string Prefix { get { return curNode.prefix; } } // Returns the text value of the current node. public override string Value { get { if ( parsingFunction >= ParsingFunction.PartialTextValue ) { if ( parsingFunction == ParsingFunction.PartialTextValue ) { FinishPartialValue(); parsingFunction = nextParsingFunction; } else { FinishOtherValueIterator(); } } return curNode.StringValue; } } // Returns the depth of the current node in the XML element stack public override int Depth { get { return curNode.depth; } } // Returns the base URI of the current node. public override string BaseURI { get { return reportedBaseUri; } } // Returns true if the current node is an empty element (for example, ). public override bool IsEmptyElement { get { return curNode.IsEmptyElement; } } // Returns true of the current node is a default attribute declared in DTD. public override bool IsDefault { get { return curNode.IsDefaultAttribute; } } #if !SILVERLIGHT // Returns the quote character used in the current attribute declaration public override char QuoteChar { get { return curNode.type == XmlNodeType.Attribute ? curNode.quoteChar : '"'; } } #endif // Returns the current xml:space scope. public override XmlSpace XmlSpace { get { return xmlContext.xmlSpace; } } // Returns the current xml:lang scope. public override string XmlLang { get { return xmlContext.xmlLang; } } // Returns the current read state of the reader public override ReadState ReadState { get { return readState; } } // Returns true if the reader reached end of the input data public override bool EOF { get { return parsingFunction == ParsingFunction.Eof; } } // Returns the XmlNameTable associated with this XmlReader public override XmlNameTable NameTable { get { return nameTable; } } // Returns true if the XmlReader knows how to resolve general entities public override bool CanResolveEntity { get { return true; } } // Returns the number of attributes on the current node. public override int AttributeCount { get { return attrCount; } } // Returns value of an attribute with the specified Name public override string GetAttribute( string name ) { int i; if ( name.IndexOf( ':' ) == -1 ) { i = GetIndexOfAttributeWithoutPrefix( name ); } else { i = GetIndexOfAttributeWithPrefix( name ); } return ( i >= 0 ) ? nodes[i].StringValue : null; } // Returns value of an attribute with the specified LocalName and NamespaceURI public override string GetAttribute( string localName, string namespaceURI ) { namespaceURI = ( namespaceURI == null ) ? string.Empty : nameTable.Get( namespaceURI ); localName = nameTable.Get( localName ); for ( int i = index + 1; i < index + attrCount + 1; i++ ) { if ( Ref.Equal( nodes[i].localName, localName ) && Ref.Equal( nodes[i].ns, namespaceURI ) ) { return nodes[i].StringValue; } } return null; } // Returns value of an attribute at the specified index (position) public override string GetAttribute( int i ) { if ( i < 0 || i >= attrCount ) { throw new ArgumentOutOfRangeException("i"); } return nodes[index + i + 1].StringValue; } // Moves to an attribute with the specified Name public override bool MoveToAttribute( string name ) { int i; if ( name.IndexOf( ':' ) == -1 ) { i = GetIndexOfAttributeWithoutPrefix( name ); } else { i = GetIndexOfAttributeWithPrefix( name ); } if ( i >= 0 ) { if ( InAttributeValueIterator ) { FinishAttributeValueIterator(); } curAttrIndex = i - index - 1; curNode = nodes[i]; return true; } else { return false; } } // Moves to an attribute with the specified LocalName and NamespceURI public override bool MoveToAttribute( string localName, string namespaceURI ) { namespaceURI = ( namespaceURI == null ) ? string.Empty : nameTable.Get( namespaceURI ); localName = nameTable.Get( localName ); for ( int i = index + 1; i < index + attrCount + 1; i++ ) { if ( Ref.Equal( nodes[i].localName, localName ) && Ref.Equal( nodes[i].ns, namespaceURI ) ) { curAttrIndex = i - index - 1; curNode = nodes[i]; if ( InAttributeValueIterator ) { FinishAttributeValueIterator(); } return true; } } return false; } // Moves to an attribute at the specified index (position) public override void MoveToAttribute( int i ) { if ( i < 0 || i >= attrCount ) { throw new ArgumentOutOfRangeException( "i" ); } if ( InAttributeValueIterator ) { FinishAttributeValueIterator(); } curAttrIndex = i; curNode = nodes[index + 1 + curAttrIndex]; } // Moves to the first attribute of the current node public override bool MoveToFirstAttribute() { if ( attrCount == 0 ) { return false; } if ( InAttributeValueIterator ) { FinishAttributeValueIterator(); } curAttrIndex = 0; curNode = nodes[index + 1]; return true; } // Moves to the next attribute of the current node public override bool MoveToNextAttribute() { if ( curAttrIndex + 1 < attrCount ) { if ( InAttributeValueIterator ) { FinishAttributeValueIterator(); } curNode = nodes[ index + 1 + ++curAttrIndex ]; return true; } return false; } // If on attribute, moves to the element that contains the attribute node public override bool MoveToElement() { if ( InAttributeValueIterator ) { FinishAttributeValueIterator(); } else if ( curNode.type != XmlNodeType.Attribute ) { return false; } curAttrIndex = -1; curNode = nodes[index]; return true; } // Reads next node from the input data public override bool Read() { for (;;) { switch ( parsingFunction ) { case ParsingFunction.ElementContent: return ParseElementContent(); case ParsingFunction.DocumentContent: return ParseDocumentContent(); #if !SILVERLIGHT // Needed only for XmlTextReader case ParsingFunction.OpenUrl: OpenUrl(); Debug.Assert( nextParsingFunction == ParsingFunction.DocumentContent ); goto case ParsingFunction.SwitchToInteractiveXmlDecl; #endif case ParsingFunction.SwitchToInteractive: Debug.Assert( !ps.appendMode ); readState = ReadState.Interactive; parsingFunction = nextParsingFunction; continue; case ParsingFunction.SwitchToInteractiveXmlDecl: readState = ReadState.Interactive; parsingFunction = nextParsingFunction; if ( ParseXmlDeclaration( false ) ) { reportedEncoding = ps.encoding; return true; } reportedEncoding = ps.encoding; continue; case ParsingFunction.ResetAttributesRootLevel: ResetAttributes(); curNode = nodes[index]; parsingFunction = ( index == 0 ) ? ParsingFunction.DocumentContent : ParsingFunction.ElementContent; continue; case ParsingFunction.MoveToElementContent: ResetAttributes(); index++; curNode = AddNode( index, index ); parsingFunction = ParsingFunction.ElementContent; continue; case ParsingFunction.PopElementContext: PopElementContext(); parsingFunction = nextParsingFunction; Debug.Assert( parsingFunction == ParsingFunction.ElementContent || parsingFunction == ParsingFunction.DocumentContent ); continue; case ParsingFunction.PopEmptyElementContext: curNode = nodes[index]; Debug.Assert( curNode.type == XmlNodeType.Element ); curNode.IsEmptyElement = false; ResetAttributes(); PopElementContext(); parsingFunction = nextParsingFunction; continue; #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) case ParsingFunction.EntityReference: parsingFunction = nextParsingFunction; ParseEntityReference(); return true; case ParsingFunction.ReportEndEntity: SetupEndEntityNodeInContent(); parsingFunction = nextParsingFunction; return true; case ParsingFunction.AfterResolveEntityInContent: curNode = AddNode( index, index ); reportedEncoding = ps.encoding; reportedBaseUri = ps.baseUriStr; parsingFunction = nextParsingFunction; continue; case ParsingFunction.AfterResolveEmptyEntityInContent: curNode = AddNode( index, index ); curNode.SetValueNode( XmlNodeType.Text, string.Empty ); curNode.SetLineInfo( ps.lineNo, ps.LinePos ); reportedEncoding = ps.encoding; reportedBaseUri = ps.baseUriStr; parsingFunction = nextParsingFunction; return true; #endif case ParsingFunction.InReadAttributeValue: FinishAttributeValueIterator(); curNode = nodes[index]; continue; #if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex) case ParsingFunction.InIncrementalRead: FinishIncrementalRead(); return true; case ParsingFunction.FragmentAttribute: return ParseFragmentAttribute(); case ParsingFunction.XmlDeclarationFragment: ParseXmlDeclarationFragment(); parsingFunction = ParsingFunction.GoToEof; return true; #endif case ParsingFunction.GoToEof: OnEof(); return false; case ParsingFunction.Error: case ParsingFunction.Eof: case ParsingFunction.ReaderClosed: return false; case ParsingFunction.NoData: ThrowWithoutLineInfo( Res.Xml_MissingRoot ); return false; case ParsingFunction.PartialTextValue: SkipPartialTextValue(); continue; case ParsingFunction.InReadValueChunk: FinishReadValueChunk(); continue; case ParsingFunction.InReadContentAsBinary: FinishReadContentAsBinary(); continue; case ParsingFunction.InReadElementContentAsBinary: FinishReadElementContentAsBinary(); continue; default: Debug.Assert( false ); break; } } } // Closes the input stream ot TextReader, changes the ReadState to Closed and sets all properties to zero/string.Empty public override void Close() { Close( closeInput ); } // Skips the current node. If on element, skips to the end tag of the element. public override void Skip() { if ( readState != ReadState.Interactive ) return; if ( InAttributeValueIterator ) { FinishAttributeValueIterator(); curNode = nodes[index]; } else { switch ( parsingFunction ) { case ParsingFunction.InReadAttributeValue: Debug.Assert( false ); break; #if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex) case ParsingFunction.InIncrementalRead: FinishIncrementalRead(); break; #endif case ParsingFunction.PartialTextValue: SkipPartialTextValue(); break; case ParsingFunction.InReadValueChunk: FinishReadValueChunk(); break; case ParsingFunction.InReadContentAsBinary: FinishReadContentAsBinary(); break; case ParsingFunction.InReadElementContentAsBinary: FinishReadElementContentAsBinary(); break; } } switch ( curNode.type ) { // skip subtree case XmlNodeType.Element: if ( curNode.IsEmptyElement ) { break; } int initialDepth = index; parsingMode = ParsingMode.SkipContent; // skip content while ( outerReader.Read() && index > initialDepth ) ; Debug.Assert( curNode.type == XmlNodeType.EndElement ); Debug.Assert( parsingFunction != ParsingFunction.Eof ); parsingMode = ParsingMode.Full; break; case XmlNodeType.Attribute: outerReader.MoveToElement(); goto case XmlNodeType.Element; } // move to following sibling node outerReader.Read(); return; } // Returns NamespaceURI associated with the specified prefix in the current namespace scope. public override String LookupNamespace( String prefix ) { if ( !supportNamespaces ) { return null; } return namespaceManager.LookupNamespace( prefix ); } // Iterates through the current attribute value's text and entity references chunks. public override bool ReadAttributeValue() { if ( parsingFunction != ParsingFunction.InReadAttributeValue ) { if ( curNode.type != XmlNodeType.Attribute ) { return false; } if ( readState != ReadState.Interactive || curAttrIndex < 0 ) { return false; } if ( parsingFunction == ParsingFunction.InReadValueChunk ) { FinishReadValueChunk(); } if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { FinishReadContentAsBinary(); } #if SILVERLIGHT NodeData simpleValueNode = AddNode( index + attrCount + 1, curNode.depth + 1 ); simpleValueNode.SetValueNode( XmlNodeType.Text, curNode.StringValue ); simpleValueNode.lineInfo = curNode.lineInfo2; simpleValueNode.depth = curNode.depth + 1; curNode = simpleValueNode; nextParsingFunction = parsingFunction; parsingFunction = ParsingFunction.InReadAttributeValue; #else if ( curNode.nextAttrValueChunk == null || entityHandling == EntityHandling.ExpandEntities ) { NodeData simpleValueNode = AddNode( index + attrCount + 1, curNode.depth + 1 ); simpleValueNode.SetValueNode( XmlNodeType.Text, curNode.StringValue ); simpleValueNode.lineInfo = curNode.lineInfo2; simpleValueNode.depth = curNode.depth + 1; curNode = simpleValueNode; simpleValueNode.nextAttrValueChunk = null; } else { curNode = curNode.nextAttrValueChunk; // Place the current node at nodes[index + attrCount + 1]. If the node type // is be EntityReference and user calls ResolveEntity, the associated EndEntity // node will be constructed from the information stored there. // This will initialize the (index + attrCount + 1) place in nodes array AddNode( index + attrCount + 1, index + 2 ); nodes[index + attrCount + 1] = curNode; fullAttrCleanup = true; } nextParsingFunction = parsingFunction; parsingFunction = ParsingFunction.InReadAttributeValue; attributeValueBaseEntityId = ps.entityId; #endif return true; } else { #if SILVERLIGHT return false; #else if ( ps.entityId == attributeValueBaseEntityId ) { if ( curNode.nextAttrValueChunk != null ) { curNode = curNode.nextAttrValueChunk; nodes[index + attrCount + 1] = curNode; // if curNode == EntityReference node, it will be picked from here by SetupEndEntityNodeInAttribute return true; } return false; } else { // expanded entity in attribute value return ParseAttributeValueChunk(); } #endif } } // Resolves the current entity reference node public override void ResolveEntity() { #if SILVERLIGHT // entities are always resolved V2 XmlReader that is Silverlight throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); #else if ( curNode.type != XmlNodeType.EntityReference ) { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); } Debug.Assert( parsingMode == ParsingMode.Full ); // entity in attribute value if ( parsingFunction == ParsingFunction.InReadAttributeValue || parsingFunction == ParsingFunction.FragmentAttribute ) { switch ( HandleGeneralEntityReference( curNode.localName, true, true, curNode.LinePos ) ) { case EntityType.ExpandedInAttribute: case EntityType.Expanded: if ( ps.charsUsed - ps.charPos == 0 ) { // entity value == "" emptyEntityInAttributeResolved = true; } break; case EntityType.FakeExpanded: emptyEntityInAttributeResolved = true; break; default: Debug.Assert( false ); throw new XmlException( Res.Xml_InternalError, string.Empty ); } } // entity in element content else { switch ( HandleGeneralEntityReference( curNode.localName, false, true, curNode.LinePos ) ) { case EntityType.ExpandedInAttribute: case EntityType.Expanded: nextParsingFunction = parsingFunction; if ( ps.charsUsed - ps.charPos == 0 && !ps.entity.IsExternal ) { // empty internal entity value parsingFunction = ParsingFunction.AfterResolveEmptyEntityInContent; } else { parsingFunction = ParsingFunction.AfterResolveEntityInContent; } break; case EntityType.FakeExpanded: nextParsingFunction = parsingFunction; parsingFunction = ParsingFunction.AfterResolveEmptyEntityInContent; break; default: Debug.Assert( false ); throw new XmlException( Res.Xml_InternalError, string.Empty ); } } ps.entityResolvedManually = true; index++; #endif } #if !SILVERLIGHT // Needed only for XmlTextReader or XmlValidatingReader internal XmlReader OuterReader { get { return outerReader; } set { Debug.Assert( value is XmlTextReader ); outerReader = value; } } internal void MoveOffEntityReference() { if ( outerReader.NodeType == XmlNodeType.EntityReference && parsingFunction == ParsingFunction.AfterResolveEntityInContent ) { if ( !outerReader.Read() ) { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); } } } public override string ReadString() { Debug.Assert( outerReader is XmlTextReaderImpl ); MoveOffEntityReference(); return base.ReadString(); } #endif public override bool CanReadBinaryContent { get { return true; } } // Reads and concatenates content nodes, base64-decodes the results and copies the decoded bytes into the provided buffer public override int ReadContentAsBase64( byte[] buffer, int index, int count ) { // check arguments if ( buffer == null ) { throw new ArgumentNullException( "buffer" ); } if ( count < 0 ) { throw new ArgumentOutOfRangeException( "count" ); } if ( index < 0 ) { throw new ArgumentOutOfRangeException( "index" ); } if ( buffer.Length - index < count ) { throw new ArgumentOutOfRangeException( "count" ); } // if not the first call to ReadContentAsBase64 if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { // and if we have a correct decoder if ( incReadDecoder == base64Decoder ) { // read more binary data return ReadContentAsBinary( buffer, index, count ); } } // first call of ReadContentAsBase64 -> initialize (move to first text child (for elements) and initialize incremental read state) else { if ( readState != ReadState.Interactive ) { return 0; } if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); } if ( !XmlReader.CanReadContentAs( curNode.type ) ) { throw CreateReadContentAsException( "ReadContentAsBase64" ); } if ( !InitReadContentAsBinary() ) { return 0; } } // setup base64 decoder InitBase64Decoder(); // read binary data return ReadContentAsBinary( buffer, index, count ); } // Reads and concatenates content nodes, binhex-decodes the results and copies the decoded bytes into the provided buffer public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) { // check arguments if ( buffer == null ) { throw new ArgumentNullException( "buffer" ); } if ( count < 0 ) { throw new ArgumentOutOfRangeException( "count" ); } if ( index < 0 ) { throw new ArgumentOutOfRangeException( "index" ); } if ( buffer.Length - index < count ) { throw new ArgumentOutOfRangeException( "count" ); } // if not the first call to ReadContentAsBinHex if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { // and if we have a correct decoder if ( incReadDecoder == binHexDecoder ) { // read more binary data return ReadContentAsBinary( buffer, index, count ); } } // first call of ReadContentAsBinHex -> initialize (move to first text child (for elements) and initialize incremental read state) else { if ( readState != ReadState.Interactive ) { return 0; } if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); } if ( !XmlReader.CanReadContentAs( curNode.type ) ) { throw CreateReadContentAsException( "ReadContentAsBinHex" ); } if ( !InitReadContentAsBinary() ) { return 0; } } // setup binhex decoder (when in first ReadContentAsBinHex call or when mixed with ReadContentAsBase64) InitBinHexDecoder(); // read binary data return ReadContentAsBinary( buffer, index, count ); } // Reads and concatenates content of an element, base64-decodes the results and copies the decoded bytes into the provided buffer public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) { // check arguments if ( buffer == null ) { throw new ArgumentNullException( "buffer" ); } if ( count < 0 ) { throw new ArgumentOutOfRangeException( "count" ); } if ( index < 0 ) { throw new ArgumentOutOfRangeException( "index" ); } if ( buffer.Length - index < count ) { throw new ArgumentOutOfRangeException( "count" ); } // if not the first call to ReadContentAsBase64 if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { // and if we have a correct decoder if ( incReadDecoder == base64Decoder ) { // read more binary data return ReadElementContentAsBinary( buffer, index, count ); } } // first call of ReadElementContentAsBase64 -> initialize else { if ( readState != ReadState.Interactive ) { return 0; } if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); } if ( curNode.type != XmlNodeType.Element ) { throw CreateReadElementContentAsException( "ReadElementContentAsBinHex" ); } if ( !InitReadElementContentAsBinary() ) { return 0; } } // setup base64 decoder InitBase64Decoder(); // read binary data return ReadElementContentAsBinary( buffer, index, count ); } // Reads and concatenates content of an element, binhex-decodes the results and copies the decoded bytes into the provided buffer public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) { // check arguments if ( buffer == null ) { throw new ArgumentNullException( "buffer" ); } if ( count < 0 ) { throw new ArgumentOutOfRangeException( "count" ); } if ( index < 0 ) { throw new ArgumentOutOfRangeException( "index" ); } if ( buffer.Length - index < count ) { throw new ArgumentOutOfRangeException( "count" ); } // if not the first call to ReadContentAsBinHex if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { // and if we have a correct decoder if ( incReadDecoder == binHexDecoder ) { // read more binary data return ReadElementContentAsBinary( buffer, index, count ); } } // first call of ReadContentAsBinHex -> initialize else { if ( readState != ReadState.Interactive ) { return 0; } if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); } if ( curNode.type != XmlNodeType.Element ) { throw CreateReadElementContentAsException( "ReadElementContentAsBinHex" ); } if ( !InitReadElementContentAsBinary() ) { return 0; } } // setup binhex decoder (when in first ReadContentAsBinHex call or when mixed with ReadContentAsBase64) InitBinHexDecoder(); // read binary data return ReadElementContentAsBinary( buffer, index, count ); } // Returns true if ReadValue is supported public override bool CanReadValueChunk { get { return true; } } // Iterates over Value property and copies it into the provided buffer public override int ReadValueChunk( char[] buffer, int index, int count ) { // throw on elements if ( !XmlReader.HasValueInternal( curNode.type ) ) { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidReadValueChunk, curNode.type ) ) ; } // check arguments if ( buffer == null ) { throw new ArgumentNullException( "buffer" ); } if ( count < 0 ) { throw new ArgumentOutOfRangeException( "count" ); } if ( index < 0 ) { throw new ArgumentOutOfRangeException( "index" ); } if ( buffer.Length - index < count ) { throw new ArgumentOutOfRangeException( "count" ); } // first call of ReadValueChunk -> initialize incremental read state if ( parsingFunction != ParsingFunction.InReadValueChunk ) { if ( readState != ReadState.Interactive ) { return 0; } if ( parsingFunction == ParsingFunction.PartialTextValue ) { incReadState = IncrementalReadState.ReadValueChunk_OnPartialValue; } else { incReadState = IncrementalReadState.ReadValueChunk_OnCachedValue; nextNextParsingFunction = nextParsingFunction; nextParsingFunction = parsingFunction; } parsingFunction = ParsingFunction.InReadValueChunk; readValueOffset = 0; } if ( count == 0 ) { return 0; } // read what is already cached in curNode int readCount = 0; int read = curNode.CopyTo( readValueOffset, buffer, index + readCount, count - readCount ); readCount += read; readValueOffset += read; if ( readCount == count ) { // take care of surrogate pairs spanning between buffers char ch = buffer[index + count - 1]; if ( XmlCharType.IsHighSurrogate(ch) ) { readCount--; readValueOffset--; if ( readCount == 0 ) { Throw( Res.Xml_NotEnoughSpaceForSurrogatePair ); } } return readCount; } // if on partial value, read the rest of it if ( incReadState == IncrementalReadState.ReadValueChunk_OnPartialValue ) { curNode.SetValue( string.Empty ); // read next chunk of text bool endOfValue = false; int startPos = 0; int endPos = 0; while ( readCount < count && !endOfValue ) { int orChars = 0; endOfValue = ParseText( out startPos, out endPos, ref orChars ); int copyCount = count - readCount; if ( copyCount > endPos - startPos ) { copyCount = endPos - startPos; } BlockCopyChars( ps.chars, startPos, buffer, ( index + readCount ), copyCount ); readCount += copyCount; startPos += copyCount; } incReadState = endOfValue ? IncrementalReadState.ReadValueChunk_OnCachedValue : IncrementalReadState.ReadValueChunk_OnPartialValue; if ( readCount == count ) { char ch = buffer[index + count - 1]; if ( XmlCharType.IsHighSurrogate(ch) ) { readCount--; startPos--; if ( readCount == 0 ) { Throw( Res.Xml_NotEnoughSpaceForSurrogatePair ); } } } readValueOffset = 0; curNode.SetValue( ps.chars, startPos, endPos - startPos ); } return readCount; } // // IXmlLineInfo members // public bool HasLineInfo() { return true; } // Returns the line number of the current node public int LineNumber { get { return curNode.LineNo; } } // Returns the line position of the current node public int LinePosition { get { return curNode.LinePos; } } // // IXmlNamespaceResolver members // IDictionary IXmlNamespaceResolver.GetNamespacesInScope( XmlNamespaceScope scope ) { return this.GetNamespacesInScope( scope ); } string IXmlNamespaceResolver.LookupNamespace(string prefix) { return this.LookupNamespace( prefix ); } string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) { return this.LookupPrefix( namespaceName ); } // Internal IXmlNamespaceResolver methods internal IDictionary GetNamespacesInScope( XmlNamespaceScope scope ) { return namespaceManager.GetNamespacesInScope( scope ); } // NOTE: there already is virtual method for "string LookupNamespace(string prefix)" internal string LookupPrefix( string namespaceName ) { return namespaceManager.LookupPrefix( namespaceName ); } // // XmlTextReader members // #if !SILVERLIGHT // Needed only for XmlTextReader // Disables or enables support of W3C XML 1.0 Namespaces internal bool Namespaces { get { return supportNamespaces; } set { if ( readState != ReadState.Initial ) { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); } supportNamespaces = value; if ( value ) { if ( namespaceManager is NoNamespaceManager ) { if ( fragment && fragmentParserContext != null && fragmentParserContext.NamespaceManager != null ) { namespaceManager = fragmentParserContext.NamespaceManager; } else { namespaceManager = new XmlNamespaceManager( nameTable ); } } xmlContext.defaultNamespace = namespaceManager.LookupNamespace( string.Empty ); } else { if ( !( namespaceManager is NoNamespaceManager ) ) { namespaceManager = new NoNamespaceManager(); } xmlContext.defaultNamespace = string.Empty; } } } // Enables or disables XML 1.0 normalization (incl. end-of-line normalization and normalization of attributes) internal bool Normalization { get { Debug.Assert( v1Compat, "XmlTextReaderImpl.Normalization property cannot be accessed on reader created via XmlReader.Create." ); return normalize; } set { Debug.Assert( v1Compat, "XmlTextReaderImpl.Normalization property cannot be changed on reader created via XmlReader.Create." ); if ( readState == ReadState.Closed ) { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); } normalize = value; if ( ps.entity == null || ps.entity.IsExternal ) { ps.eolNormalized = !value; } } } // Returns the Encoding of the XML document internal Encoding Encoding { get { return ( readState == ReadState.Interactive ) ? reportedEncoding : null; } } // Spefifies whitespace handling of the XML document, i.e. whether return all namespaces, only significant ones or none internal WhitespaceHandling WhitespaceHandling { get { Debug.Assert( v1Compat, "XmlTextReaderImpl.WhitespaceHandling property cannot be accessed on reader created via XmlReader.Create." ); return whitespaceHandling; } set { Debug.Assert( v1Compat, "XmlTextReaderImpl.WhitespaceHandling property cannot be changed on reader created via XmlReader.Create." ); if ( readState == ReadState.Closed ) { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); } if ( (uint)value > (uint)WhitespaceHandling.None ) { throw new XmlException( Res.Xml_WhitespaceHandling, string.Empty ); } whitespaceHandling = value; } } // Specifies how the DTD is processed in the XML document. internal DtdProcessing DtdProcessing { get { Debug.Assert( v1Compat, "XmlTextReaderImpl.DtdProcessing property cannot be accessed on reader created via XmlReader.Create." ); return dtdProcessing; } set { Debug.Assert( v1Compat, "XmlTextReaderImpl.DtdProcessing property cannot be changed on reader created via XmlReader.Create." ); if ((uint)value > (uint)DtdProcessing.Parse) { throw new ArgumentOutOfRangeException("value"); } dtdProcessing = value; } } // Spefifies whether general entities should be automatically expanded or not internal EntityHandling EntityHandling { get { return entityHandling; } set { if ( value != EntityHandling.ExpandEntities && value != EntityHandling.ExpandCharEntities ) { throw new XmlException( Res.Xml_EntityHandling, string.Empty ); } entityHandling = value; } } // Specifies XmlResolver used for opening the XML document and other external references internal XmlResolver XmlResolver { set { xmlResolver = value; // invalidate all baseUris on the stack ps.baseUri = null; for ( int i = 0; i <= parsingStatesStackTop; i++ ) { parsingStatesStack[i].baseUri = null; } } } // Reset the state of the reader so the reader is ready to parse another XML document from the same stream. internal void ResetState() { Debug.Assert( v1Compat, "XmlTextReaderImpl.ResetState cannot be called on reader created via XmlReader.Create." ); if ( fragment ) { Throw( new InvalidOperationException( Res.GetString( Res.Xml_InvalidResetStateCall ) ) ); } if ( readState == ReadState.Initial ) { return; } // Clear ResetAttributes(); while ( namespaceManager.PopScope() ); while ( InEntity ) { HandleEntityEnd( true ); } // Init readState = ReadState.Initial; parsingFunction = ParsingFunction.SwitchToInteractiveXmlDecl; nextParsingFunction = ParsingFunction.DocumentContent; curNode = nodes[0]; curNode.Clear( XmlNodeType.None ); curNode.SetLineInfo( 0, 0 ); index = 0; rootElementParsed = false; charactersInDocument = 0; charactersFromEntities = 0; afterResetState = true; } // returns the remaining unparsed data as TextReader internal TextReader GetRemainder() { Debug.Assert( v1Compat, "XmlTextReaderImpl.GetRemainder cannot be called on reader created via XmlReader.Create." ); Debug.Assert( stringBuilder.Length == 0 ); switch ( parsingFunction ) { case ParsingFunction.Eof: case ParsingFunction.ReaderClosed: return new StringReader( string.Empty ); case ParsingFunction.OpenUrl: OpenUrl(); break; case ParsingFunction.InIncrementalRead: if ( !InEntity ) { stringBuilder.Append( ps.chars, incReadLeftStartPos, incReadLeftEndPos - incReadLeftStartPos ); } break; } while ( InEntity ) { HandleEntityEnd( true ); } ps.appendMode = false; do { stringBuilder.Append( ps.chars, ps.charPos, ps.charsUsed - ps.charPos ); ps.charPos = ps.charsUsed; } while ( ReadData() != 0 ); OnEof(); string remainer = stringBuilder.ToString(); stringBuilder.Length = 0; return new StringReader( remainer ); } // Reads the contents of an element including markup into a character buffer. Wellformedness checks are limited. // This method is designed to read large streams of embedded text by calling it successively. internal int ReadChars( char[] buffer, int index, int count ) { Debug.Assert( v1Compat, "XmlTextReaderImpl.ReadChars cannot be called on reader created via XmlReader.Create." ); Debug.Assert( outerReader is XmlTextReader ); if ( parsingFunction == ParsingFunction.InIncrementalRead ) { if ( incReadDecoder != readCharsDecoder ) { // mixing ReadChars with ReadBase64 or ReadBinHex if ( readCharsDecoder == null ) { readCharsDecoder = new IncrementalReadCharsDecoder(); } readCharsDecoder.Reset(); incReadDecoder = readCharsDecoder; } return IncrementalRead( buffer, index, count ); } else { if ( curNode.type != XmlNodeType.Element) { return 0; } if ( curNode.IsEmptyElement ) { outerReader.Read(); return 0; } if ( readCharsDecoder == null ) { readCharsDecoder = new IncrementalReadCharsDecoder(); } InitIncrementalRead( readCharsDecoder ); return IncrementalRead( buffer, index, count ); } } // Reads the contents of an element including markup and base64-decodes it into a byte buffer. Wellformedness checks are limited. // This method is designed to read base64-encoded large streams of bytes by calling it successively. internal int ReadBase64( byte[] array, int offset, int len ) { Debug.Assert( v1Compat, "XmlTextReaderImpl.ReadBase64 cannot be called on reader created via XmlReader.Create." ); Debug.Assert( outerReader is XmlTextReader ); if ( parsingFunction == ParsingFunction.InIncrementalRead ) { if ( incReadDecoder != base64Decoder ) { // mixing ReadBase64 with ReadChars or ReadBinHex InitBase64Decoder(); } return IncrementalRead( array, offset, len ); } else { if ( curNode.type != XmlNodeType.Element) { return 0; } if ( curNode.IsEmptyElement ) { outerReader.Read(); return 0; } if ( base64Decoder == null ) { base64Decoder = new Base64Decoder(); } InitIncrementalRead( base64Decoder ); return IncrementalRead( array, offset, len ); } } // Reads the contents of an element including markup and binhex-decodes it into a byte buffer. Wellformedness checks are limited. // This method is designed to read binhex-encoded large streams of bytes by calling it successively. internal int ReadBinHex( byte[] array, int offset, int len ) { Debug.Assert( v1Compat, "XmlTextReaderImpl.ReadBinHex cannot be called on reader created via XmlReader.Create." ); Debug.Assert( outerReader is XmlTextReader ); if ( parsingFunction == ParsingFunction.InIncrementalRead ) { if ( incReadDecoder != binHexDecoder ) { // mixing ReadBinHex with ReadChars or ReadBase64 InitBinHexDecoder(); } return IncrementalRead( array, offset, len ); } else { if ( curNode.type != XmlNodeType.Element) { return 0; } if ( curNode.IsEmptyElement ) { outerReader.Read(); return 0; } if ( binHexDecoder == null ) { binHexDecoder = new BinHexDecoder(); } InitIncrementalRead( binHexDecoder ); return IncrementalRead( array, offset, len ); } } #endif // // Helpers for DtdParserProxy // internal XmlNameTable DtdParserProxy_NameTable { get { return nameTable; } } internal IXmlNamespaceResolver DtdParserProxy_NamespaceResolver { get { return namespaceManager; } } internal bool DtdParserProxy_DtdValidation { get { #if SILVERLIGHT return false; #else return DtdValidation; #endif } } internal bool DtdParserProxy_Normalization { get { return normalize; } } internal bool DtdParserProxy_Namespaces { get { return supportNamespaces; } } internal bool DtdParserProxy_V1CompatibilityMode { get { return v1Compat; } } internal Uri DtdParserProxy_BaseUri { // SxS: ps.baseUri may be initialized in the constructor (public XmlTextReaderImpl( string url, XmlNameTable nt )) based on // url provided by the user. Here the property returns ps.BaseUri - so it may expose a path. #if !SILVERLIGHT [ResourceConsumption(ResourceScope.Machine)] [ResourceExposure(ResourceScope.Machine)] #endif get { if ( ps.baseUriStr.Length > 0 && ps.baseUri == null && xmlResolver != null ) { ps.baseUri = xmlResolver.ResolveUri( null, ps.baseUriStr ); } return ps.baseUri; } } internal bool DtdParserProxy_IsEof { get { return ps.isEof; } } internal char[] DtdParserProxy_ParsingBuffer { get { return ps.chars; } } internal int DtdParserProxy_ParsingBufferLength { get { return ps.charsUsed; } } internal int DtdParserProxy_CurrentPosition { get { return ps.charPos; } set { Debug.Assert( value >= 0 && value <= ps.charsUsed ); ps.charPos = value; } } internal int DtdParserProxy_EntityStackLength { get { return parsingStatesStackTop + 1; } } internal bool DtdParserProxy_IsEntityEolNormalized { get { return ps.eolNormalized; } } #if !SILVERLIGHT internal IValidationEventHandling DtdParserProxy_ValidationEventHandling { get { return validationEventHandling; } set { validationEventHandling = value; } } #endif internal void DtdParserProxy_OnNewLine( int pos ) { this.OnNewLine( pos ); } internal int DtdParserProxy_LineNo { get { return ps.LineNo; } } internal int DtdParserProxy_LineStartPosition { get { return ps.lineStartPos; } } internal int DtdParserProxy_ReadData() { return this.ReadData(); } internal int DtdParserProxy_ParseNumericCharRef( BufferBuilder internalSubsetBuilder ) { EntityType entType; return this.ParseNumericCharRef( true, internalSubsetBuilder, out entType ); } internal int DtdParserProxy_ParseNamedCharRef( bool expand, BufferBuilder internalSubsetBuilder ) { return this.ParseNamedCharRef( expand, internalSubsetBuilder ); } internal void DtdParserProxy_ParsePI( BufferBuilder sb ) { if ( sb == null ) { ParsingMode pm = parsingMode; parsingMode = ParsingMode.SkipNode; ParsePI( null ); parsingMode = pm; } else { ParsePI( sb ); } } internal void DtdParserProxy_ParseComment( BufferBuilder sb ) { Debug.Assert( parsingMode == ParsingMode.Full ); try { if ( sb == null ) { ParsingMode savedParsingMode = parsingMode; parsingMode = ParsingMode.SkipNode; ParseCDataOrComment( XmlNodeType.Comment ); parsingMode = savedParsingMode; } else { NodeData originalCurNode = curNode; curNode = AddNode( index + attrCount + 1, index ); ParseCDataOrComment( XmlNodeType.Comment ); curNode.CopyTo( 0, sb ); curNode = originalCurNode; } } catch ( XmlException e ) { #if !SILVERLIGHT if ( e.ResString == Res.Xml_UnexpectedEOF && ps.entity != null ) { SendValidationEvent( XmlSeverityType.Error, Res.Sch_ParEntityRefNesting, null, ps.LineNo, ps.LinePos ); } else { throw; } #else throw e; #endif } } internal bool DtdParserProxy_PushEntity( IDtdEntityInfo entity, out int entityId ) { bool retValue; if ( entity.IsExternal ) { if ( xmlResolver == null ) { entityId = -1; return false; } retValue = PushExternalEntity( entity ); } else { PushInternalEntity( entity ); retValue = true; } entityId = ps.entityId; return retValue; } internal bool DtdParserProxy_PopEntity( out IDtdEntityInfo oldEntity, out int newEntityId ) { if ( parsingStatesStackTop == -1 ) { oldEntity = null; newEntityId = -1; return false; } oldEntity = ps.entity; PopEntity(); newEntityId = ps.entityId; return true; } // SxS: The caller did not provide any SxS sensitive name or resource. No resource is being exposed either. // It is OK to suppress SxS warning. #if !SILVERLIGHT [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] [ResourceExposure(ResourceScope.None)] #endif internal bool DtdParserProxy_PushExternalSubset( string systemId, string publicId ) { Debug.Assert( parsingStatesStackTop == -1 ); Debug.Assert( ( systemId != null && systemId.Length > 0 ) || ( publicId != null && publicId.Length > 0 ) ); if ( xmlResolver == null ) { return false; } PushExternalEntityOrSubset( publicId, systemId, ps.baseUriStr, ref ps.baseUri, null ); ps.entity = null; ps.entityId = 0; Debug.Assert( ps.appendMode ); int initialPos = ps.charPos; if ( v1Compat ) { EatWhitespaces( null ); } if ( !ParseXmlDeclaration( true ) ) { ps.charPos = initialPos; } return true; } internal void DtdParserProxy_PushInternalDtd( string baseUri, string internalDtd ) { Debug.Assert( parsingStatesStackTop == -1 ); PushParsingState(); RegisterConsumedCharacters(internalDtd.Length, false); InitStringInput( baseUri, Encoding.Unicode, internalDtd ); ps.entity = null; ps.entityId = 0; ps.eolNormalized = false; } internal void DtdParserProxy_Throw( Exception e ) { this.Throw( e ); } 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; } 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; } // // Throw methods: Sets the reader current position to pos, sets the error state and throws exception // void Throw( int pos, string res, string arg ) { ps.charPos = pos; Throw( res, arg ); } void Throw( int pos, string res, string[] args ) { ps.charPos = pos; Throw( res, args ); } void Throw( int pos, string res ) { ps.charPos = pos; Throw( res, string.Empty ); } void Throw( string res ) { Throw( res, string.Empty ); } void Throw( string res, int lineNo, int linePos ) { Throw( new XmlException( res, string.Empty, lineNo, linePos, ps.baseUriStr ) ); } void Throw( string res, string arg ) { Throw( new XmlException( res, arg, ps.LineNo, ps.LinePos, ps.baseUriStr ) ); } void Throw( string res, string arg, int lineNo, int linePos ) { Throw( new XmlException( res, arg, lineNo, linePos, ps.baseUriStr ) ); } void Throw( string res, string[] args ) { Throw( new XmlException( res, args, ps.LineNo, ps.LinePos, ps.baseUriStr ) ); } void Throw( string res, string arg, Exception innerException ) { Throw( res, new string[] { arg }, innerException ); } void Throw( string res, string[] args, Exception innerException ) { Throw( new XmlException( res, args, innerException, ps.LineNo, ps.LinePos, ps.baseUriStr ) ); } void Throw( Exception e ) { SetErrorState(); XmlException xmlEx = e as XmlException; if ( xmlEx != null ) { curNode.SetLineInfo( xmlEx.LineNumber, xmlEx.LinePosition ); } throw e; } void ReThrow( Exception e, int lineNo, int linePos ) { Throw( new XmlException( e.Message, (Exception)null, lineNo, linePos, ps.baseUriStr ) ); } void ThrowWithoutLineInfo( string res ) { Throw( new XmlException( res, string.Empty, ps.baseUriStr ) ); } void ThrowWithoutLineInfo( string res, string arg ) { Throw( new XmlException( res, arg, ps.baseUriStr ) ); } void ThrowWithoutLineInfo( string res, string[] args, Exception innerException ) { Throw( new XmlException( res, args, innerException, 0, 0, ps.baseUriStr ) ); } void ThrowInvalidChar( char[] data, int length, int invCharPos ) { Throw( invCharPos, Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs( data, length, invCharPos ) ); } private void SetErrorState() { parsingFunction = ParsingFunction.Error; readState = ReadState.Error; } #if !SILVERLIGHT void SendValidationEvent( XmlSeverityType severity, string code, string arg, int lineNo, int linePos ) { SendValidationEvent( severity, new XmlSchemaException( code, arg, ps.baseUriStr, lineNo, linePos ) ); } void SendValidationEvent(XmlSeverityType severity, XmlSchemaException exception) { if (validationEventHandling != null) { validationEventHandling.SendEvent(exception, severity); } } #endif // // Private implementation methods & properties // private bool InAttributeValueIterator { [System.Runtime.TargetedPatchingOptOutAttribute("Performance critical to inline across NGen image boundaries")] get { return attrCount > 0 && parsingFunction >= ParsingFunction.InReadAttributeValue; } } private void FinishAttributeValueIterator() { Debug.Assert( InAttributeValueIterator ); if ( parsingFunction == ParsingFunction.InReadValueChunk ) { FinishReadValueChunk(); } else if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { FinishReadContentAsBinary(); } if ( parsingFunction == ParsingFunction.InReadAttributeValue ) { #if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) while ( ps.entityId != attributeValueBaseEntityId ) { HandleEntityEnd( false ); } emptyEntityInAttributeResolved = false; #endif parsingFunction = nextParsingFunction; nextParsingFunction = ( index > 0 ) ? ParsingFunction.ElementContent : ParsingFunction.DocumentContent; } } #if !SILVERLIGHT private bool DtdValidation { get { return validationEventHandling != null; } } private void InitStreamInput( Stream stream, Encoding encoding ) { InitStreamInput( null, string.Empty, stream, null, 0, encoding ); } private void InitStreamInput( string baseUriStr, Stream stream, Encoding encoding ) { Debug.Assert( baseUriStr != null ); InitStreamInput( null, baseUriStr, stream, null, 0, encoding ); } #endif private void InitStreamInput( Uri baseUri, Stream stream, Encoding encoding ) { Debug.Assert( baseUri != null ); InitStreamInput( baseUri, baseUri.ToString(), stream, null, 0, encoding ); } #if !SILVERLIGHT private void InitStreamInput( Uri baseUri, string baseUriStr, Stream stream, Encoding encoding ) { InitStreamInput( baseUri, baseUriStr, stream, null, 0, encoding ); } #endif private void InitStreamInput( Uri baseUri, string baseUriStr, Stream stream, byte[] bytes, int byteCount, Encoding encoding ) { Debug.Assert( ps.charPos == 0 && ps.charsUsed == 0 && ps.textReader == null ); Debug.Assert( baseUriStr != null ); Debug.Assert( baseUri == null || ( baseUri.ToString().Equals( baseUriStr ) ) ); ps.stream = stream; ps.baseUri = baseUri; ps.baseUriStr = baseUriStr; // take over the byte buffer allocated in XmlReader.Create, if available int bufferSize; if ( bytes != null ) { ps.bytes = bytes; ps.bytesUsed = byteCount; bufferSize = ps.bytes.Length; } else { // allocate the byte buffer bufferSize = XmlReader.CalcBufferSize( stream ); if ( ps.bytes == null || ps.bytes.Length < bufferSize ) { ps.bytes = new byte[ bufferSize ]; } } // allocate char buffer if ( ps.chars == null || ps.chars.Length < bufferSize + 1 ) { ps.chars = new char[ bufferSize + 1 ]; } // make sure we have at least 4 bytes to detect the encoding (no preamble of System.Text supported encoding is longer than 4 bytes) ps.bytePos = 0; while ( ps.bytesUsed < 4 && ps.bytes.Length - ps.bytesUsed > 0 ) { int read = stream.Read( ps.bytes, ps.bytesUsed, ps.bytes.Length - ps.bytesUsed ); if ( read == 0 ) { ps.isStreamEof = true; break; } ps.bytesUsed += read; } // detect & setup encoding if ( encoding == null ) { encoding = DetectEncoding(); } SetupEncoding( encoding ); // eat preamble byte[] preamble = ps.encoding.GetPreamble(); int preambleLen = preamble.Length; int i; for ( i = 0; i < preambleLen && i < ps.bytesUsed; i++ ) { if ( ps.bytes[i] != preamble[i] ) { break; } } if ( i == preambleLen ) { ps.bytePos = preambleLen; } documentStartBytePos = ps.bytePos; ps.eolNormalized = !normalize; // decode first characters ps.appendMode = true; ReadData(); } private void InitTextReaderInput( string baseUriStr, TextReader input ) { InitTextReaderInput( baseUriStr, null, input ); } private void InitTextReaderInput( string baseUriStr, Uri baseUri, TextReader input ) { Debug.Assert( ps.charPos == 0 && ps.charsUsed == 0 && ps.stream == null ); Debug.Assert( baseUriStr != null ); ps.textReader = input; ps.baseUriStr = baseUriStr; ps.baseUri = baseUri; if ( ps.chars == null ) { ps.chars = new char[ XmlReader.DefaultBufferSize + 1 ]; } ps.encoding = Encoding.Unicode; ps.eolNormalized = !normalize; // read first characters ps.appendMode = true; ReadData(); } private void InitStringInput( string baseUriStr, Encoding originalEncoding, string str ) { Debug.Assert( ps.stream == null && ps.textReader == null ); Debug.Assert( ps.charPos == 0 && ps.charsUsed == 0 ); Debug.Assert( baseUriStr != null ); ps.baseUriStr = baseUriStr; ps.baseUri = null; int len = str.Length; ps.chars = new char[ len + 1 ]; str.CopyTo( 0, ps.chars, 0, str.Length ); ps.charsUsed = len; ps.chars[len] = (char)0; ps.encoding = originalEncoding; ps.eolNormalized = !normalize; ps.isEof = true; } #if !SILVERLIGHT private void InitFragmentReader( XmlNodeType fragmentType, XmlParserContext parserContext, bool allowXmlDeclFragment ) { fragmentParserContext = parserContext; if ( parserContext != null ) { if ( parserContext.NamespaceManager != null ) { namespaceManager = parserContext.NamespaceManager; xmlContext.defaultNamespace = namespaceManager.LookupNamespace( string.Empty ); } else { namespaceManager = new XmlNamespaceManager( nameTable ); } ps.baseUriStr = parserContext.BaseURI; ps.baseUri = null; xmlContext.xmlLang = parserContext.XmlLang; xmlContext.xmlSpace = parserContext.XmlSpace; } else { namespaceManager = new XmlNamespaceManager( nameTable ); ps.baseUriStr = string.Empty; ps.baseUri = null; } reportedBaseUri = ps.baseUriStr; switch ( fragmentType ) { case XmlNodeType.Attribute: ps.appendMode = false; parsingFunction = ParsingFunction.SwitchToInteractive; nextParsingFunction = ParsingFunction.FragmentAttribute; break; case XmlNodeType.Element: Debug.Assert( parsingFunction == ParsingFunction.SwitchToInteractiveXmlDecl ); nextParsingFunction = ParsingFunction.DocumentContent; break; case XmlNodeType.Document: Debug.Assert( parsingFunction == ParsingFunction.SwitchToInteractiveXmlDecl ); Debug.Assert( nextParsingFunction == ParsingFunction.DocumentContent ); break; case XmlNodeType.XmlDeclaration: if ( allowXmlDeclFragment ) { ps.appendMode = false; parsingFunction = ParsingFunction.SwitchToInteractive; nextParsingFunction = ParsingFunction.XmlDeclarationFragment; break; } else { goto default; } default: Throw( Res.Xml_PartialContentNodeTypeNotSupportedEx, fragmentType.ToString() ); return; } this.fragmentType = fragmentType; this.fragment = true; } #endif private void ProcessDtdFromParserContext(XmlParserContext context) { Debug.Assert( context != null && context.HasDtdInfo ); switch ( dtdProcessing ) { case DtdProcessing.Prohibit: ThrowWithoutLineInfo( Res.Xml_DtdIsProhibitedEx ); break; case DtdProcessing.Ignore: // do nothing break; case DtdProcessing.Parse: ParseDtdFromParserContext(); break; default: Debug.Assert( false, "Unhandled DtdProcessing enumeration value." ); break; } } #if !SILVERLIGHT // Needed only for XmlTextReader // SxS: This method resolve Uri but does not expose it to the caller. It's OK to suppress the warning. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] [ResourceExposure(ResourceScope.None)] private void OpenUrl() { Debug.Assert( url != null && url.Length > 0 ); Debug.Assert( compressedStack != null ); XmlResolver tmpResolver; if ( ps.baseUri != null ) { Debug.Assert( xmlResolver != null ); tmpResolver = xmlResolver; } else { tmpResolver = ( xmlResolver == null ) ? new XmlUrlResolver() : xmlResolver; ps.baseUri = tmpResolver.ResolveUri( null, url ); ps.baseUriStr = ps.baseUri.ToString(); } try { CompressedStack.Run( compressedStack, new ContextCallback( OpenUrlDelegate ), tmpResolver ); } catch { SetErrorState(); throw; } if ( ps.stream == null ) { ThrowWithoutLineInfo( Res.Xml_CannotResolveUrl, ps.baseUriStr ); } InitStreamInput( ps.baseUri, ps.baseUriStr, ps.stream, null ); reportedEncoding = ps.encoding; } void OpenUrlDelegate(object xmlResolver) { ps.stream = (Stream) ((XmlResolver)xmlResolver).GetEntity( ps.baseUri, null, typeof( Stream ) ); } #endif // Stream input only: detect encoding from the first 4 bytes of the byte buffer starting at ps.bytes[ps.bytePos] private Encoding DetectEncoding() { Debug.Assert( ps.bytes != null ); Debug.Assert( ps.bytePos == 0 ); if ( ps.bytesUsed < 2 ) { return null; } int first2Bytes = ps.bytes[0] << 8 | ps.bytes[1]; int next2Bytes = ( ps.bytesUsed >= 4 ) ? ( ps.bytes[2] << 8 | ps.bytes[3] ) : 0; switch ( first2Bytes ) { #if !SILVERLIGHT // Removing USC4 encoding case 0x0000: switch ( next2Bytes ) { case 0xFEFF: return Ucs4Encoding.UCS4_Bigendian; case 0x003C: return Ucs4Encoding.UCS4_Bigendian; case 0xFFFE: return Ucs4Encoding.UCS4_2143; case 0x3C00: return Ucs4Encoding.UCS4_2143; } break; #endif case 0xFEFF: #if SILVERLIGHT // Removing USC4 encoding return Encoding.BigEndianUnicode; #else if (next2Bytes == 0x0000) { return Ucs4Encoding.UCS4_3412; } else { return Encoding.BigEndianUnicode; } #endif case 0xFFFE: #if SILVERLIGHT // Removing USC4 encoding return Encoding.Unicode; #else if ( next2Bytes == 0x0000 ) { return Ucs4Encoding.UCS4_Littleendian; } else { return Encoding.Unicode; } #endif case 0x3C00: #if SILVERLIGHT // Removing USC4 encoding return Encoding.Unicode; #else if ( next2Bytes == 0x0000 ) { return Ucs4Encoding.UCS4_Littleendian; } else { return Encoding.Unicode; } #endif case 0x003C: #if SILVERLIGHT // Removing USC4 encoding return Encoding.BigEndianUnicode; #else if ( next2Bytes == 0x0000 ) { return Ucs4Encoding.UCS4_3412; } else { return Encoding.BigEndianUnicode; } #endif case 0x4C6F: if ( next2Bytes == 0xA794 ) { Throw( Res.Xml_UnknownEncoding, "ebcdic" ); } break; case 0xEFBB: if ( ( next2Bytes & 0xFF00 ) == 0xBF00 ) { return new UTF8Encoding( true, true ); } break; } // Default encoding is ASCII (using SafeAsciiDecoder) until we read xml declaration. // If we set UTF8 encoding now, it will throw exceptions (=slow) when decoding non-UTF8-friendly // characters after the xml declaration, which may be perfectly valid in the encoding // specified in xml declaration. return null; } private void SetupEncoding( Encoding encoding ) { if ( encoding == null ) { Debug.Assert( ps.charPos == 0 ); ps.encoding = Encoding.UTF8; ps.decoder = new SafeAsciiDecoder(); } else { ps.encoding = encoding; switch ( ps.encoding.WebName ) { // Encoding.Codepage is not supported in Silverlight case "utf-16": ps.decoder = new UTF16Decoder( false ); break; case "utf-16BE": ps.decoder = new UTF16Decoder( true ); break; default: ps.decoder = encoding.GetDecoder(); break; } } } // Switches the reader's encoding private void SwitchEncoding( Encoding newEncoding ) { #if SILVERLIGHT if ( ( newEncoding.WebName != ps.encoding.WebName || ps.decoder is SafeAsciiDecoder ) ) { #else if ( ( newEncoding.WebName != ps.encoding.WebName || ps.decoder is SafeAsciiDecoder ) && !afterResetState) { #endif Debug.Assert( ps.stream != null ); UnDecodeChars(); ps.appendMode = false; SetupEncoding( newEncoding ); ReadData(); } } // Returns the Encoding object for the given encoding name, if the reader's encoding can be switched to that encoding. // Performs checks whether switching from current encoding to specified encoding is allowed. private Encoding CheckEncoding( string newEncodingName ) { // encoding can be switched on stream input only if ( ps.stream == null ) { return ps.encoding; } if ( 0 == String.Compare( newEncodingName, "ucs-2", StringComparison.OrdinalIgnoreCase ) || 0 == String.Compare( newEncodingName, "utf-16", StringComparison.OrdinalIgnoreCase ) || 0 == String.Compare( newEncodingName, "iso-10646-ucs-2", StringComparison.OrdinalIgnoreCase ) || 0 == String.Compare( newEncodingName, "ucs-4", StringComparison.OrdinalIgnoreCase ) ) { if ( ps.encoding.WebName != "utf-16BE" && ps.encoding.WebName != "utf-16" && 0 != String.Compare( newEncodingName, "ucs-4", StringComparison.OrdinalIgnoreCase ) ) { #if SILVERLIGHT // Needed only for XmlTextReader ThrowWithoutLineInfo(Res.Xml_MissingByteOrderMark); #else if ( afterResetState ) { Throw( Res.Xml_EncodingSwitchAfterResetState, newEncodingName ); } else { ThrowWithoutLineInfo( Res.Xml_MissingByteOrderMark ); } #endif } return ps.encoding; } Encoding newEncoding = null; if ( 0 == String.Compare( newEncodingName, "utf-8", StringComparison.OrdinalIgnoreCase ) ) { newEncoding = new UTF8Encoding( true, true ); } else { try { newEncoding = Encoding.GetEncoding( newEncodingName ); } catch ( NotSupportedException innerEx ) { Throw( Res.Xml_UnknownEncoding, newEncodingName, innerEx ); } catch ( ArgumentException innerEx) { Throw( Res.Xml_UnknownEncoding, newEncodingName, innerEx ); } #if !SILVERLIGHT Debug.Assert( newEncoding.EncodingName != "UTF-8" ); #endif } #if !SILVERLIGHT // Needed only for XmlTextReader // check for invalid encoding switches after ResetState if ( afterResetState && ps.encoding.WebName != newEncoding.WebName ) { Throw( Res.Xml_EncodingSwitchAfterResetState, newEncodingName ); } #endif return newEncoding; } void UnDecodeChars() { Debug.Assert( ps.stream != null && ps.decoder != null && ps.bytes != null ); Debug.Assert( ps.appendMode, "UnDecodeChars cannot be called after ps.appendMode has been changed to false" ); Debug.Assert(ps.charsUsed >= ps.charPos, "The current position must be in the valid character range."); if (maxCharactersInDocument > 0) { // We're returning back in the input (potentially) so we need to fixup // the character counters to avoid counting some of them twice. // The following code effectively rolls-back all decoded characters // after the ps.charPos (which typically points to the first character // after the XML decl). Debug.Assert(charactersInDocument >= ps.charsUsed - ps.charPos, "We didn't correctly count some of the decoded characters against the MaxCharactersInDocument."); charactersInDocument -= ps.charsUsed - ps.charPos; } if (maxCharactersFromEntities > 0) { if (InEntity) { Debug.Assert(charactersFromEntities >= ps.charsUsed - ps.charPos, "We didn't correctly count some of the decoded characters against the MaxCharactersFromEntities."); charactersFromEntities -= ps.charsUsed - ps.charPos; } } ps.bytePos = documentStartBytePos; // byte position after preamble if ( ps.charPos > 0 ) { ps.bytePos += ps.encoding.GetByteCount( ps.chars, 0, ps.charPos ); } ps.charsUsed = ps.charPos; ps.isEof = false; } private void SwitchEncodingToUTF8() { SwitchEncoding( new UTF8Encoding( true, true ) ); } // Reads more data to the character buffer, discarding already parsed chars / decoded bytes. int ReadData() { // Append Mode: Append new bytes and characters to the buffers, do not rewrite them. Allocate new buffers // if the current ones are full // Rewrite Mode: Reuse the buffers. If there is less than half of the char buffer left for new data, move // the characters that has not been parsed yet to the front of the buffer. Same for bytes. if ( ps.isEof ) { return 0; } int charsRead; if ( ps.appendMode ) { // the character buffer is full -> allocate a new one if ( ps.charsUsed == ps.chars.Length - 1 ) { // invalidate node values kept in buffer - applies to attribute values only for ( int i = 0; i < attrCount; i++ ) { nodes[index + i + 1].OnBufferInvalidated(); } char[] newChars = new char[ ps.chars.Length * 2 ]; BlockCopyChars( ps.chars, 0, newChars, 0, ps.chars.Length ); ps.chars = newChars; } if ( ps.stream != null ) { // the byte buffer is full -> allocate a new one if ( ps.bytesUsed - ps.bytePos < MaxByteSequenceLen ) { if ( ps.bytes.Length - ps.bytesUsed < MaxByteSequenceLen ) { byte[] newBytes = new byte[ ps.bytes.Length * 2 ]; BlockCopy( ps.bytes, 0, newBytes, 0, ps.bytesUsed ); ps.bytes = newBytes; } } } charsRead = ps.chars.Length - ps.charsUsed - 1; if ( charsRead > ApproxXmlDeclLength ) { charsRead = ApproxXmlDeclLength; } } else { int charsLen = ps.chars.Length; if ( charsLen - ps.charsUsed <= charsLen/2 ) { // invalidate node values kept in buffer - applies to attribute values only for ( int i = 0; i < attrCount; i++ ) { nodes[index + i + 1].OnBufferInvalidated(); } // move unparsed characters to front, unless the whole buffer contains unparsed characters int copyCharsCount = ps.charsUsed - ps.charPos; if ( copyCharsCount < charsLen - 1 ) { ps.lineStartPos = ps.lineStartPos - ps.charPos; if ( copyCharsCount > 0 ) { BlockCopyChars( ps.chars, ps.charPos, ps.chars, 0, copyCharsCount ); } ps.charPos = 0; ps.charsUsed = copyCharsCount; } else { char[] newChars = new char[ ps.chars.Length * 2 ]; BlockCopyChars( ps.chars, 0, newChars, 0, ps.chars.Length ); ps.chars = newChars; } } if ( ps.stream != null ) { // move undecoded bytes to the front to make some space in the byte buffer int bytesLeft = ps.bytesUsed - ps.bytePos; if ( bytesLeft <= MaxBytesToMove ) { if ( bytesLeft == 0 ) { ps.bytesUsed = 0; } else { BlockCopy( ps.bytes, ps.bytePos, ps.bytes, 0, bytesLeft ); ps.bytesUsed = bytesLeft; } ps.bytePos = 0; } } charsRead = ps.chars.Length - ps.charsUsed - 1; } if ( ps.stream != null ) { if ( !ps.isStreamEof ) { // read new bytes if ( ps.bytePos == ps.bytesUsed && ps.bytes.Length - ps.bytesUsed > 0 ) { int read = ps.stream.Read( ps.bytes, ps.bytesUsed, ps.bytes.Length - ps.bytesUsed ); if ( read == 0 ) { ps.isStreamEof = true; } ps.bytesUsed += read; } } int originalBytePos = ps.bytePos; // decode chars charsRead = GetChars( charsRead ); if ( charsRead == 0 && ps.bytePos != originalBytePos ) { // GetChars consumed some bytes but it was not enough bytes to form a character -> try again return ReadData(); } } else if ( ps.textReader != null ) { // read chars charsRead = ps.textReader.Read( ps.chars, ps.charsUsed, ps.chars.Length - ps.charsUsed - 1 ); ps.charsUsed += charsRead; } else { charsRead = 0; } RegisterConsumedCharacters(charsRead, InEntity); if ( charsRead == 0 ) { Debug.Assert ( ps.charsUsed < ps.chars.Length ); ps.isEof = true; } ps.chars[ ps.charsUsed ] = (char)0; return charsRead; } // Stream input only: read bytes from stream and decodes them according to the current encoding int GetChars( int maxCharsCount ) { Debug.Assert( ps.stream != null && ps.decoder != null && ps.bytes != null ); Debug.Assert( maxCharsCount <= ps.chars.Length - ps.charsUsed - 1 ); // determine the maximum number of bytes we can pass to the decoder int bytesCount = ps.bytesUsed - ps.bytePos; if ( bytesCount == 0 ) { return 0; } int charsCount; bool completed; try { // decode chars ps.decoder.Convert( ps.bytes, ps.bytePos, bytesCount, ps.chars, ps.charsUsed, maxCharsCount, false, out bytesCount, out charsCount, out completed ); } catch ( ArgumentException ) { InvalidCharRecovery( ref bytesCount, out charsCount ); } // move pointers and return ps.bytePos += bytesCount; ps.charsUsed += charsCount; Debug.Assert( maxCharsCount >= charsCount ); return charsCount; } private void InvalidCharRecovery( ref int bytesCount, out int charsCount ) { int charsDecoded = 0; int bytesDecoded = 0; try { while ( bytesDecoded < bytesCount ) { int chDec; int bDec; bool completed; ps.decoder.Convert( ps.bytes, ps.bytePos + bytesDecoded, 1, ps.chars, ps.charsUsed + charsDecoded, 1, false, out bDec, out chDec, out completed ); charsDecoded += chDec; bytesDecoded += bDec; } Debug.Assert( false, "We should get an exception again." ); } catch ( ArgumentException ) { } if ( charsDecoded == 0 ) { Throw( ps.charsUsed, Res.Xml_InvalidCharInThisEncoding ); } charsCount = charsDecoded; bytesCount = bytesDecoded; } internal void Close( bool closeInput ) { if ( parsingFunction == ParsingFunction.ReaderClosed ) { return; } while ( InEntity ) { PopParsingState(); } ps.Close( closeInput ); curNode = NodeData.None; parsingFunction = ParsingFunction.ReaderClosed; reportedEncoding = null; reportedBaseUri = string.Empty; readState = ReadState.Closed; fullAttrCleanup = false; ResetAttributes(); } void ShiftBuffer( int sourcePos, int destPos, int count ) { BlockCopyChars( ps.chars, sourcePos, ps.chars, destPos, count ); } // Parses the xml or text declaration and switched encoding if needed private bool ParseXmlDeclaration( bool isTextDecl ) { while ( ps.charsUsed - ps.charPos < 6 ) { // minimum " Encoding encoding = null; for (;;) { int originalSbLen = sb.Length; int wsCount = EatWhitespaces( xmlDeclState == 0 ? null : sb ); // end of xml declaration if ( ps.chars[ps.charPos] == '?' ) { sb.Length = originalSbLen; if ( ps.chars[ps.charPos + 1] == '>' ) { if ( xmlDeclState == 0 ) { Throw( isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl ); } ps.charPos += 2; if ( !isTextDecl ) { curNode.SetValue( sb.ToString() ); sb.Length = 0; nextParsingFunction = parsingFunction; parsingFunction = ParsingFunction.ResetAttributesRootLevel; } // switch to encoding specified in xml declaration if ( encoding == null ) { if ( isTextDecl ) { Throw( Res.Xml_InvalidTextDecl ); } #if !SILVERLIGHT // Needed only for XmlTextReader if ( afterResetState ) { // check for invalid encoding switches to default encoding string encodingName = ps.encoding.WebName; if ( encodingName != "utf-8" && encodingName != "utf-16" && encodingName != "utf-16BE" && !( ps.encoding is Ucs4Encoding ) ) { Throw( Res.Xml_EncodingSwitchAfterResetState, ( ps.encoding.GetByteCount( "A" ) == 1 ) ? "UTF-8" : "UTF-16" ); } } #endif if ( ps.decoder is SafeAsciiDecoder ) { SwitchEncodingToUTF8(); } } else { SwitchEncoding( encoding ); } ps.appendMode = false; return true; } else if ( ps.charPos + 1 == ps.charsUsed ) { goto ReadData; } else { ThrowUnexpectedToken( "'>'" ); } } if ( wsCount == 0 && xmlDeclState != 0 ) { ThrowUnexpectedToken( "?>" ); } // read attribute name int nameEndPos = ParseName(); NodeData attr = null; switch ( ps.chars[ps.charPos] ) { case 'v': if ( XmlConvert.StrEqual( ps.chars, ps.charPos, nameEndPos - ps.charPos, "version" ) && xmlDeclState == 0 ) { if ( !isTextDecl ) { attr = AddAttributeNoChecks( "version", 1 ); } break; } goto default; case 'e': if ( XmlConvert.StrEqual( ps.chars, ps.charPos, nameEndPos - ps.charPos, "encoding" ) && ( xmlDeclState == 1 || ( isTextDecl && xmlDeclState == 0 ) ) ) { if ( !isTextDecl ) { attr = AddAttributeNoChecks( "encoding", 1 ); } xmlDeclState = 1; break; } goto default; case 's': if ( XmlConvert.StrEqual( ps.chars, ps.charPos, nameEndPos - ps.charPos, "standalone" ) && ( xmlDeclState == 1 || xmlDeclState == 2 ) && !isTextDecl ) { if ( !isTextDecl ) { attr = AddAttributeNoChecks( "standalone", 1 ); } xmlDeclState = 2; break; } goto default; default: Throw( isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl ); break; } if ( !isTextDecl ) { attr.SetLineInfo( ps.LineNo, ps.LinePos ); } sb.Append( ps.chars, ps.charPos, nameEndPos - ps.charPos ); ps.charPos = nameEndPos; // parse equals and quote char; if ( ps.chars[ps.charPos] != '=' ) { EatWhitespaces( sb ); if ( ps.chars[ps.charPos] != '=' ) { ThrowUnexpectedToken( "=" ); } } sb.Append( '=' ); ps.charPos++; char quoteChar = ps.chars[ps.charPos]; if ( quoteChar != '"' && quoteChar != '\'' ) { EatWhitespaces( sb ); quoteChar = ps.chars[ps.charPos]; if ( quoteChar != '"' && quoteChar != '\'' ) { ThrowUnexpectedToken( "\"", "'" ); } } sb.Append( quoteChar ); ps.charPos++; if ( !isTextDecl ) { attr.quoteChar = quoteChar; attr.SetLineInfo2( ps.LineNo, ps.LinePos ); } // parse attribute value int pos = ps.charPos; char[] chars; Continue: chars = ps.chars; #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 ( ps.chars[pos] == quoteChar ) { switch ( xmlDeclState ) { // version case 0: #if XML10_FIFTH_EDITION // VersionNum ::= '1.' [0-9]+ (starting with XML Fifth Edition) if ( pos - ps.charPos >= 3 && ps.chars[ps.charPos] == '1' && ps.chars[ps.charPos + 1] == '.' && XmlCharType.IsOnlyDigits( ps.chars, ps.charPos + 2, pos - ps.charPos - 2 ) ) { #else // VersionNum ::= '1.0' (XML Fourth Edition and earlier) if ( XmlConvert.StrEqual( ps.chars, ps.charPos, pos - ps.charPos, "1.0" ) ) { #endif if ( !isTextDecl ) { attr.SetValue( ps.chars, ps.charPos, pos - ps.charPos ); } xmlDeclState = 1; } else { string badVersion = new string( ps.chars, ps.charPos, pos - ps.charPos ); Throw( Res.Xml_InvalidVersionNumber, badVersion ); } break; case 1: string encName = new string( ps.chars, ps.charPos, pos - ps.charPos ); encoding = CheckEncoding( encName ); if ( !isTextDecl ) { attr.SetValue( encName ); } xmlDeclState = 2; break; case 2: if ( XmlConvert.StrEqual( ps.chars, ps.charPos, pos - ps.charPos, "yes" ) ) { this.standalone = true; } else if ( XmlConvert.StrEqual( ps.chars, ps.charPos, pos - ps.charPos, "no" ) ) { this.standalone = false; } else { Debug.Assert( !isTextDecl ); Throw( Res.Xml_InvalidXmlDecl, ps.LineNo, ps.LinePos - 1 ); } if ( !isTextDecl ) { attr.SetValue( ps.chars, ps.charPos, pos - ps.charPos ); } xmlDeclState = 3; break; default: Debug.Assert( false ); break; } sb.Append( chars, ps.charPos, pos - ps.charPos ); sb.Append( quoteChar ); ps.charPos = pos + 1; continue; } else if ( pos == ps.charsUsed ) { if ( ReadData() != 0 ) { goto Continue; } else { Throw( Res.Xml_UnclosedQuote ); } } else { Throw( isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl ); } ReadData: if ( ps.isEof || ReadData() == 0 ) { Throw( Res.Xml_UnexpectedEOF1 ); } } NoXmlDecl: // no xml declaration if ( !isTextDecl ) { parsingFunction = nextParsingFunction; } #if !SILVERLIGHT // Needed only for XmlTextReader if ( afterResetState ) { // check for invalid encoding switches to default encoding string encodingName = ps.encoding.WebName; if ( encodingName != "utf-8" && encodingName != "utf-16" && encodingName != "utf-16BE" && !( ps.encoding is Ucs4Encoding ) ) { Throw( Res.Xml_EncodingSwitchAfterResetState, ( ps.encoding.GetByteCount( "A" ) == 1 ) ? "UTF-8" : "UTF-16" ); } } #endif if ( ps.decoder is SafeAsciiDecoder ) { SwitchEncodingToUTF8(); } ps.appendMode = false; return false; } // Parses the document content private bool ParseDocumentContent() { for (;;) { bool needMoreChars = false; int pos = ps.charPos; char[] chars = ps.chars; // some tag if ( chars[pos] == '<' ) { needMoreChars = true; if ( ps.charsUsed - pos < 4 ) // minimum "" goto ReadData; pos++; switch ( chars[pos] ) { // processing instruction case '?': ps.charPos = pos + 1; if ( ParsePI() ) { return true; } continue; case '!': pos++; if ( ps.charsUsed - pos < 2 ) // minimum characters expected "--" goto ReadData; // comment if ( chars[pos] == '-' ) { if ( chars[pos+1] == '-' ) { ps.charPos = pos + 2; if ( ParseComment() ) { return true; } continue; } else { ThrowUnexpectedToken( pos + 1, "-" ); } } // CDATA section else if ( chars[pos] == '[' ) { if ( fragmentType != XmlNodeType.Document ) { pos++; if ( ps.charsUsed - pos < 6 ) { goto ReadData; } if ( XmlConvert.StrEqual( chars, pos, 6, "CDATA[" ) ) { ps.charPos = pos + 6; ParseCData(); if ( fragmentType == XmlNodeType.None ) { fragmentType = XmlNodeType.Element; } return true; } else { ThrowUnexpectedToken( pos, "CDATA[" ); } } else { Throw( ps.charPos, Res.Xml_InvalidRootData ); } } // DOCTYPE declaration else { if ( fragmentType == XmlNodeType.Document || fragmentType == XmlNodeType.None ) { fragmentType = XmlNodeType.Document; ps.charPos = pos; if ( ParseDoctypeDecl() ) { return true; } continue; } else { if ( ParseUnexpectedToken( pos ) == "DOCTYPE" ) { Throw( Res.Xml_BadDTDLocation ); } else { ThrowUnexpectedToken( pos, "" ) ); ps.charPos -= 3; incReadState = IncrementalReadState.Text; } goto Append; case IncrementalReadState.CDATA: if ( ParseCDataOrComment( XmlNodeType.CDATA, out startPos, out pos ) ) { Debug.Assert( XmlConvert.StrEqual( ps.chars, ps.charPos - 3, 3, "]]>" ) ); ps.charPos -= 3; incReadState = IncrementalReadState.Text; } goto Append; case IncrementalReadState.EndElement: parsingFunction = ParsingFunction.PopElementContext; nextParsingFunction = ( index > 0 || fragmentType != XmlNodeType.Document ) ? ParsingFunction.ElementContent : ParsingFunction.DocumentContent; outerReader.Read(); incReadState = IncrementalReadState.End; goto case IncrementalReadState.End; case IncrementalReadState.End: return charsDecoded; case IncrementalReadState.ReadData: if ( ReadData() == 0 ) { ThrowUnclosedElements(); } incReadState = IncrementalReadState.Text; startPos = ps.charPos; pos = startPos; break; default: Debug.Assert( false ); break; } Debug.Assert( incReadState == IncrementalReadState.Text || incReadState == IncrementalReadState.Attributes || incReadState == IncrementalReadState.AttributeValue ); char[] chars = ps.chars; startPos = ps.charPos; pos = startPos; for (;;) { incReadLineInfo.Set( ps.LineNo, ps.LinePos ); char c; unsafe { if ( incReadState == IncrementalReadState.Attributes ) { while ( ( ( xmlCharType.charProperties[c = chars[pos]] & XmlCharType.fAttrValue ) != 0 ) && c != '/' ) { pos++; } } else { while ( ( ( xmlCharType.charProperties[c = chars[pos]] & XmlCharType.fAttrValue ) != 0 ) ) { pos++; } } } if ( chars[pos] == '&' || chars[pos] == (char)0x9 ) { pos++; continue; } if ( pos - startPos > 0 ) { goto AppendAndUpdateCharPos; } switch ( chars[pos] ) { // eol case (char)0xA: pos++; OnNewLine( pos ); continue; case (char)0xD: if ( chars[pos+1] == (char)0xA ) { pos += 2; } else if ( pos+1 < ps.charsUsed ) { pos++; } else { goto ReadData; } OnNewLine( pos ); continue; // some tag case '<': if ( incReadState != IncrementalReadState.Text ) { pos++; continue; } if ( ps.charsUsed - pos < 2 ) { goto ReadData; } switch ( chars[pos+1] ) { // pi case '?': pos += 2; incReadState = IncrementalReadState.PI; goto AppendAndUpdateCharPos; // comment case '!': if ( ps.charsUsed - pos < 4 ) { goto ReadData; } if ( chars[pos+2] == '-' && chars[pos+3] == '-' ) { pos += 4; incReadState = IncrementalReadState.Comment; goto AppendAndUpdateCharPos; } if ( ps.charsUsed - pos < 9 ) { goto ReadData; } if ( XmlConvert.StrEqual( chars, pos + 2, 7, "[CDATA[" ) ) { pos += 9; incReadState = IncrementalReadState.CDATA; goto AppendAndUpdateCharPos; } else { ;//Throw( ); } break; // end tag case '/': { Debug.Assert( ps.charPos - pos == 0 ); Debug.Assert( ps.charPos - startPos == 0); int colonPos; // ParseQName can flush the buffer, so we need to update the startPos, pos and chars after calling it int endPos = ParseQName( true, 2, out colonPos ); if ( XmlConvert.StrEqual( chars, ps.charPos + 2, endPos - ps.charPos - 2, curNode.GetNameWPrefix( nameTable ) ) && ( ps.chars[endPos] == '>' || xmlCharType.IsWhiteSpace( ps.chars[endPos] ) ) ) { if ( --incReadDepth > 0 ) { pos = endPos + 1; continue; } ps.charPos = endPos; if ( xmlCharType.IsWhiteSpace( ps.chars[endPos] ) ) { EatWhitespaces( null ); } if ( ps.chars[ps.charPos] != '>' ) { ThrowUnexpectedToken( ">" ); } ps.charPos++; incReadState = IncrementalReadState.EndElement; goto OuterContinue; } else { pos = endPos; startPos = ps.charPos; chars = ps.chars; continue; } } // start tag default: { Debug.Assert( ps.charPos - pos == 0 ); Debug.Assert( ps.charPos - startPos == 0 ); int colonPos; // ParseQName can flush the buffer, so we need to update the startPos, pos and chars after calling it int endPos = ParseQName( true, 1, out colonPos ); if ( XmlConvert.StrEqual( ps.chars, ps.charPos + 1, endPos - ps.charPos - 1, curNode.localName ) && ( ps.chars[endPos] == '>' || ps.chars[endPos] == '/' || xmlCharType.IsWhiteSpace( ps.chars[endPos] ) ) ) { incReadDepth++; incReadState = IncrementalReadState.Attributes; pos = endPos; goto AppendAndUpdateCharPos; } pos = endPos; startPos = ps.charPos; chars = ps.chars; continue; } } break; // end of start tag case '/': if ( incReadState == IncrementalReadState.Attributes ) { if ( ps.charsUsed - pos < 2 ) { goto ReadData; } if ( chars[pos+1] == '>' ) { incReadState = IncrementalReadState.Text; incReadDepth--; } } pos++; continue; // end of start tag case '>': if ( incReadState == IncrementalReadState.Attributes ) { incReadState = IncrementalReadState.Text; } pos++; continue; case '"': case '\'': switch ( incReadState ) { case IncrementalReadState.AttributeValue: if ( chars[pos] == curNode.quoteChar ) { incReadState = IncrementalReadState.Attributes; } break; case IncrementalReadState.Attributes: curNode.quoteChar = chars[pos]; incReadState = IncrementalReadState.AttributeValue; break; } pos++; continue; default: // end of buffer if ( pos == ps.charsUsed ) { goto ReadData; } // surrogate chars or invalid chars are ignored else { pos++; continue; } } } ReadData: incReadState = IncrementalReadState.ReadData; AppendAndUpdateCharPos: ps.charPos = pos; Append: // decode characters int charsParsed = pos - startPos; if ( charsParsed > 0 ) { int count; try { count = incReadDecoder.Decode( ps.chars, startPos, charsParsed ); } catch ( XmlException e ) { ReThrow( e, (int)incReadLineInfo.lineNo, (int)incReadLineInfo.linePos ); return 0; } Debug.Assert( count == charsParsed || incReadDecoder.IsFull, "Check if decoded consumed all characters unless it's full." ); charsDecoded += count; if ( incReadDecoder.IsFull ) { incReadLeftStartPos = startPos + count; incReadLeftEndPos = pos; incReadLineInfo.linePos += count; // we have never more than 1 line cached return charsDecoded; } } } } private void FinishIncrementalRead() { incReadDecoder = new IncrementalReadDummyDecoder(); IncrementalRead(); Debug.Assert( IncrementalRead() == 0, "Previous call of IncrementalRead should eat up all characters!" ); incReadDecoder = null; } private bool ParseFragmentAttribute() { Debug.Assert( fragmentType == XmlNodeType.Attribute ); // if first call then parse the whole attribute value if ( curNode.type == XmlNodeType.None ) { curNode.type = XmlNodeType.Attribute; curAttrIndex = 0; ParseAttributeValueSlow( ps.charPos, ' ', curNode ); // The quote char is intentionally empty (space) because we need to parse ' and " into the attribute value } else { parsingFunction = ParsingFunction.InReadAttributeValue; } // return attribute value chunk if ( ReadAttributeValue() ) { Debug.Assert( parsingFunction == ParsingFunction.InReadAttributeValue ); parsingFunction = ParsingFunction.FragmentAttribute; return true; } else { OnEof(); return false; } } #endif #if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex) private bool ParseAttributeValueChunk() { char[] chars = ps.chars; int pos = ps.charPos; curNode = AddNode( index + attrCount + 1, index + 2 ); curNode.SetLineInfo( ps.LineNo, ps.LinePos ); if ( emptyEntityInAttributeResolved ) { curNode.SetValueNode( XmlNodeType.Text, string.Empty ); emptyEntityInAttributeResolved = false; return true; } Debug.Assert( stringBuilder.Length == 0 ); for (;;) { unsafe { while ( ( ( xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue ) != 0 ) ) pos++; } switch ( chars[pos] ) { // eol D case (char)0xD: Debug.Assert( ps.eolNormalized, "Entity replacement text for attribute values should be EOL-normalized!" ); pos++; continue; // eol A, tab case (char)0xA: case (char)0x9: if ( normalize ) { chars[pos] = (char)0x20; // CDATA normalization of 0xA and 0x9 } pos++; continue; case '"': case '\'': case '>': pos++; continue; // attribute values cannot contain '<' case '<': Throw( pos, Res.Xml_BadAttributeChar, XmlException.BuildCharExceptionArgs( '<', '\0' ) ); break; // entity reference case '&': if ( pos - ps.charPos > 0 ) { stringBuilder.Append( chars, ps.charPos, pos - ps.charPos ); } ps.charPos = pos; // expand char entities but not general entities switch ( HandleEntityReference( true, EntityExpandType.OnlyCharacter, out pos ) ) { case EntityType.CharacterDec: case EntityType.CharacterHex: case EntityType.CharacterNamed: chars = ps.chars; if ( normalize && xmlCharType.IsWhiteSpace( chars[ps.charPos] ) && pos - ps.charPos == 1 ) { chars[ps.charPos] = (char)0x20; // CDATA normalization of character references in entities } break; case EntityType.Unexpanded: if ( stringBuilder.Length == 0 ) { curNode.lineInfo.linePos++; ps.charPos++; curNode.SetNamedNode( XmlNodeType.EntityReference, ParseEntityName() ); return true; } else { goto ReturnText; } default: Debug.Assert( false, "We should never get to this point." ); 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: if ( pos - ps.charPos > 0 ) { stringBuilder.Append( chars, ps.charPos, pos - ps.charPos ); ps.charPos = pos; } // read new characters into the buffer if ( ReadData() == 0 ) { if ( stringBuilder.Length > 0 ) { goto ReturnText; } else { if ( HandleEntityEnd( false ) ) { SetupEndEntityNodeInAttribute(); return true; } else { Debug.Assert( false, "We should never get to this point." ); } } } pos = ps.charPos; chars = ps.chars; } ReturnText: if ( pos - ps.charPos > 0 ) { stringBuilder.Append( chars, ps.charPos, pos - ps.charPos ); ps.charPos = pos; } curNode.SetValueNode( XmlNodeType.Text, stringBuilder.ToString() ); stringBuilder.Length = 0; return true; } private void ParseXmlDeclarationFragment() { try { ParseXmlDeclaration( false ); } catch ( XmlException e ) { ReThrow( e, e.LineNumber, e.LinePosition - 6 ); // 6 == strlen( " create a new one else if ( nt == null ) { nt = new NameTable(); Debug.Assert( nameTableFromSettings == false ); } nameTable = nt; // make sure we have namespace manager if ( namespaceManager == null ) { namespaceManager = new XmlNamespaceManager( nt ); } // copy xml:space and xml:lang xmlContext.xmlSpace = context.XmlSpace; xmlContext.xmlLang = context.XmlLang; } // // DtdInfo // #if !SILVERLIGHT internal override IDtdInfo DtdInfo { get { return dtdInfo; } } internal void SetDtdInfo(IDtdInfo newDtdInfo) { Debug.Assert( dtdInfo == null ); dtdInfo = newDtdInfo; if ( dtdInfo != null ) { if ( ( validatingReaderCompatFlag || !v1Compat ) && ( dtdInfo.HasDefaultAttributes || dtdInfo.HasNonCDataAttributes ) ) { addDefaultAttributesAndNormalize = true; } } } #endif // // Validation support // #if !SILVERLIGHT // no validation in Silverlight internal IValidationEventHandling ValidationEventHandling { set { validationEventHandling = value; } } internal OnDefaultAttributeUseDelegate OnDefaultAttributeUse { set { onDefaultAttributeUse = value; } } #endif // // Internal properties for XmlValidatingReader // #if !SILVERLIGHT // Needed only for XmlValidatingReader internal bool XmlValidatingReaderCompatibilityMode { set { validatingReaderCompatFlag = value; // Fix for VSWhidbey 516556; These namespaces must be added to the nametable for back compat reasons. if ( value ) { nameTable.Add( XmlReservedNs.NsXs ); // Note: this is equal to XmlReservedNs.NsXsd in Everett nameTable.Add( XmlReservedNs.NsXsi ); nameTable.Add( XmlReservedNs.NsDataType ); } } } internal XmlNodeType FragmentType { get { return fragmentType; } } internal void ChangeCurrentNodeType( XmlNodeType newNodeType ) { Debug.Assert( curNode.type == XmlNodeType.Whitespace && newNodeType == XmlNodeType.SignificantWhitespace, "Incorrect node type change!" ); curNode.type = newNodeType; } internal XmlResolver GetResolver() { return xmlResolver; } internal object InternalSchemaType { get { return curNode.schemaType; } set { curNode.schemaType = value; } } internal object InternalTypedValue { get { return curNode.typedValue; } set { curNode.typedValue = value; } } internal bool StandAlone { get { return standalone; } } internal override XmlNamespaceManager NamespaceManager { get { return namespaceManager; } } internal bool V1Compat { get { return v1Compat; } } internal ConformanceLevel V1ComformanceLevel { get { return fragmentType == XmlNodeType.Element ? ConformanceLevel.Fragment : ConformanceLevel.Document; } } #endif private bool AddDefaultAttributeDtd(IDtdDefaultAttributeInfo defAttrInfo, bool definedInDtd, NodeData[] nameSortedNodeData) { if ( defAttrInfo.Prefix.Length > 0 ) { attrNeedNamespaceLookup = true; } string localName = defAttrInfo.LocalName; string prefix = defAttrInfo.Prefix; // check for duplicates if (nameSortedNodeData != null) { if (Array.BinarySearch
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TableLayoutPanelResizeGlyph.cs
- ContainerControl.cs
- XpsFilter.cs
- ArrayTypeMismatchException.cs
- DataGridColumnHeaderAutomationPeer.cs
- SmtpReplyReaderFactory.cs
- SizeAnimationBase.cs
- Divide.cs
- SoapHttpTransportImporter.cs
- DbModificationCommandTree.cs
- InputMethodStateTypeInfo.cs
- UrlPropertyAttribute.cs
- InfoCardUIAgent.cs
- TableLayout.cs
- HashCodeCombiner.cs
- InkCanvasSelectionAdorner.cs
- SimpleColumnProvider.cs
- SqlDependencyListener.cs
- XmlCharCheckingWriter.cs
- PlacementWorkspace.cs
- Matrix3D.cs
- QuaternionKeyFrameCollection.cs
- TransformDescriptor.cs
- ActivityCollectionMarkupSerializer.cs
- SynchronizedDispatch.cs
- ScriptingRoleServiceSection.cs
- ModelItemDictionary.cs
- PersonalizationStateInfo.cs
- RelationshipConstraintValidator.cs
- DrawTreeNodeEventArgs.cs
- COM2TypeInfoProcessor.cs
- EventBuilder.cs
- StringAnimationUsingKeyFrames.cs
- EllipseGeometry.cs
- BoolExpr.cs
- TlsSspiNegotiation.cs
- BamlResourceSerializer.cs
- TextMetrics.cs
- HttpHandlersSection.cs
- MethodAccessException.cs
- TraceSource.cs
- Lease.cs
- X509CertificateEndpointIdentity.cs
- WebBrowserContainer.cs
- ColumnWidthChangingEvent.cs
- SecureStringHasher.cs
- DBConnectionString.cs
- Attributes.cs
- hwndwrapper.cs
- XsltArgumentList.cs
- CircleHotSpot.cs
- listitem.cs
- Point3DAnimationUsingKeyFrames.cs
- OptimalBreakSession.cs
- SamlDoNotCacheCondition.cs
- SynchronizationLockException.cs
- ProcessHostConfigUtils.cs
- ListViewItem.cs
- ConstraintConverter.cs
- BackStopAuthenticationModule.cs
- TriggerBase.cs
- Brush.cs
- Stack.cs
- StateManagedCollection.cs
- ConfigurationException.cs
- RegexCharClass.cs
- followingquery.cs
- Rotation3DAnimationUsingKeyFrames.cs
- DataGridViewTextBoxColumn.cs
- DropSource.cs
- MimeReturn.cs
- ContentControl.cs
- PropertyGroupDescription.cs
- LinkButton.cs
- PublisherIdentityPermission.cs
- CollaborationHelperFunctions.cs
- ResourceDefaultValueAttribute.cs
- MethodBody.cs
- ProviderConnectionPointCollection.cs
- MediaSystem.cs
- HttpDictionary.cs
- smtpconnection.cs
- XmlDownloadManager.cs
- FormViewUpdatedEventArgs.cs
- EntityWithKeyStrategy.cs
- PublisherIdentityPermission.cs
- WeakEventManager.cs
- CqlParser.cs
- Clock.cs
- BuildManager.cs
- LinqExpressionNormalizer.cs
- SharedPersonalizationStateInfo.cs
- Utils.cs
- TreeNodeCollection.cs
- InstanceCreationEditor.cs
- ProtocolImporter.cs
- TableParaClient.cs
- RectConverter.cs
- SiteMapPath.cs
- ReferentialConstraintRoleElement.cs