/* 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.Text; using dnSpy.Contracts.Text; namespace dnSpy.Contracts.Decompiler { /// /// Implements and writes the text to a /// public class StringBuilderDecompilerOutput : IDecompilerOutput { readonly StringBuilder sb; readonly Indenter indenter; bool addIndent = true; /// /// Gets the total length of the written text /// public virtual int Length => sb.Length; /// /// This equals plus any indentation that must be written /// before the next text. /// public virtual int NextPosition => sb.Length + (addIndent ? indenter.String.Length : 0); bool IDecompilerOutput.UsesCustomData => false; /// /// Constructor /// public StringBuilderDecompilerOutput() { sb = new StringBuilder(); indenter = new Indenter(4, 4, true); } /// /// Constructor /// /// Indenter public StringBuilderDecompilerOutput(Indenter indenter) { sb = new StringBuilder(); this.indenter = indenter ?? throw new ArgumentNullException(nameof(indenter)); } /// /// Constructor /// /// String builder to use. Its method gets called by the constructor /// Indenter or null public StringBuilderDecompilerOutput(StringBuilder stringBuilder, Indenter? indenter = null) { if (stringBuilder is null) throw new ArgumentNullException(nameof(stringBuilder)); stringBuilder.Clear(); sb = stringBuilder; this.indenter = indenter ?? new Indenter(4, 4, true); } void IDecompilerOutput.AddCustomData(string id, TData data) { } /// /// Increments the indentation level. Nothing is added to the output stream. /// public virtual void IncreaseIndent() => indenter.IncreaseIndent(); /// /// Decrements the indentation level. Nothing is added to the output stream. /// public virtual void DecreaseIndent() => indenter.DecreaseIndent(); /// /// Writes a new line without writing any indentation /// public virtual void WriteLine() { sb.AppendLine(); addIndent = true; } void AddIndent() { if (!addIndent) return; addIndent = false; sb.Append(indenter.String); } void AddText(string text, object color) { if (addIndent) AddIndent(); sb.Append(text); } void AddText(string text, int index, int length, object color) { if (addIndent) AddIndent(); sb.Append(text, index, length); } /// /// Writes text. The text will be indented if needed. /// /// Text public virtual void Write(string text) => AddText(text, BoxedTextColor.Text); /// /// Writes text and color. The text will be indented if needed. /// /// Text /// Color, eg. public virtual void Write(string text, object color) => AddText(text, color); /// /// Writes text and color. The text will be indented if needed. /// /// Text /// Index in /// Number of characters to write /// Color, eg. public virtual void Write(string text, int index, int length, object color) => AddText(text, index, length, color); /// /// Writes text, color and a reference. The text will be indented if needed. /// /// Text /// Reference /// Flags /// Color, eg. public virtual void Write(string text, object? reference, DecompilerReferenceFlags flags, object color) { if (addIndent) AddIndent(); AddText(text, color); } /// /// Writes text, color and a reference. The text will be indented if needed. /// /// Text /// Index in /// Number of characters to write /// Reference /// Flags /// Color, eg. public virtual void Write(string text, int index, int length, object? reference, DecompilerReferenceFlags flags, object color) { if (addIndent) AddIndent(); AddText(text, index, length, color); } /// /// Gets the text /// /// public string GetText() => sb.ToString(); /// /// Gets the text /// /// public override string ToString() => sb.ToString(); } }