private void Read()

in src/PerfView/OtherSources/XMLStackSource.cs [312:575]


        private void Read(XmlReader reader)
        {
            Stack<string> frameStack = null;
            // We use the invarient culture, otherwise if we encode in france and decode 
            // in english we get parse errors (this happened!);
            var invariantCulture = CultureInfo.InvariantCulture;
            var inputDepth = reader.Depth;
            var depthForSamples = 0;
            while (reader.Read())
            {
                PROCESS_NODE:
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (reader.Name == "Sample")
                        {
                            var sample = new StackSourceSample(this);
                            sample.Metric = 1;
                            if (reader.MoveToFirstAttribute())
                            {
                                do
                                {
                                    if (reader.Name == "Time")
                                    {
                                        sample.TimeRelativeMSec = double.Parse(reader.ReadContentAsString(), invariantCulture);
                                    }
                                    else if (reader.Name == "StackID")
                                    {
                                        sample.StackIndex = (StackSourceCallStackIndex)reader.ReadContentAsInt();
                                    }
                                    else if (reader.Name == "Metric")
                                    {
                                        sample.Metric = float.Parse(reader.ReadContentAsString(), invariantCulture);
                                    }
                                } while (reader.MoveToNextAttribute());
                            }
                            sample.SampleIndex = (StackSourceSampleIndex)m_curSample;
                            m_samples.Set(m_curSample++, sample);
                            if (sample.TimeRelativeMSec > m_maxTime)
                            {
                                m_maxTime = sample.TimeRelativeMSec;
                            }

                            // See if there is a literal stack present as the body of 
                            if (!reader.Read())
                            {
                                break;
                            }

                            if (reader.NodeType != XmlNodeType.Text)
                            {
                                goto PROCESS_NODE;
                            }

                            string rawStack = reader.Value.Trim();
                            if (0 < rawStack.Length)
                            {
                                InitInterner();

                                StackSourceCallStackIndex stackIdx = StackSourceCallStackIndex.Invalid;
                                string[] frames = rawStack.Split('\n');
                                for (int i = frames.Length - 1; 0 <= i; --i)
                                {
                                    var frameIdx = m_interner.FrameIntern(frames[i].Trim());
                                    stackIdx = m_interner.CallStackIntern(frameIdx, stackIdx);
                                }
                                sample.StackIndex = stackIdx;
                            }
                        }
                        else if (reader.Name == "Stack")
                        {
                            int stackID = -1;
                            int callerID = -1;
                            int frameID = -1;
                            if (reader.MoveToFirstAttribute())
                            {
                                do
                                {
                                    if (reader.Name == "ID")
                                    {
                                        stackID = reader.ReadContentAsInt();
                                    }
                                    else if (reader.Name == "FrameID")
                                    {
                                        frameID = reader.ReadContentAsInt();
                                    }
                                    else if (reader.Name == "CallerID")
                                    {
                                        callerID = reader.ReadContentAsInt();
                                    }
                                } while (reader.MoveToNextAttribute());
                                if (0 <= stackID)
                                {
                                    m_stacks.Set(stackID, new Frame(frameID, callerID));
                                }
                            }

                        }
                        else if (reader.Name == "Frame")
                        {
                            var frameID = -1;
                            var optimizationTierStr = string.Empty;
                            if (reader.MoveToFirstAttribute())
                            {
                                do
                                {
                                    if (reader.Name == "ID")
                                    {
                                        frameID = reader.ReadContentAsInt();
                                    }
                                    else if (reader.Name == "OptimizationTier")
                                    {
                                        if (m_showOptimizationTiers)
                                        {
                                            var optimizationTierCandidateStr = reader.ReadContentAsString();
                                            if (Enum.TryParse<OptimizationTier>(optimizationTierCandidateStr, out var optimizationTier) &&
                                                optimizationTier != OptimizationTier.Unknown)
                                            {
                                                optimizationTierStr = optimizationTierCandidateStr;
                                            }
                                        }
                                    }
                                } while (reader.MoveToNextAttribute());
                            }
                            reader.Read();      // Move on to body of the element
                            var frameName = reader.ReadContentAsString();

                            if (optimizationTierStr.Length > 0)
                            {
                                int exclamationIndex = frameName.IndexOf('!');
                                if (exclamationIndex >= 0)
                                {
                                    frameName =
                                        frameName.Substring(0, exclamationIndex + 1) +
                                        $"[{optimizationTierStr}]" +
                                        frameName.Substring(exclamationIndex + 1);
                                }
                            }

                            m_frames.Set(frameID, frameName);
                        }
                        else if (reader.Name == "Frames")
                        {
                            var count = reader.GetAttribute("Count");
                            if (count != null && m_frames.Count == 0)
                            {
                                m_frames = new GrowableArray<string>(int.Parse(count));
                            }
                        }
                        else if (reader.Name == "Stacks")
                        {
                            var count = reader.GetAttribute("Count");
                            if (count != null && m_stacks.Count == 0)
                            {
                                m_stacks = new GrowableArray<Frame>(int.Parse(count));
                            }
#if DEBUG
                            for (int i = 0; i < m_stacks.Count; i++)
                                m_stacks[i] = new Frame(int.MinValue, int.MinValue);
#endif
                        }
                        else if (reader.Name == "Samples")
                        {
                            var count = reader.GetAttribute("Count");
                            if (count != null && m_samples.Count == 0)
                            {
                                m_samples = new GrowableArray<StackSourceSample>(int.Parse(count));
                            }

                            depthForSamples = reader.Depth;
                        }
                        // This is the logic for the JSON case.  These are the anonymous object representing a sample.  
                        else if (reader.Name == "item")
                        {
                            // THis is an item which is an element of the 'Samples' array.  
                            if (reader.Depth == depthForSamples + 1)
                            {
                                var sample = new StackSourceSample(this);
                                sample.Metric = 1;

                                InitInterner();
                                int depthForSample = reader.Depth;
                                if (frameStack == null)
                                {
                                    frameStack = new Stack<string>();
                                }

                                frameStack.Clear();

                                while (reader.Read())
                                {
                                    PROCESS_NODE_SAMPLE:
                                    if (reader.Depth <= depthForSample)
                                    {
                                        break;
                                    }

                                    if (reader.NodeType == XmlNodeType.Element)
                                    {
                                        if (reader.Name == "Time")
                                        {
                                            sample.TimeRelativeMSec = reader.ReadElementContentAsDouble();
                                            goto PROCESS_NODE_SAMPLE;
                                        }
                                        else if (reader.Name == "Metric")
                                        {
                                            sample.Metric = (float)reader.ReadElementContentAsDouble();
                                            goto PROCESS_NODE_SAMPLE;
                                        }
                                        else if (reader.Name == "item")
                                        {
                                            // Item is a string under stack under the sample.  
                                            if (reader.Depth == depthForSample + 2)
                                            {
                                                frameStack.Push(reader.ReadElementContentAsString());
                                                goto PROCESS_NODE_SAMPLE;
                                            }
                                        }
                                    }
                                }

                                // Reverse the order of the frames in the stack.  
                                sample.StackIndex = StackSourceCallStackIndex.Invalid;
                                while (0 < frameStack.Count)
                                {
                                    var frameIdx = m_interner.FrameIntern(frameStack.Pop());
                                    sample.StackIndex = m_interner.CallStackIntern(frameIdx, sample.StackIndex);
                                }

                                if (sample.TimeRelativeMSec > m_maxTime)
                                {
                                    m_maxTime = sample.TimeRelativeMSec;
                                }

                                sample.SampleIndex = (StackSourceSampleIndex)m_curSample;
                                m_samples.Set(m_curSample++, sample);
                            }
                        }
                        break;
                    case XmlNodeType.EndElement:
                        if (reader.Depth <= inputDepth)
                        {
                            reader.Read();
                            goto Done;
                        }
                        break;
                    case XmlNodeType.Text:
                    default:
                        break;
                }
            }
            Done:;
#if DEBUG
            for (int i = 0; i < m_samples.Count; i++)
                Debug.Assert(m_samples[i] != null);
            for (int i = 0; i < m_frames.Count; i++)
                Debug.Assert(m_frames[i] != null);
            for (int i = 0; i < m_stacks.Count; i++)
            {
                Debug.Assert(m_stacks[i].frameID >= 0);
                Debug.Assert(m_stacks[i].callerID >= -1);
            }
#endif
        }