File: XsdCachingReaderAsync.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (128 lines) | stat: -rw-r--r-- 5,778 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

using System.IO;
using System.Text;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Diagnostics;
using System.Globalization;
using System.Collections;
using System.Security.Policy;

using System.Threading.Tasks;

namespace System.Xml {

    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
        }

    }
}