| File: System\Number.Polyfill.cs | Web Access |
| Project: src\runtime\src\libraries\System.Runtime.Numerics\src\System.Runtime.Numerics.csproj (System.Runtime.Numerics) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.Wasm; using System.Runtime.Intrinsics.X86; using System.Text; namespace System { // Polyfill CoreLib internal interfaces and methods // Define necessary members only internal interface IUtfChar<TSelf> : IEquatable<TSelf> where TSelf : unmanaged, IUtfChar<TSelf> { public static abstract TSelf CastFrom(byte value); public static abstract TSelf CastFrom(char value); public static abstract TSelf CastFrom(int value); public static abstract TSelf CastFrom(uint value); public static abstract TSelf CastFrom(ulong value); public static abstract uint CastToUInt32(TSelf value); } #pragma warning disable CA1067 // Polyfill only type internal readonly struct Utf16Char(char ch) : IUtfChar<Utf16Char> #pragma warning restore CA1067 { private readonly char value = ch; public static Utf16Char CastFrom(byte value) => new((char)value); public static Utf16Char CastFrom(char value) => new(value); public static Utf16Char CastFrom(int value) => new((char)value); public static Utf16Char CastFrom(uint value) => new((char)value); public static Utf16Char CastFrom(ulong value) => new((char)value); public static uint CastToUInt32(Utf16Char value) => value.value; public bool Equals(Utf16Char other) => value == other.value; } #pragma warning disable CA1067 // Polyfill only type internal readonly struct Utf8Char(byte ch) : IUtfChar<Utf8Char> #pragma warning restore CA1067 { private readonly byte value = ch; public static Utf8Char CastFrom(byte value) => new(value); public static Utf8Char CastFrom(char value) => new((byte)value); public static Utf8Char CastFrom(int value) => new((byte)value); public static Utf8Char CastFrom(uint value) => new((byte)value); public static Utf8Char CastFrom(ulong value) => new((byte)value); public static uint CastToUInt32(Utf8Char value) => value.value; public bool Equals(Utf8Char other) => value == other.value; } internal static partial class Number { internal static bool AllowHyphenDuringParsing(this NumberFormatInfo info) { string negativeSign = info.NegativeSign; return negativeSign.Length == 1 && negativeSign[0] switch { '\u2012' or // Figure Dash '\u207B' or // Superscript Minus '\u208B' or // Subscript Minus '\u2212' or // Minus Sign '\u2796' or // Heavy Minus Sign '\uFE63' or // Small Hyphen-Minus '\uFF0D' => true, // Fullwidth Hyphen-Minus _ => false }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool IsWhiteSpace<TChar>(this ReadOnlySpan<TChar> span, out int elementsConsumed) where TChar : unmanaged, IUtfChar<TChar> { int elemsConsumed; for (int i = 0; i < span.Length; i += elemsConsumed) { if (DecodeFromUtfChar(span[i..], out Rune rune, out elemsConsumed) != OperationStatus.Done) { elementsConsumed = i; return false; } if (!Rune.IsWhiteSpace(rune)) { elementsConsumed = i; return false; } } elementsConsumed = span.Length; return true; } internal static OperationStatus DecodeFromUtfChar<TChar>(ReadOnlySpan<TChar> span, out Rune result, out int elemsConsumed) where TChar : unmanaged, IUtfChar<TChar> { return (typeof(TChar) == typeof(Utf8Char)) ? Rune.DecodeFromUtf8(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(span), out result, out elemsConsumed) : Rune.DecodeFromUtf16(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(span), out result, out elemsConsumed); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> FromString<TChar>(string value) where TChar : unmanaged, IUtfChar<TChar> { if (typeof(TChar) == typeof(Utf8Char)) { return Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(Encoding.UTF8.GetBytes(value)); } else { Debug.Assert(typeof(TChar) == typeof(Utf16Char)); return Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> PositiveSignTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.PositiveSign); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> NegativeSignTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.NegativeSign); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> CurrencySymbolTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.CurrencySymbol); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> PercentSymbolTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.PercentSymbol); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> PerMilleSymbolTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.PerMilleSymbol); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> CurrencyDecimalSeparatorTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.CurrencyDecimalSeparator); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> CurrencyGroupSeparatorTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.CurrencyGroupSeparator); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> NumberDecimalSeparatorTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.NumberDecimalSeparator); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> NumberGroupSeparatorTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.NumberGroupSeparator); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> PercentDecimalSeparatorTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.PercentDecimalSeparator); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ReadOnlySpan<TChar> PercentGroupSeparatorTChar<TChar>(this NumberFormatInfo info) where TChar : unmanaged, IUtfChar<TChar> => FromString<TChar>(info.PercentGroupSeparator); } }