// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using Internal.Runtime.CompilerServices;
// s_casingTable is covering the Unicode BMP plane only. Surrogate casing is handled separately.
// Every cell in the table is covering the casing of 256 characters in the BMP.
// Every cell is array of 512 character for uppercasing mapping.
- private static ushort []?[] s_casingTable =
+ private static ushort []?[] s_casingTable = InitCasingTable();
+
+ /*
+ The table is initialized to:
{
- /* 0000-07FF */ s_basicLatin, null, null, null, null, null, null, null,
- /* 0800-0FFF */ null, null, null, null, null, null, null, null,
- /* 1000-17FF */ null, s_noCasingPage, null, null, s_noCasingPage, s_noCasingPage, null, null,
- /* 1800-1FFF */ null, null, null, null, null, null, null, null,
- /* 2000-27FF */ null, null, s_noCasingPage, s_noCasingPage, null, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 2800-2FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, null, null, null, null, null,
- /* 3000-37FF */ null, null, null, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 3800-3FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 4000-47FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 4800-4FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 5000-57FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 5800-5FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 6000-67FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 6800-6FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 7000-77FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 7800-7FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 8000-87FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 8800-8FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 9000-97FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* 9800-9FFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, null,
- /* A000-A7FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, null, s_noCasingPage, null, null,
- /* A800-AFFF */ null, null, null, null, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* B000-B7FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* B800-BFFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* C000-C7FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* C800-CFFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* D000-D7FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, null,
- /* D800-DFFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* E000-E7FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* E800-EFFF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* F000-F7FF */ s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
- /* F800-FFFF */ s_noCasingPage, s_noCasingPage, null, null, s_noCasingPage, null, null, null,
+ // 0000-07FF // s_basicLatin, null, null, null, null, null, null, null,
+ // 0800-0FFF // null, null, null, null, null, null, null, null,
+ // 1000-17FF // null, s_noCasingPage, null, null, s_noCasingPage, s_noCasingPage, null, null,
+ // 1800-1FFF // null, null, null, null, null, null, null, null,
+ // 2000-27FF // null, null, s_noCasingPage, s_noCasingPage, null, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 2800-2FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, null, null, null, null, null,
+ // 3000-37FF // null, null, null, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 3800-3FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 4000-47FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 4800-4FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 5000-57FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 5800-5FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 6000-67FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 6800-6FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 7000-77FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 7800-7FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 8000-87FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 8800-8FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 9000-97FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // 9800-9FFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, null,
+ // A000-A7FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, null, s_noCasingPage, null, null,
+ // A800-AFFF // null, null, null, null, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // B000-B7FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // B800-BFFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // C000-C7FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // C800-CFFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // D000-D7FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, null,
+ // D800-DFFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // E000-E7FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // E800-EFFF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // F000-F7FF // s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage, s_noCasingPage,
+ // F800-FFFF // s_noCasingPage, s_noCasingPage, null, null, s_noCasingPage, null, null, null,
+ };
+*/
+
+ // 0 - null
+ // 1 - s_noCasingPage
+ // The bits are in reverse order for readability, i.e. the highest order bit refers to
+ // the lowest index.
+ private static ReadOnlySpan<byte> s_casingTableInit => new byte[32]
+ {
+ /* 0000-07FF */ 0b00000000,
+ /* 0800-0FFF */ 0b00000000,
+ /* 1000-17FF */ 0b01001100,
+ /* 1800-1FFF */ 0b00000000,
+ /* 2000-27FF */ 0b00110111,
+ /* 2800-2FFF */ 0b11100000,
+ /* 3000-37FF */ 0b00011111,
+ /* 3800-3FFF */ 0b11111111,
+ /* 4000-47FF */ 0b11111111,
+ /* 4800-4FFF */ 0b11111111,
+ /* 5000-57FF */ 0b11111111,
+ /* 5800-5FFF */ 0b11111111,
+ /* 6000-67FF */ 0b11111111,
+ /* 6800-6FFF */ 0b11111111,
+ /* 7000-77FF */ 0b11111111,
+ /* 7800-7FFF */ 0b11111111,
+ /* 8000-87FF */ 0b11111111,
+ /* 8800-8FFF */ 0b11111111,
+ /* 9000-97FF */ 0b11111111,
+ /* 9800-9FFF */ 0b11111110,
+ /* A000-A7FF */ 0b11110100,
+ /* A800-AFFF */ 0b00001111,
+ /* B000-B7FF */ 0b11111111,
+ /* B800-BFFF */ 0b11111111,
+ /* C000-C7FF */ 0b11111111,
+ /* C800-CFFF */ 0b11111111,
+ /* D000-D7FF */ 0b11111110,
+ /* D800-DFFF */ 0b11111111,
+ /* E000-E7FF */ 0b11111111,
+ /* E800-EFFF */ 0b11111111,
+ /* F000-F7FF */ 0b11111111,
+ /* F800-FFFF */ 0b11001000,
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
}
}
+ private static ushort[]?[] InitCasingTable()
+ {
+ ushort[]?[] table = new ushort[]?[s_casingTableInit.Length * 8];
+ for (int i = 0; i < s_casingTableInit.Length * 8; ++i)
+ {
+ // The bits are in reverse order
+ byte val = (byte)(s_casingTableInit[i / 8] >> (7 - (i % 8)));
+ if ((val & 1) == 1)
+ table[i] = s_noCasingPage;
+ }
+ table[0] = s_basicLatin;
+ return table;
+ }
+
private static unsafe ushort [] InitOrdinalCasingPage(int pageNumber)
{
Debug.Assert(pageNumber >= 0 && pageNumber < 256);
- ushort [] casingTable = new ushort[256];
+ ushort[] casingTable = new ushort[256];
fixed (ushort* table = casingTable)
{
char* pTable = (char*)table;
Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable);
}
- s_casingTable[pageNumber] = casingTable;
+ Volatile.Write(ref s_casingTable[pageNumber], casingTable);
return casingTable;
}
}