using System; using System.Globalization; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Cysharp.Text { /// /// A implementation that is backed with . /// /// /// It's important to make sure the writer is always properly disposed. /// public sealed class ZStringWriter : TextWriter { private Utf16ValueStringBuilder sb; private bool isOpen; private UnicodeEncoding? encoding; /// /// Creates a new instance using as format provider. /// public ZStringWriter() : this(CultureInfo.CurrentCulture) { } /// /// Creates a new instance with given format provider. /// public ZStringWriter(IFormatProvider formatProvider) : base(formatProvider) { sb = ZString.CreateStringBuilder(); isOpen = true; } /// /// Disposes this instance, operations are no longer allowed. /// public override void Close() { Dispose(true); } protected override void Dispose(bool disposing) { sb.Dispose(); isOpen = false; base.Dispose(disposing); } public override Encoding Encoding => encoding = encoding ?? new UnicodeEncoding(false, false); public override void Write(char value) { AssertNotDisposed(); sb.Append(value); } public override void Write(char[] buffer, int index, int count) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (index < 0) { throw new ArgumentOutOfRangeException(nameof(index)); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (buffer.Length - index < count) { throw new ArgumentException(); } AssertNotDisposed(); sb.Append(buffer, index, count); } public override void Write(string value) { AssertNotDisposed(); if (value != null) { sb.Append(value); } } public override Task WriteAsync(char value) { Write(value); return Task.CompletedTask; } public override Task WriteAsync(string value) { Write(value); return Task.CompletedTask; } public override Task WriteAsync(char[] buffer, int index, int count) { Write(buffer, index, count); return Task.CompletedTask; } public override Task WriteLineAsync(char value) { WriteLine(value); return Task.CompletedTask; } public override Task WriteLineAsync(string value) { WriteLine(value); return Task.CompletedTask; } public override Task WriteLineAsync(char[] buffer, int index, int count) { WriteLine(buffer, index, count); return Task.CompletedTask; } public override void Write(bool value) { AssertNotDisposed(); sb.Append(value); } public override void Write(decimal value) { AssertNotDisposed(); sb.Append(value); } /// /// No-op. /// public override Task FlushAsync() { return Task.CompletedTask; } /// /// Materializes the current state from underlying string builder. /// public override string ToString() { return sb.ToString(); } #if !NETSTANDARD2_0 #if !UNITY_2018_3_OR_NEWER public override void Write(ReadOnlySpan buffer) { AssertNotDisposed(); sb.Append(buffer); } public override void WriteLine(ReadOnlySpan buffer) { AssertNotDisposed(); sb.Append(buffer); WriteLine(); } public override Task WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } Write(buffer.Span); return Task.CompletedTask; } public override Task WriteLineAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } WriteLine(buffer.Span); return Task.CompletedTask; } #endif #endif private void AssertNotDisposed() { if (!isOpen) { throw new ObjectDisposedException(nameof(sb)); } } } }