Slightly improved the lookup for character data.
This commit is contained in:
@@ -18,19 +18,22 @@ namespace System.Unicode
|
|||||||
private static readonly UnicodeCharacterData[] unicodeCharacterData;
|
private static readonly UnicodeCharacterData[] unicodeCharacterData;
|
||||||
private static readonly UnihanCharacterData[] unihanCharacterData;
|
private static readonly UnihanCharacterData[] unihanCharacterData;
|
||||||
private static readonly UnicodeBlock[] blocks;
|
private static readonly UnicodeBlock[] blocks;
|
||||||
|
private static readonly int maxContiguousIndex;
|
||||||
|
|
||||||
static UnicodeInfo()
|
static UnicodeInfo()
|
||||||
{
|
{
|
||||||
using (var stream = new DeflateStream(typeof(UnicodeInfo).GetTypeInfo().Assembly.GetManifestResourceStream("ucd.dat"), CompressionMode.Decompress, false))
|
using (var stream = new DeflateStream(typeof(UnicodeInfo).GetTypeInfo().Assembly.GetManifestResourceStream("ucd.dat"), CompressionMode.Decompress, false))
|
||||||
{
|
{
|
||||||
ReadFromStream(stream, out unicodeVersion, out unicodeCharacterData, out unihanCharacterData, out blocks);
|
ReadFromStream(stream, out unicodeVersion, out unicodeCharacterData, out unihanCharacterData, out blocks, out maxContiguousIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ReadFromStream(Stream stream, out Version unicodeVersion, out UnicodeCharacterData[] unicodeCharacterData, out UnihanCharacterData[] unihanCharacterData, out UnicodeBlock[] blocks)
|
internal static void ReadFromStream(Stream stream, out Version unicodeVersion, out UnicodeCharacterData[] unicodeCharacterData, out UnihanCharacterData[] unihanCharacterData, out UnicodeBlock[] blocks, out int maxContiguousIndex)
|
||||||
{
|
{
|
||||||
using (var reader = new BinaryReader(stream, Encoding.UTF8))
|
using (var reader = new BinaryReader(stream, Encoding.UTF8))
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (reader.ReadByte() != 'U'
|
if (reader.ReadByte() != 'U'
|
||||||
| reader.ReadByte() != 'C'
|
| reader.ReadByte() != 'C'
|
||||||
| reader.ReadByte() != 'D')
|
| reader.ReadByte() != 'D')
|
||||||
@@ -44,22 +47,35 @@ namespace System.Unicode
|
|||||||
|
|
||||||
var unicodeCharacterDataEntries = new UnicodeCharacterData[ReadCodePoint(reader)];
|
var unicodeCharacterDataEntries = new UnicodeCharacterData[ReadCodePoint(reader)];
|
||||||
byte[] nameBuffer = new byte[128];
|
byte[] nameBuffer = new byte[128];
|
||||||
|
int mci = 0;
|
||||||
|
|
||||||
for (int i = 0; i < unicodeCharacterDataEntries.Length; ++i)
|
for (i = 0; i < unicodeCharacterDataEntries.Length; ++i)
|
||||||
|
{
|
||||||
|
if ((unicodeCharacterDataEntries[i] = ReadUnicodeCharacterDataEntry(reader, nameBuffer)).CodePointRange.Contains(i)) mci = i;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maxContiguousIndex = mci;
|
||||||
|
|
||||||
|
for (; i < unicodeCharacterDataEntries.Length; ++i)
|
||||||
{
|
{
|
||||||
unicodeCharacterDataEntries[i] = ReadUnicodeCharacterDataEntry(reader, nameBuffer);
|
unicodeCharacterDataEntries[i] = ReadUnicodeCharacterDataEntry(reader, nameBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
var blockEntries = new UnicodeBlock[reader.ReadByte()];
|
var blockEntries = new UnicodeBlock[reader.ReadByte()];
|
||||||
|
|
||||||
for (int i = 0; i < blockEntries.Length; ++i)
|
for (i = 0; i < blockEntries.Length; ++i)
|
||||||
{
|
{
|
||||||
blockEntries[i] = ReadBlockEntry(reader);
|
blockEntries[i] = ReadBlockEntry(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
var unihanCharacterDataEntries = new UnihanCharacterData[ReadCodePoint(reader)];
|
var unihanCharacterDataEntries = new UnihanCharacterData[ReadCodePoint(reader)];
|
||||||
|
|
||||||
for (int i = 0; i < unihanCharacterDataEntries.Length; ++i)
|
for (i = 0; i < unihanCharacterDataEntries.Length; ++i)
|
||||||
{
|
{
|
||||||
unihanCharacterDataEntries[i] = ReadUnihanCharacterDataEntry(reader);
|
unihanCharacterDataEntries[i] = ReadUnihanCharacterDataEntry(reader);
|
||||||
}
|
}
|
||||||
@@ -228,8 +244,24 @@ namespace System.Unicode
|
|||||||
|
|
||||||
private static UnicodeCharacterData FindUnicodeCodePoint(int codePoint)
|
private static UnicodeCharacterData FindUnicodeCodePoint(int codePoint)
|
||||||
{
|
{
|
||||||
int minIndex = 0;
|
// For the first code points (this includes all of ASCII, and quite a bit more), the index in the table will be the code point itself.
|
||||||
int maxIndex = unicodeCharacterData.Length - 1;
|
if (codePoint <= maxContiguousIndex)
|
||||||
|
{
|
||||||
|
return unicodeCharacterData[codePoint];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For other code points, we will use a classic binary search with adjusted search indexes.
|
||||||
|
return BinarySearchUnicodeCodePoint(codePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UnicodeCharacterData BinarySearchUnicodeCodePoint(int codePoint)
|
||||||
|
{
|
||||||
|
// NB: Due to the strictly ordered nature of the table, we know that a code point can never happen after the index which is the code point itself.
|
||||||
|
// This will greatly reduce the range to scan for characters close to maxContiguousIndex, and will have a lesser impact on other characters.
|
||||||
|
int minIndex = maxContiguousIndex + 1;
|
||||||
|
int maxIndex = codePoint < unicodeCharacterData.Length ? codePoint - 1 : unicodeCharacterData.Length - 1;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user