From f3e2ff53c51b310cfbc640866e6bc8f9c523cfb7 Mon Sep 17 00:00:00 2001 From: GoldenCrystal Date: Sat, 1 Nov 2014 14:09:56 +0100 Subject: [PATCH] Added code for supporting contributory properties. --- UnicodeInformation/ContributoryProperties.cs | 78 +++++++++++++++++++ UnicodeInformation/EnumHelper.cs | 36 +++++++++ UnicodeInformation/UnicodeCharacterData.cs | 5 +- .../UnicodeCharacterDataBuilder.cs | 8 ++ UnicodeInformation/UnicodeCharacterRange.cs | 33 +++++++- UnicodeInformation/UnicodeDataManager.cs | 16 +++- UnicodeInformation/UnicodeInformation.csproj | 2 + UnicodeInformation/UnicodeRationalNumber.cs | 9 +-- 8 files changed, 174 insertions(+), 13 deletions(-) create mode 100644 UnicodeInformation/ContributoryProperties.cs create mode 100644 UnicodeInformation/EnumHelper.cs diff --git a/UnicodeInformation/ContributoryProperties.cs b/UnicodeInformation/ContributoryProperties.cs new file mode 100644 index 0000000..c938c9c --- /dev/null +++ b/UnicodeInformation/ContributoryProperties.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnicodeInformation +{ + [Flags] + public enum ContributoryProperties : int + { + [Display(Name = "ASCII_Hex_Digit", Description = "ASCII characters commonly used for the representation of hexadecimal numbers.")] + ASCIIHexDigit = 0x00000001, + [Display(Name = "Bidi_Control", Description = "Format control characters which have specific functions in the Unicode Bidirectional Algorithm [UAX9].")] + BidiControl = 0x00000002, + [Display(Name = "Dash", Description = "Punctuation characters explicitly called out as dashes in the Unicode Standard, plus their compatibility equivalents. Most of these have the General_Category value Pd, but some have the General_Category value Sm because of their use in mathematics.")] + Dash = 0x00000004, + [Display(Name = "Deprecated", Description = "For a machine-readable list of deprecated characters. No characters will ever be removed from the standard, but the usage of deprecated characters is strongly discouraged.")] + Deprecated = 0x00000008, + [Display(Name = "Diacritic", Description = "Characters that linguistically modify the meaning of another character to which they apply. Some diacritics are not combining characters, and some combining characters are not diacritics.")] + Diacritic = 0x00000010, + [Display(Name = "Extender", Description = "Characters whose principal function is to extend the value or shape of a preceding alphabetic character. Typical of these are length and iteration marks.")] + Extender = 0x00000020, + [Display(Name = "Hex_Digit", Description = "Characters commonly used for the representation of hexadecimal numbers, plus their compatibility equivalents.")] + HexDigit = 0x00000040, + [Display(Name = "Hyphen", Description = "Dashes which are used to mark connections between pieces of words, plus the Katakana middle dot. The Katakana middle dotfunctions like a hyphen, but is shaped like a dot rather than a dash.")] + Hyphen = 0x00000080, + [Display(Name = "Ideographic", Description = "Characters considered to be CJKV (Chinese, Japanese, Korean, and Vietnamese) ideographs. This property roughly defines the class of \"Chinese characters\" and does not include characters of other logographic scripts such as Cuneiform or Egyptian Hieroglyphs.")] + Ideographic = 0x00000100, + [Display(Name = "IDS_Binary_Operator", Description = "Used in Ideographic Description Sequences.")] + IDSBinaryOperator = 0x00000200, + [Display(Name = "IDS_Trinary_Operator", Description = "Used in Ideographic Description Sequences.")] + IDSTrinaryOperator = 0x00000400, + [Display(Name = "Join_Control", Description = "Format control characters which have specific functions for control of cursive joining and ligation.")] + JoinControl = 0x00000800, + [Display(Name = "Logical_Order_Exception", Description = "A small number of spacing vowel letters occurring in certain Southeast Asian scripts such as Thai and Lao, which use a visual order display model. These letters are stored in text ahead of syllable-initial consonants, and require special handling for processes such as searching and sorting.")] + LogicalOrderException = 0x00001000, + [Display(Name = "Noncharacter_Code_Point", Description = "Code points permanently reserved for internal use.")] + NoncharacterCodePoint = 0x00002000, + [Display(Name = "Other_Alphabetic", Description = "Used in deriving the Alphabetic property.")] + OtherAlphabetic = 0x00004000, + [Display(Name = "Other_Default_Ignorable_Code_Point", Description = "Used in deriving the Default_Ignorable_Code_Point property.")] + OtherDefaultIgnorableCodePoint = 0x00008000, + [Display(Name = "Other_Grapheme_Extend", Description = "Used in deriving  the Grapheme_Extend property.")] + OtherGraphemeExtend = 0x00010000, + [Display(Name = "Other_ID_Continue", Description = "Used to maintain backward compatibility of ID_Continue.")] + OtherIDContinue = 0x00020000, + [Display(Name = "Other_ID_Start", Description = "Used to maintain backward compatibility of ID_Start.")] + OtherIDStart = 0x00040000, + [Display(Name = "Other_Lowercase", Description = "Used in deriving the Lowercase property.")] + OtherLowercase = 0x00080000, + [Display(Name = "Other_Math", Description = "Used in deriving the Math property.")] + OtherMath = 0x00100000, + [Display(Name = "Other_Uppercase", Description = "Used in deriving the Uppercase property.")] + OtherUppercase = 0x00200000, + [Display(Name = "Pattern_Syntax", Description = "Used for pattern syntax as described in Unicode Standard Annex #31, \"Unicode Identifier and Pattern Syntax\" [UAX31].")] + PatternSyntax = 0x00400000, + [Display(Name = "Pattern_White_Space")] + PatternWhiteSpace = 0x00800000, + [Display(Name = "Quotation_Mark", Description = "Punctuation characters that function as quotation marks.")] + QuotationMark = 0x01000000, + [Display(Name = "Radical", Description = "Used in Ideographic Description Sequences.")] + Radical = 0x02000000, + [Display(Name = "Soft_Dotted", Description = "Characters with a \"soft dot\", like i or j. An accent placed on these characters causes the dot to disappear. An explicit dot abovecan be added where required, such as in Lithuanian.")] + SoftDotted = 0x04000000, + [Display(Name = "STerm", Description = "Sentence Terminal. Used in Unicode Standard Annex #29, \"Unicode Text Segmentation\" [UAX29].")] + STerm = 0x08000000, + [Display(Name = "Terminal_Punctuation", Description = "Punctuation characters that generally mark the end of textual units.")] + TerminalPunctuation = 0x10000000, + [Display(Name = "Unified_Ideograph", Description = "A property which specifies the exact set of Unified CJK Ideographs in the standard. This set excludes CJK Compatibility Ideographs (which have canonical decompositions to Unified CJK Ideographs), as well as characters from the CJK Symbols and Punctuation block. The property is used in the definition of Ideographic Description Sequences.")] + UnifiedIdeograph = 0x20000000, + [Display(Name = "Variation_Selector", Description = "Indicates characters that are Variation Selectors. For details on the behavior of these characters, seeStandardizedVariants.html, Section 23.4, Variation Selectors in [Unicode], and Unicode Technical Standard #37, \"Unicode Ideographic Variation Database\" [UTS37].")] + VariationSelector = 0x40000000, + [Display(Name = "White_Space", Description = "Spaces, separator characters and other control characters which should be treated by programming languages as \"white space\" for the purpose of parsing elements. See also Line_Break, Grapheme_Cluster_Break, Sentence_Break, and Word_Break, which classify space characters and related controls somewhat differently for particular text segmentation contexts.")] + WhiteSpace = -0x7FFFFFFF, + } +} diff --git a/UnicodeInformation/EnumHelper.cs b/UnicodeInformation/EnumHelper.cs new file mode 100644 index 0000000..ab7aabc --- /dev/null +++ b/UnicodeInformation/EnumHelper.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace UnicodeInformation +{ + internal sealed class EnumHelper + where T : struct + { + private static readonly Dictionary namedValueDictionary = CreateNamedValueDictionary(); + + private static Dictionary CreateNamedValueDictionary() + { + var type = typeof(T).GetTypeInfo(); + + if (!type.IsEnum) throw new InvalidOperationException(); + + return + ( + from field in type.DeclaredFields + let attr = field.GetCustomAttribute() + where attr != null && attr.Name != null + select new KeyValuePair(attr.Name, (T)field.GetValue(null)) + ).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + } + + public static bool TryGetNamedValue(string name, out T value) + { + return namedValueDictionary.TryGetValue(name, out value); + } + } +} diff --git a/UnicodeInformation/UnicodeCharacterData.cs b/UnicodeInformation/UnicodeCharacterData.cs index 5e63874..20c7ff3 100644 --- a/UnicodeInformation/UnicodeCharacterData.cs +++ b/UnicodeInformation/UnicodeCharacterData.cs @@ -22,10 +22,11 @@ namespace UnicodeInformation public readonly string SimpleUpperCaseMapping; public readonly string SimpleLowerCaseMapping; public readonly string SimpleTitleCaseMapping; + public readonly ContributoryProperties ContributoryProperties; public readonly int[] RelatedCodePoints; - public UnicodeCharacterData + internal UnicodeCharacterData ( int codePoint, string name, @@ -40,6 +41,7 @@ namespace UnicodeInformation string simpleUpperCaseMapping, string simpleLowerCaseMapping, string simpleTitleCaseMapping, + ContributoryProperties contributoryProperties, int[] relatedCodePoints ) { @@ -56,6 +58,7 @@ namespace UnicodeInformation this.SimpleUpperCaseMapping = simpleUpperCaseMapping; this.SimpleLowerCaseMapping = simpleLowerCaseMapping; this.SimpleTitleCaseMapping = simpleTitleCaseMapping; + this.ContributoryProperties = contributoryProperties; this.RelatedCodePoints = relatedCodePoints; } } diff --git a/UnicodeInformation/UnicodeCharacterDataBuilder.cs b/UnicodeInformation/UnicodeCharacterDataBuilder.cs index 2389123..599636f 100644 --- a/UnicodeInformation/UnicodeCharacterDataBuilder.cs +++ b/UnicodeInformation/UnicodeCharacterDataBuilder.cs @@ -22,6 +22,7 @@ namespace UnicodeInformation private string simpleUpperCaseMapping; private string simpleLowerCaseMapping; private string simpleTitleCaseMapping; + private ContributoryProperties contributoryProperties; private List relatedCodePoints = new List(); @@ -106,6 +107,12 @@ namespace UnicodeInformation set { simpleTitleCaseMapping = value; } } + public ContributoryProperties ContributoryProperties + { + get { return contributoryProperties; } + set { contributoryProperties = value; } + } + public ICollection RelatedCodePoints { get { return relatedCodePoints; } } public UnicodeCharacterDataBuilder(int codePoint) @@ -130,6 +137,7 @@ namespace UnicodeInformation simpleUpperCaseMapping, simpleLowerCaseMapping, simpleTitleCaseMapping, + contributoryProperties, relatedCodePoints.Count > 0 ? relatedCodePoints.ToArray() : null ); } diff --git a/UnicodeInformation/UnicodeCharacterRange.cs b/UnicodeInformation/UnicodeCharacterRange.cs index 715e0a4..5adee1f 100644 --- a/UnicodeInformation/UnicodeCharacterRange.cs +++ b/UnicodeInformation/UnicodeCharacterRange.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -13,14 +14,44 @@ namespace UnicodeInformation public UnicodeCharacterRange(int codePoint) { + if (codePoint < 0 || codePoint > 0x10FFFF) throw new ArgumentOutOfRangeException("codePoint"); + FirstCodePoint = codePoint; LastCodePoint = codePoint; } public UnicodeCharacterRange(int firstCodePoint, int lastCodePoint) { - FirstCodePoint = firstCodePoint; + if (firstCodePoint < 0 || firstCodePoint > 0x10FFFF) throw new ArgumentOutOfRangeException("firstCodePoint"); + if (lastCodePoint < firstCodePoint || lastCodePoint > 0x10FFFF) throw new ArgumentOutOfRangeException("lastCodePoint"); + + FirstCodePoint = firstCodePoint; LastCodePoint = lastCodePoint; } + + public override string ToString() + { + return FirstCodePoint == LastCodePoint ? FirstCodePoint.ToString("X4") : FirstCodePoint.ToString("X4") + ".." + LastCodePoint.ToString("X4"); + } + + public static UnicodeCharacterRange Parse(string s) + { + int start, end; + + var rangeSeparatorOffset = s.IndexOf(".."); + + if (rangeSeparatorOffset == 0) throw new FormatException(); + else if (rangeSeparatorOffset < 0) + { + start = end = int.Parse(s, NumberStyles.HexNumber); + } + else + { + start = int.Parse(s.Substring(0, rangeSeparatorOffset), NumberStyles.HexNumber); + end = int.Parse(s.Substring(rangeSeparatorOffset + 2), NumberStyles.HexNumber); + } + + return new UnicodeCharacterRange(start, end); + } } } diff --git a/UnicodeInformation/UnicodeDataManager.cs b/UnicodeInformation/UnicodeDataManager.cs index e09a21f..a359f22 100644 --- a/UnicodeInformation/UnicodeDataManager.cs +++ b/UnicodeInformation/UnicodeDataManager.cs @@ -81,10 +81,20 @@ namespace UnicodeInformation characterDataBuilders.Add(characterData); } } + /* + using (var reader = new UnicodeDataFileReader(await httpClient.GetStreamAsync(UnicodeCharacterDataUri + PropListFileName).ConfigureAwait(false))) + { + while (reader.MoveToNextLine()) + { + ContributoryProperties property; - //using (var reader = new UnicodeDataFileReader(await httpClient.GetStreamAsync(UnicodeCharacterDataUri + PropListFileName).ConfigureAwait(false))) - //{ - //} + var range = UnicodeCharacterRange.Parse(reader.ReadField().TrimEnd()); + if (EnumHelper.TryGetNamedValue(reader.ReadField().Trim(), out property)) + { + } + } + } + */ } var finalData = new UnicodeCharacterData[characterDataBuilders.Count]; diff --git a/UnicodeInformation/UnicodeInformation.csproj b/UnicodeInformation/UnicodeInformation.csproj index a6025ea..7497c63 100644 --- a/UnicodeInformation/UnicodeInformation.csproj +++ b/UnicodeInformation/UnicodeInformation.csproj @@ -47,9 +47,11 @@ + + diff --git a/UnicodeInformation/UnicodeRationalNumber.cs b/UnicodeInformation/UnicodeRationalNumber.cs index 8c4197c..630ea62 100644 --- a/UnicodeInformation/UnicodeRationalNumber.cs +++ b/UnicodeInformation/UnicodeRationalNumber.cs @@ -15,14 +15,7 @@ namespace UnicodeInformation int fractionBarIndex = s.IndexOf('/'); - try - { - return new UnicodeRationalNumber(long.Parse(fractionBarIndex >= 0 ? s.Substring(0, fractionBarIndex) : s), fractionBarIndex >= 0 ? byte.Parse(s.Substring(fractionBarIndex + 1)) : (byte)1); - } - catch (Exception ex) - { - throw; - } + return new UnicodeRationalNumber(long.Parse(fractionBarIndex >= 0 ? s.Substring(0, fractionBarIndex) : s), fractionBarIndex >= 0 ? byte.Parse(s.Substring(fractionBarIndex + 1)) : (byte)1); } public readonly long Numerator;