Files

85 lines
2.1 KiB
C#
Raw Permalink Normal View History

2026-08-27 10:56:38 -06:00
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
using System.Text.Unicode;
namespace System.Text.Encodings.Web;
internal struct AllowedBmpCodePointsBitmap
{
private const int BitmapLengthInDWords = 2048;
private unsafe fixed uint Bitmap[2048];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void AllowChar(char value)
{
_GetIndexAndOffset(value, out UIntPtr index, out int offset);
ref uint reference = ref Bitmap[(ulong)index];
reference |= (uint)(1 << offset);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void ForbidChar(char value)
{
_GetIndexAndOffset(value, out UIntPtr index, out int offset);
ref uint reference = ref Bitmap[(ulong)index];
reference &= (uint)(~(1 << offset));
}
public void ForbidHtmlCharacters()
{
ForbidChar('<');
ForbidChar('>');
ForbidChar('&');
ForbidChar('\'');
ForbidChar('"');
ForbidChar('+');
}
public unsafe void ForbidUndefinedCharacters()
{
fixed (uint* bitmap = Bitmap)
{
ReadOnlySpan<byte> definedBmpCodePointsBitmapLittleEndian = UnicodeHelpers.GetDefinedBmpCodePointsBitmapLittleEndian();
Span<uint> span = new Span<uint>(bitmap, 2048);
for (int i = 0; i < span.Length; i++)
{
span[i] &= BinaryPrimitives.ReadUInt32LittleEndian(definedBmpCodePointsBitmapLittleEndian.Slice(i * 4));
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe readonly bool IsCharAllowed(char value)
{
_GetIndexAndOffset(value, out UIntPtr index, out int offset);
if ((Bitmap[(ulong)index] & (uint)(1 << offset)) != 0)
{
return true;
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe readonly bool IsCodePointAllowed(uint value)
{
if (!System.Text.UnicodeUtility.IsBmpCodePoint(value))
{
return false;
}
_GetIndexAndOffset(value, out UIntPtr index, out int offset);
if ((Bitmap[(ulong)index] & (uint)(1 << offset)) != 0)
{
return true;
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void _GetIndexAndOffset(uint value, out nuint index, out int offset)
{
index = value >> 5;
offset = (int)(value & 0x1F);
}
}