Use ref returns to access character data, which should reduce memory consumption a bit.

Reduced some parts of the code by leveraging C# 6 and C# 7 features.
Preliminary work for adding emoji properties to characters.
This commit is contained in:
GoldenCrystal
2017-06-25 02:36:38 +02:00
parent b9d732f561
commit f9976c7a03
9 changed files with 213 additions and 263 deletions
+2
View File
@@ -12,6 +12,8 @@ namespace System.Unicode
[Flags]
public enum CoreProperties : int
{
// NB: Be careful when adding new properties to the enum, as EmojiProperties will be stored in the 4 upper bits out of 24.
/// <summary>Represents the Lowercase property.</summary>
[ValueName("Lowercase"), ValueName("Lower"), Display(Name = "Lowercase")]
Lowercase = 0x00000001,
+29
View File
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace System.Unicode
{
/// <summary>A bitmask of the various available emoji properties.</summary>
/// <remarks>Emoji properties are not formally part of UCD, but .</remarks>
[Flags]
public enum EmojiProperties : byte
{
// NB: These values will be stored in as the most significant bits of CoreProperties.
// CoreProperties are stored using 18 bits out of 24 available bits, leaving at most 6 bits to use. 4 of those will be used by emoji properties.
/// <summary>Represents the Emoji property.</summary>
[ValueName("Emoji"), Display(Name = "Emoji")]
Emoji = 0x1,
/// <summary>Represents the Emoji property.</summary>
[ValueName("Emoji_Presentation"), Display(Name = "Emoji_Presentation")]
EmojiPresentation = 0x2,
/// <summary>Represents the Emoji property.</summary>
[ValueName("Emoji_Modifier_Base"), Display(Name = "Emoji_Modifier_Base")]
EmojiModifierBase = 0x4,
/// <summary>Represents the Emoji property.</summary>
[ValueName("Emoji_Component"), Display(Name = "Emoji_Component")]
EmojiComponent = 0x8,
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ namespace System.Unicode
SimpleTitleCaseMapping = 4096,
ContributoryProperties = 8192,
CoreProperties = 16384,
CorePropertiesAndEmojiProperties = 16384,
CrossRerefences = 32768,
}
+56 -37
View File
@@ -14,46 +14,49 @@ namespace System.Unicode
private readonly int codePoint;
/// <summary>The name of the code point.</summary>
private readonly string name;
private readonly UnicodeCharacterData unicodeCharacterData;
private readonly UnihanCharacterData unihanCharacterData;
private readonly int unicodeCharacterDataIndex;
private readonly int unihanCharacterDataIndex;
private readonly string block;
private ref UnicodeCharacterData UnicodeCharacterData => ref UnicodeInfo.GetUnicodeCharacterData(unicodeCharacterDataIndex);
private ref UnihanCharacterData UnihanCharacterData => ref UnicodeInfo.GetUnihanCharacterData(unihanCharacterDataIndex);
/// <summary>Gets the code point as an UTF-32 value.</summary>
public int CodePoint { get { return codePoint; } }
public int CodePoint => codePoint;
/// <summary>Gets the code point name.</summary>
/// <remarks>This is the Name Unicode property.</remarks>
[ValueName("Name"), ValueName("na")]
public string Name { get { return name; } }
public string Name => name;
/// <summary>Gets the name aliases defined for the code point.</summary>
/// <remarks>This is the Name_Alias Unicode property.</remarks>
[ValueName("Name_Alias")]
public UnicodeNameAliasCollection NameAliases { get { return new UnicodeNameAliasCollection(unicodeCharacterData?.NameAliases); } }
public UnicodeNameAliasCollection NameAliases => new UnicodeNameAliasCollection(UnicodeCharacterData.NameAliases);
/// <summary>Gets the category defined for the code point.</summary>
/// <remarks>This is the General_Category Unicode property.</remarks>
[ValueName("General_Category"), ValueName("gc")]
public UnicodeCategory Category { get { return unicodeCharacterData?.Category ?? UnicodeCategory.OtherNotAssigned; } }
public UnicodeCategory Category => UnicodeCharacterData.Category;
/// <summary>Gets the name of the block where the code point is located.</summary>
/// <remarks>This is the Block Unicode property.</remarks>
[ValueName("Block"), ValueName("blk")]
public string Block { get { return block ?? UnicodeInfo.DefaultBlock; } }
public string Block => block ?? UnicodeInfo.DefaultBlock;
/// <summary>Gets the canonical combining class defined for the code point.</summary>
/// <remarks>This is the Canonical_Combining_Class Unicode property.</remarks>
[ValueName("Canonical_Combining_Class"), ValueName("ccc")]
public CanonicalCombiningClass CanonicalCombiningClass { get { return unicodeCharacterData?.CanonicalCombiningClass ?? CanonicalCombiningClass.NotReordered; } }
public CanonicalCombiningClass CanonicalCombiningClass => UnicodeCharacterData.CanonicalCombiningClass;
/// <summary>Gets the bidirectional class defined for the code point.</summary>
/// <remarks>This is the Bidi_Class Unicode property.</remarks>
[ValueName("Bidi_Class"), ValueName("bc")]
public BidirectionalClass BidirectionalClass { get { return unicodeCharacterData?.BidirectionalClass ?? BidirectionalClass.LeftToRight; } }
public BidirectionalClass BidirectionalClass => UnicodeCharacterData.BidirectionalClass;
/// <summary>Gets the decomposition type defined for the code point.</summary>
/// <remarks>This is the Decomposition_Type Unicode property.</remarks>
[ValueName("Decomposition_Type"), ValueName("dt")]
public CompatibilityFormattingTag DecompositionType { get { return unicodeCharacterData?.DecompositionType ?? CompatibilityFormattingTag.Canonical; } }
public CompatibilityFormattingTag DecompositionType => UnicodeCharacterData.DecompositionType;
/// <summary>Gets the decomposition mapping defined for the code point.</summary>
/// <remarks>This is the Decomposition_Mapping Unicode property.</remarks>
[ValueName("Decomposition_Mapping"), ValueName("dm")]
public string DecompositionMapping { get { return unicodeCharacterData?.DecompositionMapping; } }
public string DecompositionMapping => UnicodeCharacterData.DecompositionMapping;
/// <summary>Gets the numeric type defined for the code point.</summary>
/// <remarks>
/// This is the Numeric_Type Unicode property.
@@ -62,10 +65,10 @@ namespace System.Unicode
/// In this case, the property <see cref="UnihanNumericType"/> will indicate the origin of the numeric value in Unihan data.
/// </remarks>
[ValueName("Numeric_Type"), ValueName("nt")]
public UnicodeNumericType NumericType { get { return unihanCharacterData != null ? unihanCharacterData.NumericType != UnihanNumericType.None ? UnicodeNumericType.Numeric : UnicodeNumericType.None : unicodeCharacterData?.NumericType ?? UnicodeNumericType.None; } }
public UnicodeNumericType NumericType => unihanCharacterDataIndex >= 0 ? UnihanCharacterData.NumericType != UnihanNumericType.None ? UnicodeNumericType.Numeric : UnicodeNumericType.None : UnicodeCharacterData.NumericType;
/// <summary>Gets the Unihan numeric type defined for the code point.</summary>
/// <remarks>The value of this property indicates which of the kPrimaryNumeric, kAccountingNumeric, or kOtherNumeric Unihan property is set, if any.</remarks>
public UnihanNumericType UnihanNumericType { get { return unihanCharacterData != null ? unihanCharacterData.NumericType : UnihanNumericType.None; } }
public UnihanNumericType UnihanNumericType => unihanCharacterDataIndex >= 0 ? UnihanCharacterData.NumericType : UnihanNumericType.None;
/// <summary>Gets the numeric value defined for the code point.</summary>
/// <remarks>
/// This is the Numeric_Value Unicode property.
@@ -73,47 +76,63 @@ namespace System.Unicode
/// When this property set, the <see cref="NumericType"/> and <see cref="UnihanNumericType"/> indicates the nature of the numeric value.
/// </remarks>
[ValueName("Numeric_Value"), ValueName("nv")]
public UnicodeRationalNumber? NumericValue { get { return unihanCharacterData != null && unihanCharacterData.NumericType != UnihanNumericType.None ? new UnicodeRationalNumber(unihanCharacterData.NumericValue, 1) : unicodeCharacterData?.NumericValue; } }
public UnicodeRationalNumber? NumericValue
{
get
{
if (unihanCharacterDataIndex >= 0)
{
ref var unihanCharacterData = ref UnihanCharacterData;
if (unihanCharacterData.NumericType != UnihanNumericType.None)
{
return new UnicodeRationalNumber(unihanCharacterData.NumericValue, 1);
}
}
return UnicodeCharacterData.NumericValue;
}
}
/// <summary>Gets a value indicating whether the character is mirrored in bidirectional text.</summary>
/// <remarks>This is the Bidi_Mirrored Unicode property.</remarks>
[ValueName("Bidi_Mirrored")]
public bool BidirectionalMirrored { get { return unicodeCharacterData?.BidirectionalMirrored ?? false; } }
public bool BidirectionalMirrored => UnicodeCharacterData.BidirectionalMirrored;
/// <summary>Gets the Unicode 1 name of the code point.</summary>
/// <remarks>This is the Unicode_1_Name Unicode property.</remarks>
[ValueName("Unicode_1_Name"), ValueName("na1")]
public string OldName { get { return unicodeCharacterData?.OldName; } }
public string OldName => UnicodeCharacterData.OldName;
/// <summary>Gets the simple uppercase mapping defined for the code point.</summary>
/// <remarks>This is the Simple_Uppercase_Mapping Unicode property.</remarks>
[ValueName("Simple_Uppercase_Mapping"), ValueName("suc")]
public string SimpleUpperCaseMapping { get { return unicodeCharacterData?.SimpleUpperCaseMapping; } }
public string SimpleUpperCaseMapping => UnicodeCharacterData.SimpleUpperCaseMapping;
/// <summary>Gets the simple lowercase mapping defined for the code point.</summary>
/// <remarks>This is the Simple_Lowercase_Mapping Unicode property.</remarks>
[ValueName("Simple_Lowercase_Mapping"), ValueName("slc")]
public string SimpleLowerCaseMapping { get { return unicodeCharacterData?.SimpleLowerCaseMapping; } }
public string SimpleLowerCaseMapping => UnicodeCharacterData.SimpleLowerCaseMapping;
/// <summary>Gets the simple titlecase mapping defined for the code point.</summary>
/// <remarks>This is the Simple_Titlecase_Mapping Unicode property.</remarks>
[ValueName("Simple_Titlecase_Mapping"), ValueName("stc")]
public string SimpleTitleCaseMapping { get { return unicodeCharacterData?.SimpleTitleCaseMapping; } }
public string SimpleTitleCaseMapping => UnicodeCharacterData.SimpleTitleCaseMapping;
/// <summary>Gets a value indicating which of the boolean contributory properties are defined for the code point.</summary>
/// <remarks>
/// The Unicode standard indicates contributory properties as neither normative nor informational.
/// However, contributory properties are used by Unicode to define the code properties.
/// The corresponding core properties may be accessed from the <see cref="CoreProperties"/> member.
/// </remarks>
public ContributoryProperties ContributoryProperties { get { return unicodeCharacterData?.ContributoryProperties ?? 0; } }
public ContributoryProperties ContributoryProperties => UnicodeCharacterData.ContributoryProperties;
/// <summary>Gets a value indicating which of the boolean core properties are defined for the code point.</summary>
/// <remarks>The core properties are computed by combining various character information together with contributory properties.</remarks>
public CoreProperties CoreProperties { get { return unicodeCharacterData?.CoreProperties ?? 0; } }
public CoreProperties CoreProperties => UnicodeCharacterData.CoreProperties;
/// <summary>Gets a collection of cross references associated with the code point.</summary>
/// <remarks>The cross references have been extracted from Unicode data but are not normative.</remarks>
public UnicodeCrossReferenceCollection CrossRerefences { get { return new UnicodeCrossReferenceCollection(unicodeCharacterData?.CrossRerefences); } }
public UnicodeCrossReferenceCollection CrossRerefences => new UnicodeCrossReferenceCollection(UnicodeCharacterData.CrossRerefences);
/// <summary>Gets the radical and stroke count for the code point.</summary>
/// <remarks>
/// This is the Unicode_Radical_Stroke Unicode property, defined as kRSUnicode in Unihan data.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kRSUnicode"), ValueName("cjkRSUnicode"), ValueName("Unicode_Radical_Stroke"), ValueName("URS")]
public UnicodeRadicalStrokeCountCollection UnicodeRadicalStrokeCounts { get { return new UnicodeRadicalStrokeCountCollection(unihanCharacterData?.UnicodeRadicalStrokeCounts); } }
public UnicodeRadicalStrokeCountCollection UnicodeRadicalStrokeCounts => new UnicodeRadicalStrokeCountCollection(UnihanCharacterData.UnicodeRadicalStrokeCounts);
/// <summary>Gets the definition of the character from the Unihan data.</summary>
/// <remarks>
@@ -121,56 +140,56 @@ namespace System.Unicode
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kDefinition")]
public string Definition { get { return unihanCharacterData?.Definition; } }
public string Definition => UnihanCharacterData.Definition;
/// <summary>Gets the Mandarin reading of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kMandarin Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kMandarin")]
public string MandarinReading { get { return unihanCharacterData?.MandarinReading; } }
public string MandarinReading => UnihanCharacterData.MandarinReading;
/// <summary>Gets the Cantonese reading of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kCantonese Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kCantonese")]
public string CantoneseReading { get { return unihanCharacterData?.CantoneseReading; } }
public string CantoneseReading => UnihanCharacterData.CantoneseReading;
/// <summary>Gets the Japanese Kun reading of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kJapaneseKun Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kJapaneseKun")]
public string JapaneseKunReading { get { return unihanCharacterData?.JapaneseKunReading; } }
public string JapaneseKunReading => UnihanCharacterData.JapaneseKunReading;
/// <summary>Gets the Japanese On reading of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kJapaneseOn Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kJapaneseOn")]
public string JapaneseOnReading { get { return unihanCharacterData?.JapaneseOnReading; } }
public string JapaneseOnReading => UnihanCharacterData.JapaneseOnReading;
/// <summary>Gets the Korean reading of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kKorean Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kKorean")]
public string KoreanReading { get { return unihanCharacterData?.KoreanReading; } }
public string KoreanReading => UnihanCharacterData.KoreanReading;
/// <summary>Gets the Hangul reading of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kHangul Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kHangul")]
public string HangulReading { get { return unihanCharacterData?.HangulReading; } }
public string HangulReading => UnihanCharacterData.HangulReading;
/// <summary>Gets the Vietnamese reading of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kVietnamese Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kVietnamese")]
public string VietnameseReading { get { return unihanCharacterData?.VietnameseReading; } }
public string VietnameseReading => UnihanCharacterData.VietnameseReading;
/// <summary>Gets the simplified variant of the character from the Unihan data.</summary>
/// <remarks>
@@ -178,21 +197,21 @@ namespace System.Unicode
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kSimplifiedVariant")]
public string SimplifiedVariant { get { return unihanCharacterData?.SimplifiedVariant; } }
public string SimplifiedVariant => UnihanCharacterData.SimplifiedVariant;
/// <summary>Gets the traditional variant of the character from the Unihan data.</summary>
/// <remarks>
/// This is the kTraditionalVariant Unicode property.
/// This property is only ever useful when the character is a CJK ideograph.
/// </remarks>
[ValueName("kTraditionalVariant")]
public string TraditionalVariant { get { return unihanCharacterData?.TraditionalVariant; } }
public string TraditionalVariant => UnihanCharacterData.TraditionalVariant;
internal UnicodeCharInfo(int codePoint, UnicodeCharacterData unicodeCharacterData, UnihanCharacterData unihanCharacterData, string block)
internal UnicodeCharInfo(int codePoint, int unicodeCharacterDataIndex, int unihanCharacterDataIndex, string block)
{
this.codePoint = codePoint;
this.name = unicodeCharacterData != null ? UnicodeInfo.GetName(codePoint, unicodeCharacterData) : null;
this.unicodeCharacterData = unicodeCharacterData;
this.unihanCharacterData = unihanCharacterData;
this.name = unicodeCharacterDataIndex >= 0 ? UnicodeInfo.GetName(codePoint, ref UnicodeInfo.GetUnicodeCharacterData(unicodeCharacterDataIndex)) : null;
this.unicodeCharacterDataIndex = unicodeCharacterDataIndex;
this.unihanCharacterDataIndex = unihanCharacterDataIndex;
this.block = block;
}
}
+8 -11
View File
@@ -1,13 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
namespace System.Unicode
{
internal sealed class UnicodeCharacterData
internal struct UnicodeCharacterData
{
public readonly UnicodeCodePointRange CodePointRange;
public readonly string Name;
@@ -25,7 +20,9 @@ namespace System.Unicode
public readonly string SimpleLowerCaseMapping;
public readonly string SimpleTitleCaseMapping;
public readonly ContributoryProperties ContributoryProperties;
public readonly CoreProperties CoreProperties;
private readonly int corePropertiesAndEmojiProperties;
public CoreProperties CoreProperties => (CoreProperties)(corePropertiesAndEmojiProperties & 0x000FFFFF);
public EmojiProperties EmojiProperties => (EmojiProperties)(corePropertiesAndEmojiProperties >> 20);
public readonly int[] CrossRerefences; // NB: It seems that parsing NamesList is required in order to provide data for this field ?
@@ -47,7 +44,7 @@ namespace System.Unicode
string simpleLowerCaseMapping,
string simpleTitleCaseMapping,
ContributoryProperties contributoryProperties,
CoreProperties coreProperties,
int corePropertiesAndEmojiProperties,
int[] crossRerefences
)
{
@@ -67,10 +64,10 @@ namespace System.Unicode
this.SimpleLowerCaseMapping = simpleLowerCaseMapping;
this.SimpleTitleCaseMapping = simpleTitleCaseMapping;
this.ContributoryProperties = contributoryProperties;
this.CoreProperties = coreProperties;
this.corePropertiesAndEmojiProperties = corePropertiesAndEmojiProperties;
this.CrossRerefences = crossRerefences;
}
public UnicodeRationalNumber? NumericValue { get { return NumericType != UnicodeNumericType.None ? numericValue : null as UnicodeRationalNumber?; } }
public UnicodeRationalNumber? NumericValue => NumericType != UnicodeNumericType.None ? numericValue : null as UnicodeRationalNumber?;
}
}
+62 -69
View File
@@ -13,6 +13,11 @@ namespace System.Unicode
/// <summary>Provides access to unicode information.</summary>
public static class UnicodeInfo
{
// NB: These fields will be used as a default value for UnicodeCharacterData and UnihanCharacterData, and passed by reference.
// They should be considered as being redonly, even if they aren't explicitely.
private static /*readonly*/ UnicodeCharacterData DefaultUnicodeCharacterData = new UnicodeCharacterData(default(UnicodeCodePointRange), null, null, UnicodeCategory.OtherNotAssigned, 0, 0, 0, null, 0, default(UnicodeRationalNumber), false, null, null, null, null, 0, 0, null);
private static /*readonly*/ UnihanCharacterData DefaultUnihanCharacterData = default(UnihanCharacterData);
/// <summary>The block name returned when no block is assigned to a specific code point.</summary>
public const string DefaultBlock = "No_Block";
@@ -47,14 +52,18 @@ namespace System.Unicode
if (formatVersion != 2) throw new InvalidDataException();
var fileUnicodeVersion = new Version(reader.ReadUInt16(), reader.ReadByte(), reader.ReadByte());
var unicodeCharacterDataEntries = new UnicodeCharacterData[ReadCodePoint(reader)];
var unicodeCharacterDataEntries = new UnicodeCharacterData[ReadCodePoint(reader)]; // Allocate one extra entry to act as a dummy entry.
byte[] nameBuffer = new byte[128];
int mci = 0;
for (i = 0; i < unicodeCharacterDataEntries.Length; ++i)
{
if ((unicodeCharacterDataEntries[i] = ReadUnicodeCharacterDataEntry(reader, nameBuffer)).CodePointRange.Contains(i)) mci = i;
ReadUnicodeCharacterDataEntry(reader, nameBuffer, out unicodeCharacterDataEntries[i]);
if (unicodeCharacterDataEntries[i].CodePointRange.Contains(i))
{
mci = i;
}
else
{
++i;
@@ -66,7 +75,7 @@ namespace System.Unicode
for (; i < unicodeCharacterDataEntries.Length; ++i)
{
unicodeCharacterDataEntries[i] = ReadUnicodeCharacterDataEntry(reader, nameBuffer);
ReadUnicodeCharacterDataEntry(reader, nameBuffer, out unicodeCharacterDataEntries[i]);
}
var blockEntries = new UnicodeBlock[reader.ReadUInt16()];
@@ -87,7 +96,7 @@ namespace System.Unicode
for (i = 0; i < unihanCharacterDataEntries.Length; ++i)
{
unihanCharacterDataEntries[i] = ReadUnihanCharacterDataEntry(reader);
ReadUnihanCharacterDataEntry(reader, out unihanCharacterDataEntries[i]);
}
unicodeVersion = fileUnicodeVersion;
@@ -98,7 +107,7 @@ namespace System.Unicode
}
}
private static UnicodeCharacterData ReadUnicodeCharacterDataEntry(BinaryReader reader, byte[] nameBuffer)
private static void ReadUnicodeCharacterDataEntry(BinaryReader reader, byte[] nameBuffer, out UnicodeCharacterData value)
{
var fields = (UcdFields)reader.ReadUInt16();
@@ -153,7 +162,7 @@ namespace System.Unicode
string simpleLowerCaseMapping = (fields & UcdFields.SimpleLowerCaseMapping) != 0 ? reader.ReadString() : null;
string simpleTitleCaseMapping = (fields & UcdFields.SimpleTitleCaseMapping) != 0 ? reader.ReadString() : null;
ContributoryProperties contributoryProperties = (fields & UcdFields.ContributoryProperties) != 0 ? (ContributoryProperties)reader.ReadInt32() : 0;
CoreProperties coreProperties = (fields & UcdFields.CoreProperties) != 0 ? (CoreProperties)ReadInt24(reader) : 0;
int corePropertiesAndEmojiProperties = (fields & UcdFields.CorePropertiesAndEmojiProperties) != 0 ? ReadInt24(reader) : 0;
int[] crossReferences = (fields & UcdFields.CrossRerefences) != 0 ? new int[reader.ReadByte() + 1] : null;
if (crossReferences != null)
@@ -162,7 +171,7 @@ namespace System.Unicode
crossReferences[i] = ReadCodePoint(reader);
}
return new UnicodeCharacterData
value = new UnicodeCharacterData
(
codePointRange,
name,
@@ -180,12 +189,12 @@ namespace System.Unicode
simpleLowerCaseMapping,
simpleTitleCaseMapping,
contributoryProperties,
coreProperties,
corePropertiesAndEmojiProperties,
crossReferences
);
}
private static UnihanCharacterData ReadUnihanCharacterDataEntry(BinaryReader reader)
private static void ReadUnihanCharacterDataEntry(BinaryReader reader, out UnihanCharacterData value)
{
var fields = (UnihanFields)reader.ReadUInt16();
@@ -219,7 +228,7 @@ namespace System.Unicode
string simplifiedVariant = (fields & UnihanFields.SimplifiedVariant) != 0 ? reader.ReadString() : null;
string traditionalVariant = (fields & UnihanFields.TraditionalVariant) != 0 ? reader.ReadString() : null;
return new UnihanCharacterData
value = new UnihanCharacterData
(
codePoint,
numericType,
@@ -250,14 +259,9 @@ namespace System.Unicode
}
private static UnicodeBlock ReadBlockEntry(BinaryReader reader)
{
return new UnicodeBlock(new UnicodeCodePointRange(ReadCodePoint(reader), ReadCodePoint(reader)), reader.ReadString());
}
=> new UnicodeBlock(new UnicodeCodePointRange(ReadCodePoint(reader), ReadCodePoint(reader)), reader.ReadString());
private static int ReadInt24(BinaryReader reader)
{
return reader.ReadByte() | ((reader.ReadByte() | (reader.ReadByte() << 8)) << 8);
}
private static int ReadInt24(BinaryReader reader) => reader.ReadByte() | ((reader.ReadByte() | (reader.ReadByte() << 8)) << 8);
#if DEBUG
internal static int ReadCodePoint(BinaryReader reader)
@@ -285,21 +289,12 @@ namespace System.Unicode
/// <summary>Gets the version of the Unicode standard supported by the class.</summary>
public static Version UnicodeVersion { get { return unicodeVersion; } }
private static UnicodeCharacterData FindUnicodeCodePoint(int codePoint)
{
// 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.
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 int FindUnicodeCodePointIndex(int codePoint)
=> codePoint <= maxContiguousIndex ?
codePoint : // 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.
BinarySearchUnicodeCodePointIndex(codePoint); // For other code points, we will use a classic binary search with adjusted search indexes.
private static UnicodeCharacterData BinarySearchUnicodeCodePoint(int codePoint)
private static int BinarySearchUnicodeCodePointIndex(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.
@@ -312,22 +307,22 @@ namespace System.Unicode
int Δ = unicodeCharacterData[index].CodePointRange.CompareCodePoint(codePoint);
if (Δ == 0) return unicodeCharacterData[index];
if (Δ == 0) return index;
else if (Δ < 0) maxIndex = index - 1;
else minIndex = index + 1;
} while (minIndex <= maxIndex);
return null;
return -1;
}
private static UnihanCharacterData FindUnihanCodePoint(int codePoint)
private static int FindUnihanCodePointIndex(int codePoint)
{
int minIndex;
int maxIndex;
if (unihanCharacterData.Length == 0 || codePoint < unihanCharacterData[minIndex = 0].CodePoint || codePoint > unihanCharacterData[maxIndex = unihanCharacterData.Length - 1].CodePoint)
{
return null;
return -1;
}
do
@@ -336,12 +331,12 @@ namespace System.Unicode
int Δ = codePoint - unihanCharacterData[index].CodePoint;
if (Δ == 0) return unihanCharacterData[index];
if (Δ == 0) return index;
else if (Δ < 0) maxIndex = index - 1;
else minIndex = index + 1;
} while (minIndex <= maxIndex);
return null;
return -1;
}
private static int FindBlockIndex(int codePoint)
@@ -363,16 +358,26 @@ namespace System.Unicode
return -1;
}
internal static ref UnicodeCharacterData GetUnicodeCharacterData(int index)
{
if (index >= 0) return ref unicodeCharacterData[index];
return ref DefaultUnicodeCharacterData;
}
internal static ref UnihanCharacterData GetUnihanCharacterData(int index)
{
if (index >= 0) return ref unihanCharacterData[index];
return ref DefaultUnihanCharacterData;
}
/// <summary>Gets the name of the Unicode block containing the character.</summary>
/// <remarks>If the character has not been assigned to a block, the value of <see cref="DefaultBlock"/> will be returned.</remarks>
/// <param name="codePoint">The Unicode code point whose block should be retrieved.</param>
/// <returns>The name of the block the code point was assigned to.</returns>
public static string GetBlockName(int codePoint)
{
int i = FindBlockIndex(codePoint);
return i >= 0 ? blocks[i].Name : DefaultBlock;
}
=> FindBlockIndex(codePoint) is int i && i >= 0 ?
blocks[i].Name :
DefaultBlock;
/// <summary>Gets Unicode information on the specified code point.</summary>
/// <remarks>
@@ -400,9 +405,7 @@ namespace System.Unicode
/// <param name="codePoint">The Unicode code point for which the data must be retrieved.</param>
/// <returns>The name of the code point, if defined; <see langword="null"/> otherwise.</returns>
public static UnicodeCharInfo GetCharInfo(int codePoint)
{
return new UnicodeCharInfo(codePoint, FindUnicodeCodePoint(codePoint), FindUnihanCodePoint(codePoint), GetBlockName(codePoint));
}
=> new UnicodeCharInfo(codePoint, FindUnicodeCodePointIndex(codePoint), FindUnihanCodePointIndex(codePoint), GetBlockName(codePoint));
/// <summary>Gets the category of the specified code point.</summary>
/// <remarks>
@@ -412,11 +415,9 @@ namespace System.Unicode
/// <param name="codePoint">The Unicode code point for which the category must be retrieved.</param>
/// <returns>The category of the code point.</returns>
public static UnicodeCategory GetCategory(int codePoint)
{
var charData = FindUnicodeCodePoint(codePoint);
return charData != null ? charData.Category : UnicodeCategory.OtherNotAssigned;
}
=> FindUnicodeCodePointIndex(codePoint) is int unicodeCharacterDataIndex && unicodeCharacterDataIndex >= 0 ?
GetUnicodeCharacterData(unicodeCharacterDataIndex).Category :
UnicodeCategory.OtherNotAssigned;
/// <summary>Gets a display text for the specified code point.</summary>
/// <param name="charInfo">The information for the code point.</param>
@@ -448,19 +449,16 @@ namespace System.Unicode
/// <param name="codePoint">The Unicode code point for which the name must be retrieved.</param>
/// <returns>The name of the code point, if defined; <see langword="null"/> otherwise.</returns>
public static string GetName(int codePoint)
{
if (HangulInfo.IsHangul(codePoint)) return HangulInfo.GetHangulName((char)codePoint);
else return GetNameInternal(codePoint);
}
=> HangulInfo.IsHangul(codePoint) ?
HangulInfo.GetHangulName((char)codePoint) :
GetNameInternal(codePoint);
private static string GetNameInternal(int codePoint)
{
var codePointInfo = FindUnicodeCodePoint(codePoint);
=> FindUnicodeCodePointIndex(codePoint) is int codePointInfoIndex && codePointInfoIndex >= 0 ?
GetName(codePoint, ref GetUnicodeCharacterData(codePointInfoIndex)) :
null;
return codePointInfo != null ? GetName(codePoint, codePointInfo) : null;
}
internal static string GetName(int codePoint, UnicodeCharacterData characterData)
internal static string GetName(int codePoint, ref UnicodeCharacterData characterData)
{
if (characterData.CodePointRange.IsSingleCodePoint) return characterData.Name;
else if (HangulInfo.IsHangul(codePoint)) return HangulInfo.GetHangulName((char)codePoint);
@@ -473,20 +471,15 @@ namespace System.Unicode
/// <returns>Information on the specified radical.</returns>
/// <exception cref="IndexOutOfRangeException">The <paramref name="radicalIndex"/> parameter is out of range.</exception>
public static CjkRadicalInfo GetCjkRadicalInfo(int radicalIndex)
{
return new CjkRadicalInfo(checked((byte)radicalIndex), radicals[radicalIndex - 1]);
}
=> new CjkRadicalInfo(checked((byte)radicalIndex), radicals[radicalIndex - 1]);
/// <summary>Returns the number of CJK radicals in the Unicode data.</summary>
/// <remarks>This value will be 214 for the foreseeable future.</remarks>
public static int CjkRadicalCount { get { return radicals.Length; } }
public static int CjkRadicalCount => radicals.Length;
/// <summary>Gets all the blocks defined in the Unicode data.</summary>
/// <remarks><see cref="DefaultBlock"/> is not the name of a block, but only a value indicating the abscence of block information for a given code point.</remarks>
/// <returns>An array containing an entry for every block defined in the Unicode data.</returns>
public static UnicodeBlock[] GetBlocks()
{
return (UnicodeBlock[])blocks.Clone();
}
public static UnicodeBlock[] GetBlocks() => (UnicodeBlock[])blocks.Clone();
}
}
+2 -8
View File
@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System.Unicode
namespace System.Unicode
{
internal sealed class UnihanCharacterData
internal struct UnihanCharacterData
{
public readonly int CodePoint;
public readonly UnihanNumericType NumericType;