| File: FrameworkFork\Microsoft.Xml\Xml\Core\XsdCachingReaderAsync.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.IO; using System.Text; using Microsoft.Xml.Schema; using Microsoft.Xml.XPath; using System.Diagnostics; using System.Globalization; using System.Collections; // using System.Security.Policy; using System.Threading.Tasks; namespace Microsoft.Xml { using System; internal partial class XsdCachingReader : XmlReader, IXmlLineInfo { // Gets the text value of the current node. public override Task<string> GetValueAsync() { if (_returnOriginalStringValues) { return Task.FromResult(_cachedNode.OriginalStringValue); } else { return Task.FromResult(_cachedNode.RawValue); } } // Reads the next node from the stream/TextReader. public override async Task<bool> ReadAsync() { switch (_cacheState) { case CachingReaderState.Init: _cacheState = CachingReaderState.Record; goto case CachingReaderState.Record; case CachingReaderState.Record: ValidatingReaderNodeData recordedNode = null; if (await _coreReader.ReadAsync().ConfigureAwait(false)) { switch (_coreReader.NodeType) { case XmlNodeType.Element: //Dont record element within the content of a union type since the main reader will break on this and the underlying coreReader will be positioned on this node _cacheState = CachingReaderState.ReaderClosed; return false; case XmlNodeType.EndElement: recordedNode = AddContent(_coreReader.NodeType); recordedNode.SetItemData(_coreReader.LocalName, _coreReader.Prefix, _coreReader.NamespaceURI, _coreReader.Depth); //Only created for element node type recordedNode.SetLineInfo(_lineInfo); break; case XmlNodeType.Comment: case XmlNodeType.ProcessingInstruction: case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: recordedNode = AddContent(_coreReader.NodeType); recordedNode.SetItemData(await _coreReader.GetValueAsync().ConfigureAwait(false)); recordedNode.SetLineInfo(_lineInfo); recordedNode.Depth = _coreReader.Depth; break; default: break; } _cachedNode = recordedNode; return true; } else { _cacheState = CachingReaderState.ReaderClosed; return false; } case CachingReaderState.Replay: if (_currentContentIndex >= _contentIndex) { //When positioned on the last cached node, switch back as the underlying coreReader is still positioned on this node _cacheState = CachingReaderState.ReaderClosed; _cacheHandler(this); if (_coreReader.NodeType != XmlNodeType.Element || _readAhead) { //Only when coreReader not positioned on Element node, read ahead, otherwise it is on the next element node already, since this was not cached return await _coreReader.ReadAsync().ConfigureAwait(false); } return true; } _cachedNode = _contentEvents[_currentContentIndex]; if (_currentContentIndex > 0) { ClearAttributesInfo(); } _currentContentIndex++; return true; default: return false; } } // Skips to the end tag of the current element. public override async Task SkipAsync() { //Skip on caching reader should move to the end of the subtree, past all cached events switch (_cachedNode.NodeType) { case XmlNodeType.Element: if (_coreReader.NodeType != XmlNodeType.EndElement && !_readAhead) { //will be true for IsDefault cases where we peek only one node ahead int startDepth = _coreReader.Depth - 1; while (await _coreReader.ReadAsync().ConfigureAwait(false) && _coreReader.Depth > startDepth) ; } await _coreReader.ReadAsync().ConfigureAwait(false); _cacheState = CachingReaderState.ReaderClosed; _cacheHandler(this); break; case XmlNodeType.Attribute: MoveToElement(); goto case XmlNodeType.Element; default: Debug.Assert(_cacheState == CachingReaderState.Replay); await ReadAsync().ConfigureAwait(false); break; } } //Private methods internal Task SetToReplayModeAsync() { _cacheState = CachingReaderState.Replay; _currentContentIndex = 0; _currentAttrIndex = -1; return ReadAsync(); //Position on first node recorded to begin replaying } } }