1
0
Files
named-binary-tag/Nbt/Util/QuotedWriter.cs
2024-03-15 14:44:21 +01:00

128 lines
2.9 KiB
C#
Executable File

using System.Text;
namespace Nbt;
public sealed class QuotedWriter(TextWriter baseWriter, char quoteChar, char escapeChar, bool leaveOpen = false) : TextWriter
{
private readonly TextWriter baseWriter = baseWriter;
private readonly char quoteChar = quoteChar;
private readonly char escapeChar = escapeChar;
private readonly bool leaveOpen = leaveOpen;
private bool hasWrittenOneChar = false;
public QuotedWriter(StringBuilder sb, char quoteChar, char escapeChar) : this(new StringWriter(sb), quoteChar, escapeChar) { }
public override Encoding Encoding => baseWriter.Encoding;
public override void Write(char value)
{
if (!hasWrittenOneChar)
{
baseWriter.Write(quoteChar);
hasWrittenOneChar = true;
}
foreach (var c in Escape(value))
{
baseWriter.Write(c);
}
}
public override async Task WriteAsync(char value)
{
if (!hasWrittenOneChar)
{
await baseWriter.WriteAsync(quoteChar);
hasWrittenOneChar = true;
}
foreach (var c in Escape(value))
{
await baseWriter.WriteAsync(c);
}
}
private IEnumerable<char> Escape(char c)
{
var escape = false;
switch (c)
{
case '\t':
escape = true;
c = 't';
break;
case '\r':
escape = true;
c = 'r';
break;
case '\n':
escape = true;
c = 'n';
break;
default:
if (c == quoteChar || c == escapeChar)
{
escape = true;
}
break;
}
if (escape)
{
yield return escapeChar;
}
yield return c;
}
protected override void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (!hasWrittenOneChar)
{
baseWriter.Write(quoteChar);
}
baseWriter.Write(quoteChar);
if (!leaveOpen)
{
baseWriter.Dispose();
}
}
}
finally
{
base.Dispose(disposing);
}
}
public override async ValueTask DisposeAsync()
{
try
{
if (!hasWrittenOneChar)
{
await baseWriter.WriteAsync(quoteChar);
}
await baseWriter.WriteAsync(quoteChar);
if (!leaveOpen)
{
await baseWriter.DisposeAsync();
}
}
finally
{
await base.DisposeAsync();
}
}
}