/* 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.IO; using dnSpy.Contracts.Text; namespace dnSpy.Contracts.Decompiler { /// /// Implements and writes the text to a /// public class TextWriterDecompilerOutput : IDecompilerOutput, IDisposable { readonly TextWriter writer; readonly Indenter indenter; bool addIndent = true; int position; /// /// Gets the total length of the written text /// public virtual int Length => position; /// /// This equals plus any indentation that must be written /// before the next text. /// public virtual int NextPosition => position + (addIndent ? indenter.String.Length : 0); bool IDecompilerOutput.UsesCustomData => false; /// /// Constructor /// /// Text writer to use /// Indenter or null public TextWriterDecompilerOutput(TextWriter writer, Indenter? indenter = null) { this.writer = writer ?? throw new ArgumentNullException(nameof(writer)); 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() { var nlArray = newLineArray; writer.Write(nlArray); position += nlArray.Length; addIndent = true; } static readonly char[] newLineArray = Environment.NewLine.ToCharArray(); void AddIndent() { if (!addIndent) return; addIndent = false; var s = indenter.String; writer.Write(s); position += s.Length; } void AddText(string text, object color) { if (addIndent) AddIndent(); writer.Write(text); position += text.Length; } void AddText(string text, int index, int length, object color) { if (addIndent) AddIndent(); if (index == 0 && length == text.Length) writer.Write(text); else writer.Write(text.Substring(index, length)); position += 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) => 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) => AddText(text, index, length, color); /// /// Returns the result from 's method /// /// public override string ToString() => writer.ToString()!; /// /// Disposes this instance and its underlying /// public void Dispose() => writer.Dispose(); } }