/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; namespace dnSpy.Decompiler.ILSpy.Core.XmlDoc { struct XmlDocLine : IEnumerable, IEnumerator { readonly string s; readonly int end; SubString? current; SubStringInfo? indent; StringLineIterator iter; int emptyLines; public XmlDocLine(string s) : this(s, 0, s.Length) { } public XmlDocLine(string s, int start, int length) { this.s = s; end = start + length; current = null; indent = null; iter = new StringLineIterator(s, start, end - start); emptyLines = 0; } public XmlDocLine GetEnumerator() => this; IEnumerator IEnumerable.GetEnumerator() { Debug.Fail("'this' was boxed"); return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { Debug.Fail("'this' was boxed"); return GetEnumerator(); } public SubString? Current => current; object? IEnumerator.Current { get { Debug.Fail("'this' was boxed"); return current; } } public void Dispose() { } public bool MoveNext() { if (indent is null) { for (;;) { if (!iter.MoveNext()) return false; if (!IsWhiteSpace(s, iter.Current)) break; } indent = GetIndentation(s, iter.Current); goto start2; } if (emptyLines != 0) goto start2; start: if (!iter.MoveNext()) return false; start2: if (IsWhiteSpace(s, iter.Current)) { emptyLines++; goto start; } if (emptyLines != 0) { if (emptyLines != -1) { emptyLines--; if (emptyLines == 0) emptyLines = -1; current = null; return true; } emptyLines = 0; } Trim(out int index, out int end); current = new SubString(s, index, end - index); return true; } void Trim(out int trimmedIndex, out int trimmedEnd) { Debug2.Assert(indent is not null); int index = iter.Current.Index; int end = index + iter.Current.Length; if (indent.Value.Length > iter.Current.Length) { trimmedIndex = index; trimmedEnd = end; return; } int end2 = index + indent.Value.Length; for (int i = index, j = indent.Value.Index; i < end2; i++, j++) { if (s[i] != s[j]) { trimmedIndex = index; trimmedEnd = end; return; } } trimmedIndex = index + indent.Value.Length; trimmedEnd = end; Debug.Assert(trimmedIndex <= trimmedEnd); } SubStringInfo GetIndentation(string doc, SubStringInfo info) { int end = info.Index + info.Length; int i = info.Index; for (; i < end; i++) { if (!char.IsWhiteSpace(doc[i])) break; } return new SubStringInfo(info.Index, i - info.Index); } bool IsWhiteSpace(string doc, SubStringInfo info) { int end = info.Index + info.Length; for (int i = info.Index; i < end; i++) { if (!char.IsWhiteSpace(doc[i])) return false; } return true; } public void Reset() => throw new NotImplementedException(); } }