| File: System\Reflection\Metadata\PortablePdb\SequencePointCollection.cs | Web Access |
| Project: src\runtime\src\libraries\System.Reflection.Metadata\src\System.Reflection.Metadata.csproj (System.Reflection.Metadata) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Internal; using System.Reflection.Metadata.Ecma335; namespace System.Reflection.Metadata { public readonly struct SequencePointCollection : IEnumerable<SequencePoint> { private readonly MemoryBlock _block; private readonly DocumentHandle _document; internal SequencePointCollection(MemoryBlock block, DocumentHandle document) { _block = block; _document = document; } public Enumerator GetEnumerator() { return new Enumerator(_block, _document); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator<SequencePoint> IEnumerable<SequencePoint>.GetEnumerator() { return GetEnumerator(); } public struct Enumerator : IEnumerator<SequencePoint> { private BlobReader _reader; private SequencePoint _current; private int _previousNonHiddenStartLine; private ushort _previousNonHiddenStartColumn; internal Enumerator(MemoryBlock block, DocumentHandle document) { _reader = new BlobReader(block); _current = new SequencePoint(document, -1); _previousNonHiddenStartLine = -1; _previousNonHiddenStartColumn = 0; } public bool MoveNext() { if (_reader.RemainingBytes == 0) { return false; } DocumentHandle document = _current.Document; int offset, deltaLines, deltaColumns, startLine; ushort startColumn; if (_reader.Offset == 0) { // header (skip local signature rid): _reader.ReadCompressedInteger(); if (document.IsNil) { document = ReadDocumentHandle(); } // IL offset: offset = _reader.ReadCompressedInteger(); } else { // skip all document records and update the current document accordingly: int deltaOffset; while ((deltaOffset = _reader.ReadCompressedInteger()) == 0) { document = ReadDocumentHandle(); } // IL offset: offset = AddOffsets(_current.Offset, deltaOffset); } ReadDeltaLinesAndColumns(out deltaLines, out deltaColumns); // hidden if (deltaLines == 0 && deltaColumns == 0) { _current = new SequencePoint(document, offset); return true; } // delta Start Line & Column: if (_previousNonHiddenStartLine < 0) { Debug.Assert(_previousNonHiddenStartColumn == 0); startLine = ReadLine(); startColumn = ReadColumn(); } else { startLine = AddLines(_previousNonHiddenStartLine, _reader.ReadCompressedSignedInteger()); startColumn = AddColumns(_previousNonHiddenStartColumn, _reader.ReadCompressedSignedInteger()); } _previousNonHiddenStartLine = startLine; _previousNonHiddenStartColumn = startColumn; _current = new SequencePoint( document, offset, startLine, startColumn, AddLines(startLine, deltaLines), AddColumns(startColumn, deltaColumns)); return true; } private void ReadDeltaLinesAndColumns(out int deltaLines, out int deltaColumns) { deltaLines = _reader.ReadCompressedInteger(); deltaColumns = (deltaLines == 0) ? _reader.ReadCompressedInteger() : _reader.ReadCompressedSignedInteger(); } private int ReadLine() { return _reader.ReadCompressedInteger(); } private ushort ReadColumn() { int column = _reader.ReadCompressedInteger(); if (column > ushort.MaxValue) { Throw.SequencePointValueOutOfRange(); } return (ushort)column; } private static int AddOffsets(int value, int delta) { int result = unchecked(value + delta); if (result < 0) { Throw.SequencePointValueOutOfRange(); } return result; } private static int AddLines(int value, int delta) { int result = unchecked(value + delta); if (result < 0 || result >= SequencePoint.HiddenLine) { Throw.SequencePointValueOutOfRange(); } return result; } private static ushort AddColumns(ushort value, int delta) { int result = unchecked(value + delta); if (result < 0 || result >= ushort.MaxValue) { Throw.SequencePointValueOutOfRange(); } return (ushort)result; } private DocumentHandle ReadDocumentHandle() { int rowId = _reader.ReadCompressedInteger(); if (rowId == 0 || !TokenTypeIds.IsValidRowId(rowId)) { Throw.InvalidHandle(); } return DocumentHandle.FromRowId(rowId); } public SequencePoint Current { get { return _current; } } object IEnumerator.Current { get { return _current; } } public void Reset() { _reader.Reset(); _current = default(SequencePoint); } void IDisposable.Dispose() { } } } }