[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Double : IComparable, IConvertible, IFormattable, IComparable<Double>, IEquatable<Double>
+ public struct Double : IComparable, IConvertible, IFormattable, IComparable<Double>, IEquatable<Double>, ISpanFormattable
{
private double m_value; // Do not rename (binary serialization)
return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
}
+ public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null)
+ {
+ return Number.TryFormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten);
+ }
+
public static double Parse(String s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
public static string FormatDouble(double value, string format, NumberFormatInfo info)
{
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+ Span<char> stackBuffer = stackalloc char[CharStackBufferSize];
+ var sb = new ValueStringBuilder(stackBuffer);
+ return FormatDouble(ref sb, value, format, info) ?? sb.ToString();
+ }
+
+ public static bool TryFormatDouble(double value, ReadOnlySpan<char> format, NumberFormatInfo info, Span<char> destination, out int charsWritten)
+ {
+ Span<char> stackBuffer = stackalloc char[CharStackBufferSize];
+ var sb = new ValueStringBuilder(stackBuffer);
+ string s = FormatDouble(ref sb, value, format, info);
+ return s != null ?
+ TryCopyTo(s, destination, out charsWritten) :
+ sb.TryCopyTo(destination, out charsWritten);
+ }
+ /// <summary>Formats the specified value according to the specified format and info.</summary>
+ /// <returns>
+ /// Non-null if an existing string can be returned, in which case the builder will be unmodified.
+ /// Null if no existing string was returned, in which case the formatted output is in the builder.
+ /// </returns>
+ private static string FormatDouble(ref ValueStringBuilder sb, double value, ReadOnlySpan<char> format, NumberFormatInfo info)
+ {
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = DoublePrecision;
NumberBuffer number = default;
NumberToString(ref sb, ref number, 'G', 17, info, isDecimal: false);
}
- return sb.ToString();
+ return null;
}
case 'E':
NumberToStringFormat(ref sb, ref number, format, info);
}
- return sb.ToString();
+ return null;
}
public static string FormatSingle(float value, string format, NumberFormatInfo info)
{
- ValueStringBuilder sb;
- unsafe
- {
- char* stackPtr = stackalloc char[CharStackBufferSize];
- sb = new ValueStringBuilder(new Span<char>(stackPtr, CharStackBufferSize));
- }
+ Span<char> stackBuffer = stackalloc char[CharStackBufferSize];
+ var sb = new ValueStringBuilder(stackBuffer);
+ return FormatSingle(ref sb, value, format, info) ?? sb.ToString();
+ }
+
+ public static bool TryFormatSingle(float value, ReadOnlySpan<char> format, NumberFormatInfo info, Span<char> destination, out int charsWritten)
+ {
+ Span<char> stackBuffer = stackalloc char[CharStackBufferSize];
+ var sb = new ValueStringBuilder(stackBuffer);
+ string s = FormatSingle(ref sb, value, format, info);
+ return s != null ?
+ TryCopyTo(s, destination, out charsWritten) :
+ sb.TryCopyTo(destination, out charsWritten);
+ }
+ /// <summary>Formats the specified value according to the specified format and info.</summary>
+ /// <returns>
+ /// Non-null if an existing string can be returned, in which case the builder will be unmodified.
+ /// Null if no existing string was returned, in which case the formatted output is in the builder.
+ /// </returns>
+ private static string FormatSingle(ref ValueStringBuilder sb, float value, ReadOnlySpan<char> format, NumberFormatInfo info)
+ {
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = FloatPrecision;
NumberBuffer number = default;
DoubleToNumber(value, 9, ref number);
NumberToString(ref sb, ref number, 'G', 9, info, isDecimal: false);
}
-
- return sb.ToString();
+ return null;
}
case 'E':
{
NumberToStringFormat(ref sb, ref number, format, info);
}
+ return null;
+ }
- return sb.ToString();
+ private static bool TryCopyTo(string source, Span<char> destination, out int charsWritten)
+ {
+ Debug.Assert(source != null);
+
+ if (source.AsReadOnlySpan().TryCopyTo(destination))
+ {
+ charsWritten = source.Length;
+ return true;
+ }
+
+ charsWritten = 0;
+ return false;
}
public static string FormatInt32(int value, ReadOnlySpan<char> format, NumberFormatInfo info)
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Single : IComparable, IConvertible, IFormattable, IComparable<Single>, IEquatable<Single>
+ public struct Single : IComparable, IConvertible, IFormattable, IComparable<Single>, IEquatable<Single>, ISpanFormattable
{
private float m_value; // Do not rename (binary serialization)
return Number.FormatSingle(m_value, format, NumberFormatInfo.GetInstance(provider));
}
+ public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null)
+ {
+ return Number.TryFormatSingle(m_value, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten);
+ }
+
// Parses a float from a String in the given style. If
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.