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:
@@ -1,129 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode.Builder
|
||||
{
|
||||
public sealed class UnicodeCharacterDataBuilder
|
||||
{
|
||||
private readonly UnicodeCodePointRange codePointRange;
|
||||
private string name;
|
||||
private UnicodeCategory category = UnicodeCategory.OtherNotAssigned;
|
||||
private CanonicalCombiningClass canonicalCombiningClass;
|
||||
private BidirectionalClass bidirectionalClass;
|
||||
private CharacterDecompositionMapping characterDecompositionMapping;
|
||||
private UnicodeNumericType numericType;
|
||||
private UnicodeRationalNumber numericValue;
|
||||
private bool bidirectionalMirrored;
|
||||
private string oldName;
|
||||
private string simpleUpperCaseMapping;
|
||||
private string simpleLowerCaseMapping;
|
||||
private string simpleTitleCaseMapping;
|
||||
private ContributoryProperties contributoryProperties;
|
||||
private CoreProperties coreProperties;
|
||||
|
||||
private readonly List<UnicodeNameAlias> nameAliases = new List<UnicodeNameAlias>();
|
||||
private readonly List<int> crossRerefences = new List<int>();
|
||||
|
||||
public UnicodeCodePointRange CodePointRange { get { return codePointRange; } }
|
||||
public UnicodeCodePointRange CodePointRange { get; }
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set { name = value; }
|
||||
}
|
||||
public string Name { get; set; }
|
||||
|
||||
public IList<UnicodeNameAlias> NameAliases { get { return nameAliases; } }
|
||||
|
||||
public UnicodeCategory Category
|
||||
{
|
||||
get { return category; }
|
||||
set
|
||||
{
|
||||
if (!Enum.IsDefined(typeof(UnicodeCategory), value))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
category = value;
|
||||
}
|
||||
}
|
||||
|
||||
public CanonicalCombiningClass CanonicalCombiningClass
|
||||
{
|
||||
get { return canonicalCombiningClass; }
|
||||
set { canonicalCombiningClass = value; } // Even values not defined in the enum are allowed here.
|
||||
}
|
||||
|
||||
public BidirectionalClass BidirectionalClass
|
||||
{
|
||||
get { return bidirectionalClass; }
|
||||
set { bidirectionalClass = value; }
|
||||
}
|
||||
|
||||
public CharacterDecompositionMapping CharacterDecompositionMapping
|
||||
{
|
||||
get { return characterDecompositionMapping; }
|
||||
set { characterDecompositionMapping = value; }
|
||||
}
|
||||
|
||||
public UnicodeNumericType NumericType
|
||||
{
|
||||
get { return numericType; }
|
||||
set { numericType = value; }
|
||||
}
|
||||
|
||||
public UnicodeRationalNumber NumericValue
|
||||
{
|
||||
get { return numericValue; }
|
||||
set { numericValue = value; }
|
||||
}
|
||||
|
||||
public string OldName
|
||||
{
|
||||
get { return oldName; }
|
||||
set { oldName = value; }
|
||||
}
|
||||
|
||||
public bool BidirectionalMirrored
|
||||
{
|
||||
get { return bidirectionalMirrored; }
|
||||
set { bidirectionalMirrored = value; }
|
||||
}
|
||||
|
||||
public string SimpleUpperCaseMapping
|
||||
{
|
||||
get { return simpleUpperCaseMapping; }
|
||||
set { simpleUpperCaseMapping = value; }
|
||||
}
|
||||
|
||||
public string SimpleLowerCaseMapping
|
||||
{
|
||||
get { return simpleLowerCaseMapping; }
|
||||
set { simpleLowerCaseMapping = value; }
|
||||
}
|
||||
|
||||
public string SimpleTitleCaseMapping
|
||||
{
|
||||
get { return simpleTitleCaseMapping; }
|
||||
set { simpleTitleCaseMapping = value; }
|
||||
}
|
||||
|
||||
public ContributoryProperties ContributoryProperties
|
||||
{
|
||||
get { return contributoryProperties; }
|
||||
set { contributoryProperties = value; }
|
||||
}
|
||||
|
||||
public CoreProperties CoreProperties
|
||||
{
|
||||
get { return coreProperties; }
|
||||
set { coreProperties = value; }
|
||||
get => category;
|
||||
set => category = Enum.IsDefined(typeof(UnicodeCategory), value) ?
|
||||
value :
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
|
||||
public CanonicalCombiningClass CanonicalCombiningClass { get; set; } // Even values not defined in the enum are allowed here.
|
||||
public BidirectionalClass BidirectionalClass { get; set; }
|
||||
public CharacterDecompositionMapping CharacterDecompositionMapping { get; set; }
|
||||
public UnicodeNumericType NumericType { get; set; }
|
||||
public UnicodeRationalNumber NumericValue { get; set; }
|
||||
public string OldName { get; set; }
|
||||
public bool BidirectionalMirrored { get; set; }
|
||||
public string SimpleUpperCaseMapping { get; set; }
|
||||
public string SimpleLowerCaseMapping { get; set; }
|
||||
public string SimpleTitleCaseMapping { get; set; }
|
||||
public ContributoryProperties ContributoryProperties { get; set; }
|
||||
public CoreProperties CoreProperties { get; set; }
|
||||
public EmojiProperties EmojiProperties { get; set; }
|
||||
public IList<int> CrossRerefences { get { return crossRerefences; } }
|
||||
|
||||
public UnicodeCharacterDataBuilder(int codePoint)
|
||||
@@ -133,7 +48,7 @@ namespace System.Unicode.Builder
|
||||
|
||||
public UnicodeCharacterDataBuilder(UnicodeCodePointRange codePointRange)
|
||||
{
|
||||
this.codePointRange = codePointRange;
|
||||
CodePointRange = codePointRange;
|
||||
this.category = UnicodeCategory.OtherNotAssigned;
|
||||
}
|
||||
|
||||
@@ -143,7 +58,7 @@ namespace System.Unicode.Builder
|
||||
(
|
||||
CodePointRange,
|
||||
Name,
|
||||
NameAliases.Count > 0 ? NameAliases.ToArray() : UnicodeNameAlias.EmptyArray,
|
||||
nameAliases.Count > 0 ? nameAliases.ToArray() : UnicodeNameAlias.EmptyArray,
|
||||
Category,
|
||||
CanonicalCombiningClass,
|
||||
BidirectionalClass,
|
||||
@@ -157,7 +72,7 @@ namespace System.Unicode.Builder
|
||||
SimpleLowerCaseMapping,
|
||||
SimpleTitleCaseMapping,
|
||||
ContributoryProperties,
|
||||
CoreProperties,
|
||||
(int)CoreProperties | (int)EmojiProperties << 20,
|
||||
CrossRerefences.Count > 0 ? CrossRerefences.ToArray() : null
|
||||
);
|
||||
}
|
||||
@@ -168,27 +83,27 @@ namespace System.Unicode.Builder
|
||||
|
||||
UcdFields fields = default(UcdFields);
|
||||
|
||||
if (!codePointRange.IsSingleCodePoint) fields = UcdFields.CodePointRange;
|
||||
if (!CodePointRange.IsSingleCodePoint) fields = UcdFields.CodePointRange;
|
||||
|
||||
if (name != null || nameAliases.Count > 0) fields |= UcdFields.Name; // This field combines name and alias.
|
||||
if (Name != null || nameAliases.Count > 0) fields |= UcdFields.Name; // This field combines name and alias.
|
||||
if (category != UnicodeCategory.OtherNotAssigned) fields |= UcdFields.Category;
|
||||
if (canonicalCombiningClass != CanonicalCombiningClass.NotReordered) fields |= UcdFields.CanonicalCombiningClass;
|
||||
if (CanonicalCombiningClass != CanonicalCombiningClass.NotReordered) fields |= UcdFields.CanonicalCombiningClass;
|
||||
/*if (bidirectionalClass != 0)*/
|
||||
fields |= UcdFields.BidirectionalClass;
|
||||
if (characterDecompositionMapping.DecompositionMapping != null) fields |= UcdFields.DecompositionMapping;
|
||||
fields |= (UcdFields)((int)numericType << 6);
|
||||
if (bidirectionalMirrored) fields |= UcdFields.BidirectionalMirrored;
|
||||
if (oldName != null) fields |= UcdFields.OldName;
|
||||
if (simpleUpperCaseMapping != null) fields |= UcdFields.SimpleUpperCaseMapping;
|
||||
if (simpleLowerCaseMapping != null) fields |= UcdFields.SimpleLowerCaseMapping;
|
||||
if (simpleTitleCaseMapping != null) fields |= UcdFields.SimpleTitleCaseMapping;
|
||||
if (contributoryProperties != 0) fields |= UcdFields.ContributoryProperties;
|
||||
if (coreProperties != 0) fields |= UcdFields.CoreProperties;
|
||||
if (CharacterDecompositionMapping.DecompositionMapping != null) fields |= UcdFields.DecompositionMapping;
|
||||
fields |= (UcdFields)((int)NumericType << 6);
|
||||
if (BidirectionalMirrored) fields |= UcdFields.BidirectionalMirrored;
|
||||
if (OldName != null) fields |= UcdFields.OldName;
|
||||
if (SimpleUpperCaseMapping != null) fields |= UcdFields.SimpleUpperCaseMapping;
|
||||
if (SimpleLowerCaseMapping != null) fields |= UcdFields.SimpleLowerCaseMapping;
|
||||
if (SimpleTitleCaseMapping != null) fields |= UcdFields.SimpleTitleCaseMapping;
|
||||
if (ContributoryProperties != 0) fields |= UcdFields.ContributoryProperties;
|
||||
if (CoreProperties != 0 || EmojiProperties != 0) fields |= UcdFields.CorePropertiesAndEmojiProperties;
|
||||
if (crossRerefences.Count > 0) fields |= UcdFields.CrossRerefences;
|
||||
|
||||
writer.Write((ushort)fields);
|
||||
|
||||
writer.WriteCodePoint(codePointRange.FirstCodePoint);
|
||||
writer.WriteCodePoint(CodePointRange.FirstCodePoint);
|
||||
if ((fields & UcdFields.CodePointRange) != 0) writer.WriteCodePoint(CodePointRange.LastCodePoint);
|
||||
|
||||
if ((fields & UcdFields.Name) != 0)
|
||||
@@ -200,38 +115,38 @@ namespace System.Unicode.Builder
|
||||
|
||||
if (nameAliases.Count > 0)
|
||||
{
|
||||
writer.WritePackedLength((byte)(name != null ? 3 : 2), nameAliases.Count);
|
||||
writer.WritePackedLength((byte)(Name != null ? 3 : 2), nameAliases.Count);
|
||||
|
||||
if (name != null)
|
||||
writer.WriteNamePropertyToFile(name);
|
||||
if (Name != null)
|
||||
writer.WriteNamePropertyToFile(Name);
|
||||
|
||||
foreach (var nameAlias in nameAliases)
|
||||
writer.WriteNameAliasToFile(nameAlias);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteNamePropertyToFile(name);
|
||||
writer.WriteNamePropertyToFile(Name);
|
||||
}
|
||||
}
|
||||
if ((fields & UcdFields.Category) != 0) writer.Write((byte)category);
|
||||
if ((fields & UcdFields.CanonicalCombiningClass) != 0) writer.Write((byte)canonicalCombiningClass);
|
||||
if ((fields & UcdFields.BidirectionalClass) != 0) writer.Write((byte)bidirectionalClass);
|
||||
if ((fields & UcdFields.CanonicalCombiningClass) != 0) writer.Write((byte)CanonicalCombiningClass);
|
||||
if ((fields & UcdFields.BidirectionalClass) != 0) writer.Write((byte)BidirectionalClass);
|
||||
if ((fields & UcdFields.DecompositionMapping) != 0)
|
||||
{
|
||||
writer.Write((byte)characterDecompositionMapping.DecompositionType);
|
||||
writer.Write(characterDecompositionMapping.DecompositionMapping);
|
||||
writer.Write((byte)CharacterDecompositionMapping.DecompositionType);
|
||||
writer.Write(CharacterDecompositionMapping.DecompositionMapping);
|
||||
}
|
||||
if ((fields & UcdFields.NumericNumeric) != 0)
|
||||
{
|
||||
writer.Write(numericValue.Numerator);
|
||||
writer.Write(numericValue.Denominator);
|
||||
writer.Write(NumericValue.Numerator);
|
||||
writer.Write(NumericValue.Denominator);
|
||||
}
|
||||
if ((fields & UcdFields.OldName) != 0) writer.Write(oldName);
|
||||
if ((fields & UcdFields.SimpleUpperCaseMapping) != 0) writer.Write(simpleUpperCaseMapping);
|
||||
if ((fields & UcdFields.SimpleLowerCaseMapping) != 0) writer.Write(simpleLowerCaseMapping);
|
||||
if ((fields & UcdFields.SimpleTitleCaseMapping) != 0) writer.Write(simpleTitleCaseMapping);
|
||||
if ((fields & UcdFields.ContributoryProperties) != 0) writer.Write((int)contributoryProperties);
|
||||
if ((fields & UcdFields.CoreProperties) != 0) writer.WriteUInt24((int)coreProperties);
|
||||
if ((fields & UcdFields.OldName) != 0) writer.Write(OldName);
|
||||
if ((fields & UcdFields.SimpleUpperCaseMapping) != 0) writer.Write(SimpleUpperCaseMapping);
|
||||
if ((fields & UcdFields.SimpleLowerCaseMapping) != 0) writer.Write(SimpleLowerCaseMapping);
|
||||
if ((fields & UcdFields.SimpleTitleCaseMapping) != 0) writer.Write(SimpleTitleCaseMapping);
|
||||
if ((fields & UcdFields.ContributoryProperties) != 0) writer.Write((int)ContributoryProperties);
|
||||
if ((fields & UcdFields.CorePropertiesAndEmojiProperties) != 0) writer.WriteUInt24((int)CoreProperties | (int)EmojiProperties << 20);
|
||||
if ((fields & UcdFields.CrossRerefences) != 0)
|
||||
{
|
||||
writer.Write(checked((byte)(crossRerefences.Count - 1)));
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace UnicodeInformation.Tests
|
||||
[InlineData(0x0D5D, UnicodeCategory.OtherNumber, UnicodeNumericType.Numeric, "3/20", "MALAYALAM FRACTION THREE TWENTIETHS", "Malayalam")]
|
||||
[InlineData(0x0D59, UnicodeCategory.OtherNumber, UnicodeNumericType.Numeric, "1/40", "MALAYALAM FRACTION ONE FORTIETH", "Malayalam")]
|
||||
[InlineData(0x1F953, UnicodeCategory.OtherSymbol, UnicodeNumericType.None, null, "BACON", "Supplemental Symbols and Pictographs")]
|
||||
[InlineData(0x1F966, UnicodeCategory.OtherSymbol, UnicodeNumericType.None, null, "BROCCOLI", "Supplemental Symbols and Pictographs")]
|
||||
public void CharacterInfoShouldHaveExpectedResults(int codePoint, UnicodeCategory expectedCategory, UnicodeNumericType expectedNumericType, string expectedNumericValue, string expectedName, string expectedBlock)
|
||||
{
|
||||
var info = UnicodeInfo.GetCharInfo(codePoint);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace System.Unicode
|
||||
SimpleTitleCaseMapping = 4096,
|
||||
|
||||
ContributoryProperties = 8192,
|
||||
CoreProperties = 16384,
|
||||
CorePropertiesAndEmojiProperties = 16384,
|
||||
|
||||
CrossRerefences = 32768,
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user