/*
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();
}
}