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
        }
    }
}