1 // =================================
   2 // Copyright (c) 2022 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 using System;
   7 using System.Collections;
   8 using System.IO;
   9 
  10 namespace System.Unicode
  11 {
  12     public class UnicodeException : Exception
  13     {
  14         public nothrow UnicodeException(const string& message_) : base(message_)
  15         {
  16         }
  17     }
  18     
  19     public void ThrowUnicodeException(const string& message)
  20     {
  21         throw UnicodeException(message);
  22     }
  23     
  24     public string PathToUnicodeDirectory()
  25     {
  26         return "/mnt/cmajor/unicode";
  27     }
  28     
  29     public string PathToUcdBinFile()
  30     {
  31         return Path.Combine(PathToUnicodeDirectory()"cmajor_ucd.bin");
  32     }
  33     
  34     public string MakeCanonicalPropertyName(const string& s)
  35     {
  36         string result;
  37         for (char c : s)
  38         {
  39             if (c != '_' && c != ' ' && c != '-')
  40             {
  41                 result.Append(c);
  42             }
  43         }
  44         return ToLower(result);
  45     }
  46     
  47     public enum BinaryPropertyId : byte
  48     {
  49         asciiHexDigit
  50         alphabetic
  51         bidiControl
  52         bidiMirrored
  53         cased
  54         compositionExclusion
  55         caseIgnorable
  56         fullCompositionExclusion
  57         changesWhenCasefolded
  58         changesWhenCaseMapped
  59         changesWhenNFKCCasefolded
  60         changesWhenLowercased
  61         changesWhenTitlecased
  62         changesWhenUppercased
  63         dash
  64         deprecated
  65         defaultIgnorableCodePoint
  66         diacritic
  67         extender
  68         graphemeBase
  69         graphemeExtend
  70         graphemeLink
  71         hexDigit
  72         hyphen
  73         idContinue
  74         ideographic
  75         idStart
  76         idsBinaryOperator
  77         idsTrinaryOperator
  78         joinControl
  79         logicalOrderException
  80         lowercase
  81         math
  82         noncharacterCodePoint
  83         otherAlphabetic
  84         otherDefaultIgnorableCodePoint
  85         otherGraphemeExtend
  86         otherIdContinue
  87         otherIdStart
  88         otherLowercase
  89         otherMath
  90         otherUppercase
  91         patternSyntax
  92         patternWhiteSpace
  93         prependedConcatenationMark
  94         quotationMark
  95         radical
  96         softDotted
  97         sentenceterminal
  98         terminalPunctuation
  99         unifiedIdeograph
 100         uppercase
 101         variationSelector
 102         whiteSpace
 103         xidContinue
 104         xidStart
 105         expandsOnNFC
 106         expandsOnNFD
 107         expandsOnNFKC
 108         expandsOnNFKD
 109     }
 110     
 111     public class BinaryProperty
 112     {
 113         public nothrow BinaryProperty(BinaryPropertyId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
 114         {
 115         }
 116         public inline nothrow BinaryPropertyId Id()
 117         {
 118             return id;
 119         }
 120         public inline nothrow const string& ShortName()
 121         {
 122             return shortName;
 123         }
 124         public inline nothrow const string& LongName()
 125         {
 126             return longName;
 127         }
 128         private BinaryPropertyId id;
 129         private string shortName;
 130         private string longName;
 131     }
 132     
 133     public class BinaryPropertyTable
 134     {
 135         static BinaryPropertyTable() : instance(new BinaryPropertyTable())
 136         {
 137         }
 138         public static nothrow BinaryPropertyTable& Instance()
 139         {
 140             return *instance;
 141         }
 142         public nothrow const BinaryProperty* GetBinaryProperty(BinaryPropertyId id) const
 143         {
 144             HashMap<uintvoid*>.ConstIterator it = binaryPropertyIdMap.CFind(cast<uint>(cast<byte>(id)));
 145             if (it != binaryPropertyIdMap.CEnd())
 146             {
 147                 return cast<BinaryProperty*>(it->second);
 148             }
 149             return null;
 150         }
 151         public const BinaryProperty* GetBinaryPropertyByShortName(const string& shortName) const
 152         {
 153             HashMap<stringvoid*>.ConstIterator it = shortNameMap.CFind(MakeCanonicalPropertyName(shortName));
 154             if (it != shortNameMap.CEnd())
 155             {
 156                 return cast<BinaryProperty*>(it->second);
 157             }
 158             return null;
 159         }
 160         public const BinaryProperty* GetBinaryPropertyByLongName(const string& longName) const
 161         {
 162             HashMap<stringvoid*>.ConstIterator it = longNameMap.CFind(MakeCanonicalPropertyName(longName));
 163             if (it != longNameMap.CEnd())
 164             {
 165                 return cast<BinaryProperty*>(it->second);
 166             }
 167             return null;
 168         }
 169         private BinaryPropertyTable() : binaryProperties()binaryPropertyIdMap()shortNameMap()longNameMap()
 170         {
 171             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.asciiHexDigit"AHex""Ascii Hex Digit"));
 172             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.alphabetic"Alpha""Alphabetic"));
 173             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.bidiControl"Bidi C""Bidi Control"));
 174             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.bidiMirrored"Bidi M""Bidi Mirrored"));
 175             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.cased"Cased""Cased"));
 176             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.compositionExclusion"CE""Composition Exclusion"));
 177             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.caseIgnorable"CI""Case Ignorable"));
 178             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.fullCompositionExclusion"Comp Ex""Full Composition Exclusion"));
 179             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenCasefolded"CWCF""Changes When Casefolded"));
 180             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenCaseMapped"CWCM""Changes When Casemapped"));
 181             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenNFKCCasefolded"CWKCF""Changes When NFKC Casefolded"));
 182             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenLowercased"CWL""Changes When Lowercased"));
 183             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenTitlecased"CWT""Changes When Titlecased"));
 184             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenUppercased"CWU""Changes When Uppercased"));
 185             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.dash"Dash""Dash"));
 186             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.deprecated"Dep""Deprecated"));
 187             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.defaultIgnorableCodePoint"DI""Default Ignorable Code Point"));
 188             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.diacritic"Dia""Diacritic"));
 189             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.extender"Ext""Extender"));
 190             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.graphemeBase"Gr Base""Grapheme Base"));
 191             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.graphemeExtend"Gr Ext""Grapheme Extend"));
 192             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.graphemeLink"Gr Link""Grapheme Link"));
 193             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.hexDigit"Hex""Hex Digit"));
 194             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.hyphen"Hyphen""Hyphen"));
 195             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idContinue"IDC""ID Continue"));
 196             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.ideographic"Ideo""Ideographic"));
 197             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idStart"IDS""ID Start"));
 198             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idsBinaryOperator"IDSB""IDS Binary Operator"));
 199             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idsTrinaryOperator"IDST""IDS Trinary Operator"));
 200             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.joinControl"Join C""Join Control"));
 201             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.logicalOrderException"LOE""Logical Order Exception"));
 202             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.lowercase"Lower""Lowercase"));
 203             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.math"Math""Math"));
 204             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.noncharacterCodePoint"NChar""Noncharacter Code Point"));
 205             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherAlphabetic"OAlpha""Other Alphabetic"));
 206             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherDefaultIgnorableCodePoint"ODI""Other Default Ignorable Code Point"));
 207             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherGraphemeExtend"OGr Ext""Other Grapheme Extend"));
 208             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherIdContinue"OIDC""Other ID Continue"));
 209             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherIdStart"OIDS""Other ID Start"));
 210             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherLowercase"OLower""Other Lowercase"));
 211             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherMath"OMath""Other Math"));
 212             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherUppercase"OUpper""Other Uppercase"));
 213             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.patternSyntax"Pat Syn""Pattern Syntax"));
 214             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.patternWhiteSpace"Pat WS""Pattern White Space"));
 215             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.prependedConcatenationMark"PCM""Prepended Concatenation Mark"));
 216             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.quotationMark"QMark""Quotation Mark"));
 217             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.radical"Radical""Radical"));
 218             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.softDotted"SD""Soft Dotted"));
 219             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.sentenceterminal"STerm""Sentence Terminal"));
 220             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.terminalPunctuation"Term""Terminal Punctuation"));
 221             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.unifiedIdeograph"UIdeo""Unified Ideograph"));
 222             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.uppercase"Upper""Uppercase"));
 223             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.variationSelector"VS""Variation Selector"));
 224             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.whiteSpace"WSpace""White Space"));
 225             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.xidContinue"XIDC""XID Continue"));
 226             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.xidStart"XIDS""XID Start"));
 227             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFC"XO NFC""Expands On NFC"));
 228             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFD"XO NFD""Expands On NFD"));
 229             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFKC"XO NFKC""Expands On NFKC"));
 230             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFKD"XO NFKD""Expands On NFKD"));
 231             for (BinaryProperty* binaryProperty : binaryProperties)
 232             {
 233                 binaryPropertyIdMap[cast<uint>(cast<byte>(binaryProperty->Id()))] = binaryProperty;
 234                 shortNameMap[MakeCanonicalPropertyName(binaryProperty->ShortName())] = binaryProperty;
 235                 longNameMap[MakeCanonicalPropertyName(binaryProperty->LongName())] = binaryProperty;
 236             }
 237         }
 238         public ~BinaryPropertyTable()
 239         {
 240             for (BinaryProperty* binaryProperty : binaryProperties)
 241             {
 242                 delete binaryProperty;
 243             }
 244         }
 245         private List<BinaryProperty*> binaryProperties;
 246         private HashMap<uintvoid*> binaryPropertyIdMap;
 247         private HashMap<stringvoid*> shortNameMap;
 248         private HashMap<stringvoid*> longNameMap;
 249         private static UniquePtr<BinaryPropertyTable> instance;
 250     }
 251     
 252     public nothrow const BinaryProperty* GetBinaryProperty(BinaryPropertyId id)
 253     {
 254         return BinaryPropertyTable.Instance().GetBinaryProperty(id);
 255     }
 256 
 257     public const BinaryProperty* GetBinaryPropertyByShortName(const string& shortName)
 258     {
 259         return BinaryPropertyTable.Instance().GetBinaryPropertyByShortName(shortName);
 260     }
 261 
 262     public const BinaryProperty* GetBinaryPropertyByLongName(const string& longName)
 263     {
 264         return BinaryPropertyTable.Instance().GetBinaryPropertyByLongName(longName);
 265     }
 266     
 267     public enum BlockId : ushort
 268     {
 269         none = 0u
 270         adlamaegeanNumbersahomalchemicalalphabeticPfanatolianHieroglyphsancientGreekMusicancientGreekNumbersancientSymbols
 271         arabicarabicExtAarabicMatharabicPfAarabicPfBarabicSuparmenianarrowsasciiavestan
 272         balinesebamumbamumSupbassaVahbatakbengalibhaisukiblockElementsbopomofobopomofoExtboxDrawing
 273         brahmibraillebuginesebuhidbyzantineMusic
 274         cariancaucasianAlbanianchakmachamcherokeecherokeeSupchessSymbols
 275         cjkcjkCompatcjkCompatFormscjkCompatIdeographscjkCompatIdeographsSupcjkExtAcjkExtBcjkExtCcjkExtDcjkExtEcjkExtF
 276         cjkRadicalsSupcjkStrokescjkSymbolscompatJamocontrolPicturescopticcopticEpactNumberscountingRodcuneiform
 277         cuneiformNumberscurrencySymbolscypriotSyllabarycyrilliccyrillicExtAcyrillicExtBcyrillicExtCcyrillicSup
 278         deseretdevanagaridevanagariExtdiacriticalsdiariticalsForSymbolsdiacriticalsSupdiacriticalsExtdingbatsdogradominoduployan
 279         earlyDynasticCuneiformegyptianHieroglyphsegyptianHieroglyphFormatControlselbasanelymaicemoticonsenclosedAlphanumenclosedAlphanumSupenclosedCjkenclosedIdeographicSup
 280         ethiopicethiopicExtethiopicExtAethiopicSup
 281         geometricShapesgeometricShapesExtgeorgiangeorgianExtgeorgianSupglagoliticglagoliticSupgothicgranthagreekgreekExtgujaratigunjalaGondigurmukhi
 282         halfAndFullFormshalfMarkshangulhanifiRohingyahanunoohatranhebrewhighPuSurrogateshighSurrogateshiragana
 283         idcideographicSymbolsimperialAramaicindicNumberFormsinscriptionalPahlaviinscriptionalParthianipaExtindicSiyaqNumbers
 284         jamojamoExtAjamoExtBjavanesekaithikanaExtAsmallKanaExtkanaSupkanbunkangxikannadakatakanakatakanaExtkayahLikharoshthikhmerkhmerSymbolskhojkikhudawadi
 285         laolatin1SuplatinExtAlatinExtAdditionallatinExtBlatinExtClatinExtDlatinExtElepchaletterlikeSymbolslimbu
 286         linearAlinearBIdeogramslinearBSyllabarylisulowSurrogateslycianlydian
 287         mahajanimahjongmakasarmalayalammandaicmanicheanmarchenmasaramGondimathAlphanummathOperatorsmayanNumeralsmedefaidrinmeeteiMayekmeeteiMayekExtmendeKikakuimeroiticCursivemeroiticHieroglyphs
 288         miaomiscArrowsmiscMathSymbolsAmiscMathSymbolsBmiscPictographsmiscSymbolsmiscTechnicalmodimodifierLettersmodifierToneLettersmongolianmongolianSup
 289         mromusicmultanimyanmarmyanmarExtAmyanmarExtB
 290         nabataeannbnandinagarinewTaiLuenewankonumberFormsnushunyiakengPuachueHmong
 291         ocroghamolChikioldHungarianoldItalicoldNorthArabianoldPermicoldPersianoldSogdianoldSouthArabianoldTurkicoriyaornamentalDingbatsosageosmanyaottomanSiyaqNumbers
 292         pahawhHmongpalmyrenepauCinHauphagsPaphaistosphoenicianphoneticExtphoneticExtSupplayingCardspsalterPahlavipuapunctuation
 293         rejangrumirunic
 294         samaritansaurashtrasharadashavianshorthandFormatControlssiddhamsinhalasinhalaArchaicNumberssmallFormssogdiansoraSompengsoyombospecialssundanesesundaneseSup
 295         supArrowsAsupArrowsBsupArrowsCsupMathOperatorssupPuaAsupPuaBsupPunctuationsupSymbolsAndPictographssuperAndSubsuttonSignWritingsylotiNagrisymbolsAndPictographsExtAsyriac
 296         syriacSup
 297         tagalogtagbanwatagstaiLetaiThamtaiViettaiXuanJingtakritamiltamilSuptanguttangutComponentsteluguthaanathaitibetantifinaghtirhutatransportAndMap
 298         ucasucasExtugariticvaivedicExtverticalFormsvsvsSupwanchowarangCitiyiRadicalsyiSyllablesyijingzanabazarSquare
 299     }
 300 
 301     public class Block
 302     {
 303         public nothrow Block(BlockId id_const string& shortName_const string& longName_uchar start_uchar end_) : 
 304             id(id_)shortName(shortName_)longName(longName_)start(start_)end(end_)
 305         {
 306         }
 307         public inline nothrow BlockId Id()
 308         {
 309             return id;
 310         }
 311         public inline nothrow const string& ShortName()
 312         {
 313             return shortName;
 314         }
 315         public inline nothrow const string& LongName()
 316         {
 317             return longName;
 318         }
 319         public inline nothrow uchar Start()
 320         {
 321             return start;
 322         }
 323         public inline nothrow uchar End()
 324         {
 325             return end;
 326         }
 327         private BlockId id;
 328         private string shortName;
 329         private string longName;
 330         private uchar start;
 331         private uchar end;
 332     }
 333     
 334     public class BlockTable
 335     {
 336         static BlockTable() : instance(new BlockTable())
 337         {
 338         }
 339         public static BlockTable& Instance()
 340         {
 341             return *instance;
 342         }
 343         public inline nothrow const Block* GetBlock(BlockId id) const
 344         {
 345             HashMap<uintvoid*>.ConstIterator it = blockIdMap.CFind(cast<uint>(cast<ushort>(id)));
 346             if (it != blockIdMap.CEnd())
 347             {
 348                 return cast<Block*>(it->second);
 349             }
 350             return null;
 351         }
 352         public inline const Block* GetBlockByShortName(const string& shortName) const
 353         {
 354             HashMap<stringvoid*>.ConstIterator it = shortNameMap.CFind(MakeCanonicalPropertyName(shortName));
 355             if (it != shortNameMap.CEnd())
 356             {
 357                 return cast<Block*>(it->second);
 358             }
 359             return null;
 360         }
 361         public inline const Block* GetBlockByLongName(const string& longName) const
 362         {
 363             HashMap<stringvoid*>.ConstIterator it = longNameMap.CFind(MakeCanonicalPropertyName(longName));
 364             if (it != longNameMap.CEnd())
 365             {
 366                 return cast<Block*>(it->second);
 367             }
 368             return null;
 369         }
 370         private BlockTable() : blocks()blockIdMap()shortNameMap()longNameMap()
 371         {
 372             blocks.Add(new Block(BlockId.ascii"ASCII""Basic Latin"cast<uchar>(0x0000u)cast<uchar>(0x007Fu)));
 373             blocks.Add(new Block(BlockId.latin1Sup"Latin 1 Sup""Latin-1 Supplement"cast<uchar>(0x0080u)cast<uchar>(0x00FFu)));
 374             blocks.Add(new Block(BlockId.latinExtA"Latin Ext A""Latin Extended-A"cast<uchar>(0x0100u)cast<uchar>(0x017Fu)));
 375             blocks.Add(new Block(BlockId.latinExtB"Latin Ext B""Latin Extended-B"cast<uchar>(0x0180u)cast<uchar>(0x0024Fu)));
 376             blocks.Add(new Block(BlockId.ipaExt"IPA Ext""IPA Extensions"cast<uchar>(0x0250u)cast<uchar>(0x02AFu)));
 377             blocks.Add(new Block(BlockId.modifierLetters"Modifier Letters""Spacing Modifier Letters"cast<uchar>(0x02B0u)cast<uchar>(0x02FFu)));
 378             blocks.Add(new Block(BlockId.diacriticals"Diacriticals""Combining Diacritical Marks"cast<uchar>(0x0300u)cast<uchar>(0x036Fu)));
 379             blocks.Add(new Block(BlockId.greek"Greek""Greek and Coptic"cast<uchar>(0x0370u)cast<uchar>(0x03FFu)));
 380             blocks.Add(new Block(BlockId.cyrillic"Cyrillic""Cyrillic"cast<uchar>(0x0400u)cast<uchar>(0x04FFu)));
 381             blocks.Add(new Block(BlockId.cyrillicSup"Cyrillic Sup""Cyrillic Supplement"cast<uchar>(0x0500u)cast<uchar>(0x052Fu)));
 382             blocks.Add(new Block(BlockId.armenian"Armenian""Armenian"cast<uchar>(0x0530u)cast<uchar>(0x058Fu)));
 383             blocks.Add(new Block(BlockId.hebrew"Hebrew""Hebrew"cast<uchar>(0x0590u)cast<uchar>(0x05FFu)));
 384             blocks.Add(new Block(BlockId.arabic"Arabic""Arabic"cast<uchar>(0x0600u)cast<uchar>(0x06FFu)));
 385             blocks.Add(new Block(BlockId.syriac"Syriac""Syriac"cast<uchar>(0x0700u)cast<uchar>(0x074Fu)));
 386             blocks.Add(new Block(BlockId.arabicSup"Arabic Sup""Arabic Supplement"cast<uchar>(0x0750u)cast<uchar>(0x077Fu)));
 387             blocks.Add(new Block(BlockId.thaana"Thaana""Thaana"cast<uchar>(0x0780u)cast<uchar>(0x07BFu)));
 388             blocks.Add(new Block(BlockId.nko"Nko""Nko"cast<uchar>(0x07C0u)cast<uchar>(0x07FFu)));
 389             blocks.Add(new Block(BlockId.samaritan"Samaritan""Samaritan"cast<uchar>(0x0800u)cast<uchar>(0x083Fu)));
 390             blocks.Add(new Block(BlockId.mandaic"Mandaic""Mandaic"cast<uchar>(0x0840u)cast<uchar>(0x085Fu)));
 391             blocks.Add(new Block(BlockId.syriacSup"Syriac Sup""Syriac Supplement"cast<uchar>(0x0860)cast<uchar>(0x086F)));
 392             blocks.Add(new Block(BlockId.arabicExtA"Arabic Ext A""Arabic Extended-A"cast<uchar>(0x08A0u)cast<uchar>(0x08FFu)));
 393             blocks.Add(new Block(BlockId.devanagari"Devanagari""Devanagari"cast<uchar>(0x0900u)cast<uchar>(0x097Fu)));
 394             blocks.Add(new Block(BlockId.bengali"Bengali""Bengali"cast<uchar>(0x0980u)cast<uchar>(0x09FFu)));
 395             blocks.Add(new Block(BlockId.gurmukhi"Gurmukhi""Gurmukhi"cast<uchar>(0x0A00u)cast<uchar>(0x0A7Fu)));
 396             blocks.Add(new Block(BlockId.gujarati"Gujarati""Gujarati"cast<uchar>(0x0A80u)cast<uchar>(0x0AFFu)));
 397             blocks.Add(new Block(BlockId.oriya"Oriya""Oriya"cast<uchar>(0x0B00u)cast<uchar>(0x0B7Fu)));
 398             blocks.Add(new Block(BlockId.tamil"Tamil""Tamil"cast<uchar>(0x0B80u)cast<uchar>(0x0BFFu)));
 399             blocks.Add(new Block(BlockId.telugu"Telugu""Telugu"cast<uchar>(0x0C00u)cast<uchar>(0x0C7Fu)));
 400             blocks.Add(new Block(BlockId.kannada"Kannada""Kannada"cast<uchar>(0x0C80u)cast<uchar>(0x0CFFu)));
 401             blocks.Add(new Block(BlockId.malayalam"Malayalam""Malayalam"cast<uchar>(0x0D00u)cast<uchar>(0x0D7Fu)));
 402             blocks.Add(new Block(BlockId.sinhala"Sinhala""Sinhala"cast<uchar>(0x0D80u)cast<uchar>(0x0DFFu)));
 403             blocks.Add(new Block(BlockId.thai"Thai""Thai"cast<uchar>(0x0E00u)cast<uchar>(0x0E7Fu)));
 404             blocks.Add(new Block(BlockId.lao"Lao""Lao"cast<uchar>(0x0E80u)cast<uchar>(0x0EFFu)));
 405             blocks.Add(new Block(BlockId.tibetan"Tibetan""Tibetan"cast<uchar>(0x0F00u)cast<uchar>(0x0FFFu)));
 406             blocks.Add(new Block(BlockId.myanmar"Myanmar""Myanmar"cast<uchar>(0x1000u)cast<uchar>(0x109Fu)));
 407             blocks.Add(new Block(BlockId.georgian"Georgian""Georgian"cast<uchar>(0x10A0u)cast<uchar>(0x10FFu)));
 408             blocks.Add(new Block(BlockId.jamo"Jamo""Hangul Jamo"cast<uchar>(0x1100u)cast<uchar>(0x11FFu)));
 409             blocks.Add(new Block(BlockId.ethiopic"Ethiopic""Ethiopic"cast<uchar>(0x1200u)cast<uchar>(0x137Fu)));
 410             blocks.Add(new Block(BlockId.ethiopicSup"Ethiopic Sup""Ethiopic Supplement"cast<uchar>(0x1380u)cast<uchar>(0x139Fu)));
 411             blocks.Add(new Block(BlockId.cherokee"Cherokee""Cherokee"cast<uchar>(0x13A0u)cast<uchar>(0x13FFu)));
 412             blocks.Add(new Block(BlockId.ucas"UCAS""Unified Canadian Aboriginal Syllabics"cast<uchar>(0x1400u)cast<uchar>(0x167Fu)));
 413             blocks.Add(new Block(BlockId.ogham"Ogham""Ogham"cast<uchar>(0x1680u)cast<uchar>(0x169Fu)));
 414             blocks.Add(new Block(BlockId.runic"Runic""Runic"cast<uchar>(0x16A0u)cast<uchar>(0x16FFu)));
 415             blocks.Add(new Block(BlockId.tagalog"Tagalog""Tagalog"cast<uchar>(0x1700u)cast<uchar>(0x171Fu)));
 416             blocks.Add(new Block(BlockId.hanunoo"Hanunoo""Hanunoo"cast<uchar>(0x1720u)cast<uchar>(0x173Fu)));
 417             blocks.Add(new Block(BlockId.buhid"Buhid""Buhid"cast<uchar>(0x1740u)cast<uchar>(0x175Fu)));
 418             blocks.Add(new Block(BlockId.tagbanwa"Tagbanwa""Tagbanwa"cast<uchar>(0x1760u)cast<uchar>(0x177Fu)));
 419             blocks.Add(new Block(BlockId.khmer"Khmer""Khmer"cast<uchar>(0x1780u)cast<uchar>(0x17FFu)));
 420             blocks.Add(new Block(BlockId.mongolian"Mongolian""Mongolian"cast<uchar>(0x1800u)cast<uchar>(0x18AFu)));
 421             blocks.Add(new Block(BlockId.ucasExt"UCAS Ext""Unified Canadian Aboriginal Syllabics Extended"cast<uchar>(0x18B0u)cast<uchar>(0x18FFu)));
 422             blocks.Add(new Block(BlockId.limbu"Limbu""Limbu"cast<uchar>(0x1900u)cast<uchar>(0x194Fu)));
 423             blocks.Add(new Block(BlockId.taiLe"Tai Le""Tai Le"cast<uchar>(0x1950u)cast<uchar>(0x197Fu)));
 424             blocks.Add(new Block(BlockId.newTaiLue"New Tai Lue""New Tai Lue"cast<uchar>(0x1980u)cast<uchar>(0x19DFu)));
 425             blocks.Add(new Block(BlockId.khmerSymbols"Khmer Symbols""Khmer Symbols"cast<uchar>(0x19E0u)cast<uchar>(0x19FFu)));
 426             blocks.Add(new Block(BlockId.buginese"Buginese""Buginese"cast<uchar>(0x1A00u)cast<uchar>(0x1A1Fu)));
 427             blocks.Add(new Block(BlockId.taiTham"Tai Tham""Tai Tham"cast<uchar>(0x1A20u)cast<uchar>(0x1AAFu)));
 428             blocks.Add(new Block(BlockId.diacriticalsExt"Diacriticals Ext""Combining Diacritical Marks Extended"cast<uchar>(0x1AB0u)cast<uchar>(0x1AFFu)));
 429             blocks.Add(new Block(BlockId.balinese"Balinese""Balinese"cast<uchar>(0x1B00u)cast<uchar>(0x1B7Fu)));
 430             blocks.Add(new Block(BlockId.sundanese"Sundanese""Sundanese"cast<uchar>(0x1B80u)cast<uchar>(0x1BBFu)));
 431             blocks.Add(new Block(BlockId.batak"Batak""Batak"cast<uchar>(0x1BC0u)cast<uchar>(0x1BFFu)));
 432             blocks.Add(new Block(BlockId.lepcha"Lepcha""Lepcha"cast<uchar>(0x1C00u)cast<uchar>(0x1C4Fu)));
 433             blocks.Add(new Block(BlockId.olChiki"Ol Chiki""Ol Chiki"cast<uchar>(0x1C50u)cast<uchar>(0x1C7Fu)));
 434             blocks.Add(new Block(BlockId.cyrillicExtC"Cyrillic Ext C""Cyrillic Extended-C"cast<uchar>(0x1C80u)cast<uchar>(0x1C8Fu)));
 435             blocks.Add(new Block(BlockId.georgianExt"Georgian Ext""Georgian Extended"cast<uchar>(0x1C90)cast<uchar>(0x1CBF)));
 436             blocks.Add(new Block(BlockId.sundaneseSup"Sundanese Sup""Sundanese Supplement"cast<uchar>(0x1CC0u)cast<uchar>(0x1CCFu)));
 437             blocks.Add(new Block(BlockId.vedicExt"Vedic Ext""Vedic Extensions"cast<uchar>(0x1CD0u)cast<uchar>(0x1CFFu)));
 438             blocks.Add(new Block(BlockId.phoneticExt"Phonetic Ext""Phonetic Extensions"cast<uchar>(0x1D00u)cast<uchar>(0x1D7Fu)));
 439             blocks.Add(new Block(BlockId.phoneticExtSup"Phonetic Ext Sup""Phonetic Extensions Supplement"cast<uchar>(0x1D80u)cast<uchar>(0x1DBFu)));
 440             blocks.Add(new Block(BlockId.diacriticalsSup"Diacriticals Sup""Combining Diacritical Marks Supplement"cast<uchar>(0x1DC0u)cast<uchar>(0x1DFFu)));
 441             blocks.Add(new Block(BlockId.latinExtAdditional"Latin Ext Additional""Latin Extended Additional"cast<uchar>(0x1E00u)cast<uchar>(0x1EFFu)));
 442             blocks.Add(new Block(BlockId.greekExt"Greek Ext""Greek Extended"cast<uchar>(0x1F00u)cast<uchar>(0x1FFFu)));
 443             blocks.Add(new Block(BlockId.punctuation"Punctuation""General Punctuation"cast<uchar>(0x2000u)cast<uchar>(0x206Fu)));
 444             blocks.Add(new Block(BlockId.superAndSub"Super And Sub""Superscripts and Subscripts"cast<uchar>(0x2070u)cast<uchar>(0x209Fu)));
 445             blocks.Add(new Block(BlockId.currencySymbols"Currency Symbols""Currency Symbols"cast<uchar>(0x20A0u)cast<uchar>(0x20CFu)));
 446             blocks.Add(new Block(BlockId.diariticalsForSymbols"Diacriticals For Symbols""Combining Diacritical Marks for Symbols"cast<uchar>(0x20D0u)cast<uchar>(0x20FFu)));
 447             blocks.Add(new Block(BlockId.letterlikeSymbols"Letterlike Symbols""Letterlike Symbols"cast<uchar>(0x2100u)cast<uchar>(0x214Fu)));
 448             blocks.Add(new Block(BlockId.numberForms"Number Forms""Number Forms"cast<uchar>(0x2150u)cast<uchar>(0x218Fu)));
 449             blocks.Add(new Block(BlockId.arrows"Arrows""Arrows"cast<uchar>(0x2190u)cast<uchar>(0x21FFu)));
 450             blocks.Add(new Block(BlockId.mathOperators"Math Operators""Mathematical Operators"cast<uchar>(0x2200u)cast<uchar>(0x22FFu)));
 451             blocks.Add(new Block(BlockId.miscTechnical"Misc Technical""Miscellaneous Technical"cast<uchar>(0x2300u)cast<uchar>(0x23FFu)));
 452             blocks.Add(new Block(BlockId.controlPictures"Control Pictures""Control Pictures"cast<uchar>(0x2400u)cast<uchar>(0x243Fu)));
 453             blocks.Add(new Block(BlockId.ocr"OCR""Optical Character Regognition"cast<uchar>(0x2440u)cast<uchar>(0x245Fu)));
 454             blocks.Add(new Block(BlockId.enclosedAlphanum"Enclosed Alphanum""Enclosed Alphanumerics"cast<uchar>(0x2460u)cast<uchar>(0x24FFu)));
 455             blocks.Add(new Block(BlockId.boxDrawing"Box Drawing""Box Drawing"cast<uchar>(0x2500u)cast<uchar>(0x257Fu)));
 456             blocks.Add(new Block(BlockId.blockElements"Block Elements""Block Elements"cast<uchar>(0x2580u)cast<uchar>(0x259Fu)));
 457             blocks.Add(new Block(BlockId.geometricShapes"Geometric Shapes""Geometric Shapes"cast<uchar>(0x25A0u)cast<uchar>(0x25FFu)));
 458             blocks.Add(new Block(BlockId.miscSymbols"Misc Symbols""Miscellaneous Symbols"cast<uchar>(0x2600u)cast<uchar>(0x26FFu)));
 459             blocks.Add(new Block(BlockId.dingbats"Dingbats""Dingbats"cast<uchar>(0x2700u)cast<uchar>(0x27BFu)));
 460             blocks.Add(new Block(BlockId.miscMathSymbolsA"Misc Math Symbols A""Miscellaneous Mathematical Symbols - A"cast<uchar>(0x27C0u)cast<uchar>(0x27EFu)));
 461             blocks.Add(new Block(BlockId.supArrowsA"Sup Arrows A""Supplemental Arrows-A"cast<uchar>(0x27F0u)cast<uchar>(0x27FFu)));
 462             blocks.Add(new Block(BlockId.braille"Braille""Braille Patterns"cast<uchar>(0x2800u)cast<uchar>(0x28FFu)));
 463             blocks.Add(new Block(BlockId.supArrowsB"Sup Arrows B""Supplemental Arrows-B"cast<uchar>(0x2900u)cast<uchar>(0x297Fu)));
 464             blocks.Add(new Block(BlockId.miscMathSymbolsB"Misc Math Symbols B""Miscellaneous Mathematical Symbols-B"cast<uchar>(0x2980u)cast<uchar>(0x29FFu)));
 465             blocks.Add(new Block(BlockId.supMathOperators"Sup Math Operators""Supplemental Mathematical Operators"cast<uchar>(0x2A00u)cast<uchar>(0x2AFFu)));
 466             blocks.Add(new Block(BlockId.miscArrows"Misc Arrows""Miscellaneous Symbols and Arrows"cast<uchar>(0x2B00u)cast<uchar>(0x2BFFu)));
 467             blocks.Add(new Block(BlockId.glagolitic"Glagolitic""Glagolitic"cast<uchar>(0x2C00u)cast<uchar>(0x2C5Fu)));
 468             blocks.Add(new Block(BlockId.latinExtC"Latin Ext C""Latin Extended-C"cast<uchar>(0x2C60u)cast<uchar>(0x2C7Fu)));
 469             blocks.Add(new Block(BlockId.coptic"Coptic""Coptic"cast<uchar>(0x2C80u)cast<uchar>(0x2CFFu)));
 470             blocks.Add(new Block(BlockId.georgianSup"Georgian Sup""Georgian Supplement"cast<uchar>(0x2D00u)cast<uchar>(0x2D2Fu)));
 471             blocks.Add(new Block(BlockId.tifinagh"Tifinagh""Tifinagh"cast<uchar>(0x2D30u)cast<uchar>(0x2D7Fu)));
 472             blocks.Add(new Block(BlockId.ethiopicExt"Ethiopic Ext""Ethiopic Extended"cast<uchar>(0x2D80u)cast<uchar>(0x2DDFu)));
 473             blocks.Add(new Block(BlockId.cyrillicExtA"Cyrillic Ext A""Cyrillic Extended-A"cast<uchar>(0x2DE0u)cast<uchar>(0x2DFFu)));
 474             blocks.Add(new Block(BlockId.supPunctuation"Sup Punctuation""Supplemental Punctuation"cast<uchar>(0x2E00u)cast<uchar>(0x2E7Fu)));
 475             blocks.Add(new Block(BlockId.cjkRadicalsSup"CJK Radicals Sup""CJK Radicals Supplement"cast<uchar>(0x2E80u)cast<uchar>(0x2EFFu)));
 476             blocks.Add(new Block(BlockId.kangxi"Kangxi""Kangxi Radicals"cast<uchar>(0x2F00u)cast<uchar>(0x2FDFu)));
 477             blocks.Add(new Block(BlockId.idc"IDC""Ideographic Description Characters"cast<uchar>(0x2FF0u)cast<uchar>(0x2FFFu)));
 478             blocks.Add(new Block(BlockId.cjkSymbols"CJK Symbols""CJK Symbols and Punctuation"cast<uchar>(0x3000u)cast<uchar>(0x303Fu)));
 479             blocks.Add(new Block(BlockId.hiragana"Hiragana""Hiragana"cast<uchar>(0x3040u)cast<uchar>(0x309Fu)));
 480             blocks.Add(new Block(BlockId.katakana"Katakana""Katakana"cast<uchar>(0x30A0u)cast<uchar>(0x30FFu)));
 481             blocks.Add(new Block(BlockId.bopomofo"Bopomofo""Bopomofo"cast<uchar>(0x3100u)cast<uchar>(0x312Fu)));
 482             blocks.Add(new Block(BlockId.compatJamo"Compat Jamo""Hangul Compatibility Jamo"cast<uchar>(0x3130u)cast<uchar>(0x318Fu)));
 483             blocks.Add(new Block(BlockId.kanbun"Kanbun""Kanbun"cast<uchar>(0x3190u)cast<uchar>(0x319Fu)));
 484             blocks.Add(new Block(BlockId.bopomofoExt"Bopomofo Ext""Bopomofo Extended"cast<uchar>(0x31A0u)cast<uchar>(0x31BFu)));
 485             blocks.Add(new Block(BlockId.cjkStrokes"CJK Strokes""CJK Strokes"cast<uchar>(0x31C0u)cast<uchar>(0x31EFu)));
 486             blocks.Add(new Block(BlockId.katakanaExt"Katakana Ext""Katakana Phonetic Extensions"cast<uchar>(0x31F0u)cast<uchar>(0x31FFu)));
 487             blocks.Add(new Block(BlockId.enclosedCjk"Enclosed CJK""Enclosed CJK Letters and Months"cast<uchar>(0x3200u)cast<uchar>(0x32FFu)));
 488             blocks.Add(new Block(BlockId.cjkCompat"CJK Compat""CJK Compatibility"cast<uchar>(0x3300u)cast<uchar>(0x33FFu)));
 489             blocks.Add(new Block(BlockId.cjkExtA"CJK Ext A""CJK Unified Ideographic Extension A"cast<uchar>(0x3400u)cast<uchar>(0x4DBFu)));
 490             blocks.Add(new Block(BlockId.yijing"Yijing""Yijing Hexagram Symbols"cast<uchar>(0x4DC0u)cast<uchar>(0x4DFFu)));
 491             blocks.Add(new Block(BlockId.cjk"CJK""CJK Unified Ideographs"cast<uchar>(0x4E00u)cast<uchar>(0x9FFFu)));
 492             blocks.Add(new Block(BlockId.yiSyllables"Yi Syllables""Yi Syllables"cast<uchar>(0xA000u)cast<uchar>(0xA48Fu)));
 493             blocks.Add(new Block(BlockId.yiRadicals"Yi Radicals""Yi Radicals"cast<uchar>(0xA090u)cast<uchar>(0xA4CFu)));
 494             blocks.Add(new Block(BlockId.lisu"Lisu""Lisu"cast<uchar>(0xA0D0u)cast<uchar>(0xA4FFu)));
 495             blocks.Add(new Block(BlockId.vai"Vai""Vai"cast<uchar>(0xA500u)cast<uchar>(0xA63Fu)));
 496             blocks.Add(new Block(BlockId.cyrillicExtB"Cyrillic Ext B""Cyrillic Extended-B"cast<uchar>(0xA640u)cast<uchar>(0xA69Fu)));
 497             blocks.Add(new Block(BlockId.bamum"Bamum""Bamum"cast<uchar>(0xA6A0u)cast<uchar>(0xA6FFu)));
 498             blocks.Add(new Block(BlockId.modifierToneLetters"Modifier Tone Letters""Modifier Tone Letters"cast<uchar>(0xA700u)cast<uchar>(0xA71Fu)));
 499             blocks.Add(new Block(BlockId.latinExtD"Latin Ext D""Latin Extended-D"cast<uchar>(0xA720u)cast<uchar>(0xA7FFu)));
 500             blocks.Add(new Block(BlockId.sylotiNagri"Syloti Nagri""Syloti Nagri"cast<uchar>(0xA800u)cast<uchar>(0xA82Fu)));
 501             blocks.Add(new Block(BlockId.indicNumberForms"Indic Number Forms""Common Indic Number Forms"cast<uchar>(0xA830u)cast<uchar>(0xA83Fu)));
 502             blocks.Add(new Block(BlockId.phagsPa"Phags Pa""Phags-Pa"cast<uchar>(0xA840u)cast<uchar>(0xA87Fu)));
 503             blocks.Add(new Block(BlockId.saurashtra"Saurashtra""Saurashtra"cast<uchar>(0xA880u)cast<uchar>(0xA8DFu)));
 504             blocks.Add(new Block(BlockId.devanagariExt"Devanagari Ext""Devanagari Extended"cast<uchar>(0xA8E0u)cast<uchar>(0xA8FFu)));
 505             blocks.Add(new Block(BlockId.kayahLi"Kayah Li""Kayah Li"cast<uchar>(0xA900u)cast<uchar>(0xA92Fu)));
 506             blocks.Add(new Block(BlockId.rejang"Rejang""Rejang"cast<uchar>(0xA930u)cast<uchar>(0xA95Fu)));
 507             blocks.Add(new Block(BlockId.jamoExtA"Jamo Ext A""Hangul Jamo Extended-A"cast<uchar>(0xA960u)cast<uchar>(0xA97Fu)));
 508             blocks.Add(new Block(BlockId.javanese"Javanese""Javanese"cast<uchar>(0xA980u)cast<uchar>(0xA9DFu)));
 509             blocks.Add(new Block(BlockId.myanmarExtB"Myanmar Ext B""Myanmar Extended - B"cast<uchar>(0xA9E0u)cast<uchar>(0xA9FFu)));
 510             blocks.Add(new Block(BlockId.cham"Cham""Cham"cast<uchar>(0xAA00u)cast<uchar>(0xAA5Fu)));
 511             blocks.Add(new Block(BlockId.myanmarExtA"Myanmar Ext A""Myanmar Extended-A"cast<uchar>(0xAA60u)cast<uchar>(0xAA7Fu)));
 512             blocks.Add(new Block(BlockId.taiViet"Tai Viet""Tai Viet"cast<uchar>(0xAA80u)cast<uchar>(0xAADFu)));
 513             blocks.Add(new Block(BlockId.meeteiMayekExt"Meetei Mayek Ext""Meetei Mayek Extensions"cast<uchar>(0xAAE0u)cast<uchar>(0xAAFFu)));
 514             blocks.Add(new Block(BlockId.ethiopicExtA"Ethiopic Ext A""Ethiopic Extended-A"cast<uchar>(0xAB00u)cast<uchar>(0xAB2Fu)));
 515             blocks.Add(new Block(BlockId.latinExtE"Latin Ext E""Latin Extended-E"cast<uchar>(0xAB30u)cast<uchar>(0xAB6Fu)));
 516             blocks.Add(new Block(BlockId.cherokeeSup"Cherokee Sup""Cherokee Supplement"cast<uchar>(0xAB70u)cast<uchar>(0xABBFu)));
 517             blocks.Add(new Block(BlockId.meeteiMayek"Meetei Mayek""Meetei Mayek"cast<uchar>(0xABC0u)cast<uchar>(0xABFFu)));
 518             blocks.Add(new Block(BlockId.hangul"Hangul""Hangul Syllables"cast<uchar>(0xAC00u)cast<uchar>(0xD7AFu)));
 519             blocks.Add(new Block(BlockId.jamoExtB"Jamo Ext B""Hangul Jamo Extended-B"cast<uchar>(0xD7B0u)cast<uchar>(0xD7FFu)));
 520             blocks.Add(new Block(BlockId.highSurrogates"High Surrogates""High Surrogates"cast<uchar>(0xD800u)cast<uchar>(0xDB7Fu)));
 521             blocks.Add(new Block(BlockId.highPuSurrogates "High PU Surrogates""High Private Use Surrogates"cast<uchar>(0xDB80u)cast<uchar>(0xDBFFu)));
 522             blocks.Add(new Block(BlockId.lowSurrogates"Low Surrogates""Low Surrogates"cast<uchar>(0xDC00u)cast<uchar>(0xDFFFu)));
 523             blocks.Add(new Block(BlockId.pua"PUA""Private Use Area"cast<uchar>(0xE000u)cast<uchar>(0xF8FFu)));
 524             blocks.Add(new Block(BlockId.cjkCompatIdeographs"CJK Compat Ideographs""CJK Compatibility Ideographs"cast<uchar>(0xF900u)cast<uchar>(0xFAFFu)));
 525             blocks.Add(new Block(BlockId.alphabeticPf"Alphabetic PF""Alphabetic Presentations Forms"cast<uchar>(0xFB00u)cast<uchar>(0xFB4Fu)));
 526             blocks.Add(new Block(BlockId.arabicPfA"Arabic PF A""Arabic Presentation Forms-A"cast<uchar>(0xFB50u)cast<uchar>(0xFDFFu)));
 527             blocks.Add(new Block(BlockId.vs"VS""Variation Selectors"cast<uchar>(0xFE00u)cast<uchar>(0xFE0Fu)));
 528             blocks.Add(new Block(BlockId.verticalForms"Vertical Forms""Vertical Forms"cast<uchar>(0xFE10u)cast<uchar>(0xFE1Fu)));
 529             blocks.Add(new Block(BlockId.halfMarks"Half Marks""Combining Half Marks"cast<uchar>(0xFE20u)cast<uchar>(0xFE2Fu)));
 530             blocks.Add(new Block(BlockId.cjkCompatForms"CJK Compat Forms""CJK Compatibility Forms"cast<uchar>(0xFE30u)cast<uchar>(0xFE4Fu)));
 531             blocks.Add(new Block(BlockId.smallForms"Small Forms""Small Form Variants"cast<uchar>(0xFE50u)cast<uchar>(0xFE6Fu)));
 532             blocks.Add(new Block(BlockId.arabicPfB"Arabic PF B""Arabic Presentation Forms-B"cast<uchar>(0xFE70u)cast<uchar>(0xFEFFu)));
 533             blocks.Add(new Block(BlockId.halfAndFullForms"Half And Full Forms""Halfwidth and Fullwidth Forms"cast<uchar>(0xFF00u)cast<uchar>(0xFFEFu)));
 534             blocks.Add(new Block(BlockId.specials"Specials""Specials"cast<uchar>(0xFFF0u)cast<uchar>(0xFFFFu)));
 535             blocks.Add(new Block(BlockId.linearBSyllabary"Linear B Syllabary""Linear B Syllabary"cast<uchar>(0x10000u)cast<uchar>(0x1007Fu)));
 536             blocks.Add(new Block(BlockId.linearBIdeograms"Linear B Ideograms""Linear B Ideograms"cast<uchar>(0x10080u)cast<uchar>(0x100FFu)));
 537             blocks.Add(new Block(BlockId.aegeanNumbers"Aegean Numbers""Aegean Numbers"cast<uchar>(0x10100u)cast<uchar>(0x1013Fu)));
 538             blocks.Add(new Block(BlockId.ancientGreekNumbers"Ancient Greek Numbers""Ancient Greek Numbers"cast<uchar>(0x10140u)cast<uchar>(0x1018Fu)));
 539             blocks.Add(new Block(BlockId.ancientSymbols"Ancient Symbols""Ancient Symbols"cast<uchar>(0x10190u)cast<uchar>(0x101CFu)));
 540             blocks.Add(new Block(BlockId.phaistos"Phaistos""Phaistos Disc"cast<uchar>(0x101D0u)cast<uchar>(0x101FFu)));
 541             blocks.Add(new Block(BlockId.lycian"Lycian""Lycian"cast<uchar>(0x10280u)cast<uchar>(0x1029Fu)));
 542             blocks.Add(new Block(BlockId.carian"Carian""Carian"cast<uchar>(0x102A0u)cast<uchar>(0x102DFu)));
 543             blocks.Add(new Block(BlockId.copticEpactNumbers"Coptic Epact Numbers""Coptic Epact Numbers"cast<uchar>(0x102E0u)cast<uchar>(0x102FFu)));
 544             blocks.Add(new Block(BlockId.oldItalic"Old Italic""Old Italic"cast<uchar>(0x10300u)cast<uchar>(0x1032Fu)));
 545             blocks.Add(new Block(BlockId.gothic"Gothic""Gothic"cast<uchar>(0x10330u)cast<uchar>(0x1034Fu)));
 546             blocks.Add(new Block(BlockId.oldPermic"Old Permic""Old Permic"cast<uchar>(0x10350u)cast<uchar>(0x1037Fu)));
 547             blocks.Add(new Block(BlockId.ugaritic"Ugaritic""Ugaritic"cast<uchar>(0x10380u)cast<uchar>(0x1039Fu)));
 548             blocks.Add(new Block(BlockId.oldPersian"Old Persian""Old Persian"cast<uchar>(0x103A0u)cast<uchar>(0x103DFu)));
 549             blocks.Add(new Block(BlockId.deseret"Deseret""Deseret"cast<uchar>(0x10400u)cast<uchar>(0x1044Fu)));
 550             blocks.Add(new Block(BlockId.shavian"Shavian""Shavian"cast<uchar>(0x10450u)cast<uchar>(0x1047Fu)));
 551             blocks.Add(new Block(BlockId.osmanya"Osmanya""Osmanya"cast<uchar>(0x10480u)cast<uchar>(0x104AFu)));
 552             blocks.Add(new Block(BlockId.osage"Osage""Osage"cast<uchar>(0x104B0u)cast<uchar>(0x104FFu)));
 553             blocks.Add(new Block(BlockId.elbasan"Elbasan""Elbasan"cast<uchar>(0x10500u)cast<uchar>(0x1052Fu)));
 554             blocks.Add(new Block(BlockId.caucasianAlbanian"Caucasian Albanian""Caucasian Albanian"cast<uchar>(0x10530u)cast<uchar>(0x1056Fu)));
 555             blocks.Add(new Block(BlockId.linearA"Linear A""Linear A"cast<uchar>(0x10600u)cast<uchar>(0x1077Fu)));
 556             blocks.Add(new Block(BlockId.cypriotSyllabary"Cypriot Syllabary""Cypriot Syllabary"cast<uchar>(0x10800u)cast<uchar>(0x1083Fu)));
 557             blocks.Add(new Block(BlockId.imperialAramaic"Imperial Aramaic""Imperial Aramaic"cast<uchar>(0x10840u)cast<uchar>(0x1085Fu)));
 558             blocks.Add(new Block(BlockId.palmyrene"Palmyrene""Palmyrene"cast<uchar>(0x10860u)cast<uchar>(0x1087Fu)));
 559             blocks.Add(new Block(BlockId.nabataean"Nabataean""Nabataean"cast<uchar>(0x10880u)cast<uchar>(0x108AFu)));
 560             blocks.Add(new Block(BlockId.hatran"Hatran""Hatran"cast<uchar>(0x108E0u)cast<uchar>(0x108FFu)));
 561             blocks.Add(new Block(BlockId.phoenician"Phoenician""Phoenician"cast<uchar>(0x10900u)cast<uchar>(0x1091Fu)));
 562             blocks.Add(new Block(BlockId.lydian"Lydian""Lydian"cast<uchar>(0x10920u)cast<uchar>(0x1093Fu)));
 563             blocks.Add(new Block(BlockId.meroiticHieroglyphs"Meroitic Hieroglyphs""Meroitic Hieroglyphs"cast<uchar>(0x10980u)cast<uchar>(0x1099Fu)));
 564             blocks.Add(new Block(BlockId.meroiticCursive"Meroitic Cursive""Meroitic Cursive"cast<uchar>(0x109A0u)cast<uchar>(0x109FFu)));
 565             blocks.Add(new Block(BlockId.kharoshthi"Kharoshthi""Kharoshthi"cast<uchar>(0x10A00u)cast<uchar>(0x10A5Fu)));
 566             blocks.Add(new Block(BlockId.oldSouthArabian"Old South Arabian""Old South Arabian"cast<uchar>(0x10A60u)cast<uchar>(0x10A7Fu)));
 567             blocks.Add(new Block(BlockId.oldNorthArabian"Old North Arabian""Old North Arabian"cast<uchar>(0x10A80u)cast<uchar>(0x10A9Fu)));
 568             blocks.Add(new Block(BlockId.manichean"Manichaean""Manichaean"cast<uchar>(0x10AC0u)cast<uchar>(0x10AFFu)));
 569             blocks.Add(new Block(BlockId.avestan"Avestan""Avestan"cast<uchar>(0x10B00u)cast<uchar>(0x10B3Fu)));
 570             blocks.Add(new Block(BlockId.inscriptionalParthian"Inscriptional Parthian""Inscriptional Parthian"cast<uchar>(0x10B40u)cast<uchar>(0x10B5Fu)));
 571             blocks.Add(new Block(BlockId.inscriptionalPahlavi"Inscriptional Pahlavi""Inscriptional Pahlavi"cast<uchar>(0x10B60u)cast<uchar>(0x10B7Fu)));
 572             blocks.Add(new Block(BlockId.psalterPahlavi"Psalter Pahlavi""Psalter Pahlavi"cast<uchar>(0x10B80u)cast<uchar>(0x10BAFu)));
 573             blocks.Add(new Block(BlockId.oldTurkic"Old Turkic""Old Turkic"cast<uchar>(0x10C00u)cast<uchar>(0x10C4Fu)));
 574             blocks.Add(new Block(BlockId.oldHungarian"Old Hungarian""Old Hungarian"cast<uchar>(0x10C80u)cast<uchar>(0x10CFFu)));
 575             blocks.Add(new Block(BlockId.hanifiRohingya"Hanifi Rohingya""Hanifi Rohingya"cast<uchar>(0x10D00u)cast<uchar>(0x10D3Fu)));
 576             blocks.Add(new Block(BlockId.rumi"Rumi""Rumi Numeral Symbols"cast<uchar>(0x10E60u)cast<uchar>(0x10E7Fu)));
 577             blocks.Add(new Block(BlockId.oldSogdian"Old Sogdian""Old Sogdian"cast<uchar>(0x10F00u)cast<uchar>(0x10F2Fu)));
 578             blocks.Add(new Block(BlockId.sogdian"Sogdian""Sogdian"cast<uchar>(0x10F30u)cast<uchar>(0x10F6Fu)));
 579             blocks.Add(new Block(BlockId.elymaic"Elymaic""Elymaic"cast<uchar>(0x10FE0)cast<uchar>(0x10FFF)));
 580             blocks.Add(new Block(BlockId.brahmi"Brahmi""Brahmi"cast<uchar>(0x11000u)cast<uchar>(0x1107Fu)));
 581             blocks.Add(new Block(BlockId.kaithi"Kaithi""Kaithi"cast<uchar>(0x11080u)cast<uchar>(0x110CFu)));
 582             blocks.Add(new Block(BlockId.soraSompeng"Sora Sompeng""Sora Sompeng"cast<uchar>(0x110D0u)cast<uchar>(0x110FFu)));
 583             blocks.Add(new Block(BlockId.chakma"Chakma""Chakma"cast<uchar>(0x11100u)cast<uchar>(0x1114Fu)));
 584             blocks.Add(new Block(BlockId.mahajani"Mahajani""Mahajani"cast<uchar>(0x11150u)cast<uchar>(0x1117Fu)));
 585             blocks.Add(new Block(BlockId.sharada"Sharada""Sharada"cast<uchar>(0x11180u)cast<uchar>(0x111DFu)));
 586             blocks.Add(new Block(BlockId.sinhalaArchaicNumbers"Sinhala Archaic Numbers""Sinhala Archaic Numbers"cast<uchar>(0x111E0u)cast<uchar>(0x111FFu)));
 587             blocks.Add(new Block(BlockId.khojki"Khojki""Khojki"cast<uchar>(0x11200u)cast<uchar>(0x1124Fu)));
 588             blocks.Add(new Block(BlockId.multani"Multani""Multani"cast<uchar>(0x11280u)cast<uchar>(0x112AFu)));
 589             blocks.Add(new Block(BlockId.khudawadi"Khudawadi""Khudawadi"cast<uchar>(0x112B0u)cast<uchar>(0x112FFu)));
 590             blocks.Add(new Block(BlockId.grantha"Grantha""Grantha"cast<uchar>(0x11300u)cast<uchar>(0x1137Fu)));
 591             blocks.Add(new Block(BlockId.newa"Newa""Newa"cast<uchar>(0x11400u)cast<uchar>(0x1147Fu)));
 592             blocks.Add(new Block(BlockId.tirhuta"Tirhuta""Tirhuta"cast<uchar>(0x11480u)cast<uchar>(0x114DFu)));
 593             blocks.Add(new Block(BlockId.siddham"Siddham""Siddham"cast<uchar>(0x11580u)cast<uchar>(0x115FFu)));
 594             blocks.Add(new Block(BlockId.modi"Modi""Modi"cast<uchar>(0x11600u)cast<uchar>(0x1165Fu)));
 595             blocks.Add(new Block(BlockId.mongolianSup"Mongolian Sup""Mongolian Supplement"cast<uchar>(0x11660u)cast<uchar>(0x1167Fu)));
 596             blocks.Add(new Block(BlockId.takri"Takri""Takri"cast<uchar>(0x11680u)cast<uchar>(0x116CFu)));
 597             blocks.Add(new Block(BlockId.ahom"Ahom""Ahom"cast<uchar>(0x11700u)cast<uchar>(0x1173Fu)));
 598             blocks.Add(new Block(BlockId.dogra"Dogra""Dogra"cast<uchar>(0x11800u)cast<uchar>(0x1184Fu)));
 599             blocks.Add(new Block(BlockId.warangCiti"Warang Citi""Warang Citi"cast<uchar>(0x118A0u)cast<uchar>(0x118FFu)));
 600             blocks.Add(new Block(BlockId.nandinagari"Nandinagari""Nandinagari"cast<uchar>(0x119A0)cast<uchar>(0x119FF)));
 601             blocks.Add(new Block(BlockId.zanabazarSquare"Zanabazar Square""Zanabazar Square"cast<uchar>(0x11A00u)cast<uchar>(0x11A4FFu)));
 602             blocks.Add(new Block(BlockId.soyombo"Soyombo""Soyombo"cast<uchar>(0x11A50u)cast<uchar>(0x11AAFu)));
 603             blocks.Add(new Block(BlockId.pauCinHau"Pau Cin Hau""Pau Cin Hau"cast<uchar>(0x11AC0u)cast<uchar>(0x11AFFu)));
 604             blocks.Add(new Block(BlockId.bhaisuki"Bhaiksuki""Bhaiksuki"cast<uchar>(0x11C00u)cast<uchar>(0x11C6Fu)));
 605             blocks.Add(new Block(BlockId.marchen"Marchen""Marchen"cast<uchar>(0x11C70u)cast<uchar>(0x11CBFu)));
 606             blocks.Add(new Block(BlockId.masaramGondi"Masaram Gondi""Masaram Gondi"cast<uchar>(0x11D00)cast<uchar>(0x11D5F)));
 607             blocks.Add(new Block(BlockId.gunjalaGondi"Gunjala Gondi""Gunjala Gondi"cast<uchar>(0x11D60)cast<uchar>(0x11DAF)));
 608             blocks.Add(new Block(BlockId.makasar"Makasar""Makasar"cast<uchar>(0x11EE0)cast<uchar>(0x11EFF)));
 609             blocks.Add(new Block(BlockId.tamilSup"Tamil Sup""Tamil Sup"cast<uchar>(0x11FC0)cast<uchar>(0x11FFE)));
 610             blocks.Add(new Block(BlockId.cuneiform"Cuneiform""Cuneiform"cast<uchar>(0x12000u)cast<uchar>(0x123FFu)));
 611             blocks.Add(new Block(BlockId.cuneiformNumbers"Cuneiform Numbers""Cuneiform Numbers and Punctuation"cast<uchar>(0x12400u)cast<uchar>(0x1247Fu)));
 612             blocks.Add(new Block(BlockId.earlyDynasticCuneiform"Early Dynastic Cuneiform""Early Dynastic Cuneiform"cast<uchar>(0x12480u)cast<uchar>(0x1254Fu)));
 613             blocks.Add(new Block(BlockId.egyptianHieroglyphs"Egyptian Hieroglyphs""Egyptian Hieroglyphs"cast<uchar>(0x13000u)cast<uchar>(0x1342Fu)));
 614             blocks.Add(new Block(BlockId.egyptianHieroglyphFormatControls"Egyptian Hieroglyph Format Controls""Egyptian Hieroglyph Format Controls"cast<uchar>(0x13430)cast<uchar>(0x1343F)));
 615             blocks.Add(new Block(BlockId.anatolianHieroglyphs"Anatolian Hieroglyphs""Anatolian Hieroglyphs"cast<uchar>(0x14400u)cast<uchar>(0x1467Fu)));
 616             blocks.Add(new Block(BlockId.bamumSup"Bamum Sup""Bamum Supplement"cast<uchar>(0x16800u)cast<uchar>(0x16A3Fu)));
 617             blocks.Add(new Block(BlockId.mro"Mro""Mro"cast<uchar>(0x16A40u)cast<uchar>(0x16A6Fu)));
 618             blocks.Add(new Block(BlockId.bassaVah"Bassa Vah""Bassa Vah"cast<uchar>(0x16AD0u)cast<uchar>(0x16AFFu)));
 619             blocks.Add(new Block(BlockId.pahawhHmong"Pahawh Hmong""Pahawh Hmong"cast<uchar>(0x16B00u)cast<uchar>(0x16B8Fu)));
 620             blocks.Add(new Block(BlockId.medefaidrin"Medefaidrin""Medefaidrin"cast<uchar>(0x16E40u)cast<uchar>(0x16E9Fu)));
 621             blocks.Add(new Block(BlockId.miao"Miao""Miao"cast<uchar>(0x16F00u)cast<uchar>(0x16F9Fu)));
 622             blocks.Add(new Block(BlockId.ideographicSymbols"Ideographic Symbols""Ideographic Symbols and Punctuation"cast<uchar>(0x16FE0u)cast<uchar>(0x16FFFu)));
 623             blocks.Add(new Block(BlockId.tangut"Tangut""Tangut"cast<uchar>(0x17000u)cast<uchar>(0x187FFu)));
 624             blocks.Add(new Block(BlockId.tangutComponents"Tangut Components""Tangut Components"cast<uchar>(0x18800u)cast<uchar>(0x18AFFu)));
 625             blocks.Add(new Block(BlockId.kanaSup"Kana Sup""Kana Supplement"cast<uchar>(0x1B000u)cast<uchar>(0x1B0FFu)));
 626             blocks.Add(new Block(BlockId.kanaExtA"Kana Ext A""Kana Extended-A"cast<uchar>(0x1B100u)cast<uchar>(0x1B12Fu)));
 627             blocks.Add(new Block(BlockId.smallKanaExt"Small Kana Ext""Small Kana Extension"cast<uchar>(0x1B130)cast<uchar>(0x1B16F)));
 628             blocks.Add(new Block(BlockId.nushu"Nushu""Nushu"cast<uchar>(0x1B170u)cast<uchar>(0x1B2FFu)));
 629             blocks.Add(new Block(BlockId.duployan"Duployan""Duployan"cast<uchar>(0x1BC00u)cast<uchar>(0x1BC9Fu)));
 630             blocks.Add(new Block(BlockId.shorthandFormatControls"Shorthand Format Controls""Shorthand Format Controls"cast<uchar>(0x1BCA0u)cast<uchar>(0x1BCAFu)));
 631             blocks.Add(new Block(BlockId.byzantineMusic"Byzantine Music""Byzantine Musical Symbols"cast<uchar>(0x1D000u)cast<uchar>(0x1D0FFu)));
 632             blocks.Add(new Block(BlockId.music"Music""Musical Symbols"cast<uchar>(0x1D100u)cast<uchar>(0x1D1FFu)));
 633             blocks.Add(new Block(BlockId.ancientGreekMusic"Ancient Greek Music""Ancient Greek Musical Notation"cast<uchar>(0x1D200u)cast<uchar>(0x1D24Fu)));
 634             blocks.Add(new Block(BlockId.mayanNumerals"Mayan Numerals""Mayan Numerals"cast<uchar>(0x1D2E0u)cast<uchar>(0x1D2FFu)));
 635             blocks.Add(new Block(BlockId.taiXuanJing"Tai Xuan Jing""Tai Xuan Jing Symbols"cast<uchar>(0x1D300u)cast<uchar>(0x1D35Fu)));
 636             blocks.Add(new Block(BlockId.countingRod"Counting Rod""Counting Rod Numerals"cast<uchar>(0x1D360u)cast<uchar>(0x1D37Fu)));
 637             blocks.Add(new Block(BlockId.mathAlphanum"Math Alphanum""Mathematical Alphanumeric Symbols"cast<uchar>(0x1D400u)cast<uchar>(0x1D7FFu)));
 638             blocks.Add(new Block(BlockId.suttonSignWriting"Sutton SignWriting""Sutton SignWriting"cast<uchar>(0x1D800u)cast<uchar>(0x1DAAFu)));
 639             blocks.Add(new Block(BlockId.glagoliticSup"Glagolitic Sup""Glagolitic Supplement"cast<uchar>(0x1E000u)cast<uchar>(0x1E02Fu)));
 640             blocks.Add(new Block(BlockId.nyiakengPuachueHmong"Nyiakeng Puachue Hmong""Nyiakeng Puachue Hmong"cast<uchar>(0x1E100)cast<uchar>(0x1E14F)));
 641             blocks.Add(new Block(BlockId.wancho"Wancho""Wancho"cast<uchar>(0x1E2C0)cast<uchar>(0x1E2FF)));
 642             blocks.Add(new Block(BlockId.mendeKikakui"Mende Kikakui""Mende Kikakui"cast<uchar>(0x1E800u)cast<uchar>(0x1E8DFu)));
 643             blocks.Add(new Block(BlockId.adlam"Adlam""Adlam"cast<uchar>(0x1E900u)cast<uchar>(0x1E95Fu)));
 644             blocks.Add(new Block(BlockId.indicSiyaqNumbers"Indic Siyaq Numbers""Indic Siyaq Numbers"cast<uchar>(0x1EC70)cast<uchar>(0x1ECBF)));
 645             blocks.Add(new Block(BlockId.ottomanSiyaqNumbers"Ottoman Siyaq Numbers""Ottoman Siyaq Numbers"cast<uchar>(0x1ED00)cast<uchar>(0x1ED4F)));
 646             blocks.Add(new Block(BlockId.arabicMath"Arabic Math""Arabic Mathematical Alphabetic Symbols"cast<uchar>(0x1EE00u)cast<uchar>(0x1EEFFu)));
 647             blocks.Add(new Block(BlockId.mahjong"Mahjong""Mahjong Tiles"cast<uchar>(0x1F000u)cast<uchar>(0x1F02Fu)));
 648             blocks.Add(new Block(BlockId.domino"Domino""Domino Tiles"cast<uchar>(0x1F030u)cast<uchar>(0x1F09Fu)));
 649             blocks.Add(new Block(BlockId.playingCards"Playing Cards""Playing Cards"cast<uchar>(0x1F0A0u)cast<uchar>(0x1F0FFu)));
 650             blocks.Add(new Block(BlockId.enclosedAlphanumSup"Enclosed Alphanum Sup""Enclosed Alphanumeric Supplement"cast<uchar>(0x1F100u)cast<uchar>(0x1F1FFu)));
 651             blocks.Add(new Block(BlockId.enclosedIdeographicSup"Enclosed Ideographic Sup""Enclosed Ideographic Supplement"cast<uchar>(0x1F200u)cast<uchar>(0x1F2FFu)));
 652             blocks.Add(new Block(BlockId.miscPictographs"Misc Pictographs""Miscellaneous Symbols and Pictographs"cast<uchar>(0x1F300u)cast<uchar>(0x1F5FFu)));
 653             blocks.Add(new Block(BlockId.emoticons"Emoticons""Emoticons"cast<uchar>(0x1F600u)cast<uchar>(0x1F64Fu)));
 654             blocks.Add(new Block(BlockId.ornamentalDingbats"Ornamental Dingbats""Ornamental Dingbats"cast<uchar>(0x1F650u)cast<uchar>(0x1F67Fu)));
 655             blocks.Add(new Block(BlockId.transportAndMap"Transport And Map""Transport and Map Symbols"cast<uchar>(0x1F680u)cast<uchar>(0x1F6FFu)));
 656             blocks.Add(new Block(BlockId.alchemical"Alchemical""Alchemical Symbols"cast<uchar>(0x1F700u)cast<uchar>(0x1F77Fu)));
 657             blocks.Add(new Block(BlockId.geometricShapesExt"Geometric Shapes Ext""Geometric Shapes Extended"cast<uchar>(0x1F780u)cast<uchar>(0x1F7FFu)));
 658             blocks.Add(new Block(BlockId.supArrowsC"Sup Arrows C""Supplemental Arrows-C"cast<uchar>(0x1F800u)cast<uchar>(0x1F8FFu)));
 659             blocks.Add(new Block(BlockId.supSymbolsAndPictographs"Sup Symbols And Pictographs""Supplemental Symbols and Pictographs"cast<uchar>(0x1F900u)cast<uchar>(0x1F9FFu)));
 660             blocks.Add(new Block(BlockId.chessSymbols"Chess Symbols""Chess Symbols"cast<uchar>(0x1FA00u)cast<uchar>(0x1FA6Fu)));
 661             blocks.Add(new Block(BlockId.symbolsAndPictographsExtA"Symbols And Pictographs Ext A""Symbols And Pictographs Extended A"cast<uchar>(0x1FA70)cast<uchar>(0x1FAFF)));
 662             blocks.Add(new Block(BlockId.cjkExtB"CJK Ext B""CJK Unified Ideographs Extension B"cast<uchar>(0x20000u)cast<uchar>(0x2A6DFu)));
 663             blocks.Add(new Block(BlockId.cjkExtC"CJK Ext C""CJK Unified Ideographs Extension C"cast<uchar>(0x2A700u)cast<uchar>(0x2B73Fu)));
 664             blocks.Add(new Block(BlockId.cjkExtD"CJK Ext D""CJK Unified Ideographs Extension D"cast<uchar>(0x2B740u)cast<uchar>(0x2B81Fu)));
 665             blocks.Add(new Block(BlockId.cjkExtE"CJK Ext E""CJK Unified Ideographs Extension E"cast<uchar>(0x2B820u)cast<uchar>(0x2CEAFu)));
 666             blocks.Add(new Block(BlockId.cjkExtF"CJK Ext F""CJK Unified Ideographs Extension F"cast<uchar>(0x2CEB0u)cast<uchar>(0x2EBEFu)));
 667             blocks.Add(new Block(BlockId.cjkCompatIdeographsSup"CJK Compat Ideographs Sup""CJK Compatibility Ideographs Supplement"cast<uchar>(0x2F800u)cast<uchar>(0x2FA1Fu)));
 668             blocks.Add(new Block(BlockId.tags"Tags""Tags"cast<uchar>(0xE0000u)cast<uchar>(0xE007Fu)));
 669             blocks.Add(new Block(BlockId.vsSup"VS Sup""Variation Selectors Supplement"cast<uchar>(0xE0100u)cast<uchar>(0xE01EFu)));
 670             blocks.Add(new Block(BlockId.supPuaA"Sup PUA A""Supplementary Private Use Area-A"cast<uchar>(0xF0000u)cast<uchar>(0xFFFFFu)));
 671             blocks.Add(new Block(BlockId.supPuaB"Sup PUA B""Supplementary Private Use Area-B"cast<uchar>(0x100000u)cast<uchar>(0x10FFFFu)));
 672             for (Block* block : blocks)
 673             {
 674                 blockIdMap[cast<uint>(cast<ushort>(block->Id()))] = block;
 675                 shortNameMap[MakeCanonicalPropertyName(block->ShortName())] = block;
 676                 longNameMap[MakeCanonicalPropertyName(block->LongName())] = block;
 677             }
 678         }
 679         public ~BlockTable()
 680         {
 681             for (Block* block : blocks)
 682             {
 683                 delete block;
 684             }
 685         }
 686         private static UniquePtr<BlockTable> instance;
 687         private List<Block*> blocks;
 688         private HashMap<uintvoid*> blockIdMap;
 689         private HashMap<stringvoid*> shortNameMap;
 690         private HashMap<stringvoid*> longNameMap;
 691     }
 692     
 693     public const Block* GetBlock(BlockId id)
 694     {
 695         return BlockTable.Instance().GetBlock(id);
 696     }
 697 
 698     public const Block* GetBlockByShortName(const string& shortName)
 699     {
 700         return BlockTable.Instance().GetBlockByShortName(shortName);
 701     }
 702 
 703     public const Block* GetBlockByLongName(const string& longName)
 704     {
 705         return BlockTable.Instance().GetBlockByLongName(longName);
 706     }
 707 
 708     public enum GeneralCategoryId : uint
 709     {
 710         none = 0u
 711         Lu = 1u << 0uLl = 1u << 1uLt = 1u << 2uLm = 1u << 3uLo = 1u << 4u
 712         LC = Lu | Ll | Lt
 713         L = Lu | Ll | Lt | Lm | Lo
 714         Mn = 1u << 5uMc = 1u << 6uMe = 1u << 7u
 715         M = Mn | Mc | Me
 716         Nd = 1u << 8uNl = 1u << 9uNo = 1u << 10u
 717         N = Nd | Nl | No
 718         Pc = 1u << 11uPd = 1u << 12uPs = 1u << 13uPe = 1u << 14uPi = 1u << 15uPf = 1u << 16uPo = 1u << 17u
 719         P = Pc | Pd | Ps | Pe | Pi | Pf | Po
 720         Sm = 1u << 18uSc = 1u << 19uSk = 1u << 20uSo = 1u << 21u
 721         S = Sm | Sc | Sk | So
 722         Zs = 1u << 22uZl = 1u << 23uZp = 1u << 24u
 723         Z = Zs | Zl | Zp
 724         Cc = 1u << 25uCf = 1u << 26uCs = 1u << 27uCo = 1u << 28uCn = 1u << 29u
 725         C = Cc | Cf | Cs | Co | Cn
 726         G = L | M | N | P | S | Zs
 727         B = L | N | P | S | Zs
 728     }
 729 
 730     public class GeneralCategory
 731     {
 732         public nothrow GeneralCategory(GeneralCategoryId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
 733         {
 734         }
 735         public inline nothrow GeneralCategoryId Id()
 736         {
 737             return id;
 738         }
 739         public inline nothrow const string& ShortName()
 740         {
 741             return shortName;
 742         }
 743         public inline nothrow const string& LongName()
 744         {
 745             return longName;
 746         }
 747         private GeneralCategoryId id;
 748         private string shortName;
 749         private string longName;
 750     }
 751 
 752     public class GeneralCategoryTable
 753     {
 754         static GeneralCategoryTable() : instance(new GeneralCategoryTable())
 755         {
 756         }
 757         public static GeneralCategoryTable& Instance()
 758         {
 759             return *instance;
 760         }
 761         public nothrow const GeneralCategory* GetGeneralCategory(GeneralCategoryId id) const
 762         {
 763             HashMap<uintvoid*>.ConstIterator it = generalCategoryIdMap.CFind(cast<uint>(id));
 764             if (it != generalCategoryIdMap.CEnd())
 765             {
 766                 return cast<GeneralCategory*>(it->second);
 767             }
 768             return null;
 769         }
 770         public const GeneralCategory* GetGeneralCategoryByShortName(const string& shortName) const
 771         {
 772             HashMap<stringvoid*>.ConstIterator it = shortNameMap.CFind(MakeCanonicalPropertyName(shortName));
 773             if (it != shortNameMap.CEnd())
 774             {
 775                 return cast<GeneralCategory*>(it->second);
 776             }
 777             return null;
 778         }
 779         public const GeneralCategory* GetGeneralCategoryByLongName(const string& longName) const
 780         {
 781             HashMap<stringvoid*>.ConstIterator it = longNameMap.CFind(MakeCanonicalPropertyName(longName));
 782             if (it != longNameMap.CEnd())
 783             {
 784                 return cast<GeneralCategory*>(it->second);
 785             }
 786             return null;
 787         }
 788         private GeneralCategoryTable() : generalCategories()generalCategoryIdMap()shortNameMap()longNameMap()
 789         {
 790             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lu"Lu""Uppercase Letter"));
 791             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lu"Ll""Lowercase Letter"));
 792             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lt"Lt""Titlecase Letter"));
 793             generalCategories.Add(new GeneralCategory(GeneralCategoryId.LC"LC""Cased Letter"));
 794             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lm"Lm""Modifier Letter"));
 795             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lo"Lo""Other Letter"));
 796             generalCategories.Add(new GeneralCategory(GeneralCategoryId.L"L""Letter"));
 797             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Mn"Mn""Nonspacing Mark"));
 798             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Mc"Mc""Spacing Mark"));
 799             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Me"Me""Enclosing Mark"));
 800             generalCategories.Add(new GeneralCategory(GeneralCategoryId.M"M""Mark"));
 801             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Nd"Nd""Decimal Number"));
 802             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Nl"Nl""Letter Number"));
 803             generalCategories.Add(new GeneralCategory(GeneralCategoryId.No"No""Other Number"));
 804             generalCategories.Add(new GeneralCategory(GeneralCategoryId.N"N""Number"));
 805             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pc"Pc""Connector Punctuation"));
 806             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pd"Pd""Dash Punctuation"));
 807             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Ps"Ps""Open Punctuation"));
 808             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pe"Pe""Close Punctuation"));
 809             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pi"Pi""Initial Punctuation"));
 810             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pf"Pf""Final Punctuation"));
 811             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Po"Po""Other Punctuation"));
 812             generalCategories.Add(new GeneralCategory(GeneralCategoryId.P"P""Punctuation"));
 813             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Sm"Sm""Math Symbol"));
 814             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Sc"Sc""Currency Symbol"));
 815             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Sk"Sk""Modifier Symbol"));
 816             generalCategories.Add(new GeneralCategory(GeneralCategoryId.So"So""Other Symbol"));
 817             generalCategories.Add(new GeneralCategory(GeneralCategoryId.S"S""Symbol"));
 818             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Zs"Zs""Space Separator"));
 819             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Zl"Zl""Line Separator"));
 820             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Zp"Zp""Paragraph Separator"));
 821             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Z"Z""Separator"));
 822             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cc"Cc""Control"));
 823             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cf"Cf""Format"));
 824             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cs"Cs""Surrogate"));
 825             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Co"Co""Private Use"));
 826             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cn"Cn""Unassigned"));
 827             generalCategories.Add(new GeneralCategory(GeneralCategoryId.C"C""Other"));
 828             generalCategories.Add(new GeneralCategory(GeneralCategoryId.G"G""Graphic"));
 829             generalCategories.Add(new GeneralCategory(GeneralCategoryId.B"B""Base"));
 830             for (GeneralCategory* generalCategory : generalCategories)
 831             {
 832                 generalCategoryIdMap[generalCategory->Id()] = generalCategory;
 833                 shortNameMap[MakeCanonicalPropertyName(generalCategory->ShortName())] = generalCategory;
 834                 longNameMap[MakeCanonicalPropertyName(generalCategory->LongName())] = generalCategory;
 835             }
 836         }
 837         public ~GeneralCategoryTable()
 838         {
 839             for (GeneralCategory* generalCategory : generalCategories)
 840             {
 841                 delete generalCategory;
 842             }
 843         }
 844         private static UniquePtr<GeneralCategoryTable> instance;
 845         private List<GeneralCategory*> generalCategories;
 846         private HashMap<uintvoid*> generalCategoryIdMap;
 847         private HashMap<stringvoid*> shortNameMap;
 848         private HashMap<stringvoid*> longNameMap;
 849     }
 850 
 851     public const GeneralCategory* GetGeneralCategory(GeneralCategoryId id)
 852     {
 853         return GeneralCategoryTable.Instance().GetGeneralCategory(id);
 854     }
 855     
 856     public const GeneralCategory* GetGeneralCategoryByShortName(const string& shortName)
 857     {
 858         return GeneralCategoryTable.Instance().GetGeneralCategoryByShortName(shortName);
 859     }
 860     
 861     public const GeneralCategory* GetGeneralCategoryByLongName(const string& longName)
 862     {
 863         return GeneralCategoryTable.Instance().GetGeneralCategoryByLongName(longName);
 864     }
 865     
 866     public enum AgeId : byte
 867     {
 868         age_unassigned = 0u
 869         age_1_1
 870         age_2_0age_2_1
 871         age_3_0age_3_1age_3_2
 872         age_4_0age_4_1
 873         age_5_0age_5_1age_5_2
 874         age_6_0age_6_1age_6_2age_6_3
 875         age_7_0
 876         age_8_0
 877         age_9_0
 878         age_10_0
 879         age_11_0
 880         age_12_0age_12_1
 881     }
 882 
 883     public class Age
 884     {
 885         public nothrow Age(AgeId id_const string& version_) : id(id_)version(version_)
 886         {
 887         }
 888         public inline nothrow AgeId Id() const
 889         {
 890             return id;
 891         }
 892         public inline nothrow const string& Version() const
 893         {
 894             return version;
 895         }
 896         private AgeId id;
 897         private string version;
 898     }
 899 
 900     public class AgeTable
 901     {
 902         static AgeTable() : instance(new AgeTable())
 903         {
 904         }
 905         public static AgeTable& Instance()
 906         {
 907             return *instance;
 908         }
 909         public const Age* GetAge(AgeId id) const
 910         {
 911             HashMap<uintvoid*>.ConstIterator it = ageIdMap.CFind(cast<uint>(cast<byte>(id)));
 912             if (it != ageIdMap.CEnd())
 913             {
 914                 return cast<Age*>(it->second);
 915             }
 916             return null;
 917         }
 918         public const Age* GetAge(const string& version) const
 919         {
 920             HashMap<stringvoid*>.ConstIterator it = versionMap.CFind(version);
 921             if (it != versionMap.CEnd())
 922             {
 923                 return cast<Age*>(it->second);
 924             }
 925             return null;
 926         }
 927         private AgeTable() : ages()ageIdMap()versionMap()
 928         {
 929             ages.Add(new Age(AgeId.age_1_1"1.1"));
 930             ages.Add(new Age(AgeId.age_2_0"2.0"));
 931             ages.Add(new Age(AgeId.age_2_1"2.1"));
 932             ages.Add(new Age(AgeId.age_3_0"3.0"));
 933             ages.Add(new Age(AgeId.age_3_1"3.1"));
 934             ages.Add(new Age(AgeId.age_3_2"3.2"));
 935             ages.Add(new Age(AgeId.age_4_0"4.0"));
 936             ages.Add(new Age(AgeId.age_4_1"4.1"));
 937             ages.Add(new Age(AgeId.age_5_0"5.0"));
 938             ages.Add(new Age(AgeId.age_5_1"5.1"));
 939             ages.Add(new Age(AgeId.age_5_2"5.2"));
 940             ages.Add(new Age(AgeId.age_6_0"6.0"));
 941             ages.Add(new Age(AgeId.age_6_1"6.1"));
 942             ages.Add(new Age(AgeId.age_6_2"6.2"));
 943             ages.Add(new Age(AgeId.age_6_3"6.3"));
 944             ages.Add(new Age(AgeId.age_7_0"7.0"));
 945             ages.Add(new Age(AgeId.age_8_0"8.0"));
 946             ages.Add(new Age(AgeId.age_9_0"9.0"));
 947             ages.Add(new Age(AgeId.age_10_0"10.0"));
 948             ages.Add(new Age(AgeId.age_11_0"11.0"));
 949             ages.Add(new Age(AgeId.age_12_0"12.0"));
 950             ages.Add(new Age(AgeId.age_12_1"12.1"));
 951             for (Age* age : ages)
 952             {
 953                 ageIdMap[cast<uint>(cast<byte>(age->Id()))] = age;
 954                 versionMap[age->Version()] = age;
 955             }
 956         }
 957         public ~AgeTable()
 958         {
 959             for (Age* age : ages)
 960             {
 961                 delete age;
 962             }
 963         }
 964         private static UniquePtr<AgeTable> instance;
 965         private List<Age*> ages;
 966         private HashMap<uintvoid*> ageIdMap;
 967         private HashMap<stringvoid*> versionMap;
 968     }
 969 
 970     public const Age* GetAge(AgeId id)
 971     {
 972         return AgeTable.Instance().GetAge(id);
 973     }
 974 
 975     public const Age* GetAge(const string& version)
 976     {
 977         return AgeTable.Instance().GetAge(version);
 978     }
 979 
 980     public enum ScriptId : byte
 981     {
 982         none = 0u
 983         adlmaghbahomarabarmiarmnavst
 984         balibamubassbatkbengbhksbopobrahbraibugibuhd
 985         cakmcanscarichamchercoptcprtcyrl
 986         devadogrdsrtdupl
 987         elbaelymegypethi
 988         georglaggonggonmgothgrangrekgujrguru
 989         hanghanihanohatrhebrhirahluwhmnghmnphrkthung
 990         ital
 991         java
 992         kalikanakharkhmrkhojkndakthi
 993         lanalaoolatnlepclimblinalinblisulycilydi
 994         mahjmakamandmanimarcmedfmendmercmeromlymmodimongmroomteimultmymr
 995         nandnarbnbatnewankoonshu
 996         ogamolckorkhoryaosgeosma
 997         palmpaucpermphagphliphlpphnxplrdprti
 998         qaai
 999         rjngrohgrunr
1000         samrsarbsaursgnwshawshrdsiddsindsinhsogdsogosorasoyosundsylosyrc
1001         tagbtakrtaletalutamltangtavttelutfngtglgthaathaitibttirh
1002         ugar
1003         vaii
1004         wara
1005         wcho
1006         xpeoxsux
1007         yiiizanb
1008         zinhzyyyzzzz
1009     }
1010     
1011     public class Script
1012     {
1013         public nothrow Script(ScriptId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
1014         {
1015         }
1016         public inline nothrow ScriptId Id() const
1017         {
1018             return id;
1019         }
1020         public inline nothrow const string& ShortName() const
1021         {
1022             return shortName;
1023         }
1024         public inline nothrow const string& LongName() const
1025         {
1026             return longName;
1027         }
1028         private ScriptId id;
1029         private string shortName;
1030         private string longName;
1031     }
1032     
1033     public class ScriptTable
1034     {
1035         static ScriptTable() : instance(new ScriptTable())
1036         {
1037         }
1038         public static ScriptTable& Instance()
1039         {
1040             return *instance;
1041         }
1042         public const Script* GetScript(ScriptId id) const
1043         {
1044             HashMap<uintvoid*>.ConstIterator it = scriptIdMap.CFind(cast<uint>(cast<byte>(id)));
1045             if (it != scriptIdMap.CEnd())
1046             {
1047                 return cast<Script*>(it->second);
1048             }
1049             return null;
1050         }
1051         public const Script* GetScriptByShortName(const string& shortName) const
1052         {
1053             HashMap<stringvoid*>.ConstIterator it = shortNameMap.CFind(MakeCanonicalPropertyName(shortName));
1054             if (it != shortNameMap.CEnd())
1055             {
1056                 return cast<Script*>(it->second);
1057             }
1058             return null;
1059         }
1060         public const Script* GetScriptByLongName(const string& longName) const
1061         {
1062             HashMap<stringvoid*>.ConstIterator it = longNameMap.CFind(MakeCanonicalPropertyName(longName));
1063             if (it != longNameMap.CEnd())
1064             {
1065                 return cast<Script*>(it->second);
1066             }
1067             return null;
1068         }
1069         private ScriptTable() : scripts()scriptIdMap()shortNameMap()longNameMap()
1070         {
1071             scripts.Add(new Script(ScriptId.adlm"Adlm""Adlam"));
1072             scripts.Add(new Script(ScriptId.aghb"Aghb""Caucasian Albanian"));
1073             scripts.Add(new Script(ScriptId.ahom"Ahom""Ahom"));
1074             scripts.Add(new Script(ScriptId.arab"Arab""Arabic"));
1075             scripts.Add(new Script(ScriptId.armi"Armi""Imperial Aramaic"));
1076             scripts.Add(new Script(ScriptId.armn"Armn""Armenian"));
1077             scripts.Add(new Script(ScriptId.avst"Avst""Avestan"));
1078             scripts.Add(new Script(ScriptId.bali"Bali""Balinese"));
1079             scripts.Add(new Script(ScriptId.bamu"Bamu""Bamum"));
1080             scripts.Add(new Script(ScriptId.bass"Bass""Bassa Vah"));
1081             scripts.Add(new Script(ScriptId.batk"Batk""Batak"));
1082             scripts.Add(new Script(ScriptId.beng"Beng""Bengali"));
1083             scripts.Add(new Script(ScriptId.bhks"Bhks""Bhaisuki"));
1084             scripts.Add(new Script(ScriptId.bopo"Bopo""Bopomofo"));
1085             scripts.Add(new Script(ScriptId.brah"Brah""Brahmi"));
1086             scripts.Add(new Script(ScriptId.brai"Brai""Braille"));
1087             scripts.Add(new Script(ScriptId.bugi"Bugi""Buginese"));
1088             scripts.Add(new Script(ScriptId.buhd"Buhd""Buhid"));
1089             scripts.Add(new Script(ScriptId.cakm"Cakm""Chakma"));
1090             scripts.Add(new Script(ScriptId.cans"Cans""Canadian Aboriginal"));
1091             scripts.Add(new Script(ScriptId.cari"Cari""Carian"));
1092             scripts.Add(new Script(ScriptId.cham"Cham""Cham"));
1093             scripts.Add(new Script(ScriptId.cher"Cher""Cherokee"));
1094             scripts.Add(new Script(ScriptId.copt"Copt""Coptic"));
1095             scripts.Add(new Script(ScriptId.cprt"Cprt""Cypriot"));
1096             scripts.Add(new Script(ScriptId.cyrl"Cyrl""Cyrillic"));
1097             scripts.Add(new Script(ScriptId.deva"Deva""Devanagari"));
1098             scripts.Add(new Script(ScriptId.dogr"Dogr""Dogra"));
1099             scripts.Add(new Script(ScriptId.dsrt"Dsrt""Deseret"));
1100             scripts.Add(new Script(ScriptId.dupl"Dupl""Duployan"));
1101             scripts.Add(new Script(ScriptId.egyp"Egyp""Egyptian Hieroglyphs"));
1102             scripts.Add(new Script(ScriptId.elba"Elba""Elbasan"));
1103             scripts.Add(new Script(ScriptId.elym"Elym""Elymaic"));
1104             scripts.Add(new Script(ScriptId.ethi"Ethi""Ethiopian"));
1105             scripts.Add(new Script(ScriptId.geor"Geor""Georgian"));
1106             scripts.Add(new Script(ScriptId.glag"Glag""Glagolitic"));
1107             scripts.Add(new Script(ScriptId.gong"Gong""Gunjala Gondi"));
1108             scripts.Add(new Script(ScriptId.gonm"Gonm""Masaram Gondi"));
1109             scripts.Add(new Script(ScriptId.goth"Goth""Gothic"));
1110             scripts.Add(new Script(ScriptId.gran"Gran""Grantha"));
1111             scripts.Add(new Script(ScriptId.grek"Grek""Greek"));
1112             scripts.Add(new Script(ScriptId.gujr"Gujr""Gujarati"));
1113             scripts.Add(new Script(ScriptId.guru"Guru""Gurmukhi"));
1114             scripts.Add(new Script(ScriptId.hang"Hang""Hangul"));
1115             scripts.Add(new Script(ScriptId.hani"Hani""Han"));
1116             scripts.Add(new Script(ScriptId.hano"Hano""Hanunoo"));
1117             scripts.Add(new Script(ScriptId.hatr"Hatr""Hatran"));
1118             scripts.Add(new Script(ScriptId.hebr"Hebr""Hebrew"));
1119             scripts.Add(new Script(ScriptId.hira"Hira""Hiragana"));
1120             scripts.Add(new Script(ScriptId.hluw"Hluw""Anatolian Hieroglyphs"));
1121             scripts.Add(new Script(ScriptId.hmng"Hmng""Pahawh Hmong"));
1122             scripts.Add(new Script(ScriptId.hmnp"Hmnp""Nyiakeng Puachue Hmong"));
1123             scripts.Add(new Script(ScriptId.hrkt"Hrkt""Katakana Or Hiragana"));
1124             scripts.Add(new Script(ScriptId.hung"Hung""Old Hungarian"));
1125             scripts.Add(new Script(ScriptId.ital"Ital""Old Italic"));
1126             scripts.Add(new Script(ScriptId.java"Java""Javanese"));
1127             scripts.Add(new Script(ScriptId.kali"Kali""Kayah Li"));
1128             scripts.Add(new Script(ScriptId.kana"Kana""Katakana"));
1129             scripts.Add(new Script(ScriptId.khar"Khar""Kharoshthi"));
1130             scripts.Add(new Script(ScriptId.khmr"Khmr""Khmer"));
1131             scripts.Add(new Script(ScriptId.khoj"Khoj""Khojki"));
1132             scripts.Add(new Script(ScriptId.knda"Knda""Kannada"));
1133             scripts.Add(new Script(ScriptId.kthi"Kthi""Kaithi"));
1134             scripts.Add(new Script(ScriptId.lana"Lana""Tai Tham"));
1135             scripts.Add(new Script(ScriptId.laoo"Laoo""Lao"));
1136             scripts.Add(new Script(ScriptId.latn"Latn""Latin"));
1137             scripts.Add(new Script(ScriptId.lepc"Lepc""Lepcha"));
1138             scripts.Add(new Script(ScriptId.limb"Limb""Limbu"));
1139             scripts.Add(new Script(ScriptId.lina"Lina""Linear A"));
1140             scripts.Add(new Script(ScriptId.linb"Linb""Linear B"));
1141             scripts.Add(new Script(ScriptId.lisu"Lisu""Lisu"));
1142             scripts.Add(new Script(ScriptId.lyci"Lyci""Lycian"));
1143             scripts.Add(new Script(ScriptId.lydi"Lydi""Lydian"));
1144             scripts.Add(new Script(ScriptId.mahj"Mahj""Mahajani"));
1145             scripts.Add(new Script(ScriptId.maka"Maka""Makasar"));
1146             scripts.Add(new Script(ScriptId.mand"Mand""Mandaic"));
1147             scripts.Add(new Script(ScriptId.mani"Mani""Manichaean"));
1148             scripts.Add(new Script(ScriptId.marc"Marc""Marchen"));
1149             scripts.Add(new Script(ScriptId.medf"Medf""Medefaidrin"));
1150             scripts.Add(new Script(ScriptId.mend"Mend""Mende Kikakui"));
1151             scripts.Add(new Script(ScriptId.merc"Merc""Meroitic Cursive"));
1152             scripts.Add(new Script(ScriptId.mero"Mero""Meroitic Hieroglyphs"));
1153             scripts.Add(new Script(ScriptId.mlym"Mlym""Malayalam"));
1154             scripts.Add(new Script(ScriptId.modi"Modi""Modi"));
1155             scripts.Add(new Script(ScriptId.mong"Mong""Mongolian"));
1156             scripts.Add(new Script(ScriptId.mroo"Mroo""Mro"));
1157             scripts.Add(new Script(ScriptId.mtei"Mtei""Meetei Mayak"));
1158             scripts.Add(new Script(ScriptId.mult"Mult""Multani"));
1159             scripts.Add(new Script(ScriptId.mymr"Mymr""Myanmar"));
1160             scripts.Add(new Script(ScriptId.nand"Nand""Nandinagari"));
1161             scripts.Add(new Script(ScriptId.narb"Narb""Old North Arabian"));
1162             scripts.Add(new Script(ScriptId.nbat"Nbat""Nabataean"));
1163             scripts.Add(new Script(ScriptId.newa"Newa""Newa"));
1164             scripts.Add(new Script(ScriptId.nkoo"Nkoo""Nko"));
1165             scripts.Add(new Script(ScriptId.nshu"Nshu""Nushu"));
1166             scripts.Add(new Script(ScriptId.ogam"Ogam""Ogham"));
1167             scripts.Add(new Script(ScriptId.olck"Olck""Ol Chiki"));
1168             scripts.Add(new Script(ScriptId.orkh"Orkh""Old Turkic"));
1169             scripts.Add(new Script(ScriptId.orya"Orya""Oriya"));
1170             scripts.Add(new Script(ScriptId.osge"Osge""Osage"));
1171             scripts.Add(new Script(ScriptId.osma"Osma""Osmanya"));
1172             scripts.Add(new Script(ScriptId.palm"Palm""Palmyrene"));
1173             scripts.Add(new Script(ScriptId.pauc"Pauc""Pau Cin Hau"));
1174             scripts.Add(new Script(ScriptId.perm"Perm""Old Permic"));
1175             scripts.Add(new Script(ScriptId.phag"Phag""Phags Pa"));
1176             scripts.Add(new Script(ScriptId.phli"Phli""Inscriptional Pahlavi"));
1177             scripts.Add(new Script(ScriptId.phlp"Phlp""Psalter Pahlavi"));
1178             scripts.Add(new Script(ScriptId.phnx"Phnx""Phoenician"));
1179             scripts.Add(new Script(ScriptId.plrd"Plrd""Miao"));
1180             scripts.Add(new Script(ScriptId.prti"Prti""Inscriptional Parthian"));
1181             scripts.Add(new Script(ScriptId.rjng"Rjng""Rejang"));
1182             scripts.Add(new Script(ScriptId.rohg"Rohg""Hanifi Rohingya"));
1183             scripts.Add(new Script(ScriptId.runr"Runr""Runic"));
1184             scripts.Add(new Script(ScriptId.samr"Samr""Samaritan"));
1185             scripts.Add(new Script(ScriptId.sarb"Sarb""Old South Arabian"));
1186             scripts.Add(new Script(ScriptId.saur"Saur""Saurashtra"));
1187             scripts.Add(new Script(ScriptId.sgnw"Sgnw""SignWriting"));
1188             scripts.Add(new Script(ScriptId.shaw"Shaw""Shawian"));
1189             scripts.Add(new Script(ScriptId.shrd"Shrd""Sharada"));
1190             scripts.Add(new Script(ScriptId.sidd"Sidd""Shiddham"));
1191             scripts.Add(new Script(ScriptId.sind"Sind""Khudawadi"));
1192             scripts.Add(new Script(ScriptId.sinh"Sinh""Sinhala"));
1193             scripts.Add(new Script(ScriptId.sogd"Sogd""Sogdian"));
1194             scripts.Add(new Script(ScriptId.sogo"Sogo""Old Sogdian"));
1195             scripts.Add(new Script(ScriptId.sora"Sora""Sora Sompeng"));
1196             scripts.Add(new Script(ScriptId.soyo"Soyo""Soyombo"));
1197             scripts.Add(new Script(ScriptId.sund"Sund""Sundanese"));
1198             scripts.Add(new Script(ScriptId.sylo"Sylo""Syloti Nagri"));
1199             scripts.Add(new Script(ScriptId.syrc"Syrc""Syriac"));
1200             scripts.Add(new Script(ScriptId.tagb"Tagb""Tagbanwa"));
1201             scripts.Add(new Script(ScriptId.takr"Takr""Takri"));
1202             scripts.Add(new Script(ScriptId.tale"Tale""Tai Le"));
1203             scripts.Add(new Script(ScriptId.talu"Talu""New Tai Lue"));
1204             scripts.Add(new Script(ScriptId.taml"Taml""Tamil"));
1205             scripts.Add(new Script(ScriptId.tang"Tang""Tangut"));
1206             scripts.Add(new Script(ScriptId.tavt"Tavt""Tai Viet"));
1207             scripts.Add(new Script(ScriptId.telu"Telu""Telugu"));
1208             scripts.Add(new Script(ScriptId.tfng"Tfng""Tifinag"));
1209             scripts.Add(new Script(ScriptId.tglg"Tglg""Tagalog"));
1210             scripts.Add(new Script(ScriptId.thaa"Thaa""Thaana"));
1211             scripts.Add(new Script(ScriptId.thai"Thai""Thai"));
1212             scripts.Add(new Script(ScriptId.tibt"Tibt""Tibetan"));
1213             scripts.Add(new Script(ScriptId.tirh"Tirh""Tirhuta"));
1214             scripts.Add(new Script(ScriptId.ugar"Ugar""Ugaritic"));
1215             scripts.Add(new Script(ScriptId.vaii"Vaii""Vai"));
1216             scripts.Add(new Script(ScriptId.wara"Wara""Warang Citi"));
1217             scripts.Add(new Script(ScriptId.wcho"Wcho""Wcho"));
1218             scripts.Add(new Script(ScriptId.xpeo"Xpeo""Old Persian"));
1219             scripts.Add(new Script(ScriptId.xsux"Xsux""Cuneiform"));
1220             scripts.Add(new Script(ScriptId.yiii"Yiii""Yi"));
1221             scripts.Add(new Script(ScriptId.zanb"Zanb""Zanabazar Square"));
1222             scripts.Add(new Script(ScriptId.zinh"Zinh""Inherited"));
1223             scripts.Add(new Script(ScriptId.zyyy"Zyyy""Common"));
1224             scripts.Add(new Script(ScriptId.zzzz"Zzzz""Unknown"));
1225             for (Script* script : scripts)
1226             {
1227                 scriptIdMap[cast<uint>(cast<byte>(script->Id()))] = script;
1228                 shortNameMap[MakeCanonicalPropertyName(script->ShortName())] = script;
1229                 longNameMap[MakeCanonicalPropertyName(script->LongName())] = script;
1230             }
1231         }
1232         public ~ScriptTable()
1233         {
1234             for (Script* script : scripts)
1235             {
1236                 delete script;
1237             }
1238         }
1239         private static UniquePtr<ScriptTable> instance;
1240         private List<Script*> scripts;
1241         private HashMap<uintvoid*> scriptIdMap;
1242         private HashMap<stringvoid*> shortNameMap;
1243         private HashMap<stringvoid*> longNameMap;
1244     }
1245 
1246     public const Script* GetScript(ScriptId id)
1247     {
1248         return ScriptTable.Instance().GetScript(id);
1249     }
1250 
1251     public const Script* GetScriptByShortName(const string& shortName)
1252     {
1253         return ScriptTable.Instance().GetScriptByShortName(shortName);
1254     }
1255 
1256     public const Script* GetScriptByLongName(const string& longName)
1257     {
1258         return ScriptTable.Instance().GetScriptByLongName(longName);
1259     }
1260     
1261     public class CharacterInfo
1262     {
1263         public nothrow CharacterInfo() : 
1264             binaryProperties(0u)generalCategory(GeneralCategoryId.none)upper(cast<uchar>(0u))lower(cast<uchar>(0u))title(cast<uchar>(0u))
1265             folding(cast<uchar>(0u))block(BlockId.none)age(AgeId.age_unassigned)script(ScriptId.none)
1266         {
1267         }
1268         public inline nothrow bool GetBinaryProperty(BinaryPropertyId binaryPropertyId) const
1269         {
1270             ulong mask = cast<ulong>(1u) << cast<ulong>(cast<byte>(binaryPropertyId));
1271             return (binaryProperties & mask) != 0u;
1272         }
1273         public inline nothrow bool HasGeneralCategory(GeneralCategoryId generalCategory_) const
1274         {
1275             return (generalCategory & generalCategory_) != GeneralCategoryId.none;
1276         }
1277         public inline nothrow GeneralCategoryId GeneralCategoryValue() const
1278         {
1279             return generalCategory;
1280         }
1281         public inline nothrow uchar Upper() const
1282         {
1283             return upper;
1284         }
1285         public inline nothrow uchar Lower() const
1286         {
1287             return lower;
1288         }
1289         public inline nothrow uchar Title() const
1290         {
1291             return title;
1292         }
1293         public inline nothrow uchar Folding() const
1294         {
1295             return folding;
1296         }
1297         public inline nothrow BlockId BlockValue() const
1298         {
1299             return block;
1300         }
1301         public inline nothrow AgeId AgeValue() const
1302         {
1303             return age;
1304         }
1305         public inline nothrow ScriptId ScriptValue() const
1306         {
1307             return script;
1308         }
1309         public void Read(BinaryReader& reader)
1310         {
1311             binaryProperties = reader.ReadULong();
1312             generalCategory = cast<GeneralCategoryId>(reader.ReadUInt());
1313             upper = reader.ReadUChar();
1314             lower = reader.ReadUChar();
1315             title = reader.ReadUChar();
1316             folding = reader.ReadUChar();
1317             block = cast<BlockId>(reader.ReadUShort());
1318             age = cast<AgeId>(reader.ReadByte());
1319             script = cast<ScriptId>(reader.ReadByte());
1320         }
1321         private ulong binaryProperties;
1322         private GeneralCategoryId generalCategory;
1323         private uchar upper;
1324         private uchar lower;
1325         private uchar title;
1326         private uchar folding;
1327         private BlockId block;
1328         private AgeId age;
1329         private ScriptId script;
1330     }
1331 
1332     public const long numInfosInPage = 128;
1333     public const uint characterInfoSize = 32u;
1334     public const uint characterInfoPageSize = cast<uint>(numInfosInPage) * characterInfoSize;
1335 
1336     public enum NumericTypeId : byte
1337     {
1338         none = 0u
1339         dedinu
1340     }
1341 
1342     public class NumericType
1343     {
1344         public nothrow NumericType(NumericTypeId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
1345         {
1346         }
1347         public inline nothrow NumericTypeId Id() const
1348         {
1349             return id;
1350         }
1351         public inline nothrow const string& ShortName() const
1352         {
1353             return shortName;
1354         }
1355         public inline nothrow const string& LongName() const
1356         {
1357             return longName;
1358         }
1359         private NumericTypeId id;
1360         private string shortName;
1361         private string longName;
1362     }
1363     
1364     public class NumericTypeTable
1365     {
1366         static NumericTypeTable() : instance(new NumericTypeTable())
1367         {
1368         }
1369         public static NumericTypeTable& Instance()
1370         {
1371             return *instance;
1372         }
1373         public const NumericType* GetNumericType(NumericTypeId id) const
1374         {
1375             HashMap<uintvoid*>.ConstIterator it = numericTypeIdMap.CFind(cast<uint>(cast<byte>(id)));
1376             if (it != numericTypeIdMap.CEnd())
1377             {
1378                 return cast<NumericType*>(it->second);
1379             }
1380             return null;
1381         }
1382         public const NumericType* GetNumericTypeByShortName(const string& shortName) const
1383         {
1384             HashMap<stringvoid*>.ConstIterator it = shortNameMap.CFind(MakeCanonicalPropertyName(shortName));
1385             if (it != shortNameMap.CEnd())
1386             {
1387                 return cast<NumericType*>(it->second);
1388             }
1389             return null;
1390         }
1391         public const NumericType* GetNumericTypeByLongName(const string& longName) const
1392         {
1393             HashMap<stringvoid*>.ConstIterator it = longNameMap.CFind(MakeCanonicalPropertyName(longName));
1394             if (it != longNameMap.CEnd())
1395             {
1396                 return cast<NumericType*>(it->second);
1397             }
1398             return null;
1399         }
1400         private NumericTypeTable() : numericTypes()numericTypeIdMap()shortNameMap()longNameMap()
1401         {
1402             numericTypes.Add(new NumericType(NumericTypeId.none"None""None"));
1403             numericTypes.Add(new NumericType(NumericTypeId.de"De""Decimal"));
1404             numericTypes.Add(new NumericType(NumericTypeId.di"Di""Digit"));
1405             numericTypes.Add(new NumericType(NumericTypeId.nu"Nu""Numeric"));
1406             for (NumericType* numericType : numericTypes)
1407             {
1408                 numericTypeIdMap[cast<uint>(cast<byte>(numericType->Id()))] = numericType;
1409                 shortNameMap[MakeCanonicalPropertyName(numericType->ShortName())] = numericType;
1410                 longNameMap[MakeCanonicalPropertyName(numericType->LongName())] = numericType;
1411             }
1412         }
1413         public ~NumericTypeTable()
1414         {
1415             for (NumericType* numericType : numericTypes)
1416             {
1417                 delete numericType;
1418             }
1419         }
1420         private List<NumericType*> numericTypes;
1421         private HashMap<uintvoid*> numericTypeIdMap;
1422         private HashMap<stringvoid*> shortNameMap;
1423         private HashMap<stringvoid*> longNameMap;
1424         private static UniquePtr<NumericTypeTable> instance;
1425     }
1426 
1427     public const NumericType* GetNumericType(NumericTypeId id)
1428     {
1429         return NumericTypeTable.Instance().GetNumericType(id);
1430     }
1431 
1432     public const NumericType* GetNumericTypeByShortName(const string& shortName)
1433     {
1434         return NumericTypeTable.Instance().GetNumericTypeByShortName(shortName);
1435     }
1436 
1437     public const NumericType* GetNumericTypeByLongName(const string& longName)
1438     {
1439         return NumericTypeTable.Instance().GetNumericTypeByLongName(longName);
1440     }
1441 
1442     public enum BidiClassId : byte
1443     {
1444         none = 0u
1445         alanbbncsenesetfsillrelrilronsmonpdfpdirrlerlirlosws
1446     }
1447     
1448     public class BidiClass
1449     {
1450         public nothrow BidiClass(BidiClassId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
1451         {
1452         }
1453         public inline nothrow BidiClassId Id() const
1454         {
1455             return id;
1456         }
1457         public inline nothrow const string& ShortName() const
1458         {
1459             return shortName;
1460         }
1461         public inline nothrow const string& LongName() const
1462         {
1463             return longName;
1464         }
1465         private BidiClassId id;
1466         private string shortName;
1467         private string longName;
1468     }
1469     
1470     public class BidiClassTable
1471     {
1472         static BidiClassTable() : instance(new BidiClassTable())
1473         {
1474         }
1475         public static BidiClassTable& Instance()
1476         {
1477             return *instance;
1478         }
1479         public const BidiClass* GetBidiClass(BidiClassId id) const
1480         {
1481             HashMap<uintvoid*>.ConstIterator it = bidiClassIdMap.CFind(cast<uint>(cast<byte>(id)));
1482             if (it != bidiClassIdMap.CEnd())
1483             {
1484                 return cast<BidiClass*>(it->second);
1485             }
1486             return null;
1487         }
1488         public const BidiClass* GetBidiClassByShortName(const string& shortName) const
1489         {
1490             HashMap<stringvoid*>.ConstIterator it = shortNameMap.CFind(MakeCanonicalPropertyName(shortName));
1491             if (it != shortNameMap.CEnd())
1492             {
1493                 return cast<BidiClass*>(it->second);
1494             }
1495             return null;
1496         }
1497         public const BidiClass* GetBidiClassByLongName(const string& longName) const
1498         {
1499             HashMap<stringvoid*>.ConstIterator it = longNameMap.CFind(MakeCanonicalPropertyName(longName));
1500             if (it != longNameMap.CEnd())
1501             {
1502                 return cast<BidiClass*>(it->second);
1503             }
1504             return null;
1505         }
1506         private BidiClassTable() : bidiClasses()bidiClassIdMap()shortNameMap()longNameMap()
1507         {
1508             bidiClasses.Add(new BidiClass(BidiClassId.al"AL""Arabic Letter"));
1509             bidiClasses.Add(new BidiClass(BidiClassId.an"AN""Arabic Number"));
1510             bidiClasses.Add(new BidiClass(BidiClassId.b"B""Paragraph Separator"));
1511             bidiClasses.Add(new BidiClass(BidiClassId.bn"BN""Boundary Neutral"));
1512             bidiClasses.Add(new BidiClass(BidiClassId.cs"CS""Common Separator"));
1513             bidiClasses.Add(new BidiClass(BidiClassId.en"EN""European Number"));
1514             bidiClasses.Add(new BidiClass(BidiClassId.es"ES""European Separator"));
1515             bidiClasses.Add(new BidiClass(BidiClassId.et"ET""European Terminator"));
1516             bidiClasses.Add(new BidiClass(BidiClassId.fsi"FSI""First Strong Isolate"));
1517             bidiClasses.Add(new BidiClass(BidiClassId.l"L""Left To Right"));
1518             bidiClasses.Add(new BidiClass(BidiClassId.lre"LRE""Left To Right Embedding"));
1519             bidiClasses.Add(new BidiClass(BidiClassId.lri"LRI""Left To Right Isolate"));
1520             bidiClasses.Add(new BidiClass(BidiClassId.lro"LRO""Left To Right Override"));
1521             bidiClasses.Add(new BidiClass(BidiClassId.nsm"NSM""Nonspacing Mark"));
1522             bidiClasses.Add(new BidiClass(BidiClassId.on"ON""Other Neutral"));
1523             bidiClasses.Add(new BidiClass(BidiClassId.pdf"PDF""Pop Directional Format"));
1524             bidiClasses.Add(new BidiClass(BidiClassId.pdi"PDI""Pop Directional Isolate"));
1525             bidiClasses.Add(new BidiClass(BidiClassId.r"R""Right To Left"));
1526             bidiClasses.Add(new BidiClass(BidiClassId.rle"RLE""Right To Left Embedding"));
1527             bidiClasses.Add(new BidiClass(BidiClassId.rli"RLI""Right To Left Isolate"));
1528             bidiClasses.Add(new BidiClass(BidiClassId.rlo"RLO""Right To Left Override"));
1529             bidiClasses.Add(new BidiClass(BidiClassId.s"S""Segment Separator"));
1530             bidiClasses.Add(new BidiClass(BidiClassId.ws"WS""White Space"));
1531             for (BidiClass* bidiClass : bidiClasses)
1532             {
1533                 bidiClassIdMap[cast<uint>(cast<byte>(bidiClass->Id()))] = bidiClass;
1534                 shortNameMap[MakeCanonicalPropertyName(bidiClass->ShortName())] = bidiClass;
1535                 longNameMap[MakeCanonicalPropertyName(bidiClass->LongName())] = bidiClass;
1536             }
1537         }
1538         public ~BidiClassTable()
1539         {
1540             for (BidiClass* bidiClass : bidiClasses)
1541             {
1542                 delete bidiClass;
1543             }
1544         }
1545         private static UniquePtr<BidiClassTable> instance;
1546         private List<BidiClass*> bidiClasses;
1547         private HashMap<uintvoid*> bidiClassIdMap;
1548         private HashMap<stringvoid*> shortNameMap;
1549         private HashMap<stringvoid*> longNameMap;
1550     }
1551      
1552     public const BidiClass* GetBidiClass(BidiClassId id)
1553     {
1554         return BidiClassTable.Instance().GetBidiClass(id);
1555     }
1556 
1557     public const BidiClass* GetBidiClassByShortName(const string& shortName)
1558     {
1559         return BidiClassTable.Instance().GetBidiClassByShortName(shortName);
1560     }
1561 
1562     public const BidiClass* GetBidiClassByLongName(const string& longName)
1563     {
1564         return BidiClassTable.Instance().GetBidiClassByLongName(longName);
1565     }
1566 
1567     public enum BidiPairedBracketTypeId : byte
1568     {
1569         none = 0u
1570         oc
1571     }
1572 
1573     public class BidiPairedBracketType
1574     {
1575         public nothrow BidiPairedBracketType(BidiPairedBracketTypeId id_const string& shortName_const string& longName_) : 
1576             id(id_)shortName(shortName_)longName(longName_)
1577         {
1578         }
1579         public inline nothrow BidiPairedBracketTypeId Id() const
1580         {
1581             return id;
1582         }
1583         public inline nothrow const string& ShortName() const
1584         {
1585             return shortName;
1586         }
1587         public inline nothrow const string& LongName() const
1588         {
1589             return longName;
1590         }
1591         private BidiPairedBracketTypeId id;
1592         private string shortName;
1593         private string longName;
1594     }
1595     
1596     public class BidiPairedBracketTypeTable
1597     {
1598         static BidiPairedBracketTypeTable() : instance(new BidiPairedBracketTypeTable())
1599         {
1600         }
1601         public static BidiPairedBracketTypeTable& Instance()
1602         {
1603             return *instance;
1604         }
1605         public const BidiPairedBracketType* GetBidiPairedBracketType(BidiPairedBracketTypeId id) const
1606         {
1607             HashMap<uintvoid*>.ConstIterator it = bidiPairedBracketTypeIdMap.CFind(cast<uint>(cast<byte>(id)));
1608             if (it != bidiPairedBracketTypeIdMap.CEnd())
1609             {
1610                 return cast<BidiPairedBracketType*>(it->second);
1611             }
1612             return null;
1613         }
1614         public const BidiPairedBracketType* GetBidiPairedBracketTypeByShortName(const string& shortName) const
1615         {
1616             HashMap<stringvoid*>.ConstIterator it = shortNameMap.CFind(MakeCanonicalPropertyName(shortName));
1617             if (it != shortNameMap.CEnd())
1618             {
1619                 return cast<BidiPairedBracketType*>(it->second);
1620             }
1621             return null;
1622         }
1623         public const BidiPairedBracketType* GetBidiPairedBracketTypeByLongName(const string& longName) const
1624         {
1625             HashMap<stringvoid*>.ConstIterator it = longNameMap.CFind(longName);
1626             if (it != longNameMap.CEnd())
1627             {
1628                 return cast<BidiPairedBracketType*>(it->second);
1629             }
1630             return null;
1631         }
1632         private BidiPairedBracketTypeTable() : bidiPairedBracketTypes()bidiPairedBracketTypeIdMap()shortNameMap()longNameMap()
1633         {
1634             bidiPairedBracketTypes.Add(new BidiPairedBracketType(BidiPairedBracketTypeId.o"O""Open"));
1635             bidiPairedBracketTypes.Add(new BidiPairedBracketType(BidiPairedBracketTypeId.c"C""Close"));
1636             bidiPairedBracketTypes.Add(new BidiPairedBracketType(BidiPairedBracketTypeId.none"N""None"));
1637             for (BidiPairedBracketType* bidiPairedBracketType : bidiPairedBracketTypes)
1638             {
1639                 bidiPairedBracketTypeIdMap[cast<uint>(cast<byte>(bidiPairedBracketType->Id()))] = bidiPairedBracketType;
1640                 shortNameMap[MakeCanonicalPropertyName(bidiPairedBracketType->ShortName())] = bidiPairedBracketType;
1641                 longNameMap[MakeCanonicalPropertyName(bidiPairedBracketType->LongName())] = bidiPairedBracketType;
1642             }
1643         }
1644         public ~BidiPairedBracketTypeTable()
1645         {
1646             for (BidiPairedBracketType* bidiPairedBracketType : bidiPairedBracketTypes)
1647             {
1648                 delete bidiPairedBracketType;
1649             }
1650         }
1651         private static UniquePtr<BidiPairedBracketTypeTable> instance;
1652         private List<BidiPairedBracketType*> bidiPairedBracketTypes;
1653         private HashMap<uintvoid*> bidiPairedBracketTypeIdMap;
1654         private HashMap<stringvoid*> shortNameMap;
1655         private HashMap<stringvoid*> longNameMap;
1656     }
1657 
1658     public const BidiPairedBracketType* GetBidiPairedBracketType(BidiPairedBracketTypeId id)
1659     {
1660         return BidiPairedBracketTypeTable.Instance().GetBidiPairedBracketType(id);
1661     }
1662 
1663     public const BidiPairedBracketType* GetBidiPairedBracketTypeByShortName(const string& shortName)
1664     {
1665         return BidiPairedBracketTypeTable.Instance().GetBidiPairedBracketTypeByShortName(shortName);
1666     }
1667 
1668     public const BidiPairedBracketType* GetBidiPairedBracketTypeByLongName(const string& longName)
1669     {
1670         return BidiPairedBracketTypeTable.Instance().GetBidiPairedBracketTypeByLongName(longName);
1671     }
1672 
1673     public enum AliasTypeId : byte
1674     {
1675         none = 0u
1676         correctioncontrolalternatefigmentabbreviation
1677     }
1678 
1679     public class AliasType
1680     {
1681         public nothrow AliasType(AliasTypeId id_const string& name_) : id(id_)name(name_)
1682         {
1683         }
1684         public inline nothrow AliasTypeId Id() const
1685         {
1686             return id;
1687         }
1688         public inline nothrow const string& Name() const
1689         {
1690             return name;
1691         }
1692         private AliasTypeId id;
1693         private string name;
1694     }
1695     
1696     public class AliasTypeTable
1697     {
1698         static AliasTypeTable() : instance(new AliasTypeTable())
1699         {
1700         }
1701         public static AliasTypeTable& Instance()
1702         {
1703             return *instance;
1704         }
1705         public const AliasType* GetAliasType(AliasTypeId id) const
1706         {
1707             HashMap<uintvoid*>.ConstIterator it = aliasTypeIdMap.CFind(cast<uint>(cast<byte>(id)));
1708             if (it != aliasTypeIdMap.CEnd())
1709             {
1710                 return cast<AliasType*>(it->second);
1711             }
1712             return null;
1713         }
1714         public const AliasType* GetAliasType(const string& name) const
1715         {
1716             HashMap<stringvoid*>.ConstIterator it = nameMap.CFind(name);
1717             if (it != nameMap.CEnd())
1718             {
1719                 return cast<AliasType*>(it->second);
1720             }
1721             return null;
1722         }
1723         private AliasTypeTable() : aliasTypes()aliasTypeIdMap()nameMap()
1724         {
1725             aliasTypes.Add(new AliasType(AliasTypeId.abbreviation"abbreviation"));
1726             aliasTypes.Add(new AliasType(AliasTypeId.alternate"alternate"));
1727             aliasTypes.Add(new AliasType(AliasTypeId.control"control"));
1728             aliasTypes.Add(new AliasType(AliasTypeId.correction"correction"));
1729             aliasTypes.Add(new AliasType(AliasTypeId.figment"figment"));
1730             for (AliasType* aliasType : aliasTypes)
1731             {
1732                 aliasTypeIdMap[cast<uint>(cast<byte>(aliasType->Id()))] = aliasType;
1733                 nameMap[aliasType->Name()] = aliasType;
1734             }
1735         }
1736         public ~AliasTypeTable()
1737         {
1738             for (AliasType* aliasType : aliasTypes)
1739             {
1740                 delete aliasType;
1741             }
1742         }
1743         private static UniquePtr<AliasTypeTable> instance;
1744         private List<AliasType*> aliasTypes;
1745         private HashMap<uintvoid*> aliasTypeIdMap;
1746         private HashMap<stringvoid*> nameMap;
1747     }
1748 
1749     public const AliasType* GetAliasType(AliasTypeId id)
1750     {
1751         return AliasTypeTable.Instance().GetAliasType(id);
1752     }
1753 
1754     public const AliasType* GetAliasType(const string& name)
1755     {
1756         return AliasTypeTable.Instance().GetAliasType(name);
1757     }
1758 
1759     public class Alias
1760     {
1761         public nothrow Alias() : typeId(AliasTypeId.none)name()
1762         {
1763         }
1764         public nothrow Alias(AliasTypeId typeId_const string& name_) : typeId(typeId_)name(name_)
1765         {
1766         }
1767         public inline nothrow AliasTypeId TypeId() const
1768         {
1769             return typeId;
1770         }
1771         public inline nothrow const string& Name() const
1772         {
1773             return name;
1774         }
1775         public void Read(BinaryReader& reader)
1776         {
1777             typeId = cast<AliasTypeId>(reader.ReadByte());
1778             name = reader.ReadString();
1779         }
1780         private AliasTypeId typeId;
1781         private string name;
1782     }
1783 
1784     public class ExtendedCharacterInfo
1785     {
1786         public nothrow ExtendedCharacterInfo() : 
1787             characterName()unicode1Name()canonicalCombiningClass(0u)fullUpper()fullLower()fullTitle()fullFolding()bidiClass(BidiClassId.none)
1788             numericType(NumericTypeId.none)numericValue()aliases()bidiMirroringGlyph(cast<uchar>(0u))bidiPairedBracketType(BidiPairedBracketTypeId.none)
1789             bidiPairedBracket(cast<uchar>(0u))
1790         {
1791         }
1792         public inline nothrow const string& CharacterName() const
1793         {
1794             return characterName;
1795         }
1796         public inline nothrow const string& Unicode1Name() const
1797         {
1798             return unicode1Name;
1799         }
1800         public inline nothrow byte CanonicalCombiningClass() const
1801         {
1802             return canonicalCombiningClass;
1803         }
1804         public inline nothrow const ustring& FullUpper() const
1805         {
1806             return fullUpper;
1807         }
1808         public inline nothrow const ustring& FullLower() const
1809         {
1810             return fullLower;
1811         }
1812         public inline nothrow const ustring& FullTitle() const
1813         {
1814             return fullTitle;
1815         }
1816         public inline nothrow const ustring& FullFolding() const
1817         {
1818             return fullFolding;
1819         }
1820         public inline nothrow BidiClassId BidiClassValue() const
1821         {
1822             return bidiClass;
1823         }
1824         public inline nothrow NumericTypeId NumericTypeValue() const
1825         {
1826             return numericType;
1827         }
1828         public inline nothrow const ustring& NumericValue() const
1829         {
1830             return numericValue;
1831         }
1832         public inline nothrow const List<Alias>& Aliases() const
1833         {
1834             return aliases;
1835         }
1836         public inline nothrow uchar BidiMirroringGlyph() const
1837         {
1838             return bidiMirroringGlyph;
1839         }
1840         public inline nothrow BidiPairedBracketTypeId BidiPairedBracketTypeValue() const
1841         {
1842             return bidiPairedBracketType;
1843         }
1844         public inline nothrow uchar BidiPairedBracket()
1845         {
1846             return bidiPairedBracket;
1847         }
1848         public void Read(BinaryReader& reader)
1849         {
1850             characterName = reader.ReadString();
1851             unicode1Name = reader.ReadString();
1852             canonicalCombiningClass = reader.ReadByte();
1853             byte nu = reader.ReadByte();
1854             for (byte i = 0u; i < nu; ++i;)
1855             {
1856                 fullUpper.Append(reader.ReadUChar());
1857             }
1858             byte nl = reader.ReadByte();
1859             for (byte i = 0u; i < nl; ++i;)
1860             {
1861                 fullLower.Append(reader.ReadUChar());
1862             }
1863             byte nt = reader.ReadByte();
1864             for (byte i = 0u; i < nt; ++i;)
1865             {
1866                 fullTitle.Append(reader.ReadUChar());
1867             }
1868             byte nf = reader.ReadByte();
1869             for (byte i = 0u; i < nf; ++i;)
1870             {
1871                 fullFolding.Append(reader.ReadUChar());
1872             }
1873             bidiClass = cast<BidiClassId>(reader.ReadByte());
1874             numericType = cast<NumericTypeId>(reader.ReadByte());
1875             numericValue = reader.ReadUString();
1876             byte na = reader.ReadByte();
1877             for (byte i = 0u; i < na; ++i;)
1878             {
1879                 Alias alias;
1880                 alias.Read(reader);
1881                 aliases.Add(alias);
1882             }
1883             bidiMirroringGlyph = reader.ReadUChar();
1884             bidiPairedBracketType = cast<BidiPairedBracketTypeId>(reader.ReadByte());
1885             bidiPairedBracket = reader.ReadUChar();
1886         }
1887         private string characterName;
1888         private string unicode1Name;
1889         private byte canonicalCombiningClass;
1890         private ustring fullUpper;
1891         private ustring fullLower;
1892         private ustring fullTitle;
1893         private ustring fullFolding;
1894         private BidiClassId bidiClass;
1895         private NumericTypeId numericType;
1896         private ustring numericValue;
1897         private List<Alias> aliases;
1898         private uchar bidiMirroringGlyph;
1899         private BidiPairedBracketTypeId bidiPairedBracketType;
1900         private uchar bidiPairedBracket;
1901     }
1902     
1903     public class CharacterInfoPage
1904     {
1905         public CharacterInfoPage() : characterInfos()
1906         {
1907             characterInfos.Resize(numInfosInPage);
1908         }
1909         public const CharacterInfo& operator[](long index) const
1910         {
1911             return *characterInfos[index];
1912         }
1913         public void Read(BinaryReader& reader)
1914         {
1915             for (long i = 0; i < numInfosInPage; ++i;)
1916             {
1917                 CharacterInfo* characterInfo = new CharacterInfo();
1918                 characterInfo->Read(reader);
1919                 characterInfos[i].Reset(characterInfo);
1920             }
1921         }
1922         private List<UniquePtr<CharacterInfo>> characterInfos;
1923     }
1924     
1925     public class ExtendedCharacterInfoPage
1926     {
1927         public ExtendedCharacterInfoPage() : extendedCharacterInfos()
1928         {
1929             extendedCharacterInfos.Resize(numInfosInPage);
1930         }
1931         public const ExtendedCharacterInfo& operator[](long index) const
1932         {
1933             return *extendedCharacterInfos[index];
1934         }
1935         public void Read(BinaryReader& reader)
1936         {
1937             for (long i = 0; i < numInfosInPage; ++i;)
1938             {
1939                 ExtendedCharacterInfo* extendedCharacterInfo = new ExtendedCharacterInfo();
1940                 extendedCharacterInfo->Read(reader);
1941                 extendedCharacterInfos[i].Reset(extendedCharacterInfo);
1942             }
1943         }
1944         private List<UniquePtr<ExtendedCharacterInfo>> extendedCharacterInfos;
1945     }
1946     
1947     public class ExtendedCharacterInfoHeader
1948     {
1949         public ExtendedCharacterInfoHeader() : extendedPageStarts()
1950         {
1951         }
1952         public uint operator[](long index) const
1953         {
1954             return extendedPageStarts[index];
1955         }
1956         public void Read(BinaryReader& reader)
1957         {
1958             uint n = reader.ReadUInt();
1959             extendedPageStarts.Resize(n);
1960             for (uint i = 0u; i < n; ++i;)
1961             {
1962                 extendedPageStarts[i] = reader.ReadUInt();
1963             }
1964         }
1965         private List<uint> extendedPageStarts;
1966     }
1967     
1968     public const byte cmajor_ucd_version_1 = cast<byte>('1');
1969     public const byte cmajor_ucd_version_2 = cast<byte>('2');
1970     public const byte cmajor_ucd_version_3 = cast<byte>('3');
1971     public const byte current_cmajor_ucd_version = cmajor_ucd_version_3;
1972     
1973     public class CharacterTable
1974     {
1975         static CharacterTable() : instance(new CharacterTable())
1976         {
1977         }
1978         public static CharacterTable& Instance()
1979         {
1980             return *instance;
1981         }
1982         public const CharacterInfo& GetCharacterInfo(uchar codePoint)
1983         {
1984             if (codePoint > cast<uchar>(0x10FFFF))
1985             {
1986                 throw UnicodeException("invalid Unicode code point " + ToHexString(cast<uint>(codePoint)));
1987             }
1988             long pageIndex = cast<long>(codePoint) / numInfosInPage;
1989             if (pages.Count() <= pageIndex)
1990             {
1991                 while (pages.Count() <= pageIndex)
1992                 {
1993                     pages.Add(UniquePtr<CharacterInfoPage>());
1994                 }
1995             }
1996             CharacterInfoPage* page = pages[pageIndex].Get();
1997             if (page == null)
1998             {
1999                 string pathToUcdBinFile = PathToUcdBinFile();
2000                 if (!File.Exists(pathToUcdBinFile))
2001                 {
2002                     throw UnicodeException("Error: Cmajor Unicode database file '" + pathToUcdBinFile + "' does not exist.");
2003                 }
2004                 BinaryReader reader = File.OpenBinary(pathToUcdBinFile);
2005                 if (!headerRead)
2006                 {
2007                     ReadHeader(reader);
2008                 }
2009                 uint pageStart = headerSize + characterInfoPageSize * cast<uint>(pageIndex);
2010                 reader.Seek(cast<long>(pageStart)Origin.seekSet);
2011                 page = new CharacterInfoPage();
2012                 page->Read(reader);
2013                 pages[pageIndex].Reset(page);
2014             }
2015             long infoIndex = cast<long>(codePoint) % numInfosInPage;
2016             return (*page)[infoIndex];
2017         }
2018         public const ExtendedCharacterInfo& GetExtendedCharacterInfo(uchar codePoint)
2019         {
2020             if (codePoint > cast<uchar>(0x10FFFF))
2021             {
2022                 throw UnicodeException("invalid Unicode code point " + ToHexString(cast<uint>(codePoint)));
2023             }
2024             long pageIndex = cast<long>(codePoint) / numInfosInPage;
2025             if (extendedPages.Count() <= pageIndex)
2026             {
2027                 while (extendedPages.Count() <= pageIndex)
2028                 {
2029                     extendedPages.Add(UniquePtr<ExtendedCharacterInfoPage>());
2030                 }
2031             }
2032             ExtendedCharacterInfoPage* extendedPage = extendedPages[pageIndex].Get();
2033             if (extendedPage == null)
2034             {
2035                 string pathToUcdBinFile = PathToUcdBinFile();
2036                 if (!File.Exists(pathToUcdBinFile))
2037                 {
2038                     throw UnicodeException("Error: Cmajor Unicode database file '" + pathToUcdBinFile + "' does not exist.");
2039                 }
2040                 BinaryReader reader = File.OpenBinary(pathToUcdBinFile);
2041                 if (!headerRead)
2042                 {
2043                     ReadHeader(reader);
2044                 }
2045                 if (extendedHeader.IsNull())
2046                 {
2047                     reader.Seek(cast<long>(extendedHeaderStart)Origin.seekSet);
2048                     ReadExtendedHeader(reader);
2049                 }
2050                 reader.Seek(cast<long>((*extendedHeader)[pageIndex])Origin.seekSet);
2051                 extendedPage = new ExtendedCharacterInfoPage();
2052                 extendedPage->Read(reader);
2053                 extendedPages[pageIndex].Reset(extendedPage);
2054             }
2055             long infoIndex = cast<long>(codePoint) % numInfosInPage;
2056             return (*extendedPage)[infoIndex];
2057         }
2058         private CharacterTable() : headerRead(false)pages()extendedHeaderStart(0u)extendedHeaderEnd(0u)extendedHeader()extendedPages()
2059         {
2060             headerMagic.Resize(8);
2061             string hdrmgc = "CMAJUCD";
2062             for (long i = 0; i < 8; ++i;)
2063             {
2064                 if (i < 7)
2065                 {
2066                     headerMagic[i] = cast<byte>(hdrmgc[i]);
2067                 }
2068                 else
2069                 {
2070                     headerMagic[i] = current_cmajor_ucd_version;
2071                 }
2072             }
2073         }
2074         private void ReadHeader(BinaryReader& reader)
2075         {
2076             headerRead = true;
2077             List<byte> magic;
2078             magic.Resize(8);
2079             for (long i = 0; i < 8; ++i;)
2080             {
2081                 magic[i] = reader.ReadByte();
2082             }
2083             for (long i = 0; i < 7; ++i;)
2084             {
2085                 if (magic[i] != cast<byte>(headerMagic[i]))
2086                 {
2087                     throw UnicodeException("invalid cmajor_ucd.bin header magic: 'CMAJUCD' expected");
2088                 }
2089             }
2090             if (magic[7] != headerMagic[7])
2091             {
2092                 throw UnicodeException("invalid cmajor_ucd.bin version: version " + 
2093                     string(cast<char>(headerMagic[7])1) + " expected, version " + 
2094                     string(cast<char>(magic[7])1) + " read");
2095             }
2096             extendedHeaderStart = reader.ReadUInt();
2097             extendedHeaderEnd = reader.ReadUInt();
2098         }
2099         private void ReadExtendedHeader(BinaryReader& reader)
2100         {
2101             extendedHeader.Reset(new ExtendedCharacterInfoHeader());
2102             extendedHeader->Read(reader);
2103         }
2104         public ~CharacterTable()
2105         {
2106         }
2107         private const uint headerSize = 4096u;
2108         private static UniquePtr<CharacterTable> instance;
2109         private List<byte> headerMagic;
2110         private bool headerRead;
2111         private List<UniquePtr<CharacterInfoPage>> pages;
2112         private uint extendedHeaderStart;
2113         private uint extendedHeaderEnd;
2114         private UniquePtr<ExtendedCharacterInfoHeader> extendedHeader;
2115         private List<UniquePtr<ExtendedCharacterInfoPage>> extendedPages;
2116     }
2117 
2118     public const CharacterInfo& GetCharacterInfo(uchar codePoint)
2119     {
2120         return CharacterTable.Instance().GetCharacterInfo(codePoint);
2121     }
2122     
2123     public const ExtendedCharacterInfo& GetExtendedCharacterInfo(uchar codePoint)
2124     {
2125         return CharacterTable.Instance().GetExtendedCharacterInfo(codePoint);
2126     }
2127     
2128     public GeneralCategoryId GetGeneralCategory(uchar c)
2129     {
2130         return GetCharacterInfo(c).GeneralCategoryValue();
2131     }
2132     
2133     public bool HasGeneralCategory(uchar cGeneralCategoryId generalCategory)
2134     {
2135         return GetCharacterInfo(c).HasGeneralCategory(generalCategory);
2136     }
2137 }