com.alicizax.unity.cysharp..../FormatHelper.cs
陈思海 4fbea560b5 init
2025-01-09 13:57:51 +08:00

172 lines
6.2 KiB
C#

using System;
using System.Text;
using System.Buffers;
using System.Runtime.CompilerServices;
namespace Cysharp.Text
{
internal static partial class Utf16FormatHelper
{
const char sp = (char)' ';
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void FormatTo<TBufferWriter, T>(ref TBufferWriter sb, T arg, int width, ReadOnlySpan<char> format, string argName)
where TBufferWriter : IBufferWriter<char>
{
if (width <= 0) // leftJustify
{
var span = sb.GetSpan(0);
if (!Utf16ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, span, out var argWritten, format))
{
sb.Advance(0);
span = sb.GetSpan(Math.Max(span.Length + 1, argWritten));
if (!Utf16ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, span, out argWritten, format))
{
ExceptionUtil.ThrowArgumentException(argName);
}
}
sb.Advance(argWritten);
width *= -1;
int padding = width - argWritten;
if (width > 0 && padding > 0)
{
var paddingSpan = sb.GetSpan(padding);
paddingSpan.Fill(sp);
sb.Advance(padding);
}
}
else
{
FormatToRightJustify(ref sb, arg, width, format, argName);
}
}
private static void FormatToRightJustify<TBufferWriter, T>(ref TBufferWriter sb, T arg, int width, ReadOnlySpan<char> format, string argName)
where TBufferWriter : IBufferWriter<char>
{
if (typeof(T) == typeof(string))
{
var s = Unsafe.As<string>(arg);
int padding = width - s.Length;
if (padding > 0)
{
var paddingSpan = sb.GetSpan(padding);
paddingSpan.Fill(sp);
sb.Advance(padding);
}
var span = sb.GetSpan(s.Length);
s.AsSpan().CopyTo(span);
sb.Advance(s.Length);
}
else
{
Span<char> s = stackalloc char[typeof(T).IsValueType ? Unsafe.SizeOf<T>() * 8 : 1024];
if (!Utf16ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, s, out var charsWritten, format))
{
s = stackalloc char[s.Length * 2];
if (!Utf16ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, s, out charsWritten, format))
{
ExceptionUtil.ThrowArgumentException(argName);
}
}
int padding = width - charsWritten;
if (padding > 0)
{
var paddingSpan = sb.GetSpan(padding);
paddingSpan.Fill(sp);
sb.Advance(padding);
}
var span = sb.GetSpan(charsWritten);
s.CopyTo(span);
sb.Advance(charsWritten);
}
}
}
internal static partial class Utf8FormatHelper
{
const byte sp = (byte)' ';
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void FormatTo<TBufferWriter, T>(ref TBufferWriter sb, T arg, int width, StandardFormat format, string argName)
where TBufferWriter : IBufferWriter<byte>
{
if (width <= 0) // leftJustify
{
var span = sb.GetSpan(0);
if (!Utf8ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, span, out var argWritten, format))
{
sb.Advance(0);
span = sb.GetSpan(Math.Max(span.Length + 1, argWritten));
if (!Utf8ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, span, out argWritten, format))
{
ExceptionUtil.ThrowArgumentException(argName);
}
}
sb.Advance(argWritten);
width *= -1;
int padding = width - argWritten;
if (width > 0 && padding > 0)
{
var paddingSpan = sb.GetSpan(padding);
paddingSpan.Fill(sp);
sb.Advance(padding);
}
}
else
{
FormatToRightJustify(ref sb, arg, width, format, argName);
}
}
private static void FormatToRightJustify<TBufferWriter, T>(ref TBufferWriter sb, T arg, int width, StandardFormat format, string argName)
where TBufferWriter : IBufferWriter<byte>
{
if (typeof(T) == typeof(string))
{
var s = Unsafe.As<string>(arg);
int padding = width - s.Length;
if (padding > 0)
{
var paddingSpan = sb.GetSpan(padding);
paddingSpan.Fill(sp);
sb.Advance(padding);
}
ZString.AppendChars(ref sb, s.AsSpan());
}
else
{
Span<byte> s = stackalloc byte[typeof(T).IsValueType ? Unsafe.SizeOf<T>() * 8 : 1024];
if (!Utf8ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, s, out var charsWritten, format))
{
s = stackalloc byte[s.Length * 2];
if (!Utf8ValueStringBuilder.FormatterCache<T>.TryFormatDelegate(arg, s, out charsWritten, format))
{
ExceptionUtil.ThrowArgumentException(argName);
}
}
int padding = width - charsWritten;
if (padding > 0)
{
var paddingSpan = sb.GetSpan(padding);
paddingSpan.Fill(sp);
sb.Advance(padding);
}
var span = sb.GetSpan(charsWritten);
s.CopyTo(span);
sb.Advance(charsWritten);
}
}
}
}