1 // =================================
   2 // Copyright (c) 2024 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 using System;
   7 using System.Collections;
   8 using System.IO;
   9 using System.Threading;
  10 
  11 namespace System.Unicode
  12 {
  13     [nodiscard]
  14     public Result<string> PathToUnicodeDirectory()
  15     {
  16         string cmajorRoot;
  17         int stringHandle = RtmGetEnvironmentVariable("CMAJOR_ROOT");
  18         if (stringHandle != -1)
  19         {
  20             cmajorRoot = RtmGetString(stringHandle);
  21             RtmFreeString(stringHandle);
  22         }
  23         if (cmajorRoot.IsEmpty())
  24         {
  25             int errorId = AllocateError("CMAJOR_ROOT environment variable not set (set it to /path/to/cmajor directory)");
  26             return Result<string>(ErrorId(errorId));
  27         }
  28         return Result<string>(Path.Combine(cmajorRoot"unicode"));
  29     }
  30 
  31     [nodiscard]
  32     public Result<string> PathToUcdBinFile()
  33     {
  34         auto unicodeDir = PathToUnicodeDirectory();
  35         if (unicodeDir.Error())
  36         {
  37             return unicodeDir;
  38         }
  39         return Result<string>(Path.Combine(unicodeDir.Value()"cmajor_ucd.bin"));
  40     }
  41 
  42     [nodiscard]
  43     public Result<string> MakeCanonicalPropertyName(const string& s)
  44     {
  45         string result;
  46         for (char c : s)
  47         {
  48             if (c != '_' && c != ' ' && c != '-')
  49             {
  50                 result.Append(c);
  51             }
  52         }
  53         return ToLower(result);
  54     }
  55 
  56     public enum BinaryPropertyId : byte
  57     {
  58         asciiHexDigit
  59         alphabetic
  60         bidiControl
  61         bidiMirrored
  62         cased
  63         compositionExclusion
  64         caseIgnorable
  65         fullCompositionExclusion
  66         changesWhenCasefolded
  67         changesWhenCaseMapped
  68         changesWhenNFKCCasefolded
  69         changesWhenLowercased
  70         changesWhenTitlecased
  71         changesWhenUppercased
  72         dash
  73         deprecated
  74         defaultIgnorableCodePoint
  75         diacritic
  76         extender
  77         graphemeBase
  78         graphemeExtend
  79         graphemeLink
  80         hexDigit
  81         hyphen
  82         idContinue
  83         ideographic
  84         idStart
  85         idsBinaryOperator
  86         idsTrinaryOperator
  87         joinControl
  88         logicalOrderException
  89         lowercase
  90         math
  91         noncharacterCodePoint
  92         otherAlphabetic
  93         otherDefaultIgnorableCodePoint
  94         otherGraphemeExtend
  95         otherIdContinue
  96         otherIdStart
  97         otherLowercase
  98         otherMath
  99         otherUppercase
 100         patternSyntax
 101         patternWhiteSpace
 102         prependedConcatenationMark
 103         quotationMark
 104         radical
 105         softDotted
 106         sentenceterminal
 107         terminalPunctuation
 108         unifiedIdeograph
 109         uppercase
 110         variationSelector
 111         whiteSpace
 112         xidContinue
 113         xidStart
 114         expandsOnNFC
 115         expandsOnNFD
 116         expandsOnNFKC
 117         expandsOnNFKD
 118     }
 119 
 120     public class BinaryProperty
 121     {
 122         public BinaryProperty(BinaryPropertyId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
 123         {
 124         }
 125         public inline BinaryPropertyId Id()
 126         {
 127             return id;
 128         }
 129         public inline const string& ShortName()
 130         {
 131             return shortName;
 132         }
 133         public inline const string& LongName()
 134         {
 135             return longName;
 136         }
 137         private BinaryPropertyId id;
 138         private string shortName;
 139         private string longName;
 140     }
 141 
 142     public class BinaryPropertyTable : IOBase
 143     {
 144         static BinaryPropertyTable() : instance(new BinaryPropertyTable())
 145         {
 146         }
 147         public static BinaryPropertyTable& Instance()
 148         {
 149             return *instance;
 150         }
 151         [nodiscard]
 152         public Result<const BinaryProperty*> GetBinaryProperty(BinaryPropertyId id) const
 153         {
 154             if (Error())
 155             {
 156                 return Result<const BinaryProperty*>(ErrorId(GetErrorId()));
 157             }
 158             auto it = binaryPropertyIdMap.CFind(cast<uint>(cast<byte>(id)));
 159             if (it != binaryPropertyIdMap.CEnd())
 160             {
 161                 return Result<const BinaryProperty*>(cast<BinaryProperty*>(it->second));
 162             }
 163             const BinaryProperty* n = null;
 164             return Result<const BinaryProperty*>(n);
 165         }
 166         [nodiscard]
 167         public Result<const BinaryProperty*> GetBinaryPropertyByShortName(const string& shortName) const
 168         {
 169             if (Error())
 170             {
 171                 return Result<const BinaryProperty*>(ErrorId(GetErrorId()));
 172             }
 173             auto result = MakeCanonicalPropertyName(shortName);
 174             if (result.Error())
 175             {
 176                 return Result<const BinaryProperty*>(ErrorId(result.GetErrorId()));
 177             }
 178             auto it = shortNameMap.CFind(result.Value());
 179             if (it != shortNameMap.CEnd())
 180             {
 181                 return Result<const BinaryProperty*>(cast<BinaryProperty*>(it->second));
 182             }
 183             return Result<const BinaryProperty*>(null);
 184         }
 185         [nodiscard]
 186         public Result<const BinaryProperty*> GetBinaryPropertyByLongName(const string& longName) const
 187         {
 188             if (Error())
 189             {
 190                 return Result<const BinaryProperty*>(ErrorId(GetErrorId()));
 191             }
 192             auto result = MakeCanonicalPropertyName(longName);
 193             if (result.Error())
 194             {
 195                 return Result<const BinaryProperty*>(ErrorId(result.GetErrorId()));
 196             }
 197             auto it = longNameMap.CFind(result.Value());
 198             if (it != longNameMap.CEnd())
 199             {
 200                 return Result<const BinaryProperty*>(cast<BinaryProperty*>(it->second));
 201             }
 202             return Result<const BinaryProperty*>(null);
 203         }
 204         private BinaryPropertyTable() : base()binaryProperties()binaryPropertyIdMap()shortNameMap()longNameMap()
 205         {
 206             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.asciiHexDigit"AHex""Ascii Hex Digit"));
 207             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.alphabetic"Alpha""Alphabetic"));
 208             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.bidiControl"Bidi C""Bidi Control"));
 209             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.bidiMirrored"Bidi M""Bidi Mirrored"));
 210             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.cased"Cased""Cased"));
 211             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.compositionExclusion"CE""Composition Exclusion"));
 212             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.caseIgnorable"CI""Case Ignorable"));
 213             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.fullCompositionExclusion"Comp Ex""Full Composition Exclusion"));
 214             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenCasefolded"CWCF""Changes When Casefolded"));
 215             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenCaseMapped"CWCM""Changes When Casemapped"));
 216             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenNFKCCasefolded"CWKCF""Changes When NFKC Casefolded"));
 217             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenLowercased"CWL""Changes When Lowercased"));
 218             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenTitlecased"CWT""Changes When Titlecased"));
 219             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.changesWhenUppercased"CWU""Changes When Uppercased"));
 220             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.dash"Dash""Dash"));
 221             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.deprecated"Dep""Deprecated"));
 222             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.defaultIgnorableCodePoint"DI""Default Ignorable Code Point"));
 223             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.diacritic"Dia""Diacritic"));
 224             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.extender"Ext""Extender"));
 225             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.graphemeBase"Gr Base""Grapheme Base"));
 226             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.graphemeExtend"Gr Ext""Grapheme Extend"));
 227             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.graphemeLink"Gr Link""Grapheme Link"));
 228             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.hexDigit"Hex""Hex Digit"));
 229             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.hyphen"Hyphen""Hyphen"));
 230             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idContinue"IDC""ID Continue"));
 231             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.ideographic"Ideo""Ideographic"));
 232             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idStart"IDS""ID Start"));
 233             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idsBinaryOperator"IDSB""IDS Binary Operator"));
 234             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.idsTrinaryOperator"IDST""IDS Trinary Operator"));
 235             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.joinControl"Join C""Join Control"));
 236             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.logicalOrderException"LOE""Logical Order Exception"));
 237             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.lowercase"Lower""Lowercase"));
 238             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.math"Math""Math"));
 239             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.noncharacterCodePoint"NChar""Noncharacter Code Point"));
 240             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherAlphabetic"OAlpha""Other Alphabetic"));
 241             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherDefaultIgnorableCodePoint"ODI""Other Default Ignorable Code Point"));
 242             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherGraphemeExtend"OGr Ext""Other Grapheme Extend"));
 243             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherIdContinue"OIDC""Other ID Continue"));
 244             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherIdStart"OIDS""Other ID Start"));
 245             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherLowercase"OLower""Other Lowercase"));
 246             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherMath"OMath""Other Math"));
 247             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.otherUppercase"OUpper""Other Uppercase"));
 248             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.patternSyntax"Pat Syn""Pattern Syntax"));
 249             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.patternWhiteSpace"Pat WS""Pattern White Space"));
 250             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.prependedConcatenationMark"PCM""Prepended Concatenation Mark"));
 251             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.quotationMark"QMark""Quotation Mark"));
 252             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.radical"Radical""Radical"));
 253             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.softDotted"SD""Soft Dotted"));
 254             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.sentenceterminal"STerm""Sentence Terminal"));
 255             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.terminalPunctuation"Term""Terminal Punctuation"));
 256             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.unifiedIdeograph"UIdeo""Unified Ideograph"));
 257             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.uppercase"Upper""Uppercase"));
 258             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.variationSelector"VS""Variation Selector"));
 259             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.whiteSpace"WSpace""White Space"));
 260             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.xidContinue"XIDC""XID Continue"));
 261             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.xidStart"XIDS""XID Start"));
 262             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFC"XO NFC""Expands On NFC"));
 263             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFD"XO NFD""Expands On NFD"));
 264             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFKC"XO NFKC""Expands On NFKC"));
 265             binaryProperties.Add(new BinaryProperty(BinaryPropertyId.expandsOnNFKD"XO NFKD""Expands On NFKD"));
 266             for (BinaryProperty* binaryProperty : binaryProperties)
 267             {
 268                 binaryPropertyIdMap[cast<uint>(cast<byte>(binaryProperty->Id()))] = binaryProperty;
 269                 auto result = MakeCanonicalPropertyName(binaryProperty->ShortName());
 270                 if (result.Error())
 271                 {
 272                     SetErrorId(result.GetErrorId());
 273                     return;
 274                 }
 275                 shortNameMap[result.Value()] = binaryProperty;
 276                 result = MakeCanonicalPropertyName(binaryProperty->LongName());
 277                 if (result.Error())
 278                 {
 279                     SetErrorId(result.GetErrorId());
 280                     return;
 281                 }
 282                 longNameMap[result.Value()] = binaryProperty;
 283             }
 284         }
 285         public override ~BinaryPropertyTable()
 286         {
 287             for (BinaryProperty* binaryProperty : binaryProperties)
 288             {
 289                 delete binaryProperty;
 290             }
 291         }
 292         private List<BinaryProperty*> binaryProperties;
 293         private Map<uintvoid*> binaryPropertyIdMap;
 294         private Map<stringvoid*> shortNameMap;
 295         private Map<stringvoid*> longNameMap;
 296         private static UniquePtr<BinaryPropertyTable> instance;
 297     }
 298 
 299     [nodiscard]
 300     public Result<const BinaryProperty*> GetBinaryProperty(BinaryPropertyId id)
 301     {
 302         return BinaryPropertyTable.Instance().GetBinaryProperty(id);
 303     }
 304 
 305     [nodiscard]
 306     public Result<const BinaryProperty*> GetBinaryPropertyByShortName(const string& shortName)
 307     {
 308         return BinaryPropertyTable.Instance().GetBinaryPropertyByShortName(shortName);
 309     }
 310 
 311     [nodiscard]
 312     public Result<const BinaryProperty*> GetBinaryPropertyByLongName(const string& longName)
 313     {
 314         return BinaryPropertyTable.Instance().GetBinaryPropertyByLongName(longName);
 315     }
 316 
 317     public enum BlockId : ushort
 318     {
 319         none = 0u
 320         adlamaegeanNumbersahomalchemicalalphabeticPfanatolianHieroglyphsancientGreekMusicancientGreekNumbersancientSymbols
 321         arabicarabicExtAarabicMatharabicPfAarabicPfBarabicSuparmenianarrowsasciiavestan
 322         balinesebamumbamumSupbassaVahbatakbengalibhaisukiblockElementsbopomofobopomofoExtboxDrawing
 323         brahmibraillebuginesebuhidbyzantineMusic
 324         cariancaucasianAlbanianchakmachamcherokeecherokeeSupchessSymbols
 325         cjkcjkCompatcjkCompatFormscjkCompatIdeographscjkCompatIdeographsSupcjkExtAcjkExtBcjkExtCcjkExtDcjkExtEcjkExtF
 326         cjkRadicalsSupcjkStrokescjkSymbolscompatJamocontrolPicturescopticcopticEpactNumberscountingRodcuneiform
 327         cuneiformNumberscurrencySymbolscypriotSyllabarycyrilliccyrillicExtAcyrillicExtBcyrillicExtCcyrillicSup
 328         deseretdevanagaridevanagariExtdiacriticalsdiariticalsForSymbolsdiacriticalsSupdiacriticalsExtdingbatsdogradominoduployan
 329         earlyDynasticCuneiformegyptianHieroglyphsegyptianHieroglyphFormatControlselbasanelymaicemoticonsenclosedAlphanumenclosedAlphanumSupenclosedCjkenclosedIdeographicSup
 330         ethiopicethiopicExtethiopicExtAethiopicSup
 331         geometricShapesgeometricShapesExtgeorgiangeorgianExtgeorgianSupglagoliticglagoliticSupgothicgranthagreekgreekExtgujaratigunjalaGondigurmukhi
 332         halfAndFullFormshalfMarkshangulhanifiRohingyahanunoohatranhebrewhighPuSurrogateshighSurrogateshiragana
 333         idcideographicSymbolsimperialAramaicindicNumberFormsinscriptionalPahlaviinscriptionalParthianipaExtindicSiyaqNumbers
 334         jamojamoExtAjamoExtBjavanesekaithikanaExtAsmallKanaExtkanaSupkanbunkangxikannadakatakanakatakanaExtkayahLikharoshthikhmerkhmerSymbolskhojkikhudawadi
 335         laolatin1SuplatinExtAlatinExtAdditionallatinExtBlatinExtClatinExtDlatinExtElepchaletterlikeSymbolslimbu
 336         linearAlinearBIdeogramslinearBSyllabarylisulowSurrogateslycianlydian
 337         mahajanimahjongmakasarmalayalammandaicmanicheanmarchenmasaramGondimathAlphanummathOperatorsmayanNumeralsmedefaidrinmeeteiMayekmeeteiMayekExtmendeKikakuimeroiticCursivemeroiticHieroglyphs
 338         miaomiscArrowsmiscMathSymbolsAmiscMathSymbolsBmiscPictographsmiscSymbolsmiscTechnicalmodimodifierLettersmodifierToneLettersmongolianmongolianSup
 339         mromusicmultanimyanmarmyanmarExtAmyanmarExtB
 340         nabataeannbnandinagarinewTaiLuenewankonumberFormsnushunyiakengPuachueHmong
 341         ocroghamolChikioldHungarianoldItalicoldNorthArabianoldPermicoldPersianoldSogdianoldSouthArabianoldTurkicoriyaornamentalDingbatsosageosmanyaottomanSiyaqNumbers
 342         pahawhHmongpalmyrenepauCinHauphagsPaphaistosphoenicianphoneticExtphoneticExtSupplayingCardspsalterPahlavipuapunctuation
 343         rejangrumirunic
 344         samaritansaurashtrasharadashavianshorthandFormatControlssiddhamsinhalasinhalaArchaicNumberssmallFormssogdiansoraSompengsoyombospecialssundanesesundaneseSup
 345         supArrowsAsupArrowsBsupArrowsCsupMathOperatorssupPuaAsupPuaBsupPunctuationsupSymbolsAndPictographssuperAndSubsuttonSignWritingsylotiNagrisymbolsAndPictographsExtAsyriac
 346         syriacSup
 347         tagalogtagbanwatagstaiLetaiThamtaiViettaiXuanJingtakritamiltamilSuptanguttangutComponentsteluguthaanathaitibetantifinaghtirhutatransportAndMap
 348         ucasucasExtugariticvaivedicExtverticalFormsvsvsSupwanchowarangCitiyiRadicalsyiSyllablesyijingzanabazarSquare
 349     }
 350 
 351     public class Block
 352     {
 353         public Block(BlockId id_const string& shortName_const string& longName_uchar start_uchar end_) : 
 354             id(id_)shortName(shortName_)longName(longName_)start(start_)end(end_)
 355         {
 356         }
 357         public inline BlockId Id()
 358         {
 359             return id;
 360         }
 361         public inline const string& ShortName()
 362         {
 363             return shortName;
 364         }
 365         public inline const string& LongName()
 366         {
 367             return longName;
 368         }
 369         public inline uchar Start()
 370         {
 371             return start;
 372         }
 373         public inline uchar End()
 374         {
 375             return end;
 376         }
 377         private BlockId id;
 378         private string shortName;
 379         private string longName;
 380         private uchar start;
 381         private uchar end;
 382     }
 383 
 384     public class BlockTable : IOBase
 385     {
 386         static BlockTable() : instance(new BlockTable())
 387         {
 388         }
 389         public static BlockTable& Instance()
 390         {
 391             return *instance;
 392         }
 393         [nodiscard]
 394         public inline Result<const Block*> GetBlock(BlockId id) const
 395         {
 396             if (Error())
 397             {
 398                 return Result<const Block*>(ErrorId(GetErrorId()));
 399             }
 400             auto it = blockIdMap.CFind(cast<uint>(cast<ushort>(id)));
 401             if (it != blockIdMap.CEnd())
 402             {
 403                 return Result<const Block*>(cast<Block*>(it->second));
 404             }
 405             const Block* n = null;
 406             return Result<const Block*>(n);
 407         }
 408         [nodiscard]
 409         public inline Result<const Block*> GetBlockByShortName(const string& shortName) const
 410         {
 411             if (Error())
 412             {
 413                 return Result<const Block*>(ErrorId(GetErrorId()));
 414             }
 415             auto result = MakeCanonicalPropertyName(shortName);
 416             if (result.Error())
 417             {
 418                 return Result<const Block*>(ErrorId(result.GetErrorId()));
 419             }
 420             auto it = shortNameMap.CFind(result.Value());
 421             if (it != shortNameMap.CEnd())
 422             {
 423                 return Result<const Block*>(cast<Block*>(it->second));
 424             }
 425             return Result<const Block*>(null);
 426         }
 427         [nodiscard]
 428         public inline Result<const Block*> GetBlockByLongName(const string& longName) const
 429         {
 430             if (Error())
 431             {
 432                 return Result<const Block*>(ErrorId(GetErrorId()));
 433             }
 434             auto result = MakeCanonicalPropertyName(longName);
 435             if (result.Error())
 436             {
 437                 return Result<const Block*>(ErrorId(result.GetErrorId()));
 438             }
 439             auto it = longNameMap.CFind(result.Value());
 440             if (it != longNameMap.CEnd())
 441             {
 442                 return Result<const Block*>(cast<Block*>(it->second));
 443             }
 444             return Result<const Block*>(null);
 445         }
 446         private BlockTable() : base()blocks()blockIdMap()shortNameMap()longNameMap()
 447         {
 448             blocks.Add(new Block(BlockId.ascii"ASCII""Basic Latin"cast<uchar>(0u)     cast<uchar>(127u)));
 449             blocks.Add(new Block(BlockId.latin1Sup"Latin 1 Sup""Latin-1 Supplement"cast<uchar>(128u)   cast<uchar>(255u)));
 450             blocks.Add(new Block(BlockId.latinExtA"Latin Ext A""Latin Extended-A"cast<uchar>(256u)   cast<uchar>(383u)));
 451             blocks.Add(new Block(BlockId.latinExtB"Latin Ext B""Latin Extended-B"cast<uchar>(384u)   cast<uchar>(591u)));
 452             blocks.Add(new Block(BlockId.ipaExt"IPA Ext""IPA Extensions"cast<uchar>(592u)   cast<uchar>(687u)));
 453             blocks.Add(new Block(BlockId.modifierLetters"Modifier Letters""Spacing Modifier Letters"cast<uchar>(688u)   cast<uchar>(767u)));
 454             blocks.Add(new Block(BlockId.diacriticals"Diacriticals""Combining Diacritical Marks"cast<uchar>(768u)   cast<uchar>(879u)));
 455             blocks.Add(new Block(BlockId.greek"Greek""Greek and Coptic"cast<uchar>(880u)   cast<uchar>(1023u)));
 456             blocks.Add(new Block(BlockId.cyrillic"Cyrillic""Cyrillic"cast<uchar>(1024u)  cast<uchar>(1279u)));
 457             blocks.Add(new Block(BlockId.cyrillicSup"Cyrillic Sup""Cyrillic Supplement"cast<uchar>(1280u)  cast<uchar>(1327u)));
 458             blocks.Add(new Block(BlockId.armenian"Armenian""Armenian"cast<uchar>(1328u)  cast<uchar>(1423u)));
 459             blocks.Add(new Block(BlockId.hebrew"Hebrew""Hebrew"cast<uchar>(1424u)  cast<uchar>(1535u)));
 460             blocks.Add(new Block(BlockId.arabic"Arabic""Arabic"cast<uchar>(1536u)  cast<uchar>(1791u)));
 461             blocks.Add(new Block(BlockId.syriac"Syriac""Syriac"cast<uchar>(1792u)  cast<uchar>(1871u)));
 462             blocks.Add(new Block(BlockId.arabicSup"Arabic Sup""Arabic Supplement"cast<uchar>(1872u)  cast<uchar>(1919u)));
 463             blocks.Add(new Block(BlockId.thaana"Thaana""Thaana"cast<uchar>(1920u)  cast<uchar>(1983u)));
 464             blocks.Add(new Block(BlockId.nko"Nko""Nko"cast<uchar>(1984u)  cast<uchar>(2047u)));
 465             blocks.Add(new Block(BlockId.samaritan"Samaritan""Samaritan"cast<uchar>(2048u)  cast<uchar>(2111u)));
 466             blocks.Add(new Block(BlockId.mandaic"Mandaic""Mandaic"cast<uchar>(2112u)  cast<uchar>(2143u)));
 467             blocks.Add(new Block(BlockId.syriacSup"Syriac Sup""Syriac Supplement"cast<uchar>(2144)  cast<uchar>(2159)));
 468             blocks.Add(new Block(BlockId.arabicExtA"Arabic Ext A""Arabic Extended-A"cast<uchar>(2208u)  cast<uchar>(2303u)));
 469             blocks.Add(new Block(BlockId.devanagari"Devanagari""Devanagari"cast<uchar>(2304u)  cast<uchar>(2431u)));
 470             blocks.Add(new Block(BlockId.bengali"Bengali""Bengali"cast<uchar>(2432u)  cast<uchar>(2559u)));
 471             blocks.Add(new Block(BlockId.gurmukhi"Gurmukhi""Gurmukhi"cast<uchar>(2560u)  cast<uchar>(2687u)));
 472             blocks.Add(new Block(BlockId.gujarati"Gujarati""Gujarati"cast<uchar>(2688u)  cast<uchar>(2815u)));
 473             blocks.Add(new Block(BlockId.oriya"Oriya""Oriya"cast<uchar>(2816u)  cast<uchar>(2943u)));
 474             blocks.Add(new Block(BlockId.tamil"Tamil""Tamil"cast<uchar>(2944u)  cast<uchar>(3071u)));
 475             blocks.Add(new Block(BlockId.telugu"Telugu""Telugu"cast<uchar>(3072u)  cast<uchar>(3199u)));
 476             blocks.Add(new Block(BlockId.kannada"Kannada""Kannada"cast<uchar>(3200u)  cast<uchar>(3327u)));
 477             blocks.Add(new Block(BlockId.malayalam"Malayalam""Malayalam"cast<uchar>(3328u)  cast<uchar>(3455u)));
 478             blocks.Add(new Block(BlockId.sinhala"Sinhala""Sinhala"cast<uchar>(3456u)  cast<uchar>(3583u)));
 479             blocks.Add(new Block(BlockId.thai"Thai""Thai"cast<uchar>(3584u)  cast<uchar>(3711u)));
 480             blocks.Add(new Block(BlockId.lao"Lao""Lao"cast<uchar>(3712u)  cast<uchar>(3839u)));
 481             blocks.Add(new Block(BlockId.tibetan"Tibetan""Tibetan"cast<uchar>(3840u)  cast<uchar>(4095u)));
 482             blocks.Add(new Block(BlockId.myanmar"Myanmar""Myanmar"cast<uchar>(4096u)  cast<uchar>(4255u)));
 483             blocks.Add(new Block(BlockId.georgian"Georgian""Georgian"cast<uchar>(4256u)  cast<uchar>(4351u)));
 484             blocks.Add(new Block(BlockId.jamo"Jamo""Hangul Jamo"cast<uchar>(4352u)  cast<uchar>(4607u)));
 485             blocks.Add(new Block(BlockId.ethiopic"Ethiopic""Ethiopic"cast<uchar>(4608u)  cast<uchar>(4991u)));
 486             blocks.Add(new Block(BlockId.ethiopicSup"Ethiopic Sup""Ethiopic Supplement"cast<uchar>(4992u)  cast<uchar>(5023u)));
 487             blocks.Add(new Block(BlockId.cherokee"Cherokee""Cherokee"cast<uchar>(5024u)  cast<uchar>(5119u)));
 488             blocks.Add(new Block(BlockId.ucas"UCAS""Unified Canadian Aboriginal Syllabics"cast<uchar>(5120u)  cast<uchar>(5759u)));
 489             blocks.Add(new Block(BlockId.ogham"Ogham""Ogham"cast<uchar>(5760u)  cast<uchar>(5791u)));
 490             blocks.Add(new Block(BlockId.runic"Runic""Runic"cast<uchar>(5792u)  cast<uchar>(5887u)));
 491             blocks.Add(new Block(BlockId.tagalog"Tagalog""Tagalog"cast<uchar>(5888u)  cast<uchar>(5919u)));
 492             blocks.Add(new Block(BlockId.hanunoo"Hanunoo""Hanunoo"cast<uchar>(5920u)  cast<uchar>(5951u)));
 493             blocks.Add(new Block(BlockId.buhid"Buhid""Buhid"cast<uchar>(5952u)  cast<uchar>(5983u)));
 494             blocks.Add(new Block(BlockId.tagbanwa"Tagbanwa""Tagbanwa"cast<uchar>(5984u)  cast<uchar>(6015u)));
 495             blocks.Add(new Block(BlockId.khmer"Khmer""Khmer"cast<uchar>(6016u)  cast<uchar>(6143u)));
 496             blocks.Add(new Block(BlockId.mongolian"Mongolian""Mongolian"cast<uchar>(6144u)  cast<uchar>(6319u)));
 497             blocks.Add(new Block(BlockId.ucasExt"UCAS Ext""Unified Canadian Aboriginal Syllabics Extended"cast<uchar>(6320u)  cast<uchar>(6399u)));
 498             blocks.Add(new Block(BlockId.limbu"Limbu""Limbu"cast<uchar>(6400u)  cast<uchar>(6479u)));
 499             blocks.Add(new Block(BlockId.taiLe"Tai Le""Tai Le"cast<uchar>(6480u)  cast<uchar>(6527u)));
 500             blocks.Add(new Block(BlockId.newTaiLue"New Tai Lue""New Tai Lue"cast<uchar>(6528u)  cast<uchar>(6623u)));
 501             blocks.Add(new Block(BlockId.khmerSymbols"Khmer Symbols""Khmer Symbols"cast<uchar>(6624u)  cast<uchar>(6655u)));
 502             blocks.Add(new Block(BlockId.buginese"Buginese""Buginese"cast<uchar>(6656u)  cast<uchar>(6687u)));
 503             blocks.Add(new Block(BlockId.taiTham"Tai Tham""Tai Tham"cast<uchar>(6688u)  cast<uchar>(6831u)));
 504             blocks.Add(new Block(BlockId.diacriticalsExt"Diacriticals Ext""Combining Diacritical Marks Extended"cast<uchar>(6832u)  cast<uchar>(6911u)));
 505             blocks.Add(new Block(BlockId.balinese"Balinese""Balinese"cast<uchar>(6912u)  cast<uchar>(7039u)));
 506             blocks.Add(new Block(BlockId.sundanese"Sundanese""Sundanese"cast<uchar>(7040u)  cast<uchar>(7103u)));
 507             blocks.Add(new Block(BlockId.batak"Batak""Batak"cast<uchar>(7104u)  cast<uchar>(7167u)));
 508             blocks.Add(new Block(BlockId.lepcha"Lepcha""Lepcha"cast<uchar>(7168u)  cast<uchar>(7247u)));
 509             blocks.Add(new Block(BlockId.olChiki"Ol Chiki""Ol Chiki"cast<uchar>(7248u)  cast<uchar>(7295u)));
 510             blocks.Add(new Block(BlockId.cyrillicExtC"Cyrillic Ext C""Cyrillic Extended-C"cast<uchar>(7296u)  cast<uchar>(7311u)));
 511             blocks.Add(new Block(BlockId.georgianExt"Georgian Ext""Georgian Extended"cast<uchar>(7312)  cast<uchar>(7359)));
 512             blocks.Add(new Block(BlockId.sundaneseSup"Sundanese Sup""Sundanese Supplement"cast<uchar>(7360u)  cast<uchar>(7375u)));
 513             blocks.Add(new Block(BlockId.vedicExt"Vedic Ext""Vedic Extensions"cast<uchar>(7376u)  cast<uchar>(7423u)));
 514             blocks.Add(new Block(BlockId.phoneticExt"Phonetic Ext""Phonetic Extensions"cast<uchar>(7424u)  cast<uchar>(7551u)));
 515             blocks.Add(new Block(BlockId.phoneticExtSup"Phonetic Ext Sup""Phonetic Extensions Supplement"cast<uchar>(7552u)  cast<uchar>(7615u)));
 516             blocks.Add(new Block(BlockId.diacriticalsSup"Diacriticals Sup""Combining Diacritical Marks Supplement"cast<uchar>(7616u)  cast<uchar>(7679u)));
 517             blocks.Add(new Block(BlockId.latinExtAdditional"Latin Ext Additional""Latin Extended Additional"cast<uchar>(7680u)  cast<uchar>(7935u)));
 518             blocks.Add(new Block(BlockId.greekExt"Greek Ext""Greek Extended"cast<uchar>(7936u)  cast<uchar>(8191u)));
 519             blocks.Add(new Block(BlockId.punctuation"Punctuation""General Punctuation"cast<uchar>(8192u)  cast<uchar>(8303u)));
 520             blocks.Add(new Block(BlockId.superAndSub"Super And Sub""Superscripts and Subscripts"cast<uchar>(8304u)  cast<uchar>(8351u)));
 521             blocks.Add(new Block(BlockId.currencySymbols"Currency Symbols""Currency Symbols"cast<uchar>(8352u)  cast<uchar>(8399u)));
 522             blocks.Add(new Block(BlockId.diariticalsForSymbols"Diacriticals For Symbols""Combining Diacritical Marks for Symbols"cast<uchar>(8400u)  cast<uchar>(8447u)));
 523             blocks.Add(new Block(BlockId.letterlikeSymbols"Letterlike Symbols""Letterlike Symbols"cast<uchar>(8448u)  cast<uchar>(8527u)));
 524             blocks.Add(new Block(BlockId.numberForms"Number Forms""Number Forms"cast<uchar>(8528u)  cast<uchar>(8591u)));
 525             blocks.Add(new Block(BlockId.arrows"Arrows""Arrows"cast<uchar>(8592u)  cast<uchar>(8703u)));
 526             blocks.Add(new Block(BlockId.mathOperators"Math Operators""Mathematical Operators"cast<uchar>(8704u)  cast<uchar>(8959u)));
 527             blocks.Add(new Block(BlockId.miscTechnical"Misc Technical""Miscellaneous Technical"cast<uchar>(8960u)  cast<uchar>(9215u)));
 528             blocks.Add(new Block(BlockId.controlPictures"Control Pictures""Control Pictures"cast<uchar>(9216u)  cast<uchar>(9279u)));
 529             blocks.Add(new Block(BlockId.ocr"OCR""Optical Character Regognition"cast<uchar>(9280u)  cast<uchar>(9311u)));
 530             blocks.Add(new Block(BlockId.enclosedAlphanum"Enclosed Alphanum""Enclosed Alphanumerics"cast<uchar>(9312u)  cast<uchar>(9471u)));
 531             blocks.Add(new Block(BlockId.boxDrawing"Box Drawing""Box Drawing"cast<uchar>(9472u)  cast<uchar>(9599u)));
 532             blocks.Add(new Block(BlockId.blockElements"Block Elements""Block Elements"cast<uchar>(9600u)  cast<uchar>(9631u)));
 533             blocks.Add(new Block(BlockId.geometricShapes"Geometric Shapes""Geometric Shapes"cast<uchar>(9632u)  cast<uchar>(9727u)));
 534             blocks.Add(new Block(BlockId.miscSymbols"Misc Symbols""Miscellaneous Symbols"cast<uchar>(9728u)  cast<uchar>(9983u)));
 535             blocks.Add(new Block(BlockId.dingbats"Dingbats""Dingbats"cast<uchar>(9984u)  cast<uchar>(10175u)));
 536             blocks.Add(new Block(BlockId.miscMathSymbolsA"Misc Math Symbols A""Miscellaneous Mathematical Symbols - A"cast<uchar>(10176u) cast<uchar>(10223u)));
 537             blocks.Add(new Block(BlockId.supArrowsA"Sup Arrows A""Supplemental Arrows-A"cast<uchar>(10224u) cast<uchar>(10239u)));
 538             blocks.Add(new Block(BlockId.braille"Braille""Braille Patterns"cast<uchar>(10240u) cast<uchar>(10495u)));
 539             blocks.Add(new Block(BlockId.supArrowsB"Sup Arrows B""Supplemental Arrows-B"cast<uchar>(10496u) cast<uchar>(10623u)));
 540             blocks.Add(new Block(BlockId.miscMathSymbolsB"Misc Math Symbols B""Miscellaneous Mathematical Symbols-B"cast<uchar>(10624u) cast<uchar>(10751u)));
 541             blocks.Add(new Block(BlockId.supMathOperators"Sup Math Operators""Supplemental Mathematical Operators"cast<uchar>(10752u) cast<uchar>(11007u)));
 542             blocks.Add(new Block(BlockId.miscArrows"Misc Arrows""Miscellaneous Symbols and Arrows"cast<uchar>(11008u) cast<uchar>(11263u)));
 543             blocks.Add(new Block(BlockId.glagolitic"Glagolitic""Glagolitic"cast<uchar>(11264u) cast<uchar>(11359u)));
 544             blocks.Add(new Block(BlockId.latinExtC"Latin Ext C""Latin Extended-C"cast<uchar>(11360u) cast<uchar>(11391u)));
 545             blocks.Add(new Block(BlockId.coptic"Coptic""Coptic"cast<uchar>(11392u) cast<uchar>(11519u)));
 546             blocks.Add(new Block(BlockId.georgianSup"Georgian Sup""Georgian Supplement"cast<uchar>(11520u) cast<uchar>(11567u)));
 547             blocks.Add(new Block(BlockId.tifinagh"Tifinagh""Tifinagh"cast<uchar>(11568u) cast<uchar>(11647u)));
 548             blocks.Add(new Block(BlockId.ethiopicExt"Ethiopic Ext""Ethiopic Extended"cast<uchar>(11648u) cast<uchar>(11743u)));
 549             blocks.Add(new Block(BlockId.cyrillicExtA"Cyrillic Ext A""Cyrillic Extended-A"cast<uchar>(11744u) cast<uchar>(11775u)));
 550             blocks.Add(new Block(BlockId.supPunctuation"Sup Punctuation""Supplemental Punctuation"cast<uchar>(11776u) cast<uchar>(11903u)));
 551             blocks.Add(new Block(BlockId.cjkRadicalsSup"CJK Radicals Sup""CJK Radicals Supplement"cast<uchar>(11904u) cast<uchar>(12031u)));
 552             blocks.Add(new Block(BlockId.kangxi"Kangxi""Kangxi Radicals"cast<uchar>(12032u) cast<uchar>(12255u)));
 553             blocks.Add(new Block(BlockId.idc"IDC""Ideographic Description Characters"cast<uchar>(12272u) cast<uchar>(12287u)));
 554             blocks.Add(new Block(BlockId.cjkSymbols"CJK Symbols""CJK Symbols and Punctuation"cast<uchar>(12288u) cast<uchar>(12351u)));
 555             blocks.Add(new Block(BlockId.hiragana"Hiragana""Hiragana"cast<uchar>(12352u) cast<uchar>(12447u)));
 556             blocks.Add(new Block(BlockId.katakana"Katakana""Katakana"cast<uchar>(12448u) cast<uchar>(12543u)));
 557             blocks.Add(new Block(BlockId.bopomofo"Bopomofo""Bopomofo"cast<uchar>(12544u) cast<uchar>(12591u)));
 558             blocks.Add(new Block(BlockId.compatJamo"Compat Jamo""Hangul Compatibility Jamo"cast<uchar>(12592u) cast<uchar>(12687u)));
 559             blocks.Add(new Block(BlockId.kanbun"Kanbun""Kanbun"cast<uchar>(12688u) cast<uchar>(12703u)));
 560             blocks.Add(new Block(BlockId.bopomofoExt"Bopomofo Ext""Bopomofo Extended"cast<uchar>(12704u) cast<uchar>(12735u)));
 561             blocks.Add(new Block(BlockId.cjkStrokes"CJK Strokes""CJK Strokes"cast<uchar>(12736u) cast<uchar>(12783u)));
 562             blocks.Add(new Block(BlockId.katakanaExt"Katakana Ext""Katakana Phonetic Extensions"cast<uchar>(12784u) cast<uchar>(12799u)));
 563             blocks.Add(new Block(BlockId.enclosedCjk"Enclosed CJK""Enclosed CJK Letters and Months"cast<uchar>(12800u) cast<uchar>(13055u)));
 564             blocks.Add(new Block(BlockId.cjkCompat"CJK Compat""CJK Compatibility"cast<uchar>(13056u) cast<uchar>(13311u)));
 565             blocks.Add(new Block(BlockId.cjkExtA"CJK Ext A""CJK Unified Ideographic Extension A"cast<uchar>(13312u) cast<uchar>(19903u)));
 566             blocks.Add(new Block(BlockId.yijing"Yijing""Yijing Hexagram Symbols"cast<uchar>(19904u) cast<uchar>(19967u)));
 567             blocks.Add(new Block(BlockId.cjk"CJK""CJK Unified Ideographs"cast<uchar>(19968u) cast<uchar>(40959u)));
 568             blocks.Add(new Block(BlockId.yiSyllables"Yi Syllables""Yi Syllables"cast<uchar>(40960u) cast<uchar>(42127u)));
 569             blocks.Add(new Block(BlockId.yiRadicals"Yi Radicals""Yi Radicals"cast<uchar>(41104u) cast<uchar>(42191u)));
 570             blocks.Add(new Block(BlockId.lisu"Lisu""Lisu"cast<uchar>(41168u) cast<uchar>(42239u)));
 571             blocks.Add(new Block(BlockId.vai"Vai""Vai"cast<uchar>(42240u) cast<uchar>(42559u)));
 572             blocks.Add(new Block(BlockId.cyrillicExtB"Cyrillic Ext B""Cyrillic Extended-B"cast<uchar>(42560u) cast<uchar>(42655u)));
 573             blocks.Add(new Block(BlockId.bamum"Bamum""Bamum"cast<uchar>(42656u) cast<uchar>(42751u)));
 574             blocks.Add(new Block(BlockId.modifierToneLetters"Modifier Tone Letters""Modifier Tone Letters"cast<uchar>(42752u) cast<uchar>(42783u)));
 575             blocks.Add(new Block(BlockId.latinExtD"Latin Ext D""Latin Extended-D"cast<uchar>(42784u) cast<uchar>(43007u)));
 576             blocks.Add(new Block(BlockId.sylotiNagri"Syloti Nagri""Syloti Nagri"cast<uchar>(43008u) cast<uchar>(43055u)));
 577             blocks.Add(new Block(BlockId.indicNumberForms"Indic Number Forms""Common Indic Number Forms"cast<uchar>(43056u) cast<uchar>(43071u)));
 578             blocks.Add(new Block(BlockId.phagsPa"Phags Pa""Phags-Pa"cast<uchar>(43072u) cast<uchar>(43135u)));
 579             blocks.Add(new Block(BlockId.saurashtra"Saurashtra""Saurashtra"cast<uchar>(43136u) cast<uchar>(43231u)));
 580             blocks.Add(new Block(BlockId.devanagariExt"Devanagari Ext""Devanagari Extended"cast<uchar>(43232u) cast<uchar>(43263u)));
 581             blocks.Add(new Block(BlockId.kayahLi"Kayah Li""Kayah Li"cast<uchar>(43264u) cast<uchar>(43311u)));
 582             blocks.Add(new Block(BlockId.rejang"Rejang""Rejang"cast<uchar>(43312u) cast<uchar>(43359u)));
 583             blocks.Add(new Block(BlockId.jamoExtA"Jamo Ext A""Hangul Jamo Extended-A"cast<uchar>(43360u) cast<uchar>(43391u)));
 584             blocks.Add(new Block(BlockId.javanese"Javanese""Javanese"cast<uchar>(43392u) cast<uchar>(43487u)));
 585             blocks.Add(new Block(BlockId.myanmarExtB"Myanmar Ext B""Myanmar Extended - B"cast<uchar>(43488u) cast<uchar>(43519u)));
 586             blocks.Add(new Block(BlockId.cham"Cham""Cham"cast<uchar>(43520u)cast<uchar>(43615u)));
 587             blocks.Add(new Block(BlockId.myanmarExtA"Myanmar Ext A""Myanmar Extended-A"cast<uchar>(43616u) cast<uchar>(43647u)));
 588             blocks.Add(new Block(BlockId.taiViet"Tai Viet""Tai Viet"cast<uchar>(43648u) cast<uchar>(43743u)));
 589             blocks.Add(new Block(BlockId.meeteiMayekExt"Meetei Mayek Ext""Meetei Mayek Extensions"cast<uchar>(43744u) cast<uchar>(43775u)));
 590             blocks.Add(new Block(BlockId.ethiopicExtA"Ethiopic Ext A""Ethiopic Extended-A"cast<uchar>(43776u) cast<uchar>(43823u)));
 591             blocks.Add(new Block(BlockId.latinExtE"Latin Ext E""Latin Extended-E"cast<uchar>(43824u) cast<uchar>(43887u)));
 592             blocks.Add(new Block(BlockId.cherokeeSup"Cherokee Sup""Cherokee Supplement"cast<uchar>(43888u) cast<uchar>(43967u)));
 593             blocks.Add(new Block(BlockId.meeteiMayek"Meetei Mayek""Meetei Mayek"cast<uchar>(43968u) cast<uchar>(44031u)));
 594             blocks.Add(new Block(BlockId.hangul"Hangul""Hangul Syllables"cast<uchar>(44032u) cast<uchar>(55215u)));
 595             blocks.Add(new Block(BlockId.jamoExtB"Jamo Ext B""Hangul Jamo Extended-B"cast<uchar>(55216u) cast<uchar>(55295u)));
 596             blocks.Add(new Block(BlockId.highSurrogates"High Surrogates""High Surrogates"cast<uchar>(55296u) cast<uchar>(56191u)));
 597             blocks.Add(new Block(BlockId.highPuSurrogates "High PU Surrogates""High Private Use Surrogates"cast<uchar>(56192u) cast<uchar>(56319u)));
 598             blocks.Add(new Block(BlockId.lowSurrogates"Low Surrogates""Low Surrogates"cast<uchar>(56320u) cast<uchar>(57343u)));
 599             blocks.Add(new Block(BlockId.pua"PUA""Private Use Area"cast<uchar>(57344u) cast<uchar>(63743u)));
 600             blocks.Add(new Block(BlockId.cjkCompatIdeographs"CJK Compat Ideographs""CJK Compatibility Ideographs"cast<uchar>(63744u) cast<uchar>(64255u)));
 601             blocks.Add(new Block(BlockId.alphabeticPf"Alphabetic PF""Alphabetic Presentations Forms"cast<uchar>(64256u) cast<uchar>(64335u)));
 602             blocks.Add(new Block(BlockId.arabicPfA"Arabic PF A""Arabic Presentation Forms-A"cast<uchar>(64336u) cast<uchar>(65023u)));
 603             blocks.Add(new Block(BlockId.vs"VS""Variation Selectors"cast<uchar>(65024u) cast<uchar>(65039u)));
 604             blocks.Add(new Block(BlockId.verticalForms"Vertical Forms""Vertical Forms"cast<uchar>(65040u) cast<uchar>(65055u)));
 605             blocks.Add(new Block(BlockId.halfMarks"Half Marks""Combining Half Marks"cast<uchar>(65056u) cast<uchar>(65071u)));
 606             blocks.Add(new Block(BlockId.cjkCompatForms"CJK Compat Forms""CJK Compatibility Forms"cast<uchar>(65072u) cast<uchar>(65103u)));
 607             blocks.Add(new Block(BlockId.smallForms"Small Forms""Small Form Variants"cast<uchar>(65104u) cast<uchar>(65135u)));
 608             blocks.Add(new Block(BlockId.arabicPfB"Arabic PF B""Arabic Presentation Forms-B"cast<uchar>(65136u) cast<uchar>(65279u)));
 609             blocks.Add(new Block(BlockId.halfAndFullForms"Half And Full Forms""Halfwidth and Fullwidth Forms"cast<uchar>(65280u) cast<uchar>(65519u)));
 610             blocks.Add(new Block(BlockId.specials"Specials""Specials"cast<uchar>(65520u) cast<uchar>(65535u)));
 611             blocks.Add(new Block(BlockId.linearBSyllabary"Linear B Syllabary""Linear B Syllabary"cast<uchar>(65536u)  cast<uchar>(65663u)));
 612             blocks.Add(new Block(BlockId.linearBIdeograms"Linear B Ideograms""Linear B Ideograms"cast<uchar>(65664u)  cast<uchar>(65791u)));
 613             blocks.Add(new Block(BlockId.aegeanNumbers"Aegean Numbers""Aegean Numbers"cast<uchar>(65792u)  cast<uchar>(65855u)));
 614             blocks.Add(new Block(BlockId.ancientGreekNumbers"Ancient Greek Numbers""Ancient Greek Numbers"cast<uchar>(65856u)  cast<uchar>(65935u)));
 615             blocks.Add(new Block(BlockId.ancientSymbols"Ancient Symbols""Ancient Symbols"cast<uchar>(65936u)  cast<uchar>(65999u)));
 616             blocks.Add(new Block(BlockId.phaistos"Phaistos""Phaistos Disc"cast<uchar>(66000u)  cast<uchar>(66047u)));
 617             blocks.Add(new Block(BlockId.lycian"Lycian""Lycian"cast<uchar>(66176u)  cast<uchar>(66207u)));
 618             blocks.Add(new Block(BlockId.carian"Carian""Carian"cast<uchar>(66208u)  cast<uchar>(66271u)));
 619             blocks.Add(new Block(BlockId.copticEpactNumbers"Coptic Epact Numbers""Coptic Epact Numbers"cast<uchar>(66272u)  cast<uchar>(66303u)));
 620             blocks.Add(new Block(BlockId.oldItalic"Old Italic""Old Italic"cast<uchar>(66304u)  cast<uchar>(66351u)));
 621             blocks.Add(new Block(BlockId.gothic"Gothic""Gothic"cast<uchar>(66352u)  cast<uchar>(66383u)));
 622             blocks.Add(new Block(BlockId.oldPermic"Old Permic""Old Permic"cast<uchar>(66384u)  cast<uchar>(66431u)));
 623             blocks.Add(new Block(BlockId.ugaritic"Ugaritic""Ugaritic"cast<uchar>(66432u)  cast<uchar>(66463u)));
 624             blocks.Add(new Block(BlockId.oldPersian"Old Persian""Old Persian"cast<uchar>(66464u)  cast<uchar>(66527u)));
 625             blocks.Add(new Block(BlockId.deseret"Deseret""Deseret"cast<uchar>(66560u)  cast<uchar>(66639u)));
 626             blocks.Add(new Block(BlockId.shavian"Shavian""Shavian"cast<uchar>(66640u)  cast<uchar>(66687u)));
 627             blocks.Add(new Block(BlockId.osmanya"Osmanya""Osmanya"cast<uchar>(66688u)  cast<uchar>(66735u)));
 628             blocks.Add(new Block(BlockId.osage"Osage""Osage"cast<uchar>(66736u)  cast<uchar>(66815u)));
 629             blocks.Add(new Block(BlockId.elbasan"Elbasan""Elbasan"cast<uchar>(66816u)  cast<uchar>(66863u)));
 630             blocks.Add(new Block(BlockId.caucasianAlbanian"Caucasian Albanian""Caucasian Albanian"cast<uchar>(66864u)  cast<uchar>(66927u)));
 631             blocks.Add(new Block(BlockId.linearA"Linear A""Linear A"cast<uchar>(67072u)  cast<uchar>(67455u)));
 632             blocks.Add(new Block(BlockId.cypriotSyllabary"Cypriot Syllabary""Cypriot Syllabary"cast<uchar>(67584u)  cast<uchar>(67647u)));
 633             blocks.Add(new Block(BlockId.imperialAramaic"Imperial Aramaic""Imperial Aramaic"cast<uchar>(67648u)  cast<uchar>(67679u)));
 634             blocks.Add(new Block(BlockId.palmyrene"Palmyrene""Palmyrene"cast<uchar>(67680u)  cast<uchar>(67711u)));
 635             blocks.Add(new Block(BlockId.nabataean"Nabataean""Nabataean"cast<uchar>(67712u)  cast<uchar>(67759u)));
 636             blocks.Add(new Block(BlockId.hatran"Hatran""Hatran"cast<uchar>(67808u)  cast<uchar>(67839u)));
 637             blocks.Add(new Block(BlockId.phoenician"Phoenician""Phoenician"cast<uchar>(67840u)  cast<uchar>(67871u)));
 638             blocks.Add(new Block(BlockId.lydian"Lydian""Lydian"cast<uchar>(67872u)  cast<uchar>(67903u)));
 639             blocks.Add(new Block(BlockId.meroiticHieroglyphs"Meroitic Hieroglyphs""Meroitic Hieroglyphs"cast<uchar>(67968u)  cast<uchar>(67999u)));
 640             blocks.Add(new Block(BlockId.meroiticCursive"Meroitic Cursive""Meroitic Cursive"cast<uchar>(68000u)  cast<uchar>(68095u)));
 641             blocks.Add(new Block(BlockId.kharoshthi"Kharoshthi""Kharoshthi"cast<uchar>(68096u)  cast<uchar>(68191u)));
 642             blocks.Add(new Block(BlockId.oldSouthArabian"Old South Arabian""Old South Arabian"cast<uchar>(68192u)  cast<uchar>(68223u)));
 643             blocks.Add(new Block(BlockId.oldNorthArabian"Old North Arabian""Old North Arabian"cast<uchar>(68224u)  cast<uchar>(68255u)));
 644             blocks.Add(new Block(BlockId.manichean"Manichaean""Manichaean"cast<uchar>(68288u)  cast<uchar>(68351u)));
 645             blocks.Add(new Block(BlockId.avestan"Avestan""Avestan"cast<uchar>(68352u)  cast<uchar>(68415u)));
 646             blocks.Add(new Block(BlockId.inscriptionalParthian"Inscriptional Parthian""Inscriptional Parthian"cast<uchar>(68416u)  cast<uchar>(68447u)));
 647             blocks.Add(new Block(BlockId.inscriptionalPahlavi"Inscriptional Pahlavi""Inscriptional Pahlavi"cast<uchar>(68448u)  cast<uchar>(68479u)));
 648             blocks.Add(new Block(BlockId.psalterPahlavi"Psalter Pahlavi""Psalter Pahlavi"cast<uchar>(68480u)  cast<uchar>(68527u)));
 649             blocks.Add(new Block(BlockId.oldTurkic"Old Turkic""Old Turkic"cast<uchar>(68608u)  cast<uchar>(68687u)));
 650             blocks.Add(new Block(BlockId.oldHungarian"Old Hungarian""Old Hungarian"cast<uchar>(68736u)  cast<uchar>(68863u)));
 651             blocks.Add(new Block(BlockId.hanifiRohingya"Hanifi Rohingya""Hanifi Rohingya"cast<uchar>(68864u)  cast<uchar>(68927u)));
 652             blocks.Add(new Block(BlockId.rumi"Rumi""Rumi Numeral Symbols"cast<uchar>(69216u)  cast<uchar>(69247u)));
 653             blocks.Add(new Block(BlockId.oldSogdian"Old Sogdian""Old Sogdian"cast<uchar>(69376u)  cast<uchar>(69423u)));
 654             blocks.Add(new Block(BlockId.sogdian"Sogdian""Sogdian"cast<uchar>(69424u)  cast<uchar>(69487u)));
 655             blocks.Add(new Block(BlockId.elymaic"Elymaic""Elymaic"cast<uchar>(69600)  cast<uchar>(69631)));
 656             blocks.Add(new Block(BlockId.brahmi"Brahmi""Brahmi"cast<uchar>(69632u)  cast<uchar>(69759u)));
 657             blocks.Add(new Block(BlockId.kaithi"Kaithi""Kaithi"cast<uchar>(69760u)  cast<uchar>(69839u)));
 658             blocks.Add(new Block(BlockId.soraSompeng"Sora Sompeng""Sora Sompeng"cast<uchar>(69840u)  cast<uchar>(69887u)));
 659             blocks.Add(new Block(BlockId.chakma"Chakma""Chakma"cast<uchar>(69888u)  cast<uchar>(69967u)));
 660             blocks.Add(new Block(BlockId.mahajani"Mahajani""Mahajani"cast<uchar>(69968u)  cast<uchar>(70015u)));
 661             blocks.Add(new Block(BlockId.sharada"Sharada""Sharada"cast<uchar>(70016u)  cast<uchar>(70111u)));
 662             blocks.Add(new Block(BlockId.sinhalaArchaicNumbers"Sinhala Archaic Numbers""Sinhala Archaic Numbers"cast<uchar>(70112u)  cast<uchar>(70143u)));
 663             blocks.Add(new Block(BlockId.khojki"Khojki""Khojki"cast<uchar>(70144u)  cast<uchar>(70223u)));
 664             blocks.Add(new Block(BlockId.multani"Multani""Multani"cast<uchar>(70272u)  cast<uchar>(70319u)));
 665             blocks.Add(new Block(BlockId.khudawadi"Khudawadi""Khudawadi"cast<uchar>(70320u)  cast<uchar>(70399u)));
 666             blocks.Add(new Block(BlockId.grantha"Grantha""Grantha"cast<uchar>(70400u)  cast<uchar>(70527u)));
 667             blocks.Add(new Block(BlockId.newa"Newa""Newa"cast<uchar>(70656u)  cast<uchar>(70783u)));
 668             blocks.Add(new Block(BlockId.tirhuta"Tirhuta""Tirhuta"cast<uchar>(70784u)  cast<uchar>(70879u)));
 669             blocks.Add(new Block(BlockId.siddham"Siddham""Siddham"cast<uchar>(71040u)  cast<uchar>(71167u)));
 670             blocks.Add(new Block(BlockId.modi"Modi""Modi"cast<uchar>(71168u)  cast<uchar>(71263u)));
 671             blocks.Add(new Block(BlockId.mongolianSup"Mongolian Sup""Mongolian Supplement"cast<uchar>(71264u)  cast<uchar>(71295u)));
 672             blocks.Add(new Block(BlockId.takri"Takri""Takri"cast<uchar>(71296u)  cast<uchar>(71375u)));
 673             blocks.Add(new Block(BlockId.ahom"Ahom""Ahom"cast<uchar>(71424u)  cast<uchar>(71487u)));
 674             blocks.Add(new Block(BlockId.dogra"Dogra""Dogra"cast<uchar>(71680u)  cast<uchar>(71759u)));
 675             blocks.Add(new Block(BlockId.warangCiti"Warang Citi""Warang Citi"cast<uchar>(71840u)  cast<uchar>(71935u)));
 676             blocks.Add(new Block(BlockId.nandinagari"Nandinagari""Nandinagari"cast<uchar>(72096)  cast<uchar>(72191)));
 677             blocks.Add(new Block(BlockId.zanabazarSquare"Zanabazar Square""Zanabazar Square"cast<uchar>(72192u)  cast<uchar>(1156351u)));
 678             blocks.Add(new Block(BlockId.soyombo"Soyombo""Soyombo"cast<uchar>(72272u)  cast<uchar>(72367u)));
 679             blocks.Add(new Block(BlockId.pauCinHau"Pau Cin Hau""Pau Cin Hau"cast<uchar>(72384u)  cast<uchar>(72447u)));
 680             blocks.Add(new Block(BlockId.bhaisuki"Bhaiksuki""Bhaiksuki"cast<uchar>(72704u)  cast<uchar>(72815u)));
 681             blocks.Add(new Block(BlockId.marchen"Marchen""Marchen"cast<uchar>(72816u)  cast<uchar>(72895u)));
 682             blocks.Add(new Block(BlockId.masaramGondi"Masaram Gondi""Masaram Gondi"cast<uchar>(72960)  cast<uchar>(73055)));
 683             blocks.Add(new Block(BlockId.gunjalaGondi"Gunjala Gondi""Gunjala Gondi"cast<uchar>(73056)  cast<uchar>(73135)));
 684             blocks.Add(new Block(BlockId.makasar"Makasar""Makasar"cast<uchar>(73440)  cast<uchar>(73471)));
 685             blocks.Add(new Block(BlockId.tamilSup"Tamil Sup""Tamil Sup"cast<uchar>(73664)  cast<uchar>(73726)));
 686             blocks.Add(new Block(BlockId.cuneiform"Cuneiform""Cuneiform"cast<uchar>(73728u)  cast<uchar>(74751u)));
 687             blocks.Add(new Block(BlockId.cuneiformNumbers"Cuneiform Numbers""Cuneiform Numbers and Punctuation"cast<uchar>(74752u)  cast<uchar>(74879u)));
 688             blocks.Add(new Block(BlockId.earlyDynasticCuneiform"Early Dynastic Cuneiform""Early Dynastic Cuneiform"cast<uchar>(74880u)  cast<uchar>(75087u)));
 689             blocks.Add(new Block(BlockId.egyptianHieroglyphs"Egyptian Hieroglyphs""Egyptian Hieroglyphs"cast<uchar>(77824u)  cast<uchar>(78895u)));
 690             blocks.Add(new Block(BlockId.egyptianHieroglyphFormatControls"Egyptian Hieroglyph Format Controls""Egyptian Hieroglyph Format Controls"cast<uchar>(78896)  cast<uchar>(78911)));
 691             blocks.Add(new Block(BlockId.anatolianHieroglyphs"Anatolian Hieroglyphs""Anatolian Hieroglyphs"cast<uchar>(82944u)  cast<uchar>(83583u)));
 692             blocks.Add(new Block(BlockId.bamumSup"Bamum Sup""Bamum Supplement"cast<uchar>(92160u)  cast<uchar>(92735u)));
 693             blocks.Add(new Block(BlockId.mro"Mro""Mro"cast<uchar>(92736u)  cast<uchar>(92783u)));
 694             blocks.Add(new Block(BlockId.bassaVah"Bassa Vah""Bassa Vah"cast<uchar>(92880u)  cast<uchar>(92927u)));
 695             blocks.Add(new Block(BlockId.pahawhHmong"Pahawh Hmong""Pahawh Hmong"cast<uchar>(92928u)  cast<uchar>(93071u)));
 696             blocks.Add(new Block(BlockId.medefaidrin"Medefaidrin""Medefaidrin"cast<uchar>(93760u)  cast<uchar>(93855u)));
 697             blocks.Add(new Block(BlockId.miao"Miao""Miao"cast<uchar>(93952u)  cast<uchar>(94111u)));
 698             blocks.Add(new Block(BlockId.ideographicSymbols"Ideographic Symbols""Ideographic Symbols and Punctuation"cast<uchar>(94176u)  cast<uchar>(94207u)));
 699             blocks.Add(new Block(BlockId.tangut"Tangut""Tangut"cast<uchar>(94208u)  cast<uchar>(100351u)));
 700             blocks.Add(new Block(BlockId.tangutComponents"Tangut Components""Tangut Components"cast<uchar>(100352u) cast<uchar>(101119u)));
 701             blocks.Add(new Block(BlockId.kanaSup"Kana Sup""Kana Supplement"cast<uchar>(110592u) cast<uchar>(110847u)));
 702             blocks.Add(new Block(BlockId.kanaExtA"Kana Ext A""Kana Extended-A"cast<uchar>(110848u) cast<uchar>(110895u)));
 703             blocks.Add(new Block(BlockId.smallKanaExt"Small Kana Ext""Small Kana Extension"cast<uchar>(110896) cast<uchar>(110959)));
 704             blocks.Add(new Block(BlockId.nushu"Nushu""Nushu"cast<uchar>(110960u) cast<uchar>(111359u)));
 705             blocks.Add(new Block(BlockId.duployan"Duployan""Duployan"cast<uchar>(113664u) cast<uchar>(113823u)));
 706             blocks.Add(new Block(BlockId.shorthandFormatControls"Shorthand Format Controls""Shorthand Format Controls"cast<uchar>(113824u) cast<uchar>(113839u)));
 707             blocks.Add(new Block(BlockId.byzantineMusic"Byzantine Music""Byzantine Musical Symbols"cast<uchar>(118784u) cast<uchar>(119039u)));
 708             blocks.Add(new Block(BlockId.music"Music""Musical Symbols"cast<uchar>(119040u) cast<uchar>(119295u)));
 709             blocks.Add(new Block(BlockId.ancientGreekMusic"Ancient Greek Music""Ancient Greek Musical Notation"cast<uchar>(119296u) cast<uchar>(119375u)));
 710             blocks.Add(new Block(BlockId.mayanNumerals"Mayan Numerals""Mayan Numerals"cast<uchar>(119520u) cast<uchar>(119551u)));
 711             blocks.Add(new Block(BlockId.taiXuanJing"Tai Xuan Jing""Tai Xuan Jing Symbols"cast<uchar>(119552u) cast<uchar>(119647u)));
 712             blocks.Add(new Block(BlockId.countingRod"Counting Rod""Counting Rod Numerals"cast<uchar>(119648u) cast<uchar>(119679u)));
 713             blocks.Add(new Block(BlockId.mathAlphanum"Math Alphanum""Mathematical Alphanumeric Symbols"cast<uchar>(119808u) cast<uchar>(120831u)));
 714             blocks.Add(new Block(BlockId.suttonSignWriting"Sutton SignWriting""Sutton SignWriting"cast<uchar>(120832u) cast<uchar>(121519u)));
 715             blocks.Add(new Block(BlockId.glagoliticSup"Glagolitic Sup""Glagolitic Supplement"cast<uchar>(122880u) cast<uchar>(122927u)));
 716             blocks.Add(new Block(BlockId.nyiakengPuachueHmong"Nyiakeng Puachue Hmong""Nyiakeng Puachue Hmong"cast<uchar>(123136) cast<uchar>(123215)));
 717             blocks.Add(new Block(BlockId.wancho"Wancho""Wancho"cast<uchar>(123584) cast<uchar>(123647)));
 718             blocks.Add(new Block(BlockId.mendeKikakui"Mende Kikakui""Mende Kikakui"cast<uchar>(124928u) cast<uchar>(125151u)));
 719             blocks.Add(new Block(BlockId.adlam"Adlam""Adlam"cast<uchar>(125184u) cast<uchar>(125279u)));
 720             blocks.Add(new Block(BlockId.indicSiyaqNumbers"Indic Siyaq Numbers""Indic Siyaq Numbers"cast<uchar>(126064) cast<uchar>(126143)));
 721             blocks.Add(new Block(BlockId.ottomanSiyaqNumbers"Ottoman Siyaq Numbers""Ottoman Siyaq Numbers"cast<uchar>(126208) cast<uchar>(126287)));
 722             blocks.Add(new Block(BlockId.arabicMath"Arabic Math""Arabic Mathematical Alphabetic Symbols"cast<uchar>(126464u) cast<uchar>(126719u)));
 723             blocks.Add(new Block(BlockId.mahjong"Mahjong""Mahjong Tiles"cast<uchar>(126976u) cast<uchar>(127023u)));
 724             blocks.Add(new Block(BlockId.domino"Domino""Domino Tiles"cast<uchar>(127024u) cast<uchar>(127135u)));
 725             blocks.Add(new Block(BlockId.playingCards"Playing Cards""Playing Cards"cast<uchar>(127136u) cast<uchar>(127231u)));
 726             blocks.Add(new Block(BlockId.enclosedAlphanumSup"Enclosed Alphanum Sup""Enclosed Alphanumeric Supplement"cast<uchar>(127232u) cast<uchar>(127487u)));
 727             blocks.Add(new Block(BlockId.enclosedIdeographicSup"Enclosed Ideographic Sup""Enclosed Ideographic Supplement"cast<uchar>(127488u) cast<uchar>(127743u)));
 728             blocks.Add(new Block(BlockId.miscPictographs"Misc Pictographs""Miscellaneous Symbols and Pictographs"cast<uchar>(127744u) cast<uchar>(128511u)));
 729             blocks.Add(new Block(BlockId.emoticons"Emoticons""Emoticons"cast<uchar>(128512u) cast<uchar>(128591u)));
 730             blocks.Add(new Block(BlockId.ornamentalDingbats"Ornamental Dingbats""Ornamental Dingbats"cast<uchar>(128592u) cast<uchar>(128639u)));
 731             blocks.Add(new Block(BlockId.transportAndMap"Transport And Map""Transport and Map Symbols"cast<uchar>(128640u) cast<uchar>(128767u)));
 732             blocks.Add(new Block(BlockId.alchemical"Alchemical""Alchemical Symbols"cast<uchar>(128768u) cast<uchar>(128895u)));
 733             blocks.Add(new Block(BlockId.geometricShapesExt"Geometric Shapes Ext""Geometric Shapes Extended"cast<uchar>(128896u) cast<uchar>(129023u)));
 734             blocks.Add(new Block(BlockId.supArrowsC"Sup Arrows C""Supplemental Arrows-C"cast<uchar>(129024u) cast<uchar>(129279u)));
 735             blocks.Add(new Block(BlockId.supSymbolsAndPictographs"Sup Symbols And Pictographs""Supplemental Symbols and Pictographs"cast<uchar>(129280u) cast<uchar>(129535u)));
 736             blocks.Add(new Block(BlockId.chessSymbols"Chess Symbols""Chess Symbols"cast<uchar>(129536u) cast<uchar>(129647u)));
 737             blocks.Add(new Block(BlockId.symbolsAndPictographsExtA"Symbols And Pictographs Ext A""Symbols And Pictographs Extended A"cast<uchar>(129648) cast<uchar>(129791)));
 738             blocks.Add(new Block(BlockId.cjkExtB"CJK Ext B""CJK Unified Ideographs Extension B"cast<uchar>(131072u) cast<uchar>(173791u)));
 739             blocks.Add(new Block(BlockId.cjkExtC"CJK Ext C""CJK Unified Ideographs Extension C"cast<uchar>(173824u) cast<uchar>(177983u)));
 740             blocks.Add(new Block(BlockId.cjkExtD"CJK Ext D""CJK Unified Ideographs Extension D"cast<uchar>(177984u) cast<uchar>(178207u)));
 741             blocks.Add(new Block(BlockId.cjkExtE"CJK Ext E""CJK Unified Ideographs Extension E"cast<uchar>(178208u) cast<uchar>(183983u)));
 742             blocks.Add(new Block(BlockId.cjkExtF"CJK Ext F""CJK Unified Ideographs Extension F"cast<uchar>(183984u) cast<uchar>(191471u)));
 743             blocks.Add(new Block(BlockId.cjkCompatIdeographsSup"CJK Compat Ideographs Sup""CJK Compatibility Ideographs Supplement"cast<uchar>(194560u) cast<uchar>(195103u)));
 744             blocks.Add(new Block(BlockId.tags"Tags""Tags"cast<uchar>(917504u) cast<uchar>(917631u)));
 745             blocks.Add(new Block(BlockId.vsSup"VS Sup""Variation Selectors Supplement"cast<uchar>(917760u) cast<uchar>(917999u)));
 746             blocks.Add(new Block(BlockId.supPuaA"Sup PUA A""Supplementary Private Use Area-A"cast<uchar>(983040u) cast<uchar>(1048575u)));
 747             blocks.Add(new Block(BlockId.supPuaB"Sup PUA B""Supplementary Private Use Area-B"cast<uchar>(1048576u) cast<uchar>(1114111u)));
 748             for (Block* block : blocks)
 749             {
 750                 blockIdMap[cast<uint>(cast<ushort>(block->Id()))] = block;
 751                 auto result = MakeCanonicalPropertyName(block->ShortName());
 752                 if (result.Error())
 753                 {
 754                     SetErrorId(result.GetErrorId());
 755                     return;
 756                 }
 757                 shortNameMap[result.Value()] = block;
 758                 result = MakeCanonicalPropertyName(block->LongName());
 759                 if (result.Error())
 760                 {
 761                     SetErrorId(result.GetErrorId());
 762                     return;
 763                 }
 764                 longNameMap[result.Value()] = block;
 765             }
 766         }
 767         public override ~BlockTable()
 768         {
 769             for (Block* block : blocks)
 770             {
 771                 delete block;
 772             }
 773         }
 774         private static UniquePtr<BlockTable> instance;
 775         private List<Block*> blocks;
 776         private Map<uintvoid*> blockIdMap;
 777         private Map<stringvoid*> shortNameMap;
 778         private Map<stringvoid*> longNameMap;
 779     }
 780 
 781     [nodiscard]
 782     public Result<const Block*> GetBlock(BlockId id)
 783     {
 784         return BlockTable.Instance().GetBlock(id);
 785     }
 786 
 787     [nodiscard]
 788     public Result<const Block*> GetBlockByShortName(const string& shortName)
 789     {
 790         return BlockTable.Instance().GetBlockByShortName(shortName);
 791     }
 792 
 793     [nodiscard]
 794     public Result<const Block*> GetBlockByLongName(const string& longName)
 795     {
 796         return BlockTable.Instance().GetBlockByLongName(longName);
 797     }
 798 
 799     public enum GeneralCategoryId : uint
 800     {
 801         none = 0u
 802         Lu = 1u << 0uLl = 1u << 1uLt = 1u << 2uLm = 1u << 3uLo = 1u << 4u
 803         LC = Lu | Ll | Lt
 804         L = Lu | Ll | Lt | Lm | Lo
 805         Mn = 1u << 5uMc = 1u << 6uMe = 1u << 7u
 806         M = Mn | Mc | Me
 807         Nd = 1u << 8uNl = 1u << 9uNo = 1u << 10u
 808         N = Nd | Nl | No
 809         Pc = 1u << 11uPd = 1u << 12uPs = 1u << 13uPe = 1u << 14uPi = 1u << 15uPf = 1u << 16uPo = 1u << 17u
 810         P = Pc | Pd | Ps | Pe | Pi | Pf | Po
 811         Sm = 1u << 18uSc = 1u << 19uSk = 1u << 20uSo = 1u << 21u
 812         S = Sm | Sc | Sk | So
 813         Zs = 1u << 22uZl = 1u << 23uZp = 1u << 24u
 814         Z = Zs | Zl | Zp
 815         Cc = 1u << 25uCf = 1u << 26uCs = 1u << 27uCo = 1u << 28uCn = 1u << 29u
 816         C = Cc | Cf | Cs | Co | Cn
 817         G = L | M | N | P | S | Zs
 818         B = L | N | P | S | Zs
 819     }
 820 
 821     public class GeneralCategory
 822     {
 823         public GeneralCategory(GeneralCategoryId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
 824         {
 825         }
 826         public inline GeneralCategoryId Id()
 827         {
 828             return id;
 829         }
 830         public inline const string& ShortName()
 831         {
 832             return shortName;
 833         }
 834         public inline const string& LongName()
 835         {
 836             return longName;
 837         }
 838         private GeneralCategoryId id;
 839         private string shortName;
 840         private string longName;
 841     }
 842 
 843     public class GeneralCategoryTable : IOBase
 844     {
 845         static GeneralCategoryTable() : instance(new GeneralCategoryTable())
 846         {
 847         }
 848         public static GeneralCategoryTable& Instance()
 849         {
 850             return *instance;
 851         }
 852         [nodiscard]
 853         public Result<const GeneralCategory*> GetGeneralCategory(GeneralCategoryId id) const
 854         {
 855             if (Error())
 856             {
 857                 return Result<const GeneralCategory*>(ErrorId(GetErrorId()));
 858             }
 859             auto it = generalCategoryIdMap.CFind(cast<uint>(id));
 860             if (it != generalCategoryIdMap.CEnd())
 861             {
 862                 return Result<const GeneralCategory*>(cast<GeneralCategory*>(it->second));
 863             }
 864             const GeneralCategory* n = null;
 865             return Result<const GeneralCategory*>(n);
 866         }
 867         [nodiscard]
 868         public Result<const GeneralCategory*> GetGeneralCategoryByShortName(const string& shortName) const
 869         {
 870             if (Error())
 871             {
 872                 return Result<const GeneralCategory*>(ErrorId(GetErrorId()));
 873             }
 874             auto result = MakeCanonicalPropertyName(shortName);
 875             if (result.Error())
 876             {
 877                 return Result<const GeneralCategory*>(ErrorId(result.GetErrorId()));
 878             }
 879             auto it = shortNameMap.CFind(result.Value());
 880             if (it != shortNameMap.CEnd())
 881             {
 882                 return Result<const GeneralCategory*>(cast<GeneralCategory*>(it->second));
 883             }
 884             return Result<const GeneralCategory*>(null);
 885         }
 886         [nodiscard]
 887         public Result<const GeneralCategory*> GetGeneralCategoryByLongName(const string& longName) const
 888         {
 889             if (Error())
 890             {
 891                 return Result<const GeneralCategory*>(ErrorId(GetErrorId()));
 892             }
 893             auto result = MakeCanonicalPropertyName(longName);
 894             if (result.Error())
 895             {
 896                 return Result<const GeneralCategory*>(ErrorId(result.GetErrorId()));
 897             }
 898             auto it = longNameMap.CFind(result.Value());
 899             if (it != longNameMap.CEnd())
 900             {
 901                 return Result<const GeneralCategory*>(cast<GeneralCategory*>(it->second));
 902             }
 903             return Result<const GeneralCategory*>(null);
 904         }
 905         private GeneralCategoryTable() : base()generalCategories()generalCategoryIdMap()shortNameMap()longNameMap()
 906         {
 907             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lu"Lu""Uppercase Letter"));
 908             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lu"Ll""Lowercase Letter"));
 909             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lt"Lt""Titlecase Letter"));
 910             generalCategories.Add(new GeneralCategory(GeneralCategoryId.LC"LC""Cased Letter"));
 911             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lm"Lm""Modifier Letter"));
 912             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Lo"Lo""Other Letter"));
 913             generalCategories.Add(new GeneralCategory(GeneralCategoryId.L"L""Letter"));
 914             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Mn"Mn""Nonspacing Mark"));
 915             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Mc"Mc""Spacing Mark"));
 916             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Me"Me""Enclosing Mark"));
 917             generalCategories.Add(new GeneralCategory(GeneralCategoryId.M"M""Mark"));
 918             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Nd"Nd""Decimal Number"));
 919             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Nl"Nl""Letter Number"));
 920             generalCategories.Add(new GeneralCategory(GeneralCategoryId.No"No""Other Number"));
 921             generalCategories.Add(new GeneralCategory(GeneralCategoryId.N"N""Number"));
 922             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pc"Pc""Connector Punctuation"));
 923             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pd"Pd""Dash Punctuation"));
 924             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Ps"Ps""Open Punctuation"));
 925             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pe"Pe""Close Punctuation"));
 926             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pi"Pi""Initial Punctuation"));
 927             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Pf"Pf""Final Punctuation"));
 928             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Po"Po""Other Punctuation"));
 929             generalCategories.Add(new GeneralCategory(GeneralCategoryId.P"P""Punctuation"));
 930             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Sm"Sm""Math Symbol"));
 931             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Sc"Sc""Currency Symbol"));
 932             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Sk"Sk""Modifier Symbol"));
 933             generalCategories.Add(new GeneralCategory(GeneralCategoryId.So"So""Other Symbol"));
 934             generalCategories.Add(new GeneralCategory(GeneralCategoryId.S"S""Symbol"));
 935             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Zs"Zs""Space Separator"));
 936             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Zl"Zl""Line Separator"));
 937             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Zp"Zp""Paragraph Separator"));
 938             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Z"Z""Separator"));
 939             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cc"Cc""Control"));
 940             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cf"Cf""Format"));
 941             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cs"Cs""Surrogate"));
 942             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Co"Co""Private Use"));
 943             generalCategories.Add(new GeneralCategory(GeneralCategoryId.Cn"Cn""Unassigned"));
 944             generalCategories.Add(new GeneralCategory(GeneralCategoryId.C"C""Other"));
 945             generalCategories.Add(new GeneralCategory(GeneralCategoryId.G"G""Graphic"));
 946             generalCategories.Add(new GeneralCategory(GeneralCategoryId.B"B""Base"));
 947             for (GeneralCategory* generalCategory : generalCategories)
 948             {
 949                 generalCategoryIdMap[generalCategory->Id()] = generalCategory;
 950                 auto result = MakeCanonicalPropertyName(generalCategory->ShortName());
 951                 if (result.Error())
 952                 {
 953                     SetErrorId(result.GetErrorId());
 954                     return;
 955                 }
 956                 shortNameMap[result.Value()] = generalCategory;
 957                 result = MakeCanonicalPropertyName(generalCategory->LongName());
 958                 if (result.Error())
 959                 {
 960                     SetErrorId(result.GetErrorId());
 961                     return;
 962                 }
 963                 longNameMap[result.Value()] = generalCategory;
 964             }
 965         }
 966         public override ~GeneralCategoryTable()
 967         {
 968             for (GeneralCategory* generalCategory : generalCategories)
 969             {
 970                 delete generalCategory;
 971             }
 972         }
 973         private static UniquePtr<GeneralCategoryTable> instance;
 974         private List<GeneralCategory*> generalCategories;
 975         private Map<uintvoid*> generalCategoryIdMap;
 976         private Map<stringvoid*> shortNameMap;
 977         private Map<stringvoid*> longNameMap;
 978     }
 979 
 980     [nodiscard]
 981     public Result<const GeneralCategory*> GetGeneralCategory(GeneralCategoryId id)
 982     {
 983         return GeneralCategoryTable.Instance().GetGeneralCategory(id);
 984     }
 985 
 986     [nodiscard]
 987     public Result<const GeneralCategory*> GetGeneralCategoryByShortName(const string& shortName)
 988     {
 989         return GeneralCategoryTable.Instance().GetGeneralCategoryByShortName(shortName);
 990     }
 991 
 992     [nodiscard]
 993     public Result<const GeneralCategory*> GetGeneralCategoryByLongName(const string& longName)
 994     {
 995         return GeneralCategoryTable.Instance().GetGeneralCategoryByLongName(longName);
 996     }
 997 
 998     public enum AgeId : byte
 999     {
1000         age_unassigned = 0u
1001         age_1_1
1002         age_2_0age_2_1
1003         age_3_0age_3_1age_3_2
1004         age_4_0age_4_1
1005         age_5_0age_5_1age_5_2
1006         age_6_0age_6_1age_6_2age_6_3
1007         age_7_0
1008         age_8_0
1009         age_9_0
1010         age_10_0
1011         age_11_0
1012         age_12_0age_12_1
1013     }
1014 
1015     public class Age
1016     {
1017         public Age(AgeId id_const string& version_) : id(id_)version(version_)
1018         {
1019         }
1020         public inline AgeId Id() const
1021         {
1022             return id;
1023         }
1024         public inline const string& Version() const
1025         {
1026             return version;
1027         }
1028         private AgeId id;
1029         private string version;
1030     }
1031 
1032     public class AgeTable
1033     {
1034         static AgeTable() : instance(new AgeTable())
1035         {
1036         }
1037         public static AgeTable& Instance()
1038         {
1039             return *instance;
1040         }
1041         public const Age* GetAge(AgeId id) const
1042         {
1043             auto it = ageIdMap.CFind(cast<uint>(cast<byte>(id)));
1044             if (it != ageIdMap.CEnd())
1045             {
1046                 return cast<Age*>(it->second);
1047             }
1048             return null;
1049         }
1050         public const Age* GetAge(const string& version) const
1051         {
1052             auto it = versionMap.CFind(version);
1053             if (it != versionMap.CEnd())
1054             {
1055                 return cast<Age*>(it->second);
1056             }
1057             return null;
1058         }
1059         private AgeTable() : ages()ageIdMap()versionMap()
1060         {
1061             ages.Add(new Age(AgeId.age_1_1"1.1"));
1062             ages.Add(new Age(AgeId.age_2_0"2.0"));
1063             ages.Add(new Age(AgeId.age_2_1"2.1"));
1064             ages.Add(new Age(AgeId.age_3_0"3.0"));
1065             ages.Add(new Age(AgeId.age_3_1"3.1"));
1066             ages.Add(new Age(AgeId.age_3_2"3.2"));
1067             ages.Add(new Age(AgeId.age_4_0"4.0"));
1068             ages.Add(new Age(AgeId.age_4_1"4.1"));
1069             ages.Add(new Age(AgeId.age_5_0"5.0"));
1070             ages.Add(new Age(AgeId.age_5_1"5.1"));
1071             ages.Add(new Age(AgeId.age_5_2"5.2"));
1072             ages.Add(new Age(AgeId.age_6_0"6.0"));
1073             ages.Add(new Age(AgeId.age_6_1"6.1"));
1074             ages.Add(new Age(AgeId.age_6_2"6.2"));
1075             ages.Add(new Age(AgeId.age_6_3"6.3"));
1076             ages.Add(new Age(AgeId.age_7_0"7.0"));
1077             ages.Add(new Age(AgeId.age_8_0"8.0"));
1078             ages.Add(new Age(AgeId.age_9_0"9.0"));
1079             ages.Add(new Age(AgeId.age_10_0"10.0"));
1080             ages.Add(new Age(AgeId.age_11_0"11.0"));
1081             ages.Add(new Age(AgeId.age_12_0"12.0"));
1082             ages.Add(new Age(AgeId.age_12_1"12.1"));
1083             for (Age* age : ages)
1084             {
1085                 ageIdMap[cast<uint>(cast<byte>(age->Id()))] = age;
1086                 versionMap[age->Version()] = age;
1087             }
1088         }
1089         public ~AgeTable()
1090         {
1091             for (Age* age : ages)
1092             {
1093                 delete age;
1094             }
1095         }
1096         private static UniquePtr<AgeTable> instance;
1097         private List<Age*> ages;
1098         private Map<uintvoid*> ageIdMap;
1099         private Map<stringvoid*> versionMap;
1100     }
1101 
1102     public const Age* GetAge(AgeId id)
1103     {
1104         return AgeTable.Instance().GetAge(id);
1105     }
1106 
1107     public const Age* GetAge(const string& version)
1108     {
1109         return AgeTable.Instance().GetAge(version);
1110     }
1111 
1112     public enum ScriptId : byte
1113     {
1114         none = 0u
1115         adlmaghbahomarabarmiarmnavst
1116         balibamubassbatkbengbhksbopobrahbraibugibuhd
1117         cakmcanscarichamchercoptcprtcyrl
1118         devadogrdsrtdupl
1119         elbaelymegypethi
1120         georglaggonggonmgothgrangrekgujrguru
1121         hanghanihanohatrhebrhirahluwhmnghmnphrkthung
1122         ital
1123         java
1124         kalikanakharkhmrkhojkndakthi
1125         lanalaoolatnlepclimblinalinblisulycilydi
1126         mahjmakamandmanimarcmedfmendmercmeromlymmodimongmroomteimultmymr
1127         nandnarbnbatnewankoonshu
1128         ogamolckorkhoryaosgeosma
1129         palmpaucpermphagphliphlpphnxplrdprti
1130         qaai
1131         rjngrohgrunr
1132         samrsarbsaursgnwshawshrdsiddsindsinhsogdsogosorasoyosundsylosyrc
1133         tagbtakrtaletalutamltangtavttelutfngtglgthaathaitibttirh
1134         ugar
1135         vaii
1136         wara
1137         wcho
1138         xpeoxsux
1139         yiiizanb
1140         zinhzyyyzzzz
1141     }
1142 
1143     public class Script
1144     {
1145         public Script(ScriptId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
1146         {
1147         }
1148         public inline ScriptId Id() const
1149         {
1150             return id;
1151         }
1152         public inline const string& ShortName() const
1153         {
1154             return shortName;
1155         }
1156         public inline const string& LongName() const
1157         {
1158             return longName;
1159         }
1160         private ScriptId id;
1161         private string shortName;
1162         private string longName;
1163     }
1164 
1165     public class ScriptTable : IOBase
1166     {
1167         static ScriptTable() : instance(new ScriptTable())
1168         {
1169         }
1170         public static ScriptTable& Instance()
1171         {
1172             return *instance;
1173         }
1174         [nodiscard]
1175         public Result<const Script*> GetScript(ScriptId id) const
1176         {
1177             if (Error())
1178             {
1179                 return Result<const Script*>(ErrorId(GetErrorId()));
1180             }
1181             auto it = scriptIdMap.CFind(cast<uint>(cast<byte>(id)));
1182             if (it != scriptIdMap.CEnd())
1183             {
1184                 return Result<const Script*>(cast<Script*>(it->second));
1185             }
1186             const Script* n = null;
1187             return Result<const Script*>(n);
1188         }
1189         [nodiscard]
1190         public Result<const Script*> GetScriptByShortName(const string& shortName) const
1191         {
1192             if (Error())
1193             {
1194                 return Result<const Script*>(ErrorId(GetErrorId()));
1195             }
1196             auto result = MakeCanonicalPropertyName(shortName);
1197             if (result.Error())
1198             {
1199                 return Result<const Script*>(ErrorId(result.GetErrorId()));
1200             }
1201             auto it = shortNameMap.CFind(result.Value());
1202             if (it != shortNameMap.CEnd())
1203             {
1204                 return Result<const Script*>(cast<Script*>(it->second));
1205             }
1206             return Result<const Script*>(null);
1207         }
1208         [nodiscard]
1209         public Result<const Script*> GetScriptByLongName(const string& longName) const
1210         {
1211             if (Error())
1212             {
1213                 return Result<const Script*>(ErrorId(GetErrorId()));
1214             }
1215             auto result = MakeCanonicalPropertyName(longName);
1216             if (result.Error())
1217             {
1218                 return Result<const Script*>(ErrorId(result.GetErrorId()));
1219             }
1220             auto it = longNameMap.CFind(result.Value());
1221             if (it != longNameMap.CEnd())
1222             {
1223                 return Result<const Script*>(cast<Script*>(it->second));
1224             }
1225             return Result<const Script*>(null);
1226         }
1227         private ScriptTable() : base()scripts()scriptIdMap()shortNameMap()longNameMap()
1228         {
1229             scripts.Add(new Script(ScriptId.adlm"Adlm""Adlam"));
1230             scripts.Add(new Script(ScriptId.aghb"Aghb""Caucasian Albanian"));
1231             scripts.Add(new Script(ScriptId.ahom"Ahom""Ahom"));
1232             scripts.Add(new Script(ScriptId.arab"Arab""Arabic"));
1233             scripts.Add(new Script(ScriptId.armi"Armi""Imperial Aramaic"));
1234             scripts.Add(new Script(ScriptId.armn"Armn""Armenian"));
1235             scripts.Add(new Script(ScriptId.avst"Avst""Avestan"));
1236             scripts.Add(new Script(ScriptId.bali"Bali""Balinese"));
1237             scripts.Add(new Script(ScriptId.bamu"Bamu""Bamum"));
1238             scripts.Add(new Script(ScriptId.bass"Bass""Bassa Vah"));
1239             scripts.Add(new Script(ScriptId.batk"Batk""Batak"));
1240             scripts.Add(new Script(ScriptId.beng"Beng""Bengali"));
1241             scripts.Add(new Script(ScriptId.bhks"Bhks""Bhaisuki"));
1242             scripts.Add(new Script(ScriptId.bopo"Bopo""Bopomofo"));
1243             scripts.Add(new Script(ScriptId.brah"Brah""Brahmi"));
1244             scripts.Add(new Script(ScriptId.brai"Brai""Braille"));
1245             scripts.Add(new Script(ScriptId.bugi"Bugi""Buginese"));
1246             scripts.Add(new Script(ScriptId.buhd"Buhd""Buhid"));
1247             scripts.Add(new Script(ScriptId.cakm"Cakm""Chakma"));
1248             scripts.Add(new Script(ScriptId.cans"Cans""Canadian Aboriginal"));
1249             scripts.Add(new Script(ScriptId.cari"Cari""Carian"));
1250             scripts.Add(new Script(ScriptId.cham"Cham""Cham"));
1251             scripts.Add(new Script(ScriptId.cher"Cher""Cherokee"));
1252             scripts.Add(new Script(ScriptId.copt"Copt""Coptic"));
1253             scripts.Add(new Script(ScriptId.cprt"Cprt""Cypriot"));
1254             scripts.Add(new Script(ScriptId.cyrl"Cyrl""Cyrillic"));
1255             scripts.Add(new Script(ScriptId.deva"Deva""Devanagari"));
1256             scripts.Add(new Script(ScriptId.dogr"Dogr""Dogra"));
1257             scripts.Add(new Script(ScriptId.dsrt"Dsrt""Deseret"));
1258             scripts.Add(new Script(ScriptId.dupl"Dupl""Duployan"));
1259             scripts.Add(new Script(ScriptId.egyp"Egyp""Egyptian Hieroglyphs"));
1260             scripts.Add(new Script(ScriptId.elba"Elba""Elbasan"));
1261             scripts.Add(new Script(ScriptId.elym"Elym""Elymaic"));
1262             scripts.Add(new Script(ScriptId.ethi"Ethi""Ethiopian"));
1263             scripts.Add(new Script(ScriptId.geor"Geor""Georgian"));
1264             scripts.Add(new Script(ScriptId.glag"Glag""Glagolitic"));
1265             scripts.Add(new Script(ScriptId.gong"Gong""Gunjala Gondi"));
1266             scripts.Add(new Script(ScriptId.gonm"Gonm""Masaram Gondi"));
1267             scripts.Add(new Script(ScriptId.goth"Goth""Gothic"));
1268             scripts.Add(new Script(ScriptId.gran"Gran""Grantha"));
1269             scripts.Add(new Script(ScriptId.grek"Grek""Greek"));
1270             scripts.Add(new Script(ScriptId.gujr"Gujr""Gujarati"));
1271             scripts.Add(new Script(ScriptId.guru"Guru""Gurmukhi"));
1272             scripts.Add(new Script(ScriptId.hang"Hang""Hangul"));
1273             scripts.Add(new Script(ScriptId.hani"Hani""Han"));
1274             scripts.Add(new Script(ScriptId.hano"Hano""Hanunoo"));
1275             scripts.Add(new Script(ScriptId.hatr"Hatr""Hatran"));
1276             scripts.Add(new Script(ScriptId.hebr"Hebr""Hebrew"));
1277             scripts.Add(new Script(ScriptId.hira"Hira""Hiragana"));
1278             scripts.Add(new Script(ScriptId.hluw"Hluw""Anatolian Hieroglyphs"));
1279             scripts.Add(new Script(ScriptId.hmng"Hmng""Pahawh Hmong"));
1280             scripts.Add(new Script(ScriptId.hmnp"Hmnp""Nyiakeng Puachue Hmong"));
1281             scripts.Add(new Script(ScriptId.hrkt"Hrkt""Katakana Or Hiragana"));
1282             scripts.Add(new Script(ScriptId.hung"Hung""Old Hungarian"));
1283             scripts.Add(new Script(ScriptId.ital"Ital""Old Italic"));
1284             scripts.Add(new Script(ScriptId.java"Java""Javanese"));
1285             scripts.Add(new Script(ScriptId.kali"Kali""Kayah Li"));
1286             scripts.Add(new Script(ScriptId.kana"Kana""Katakana"));
1287             scripts.Add(new Script(ScriptId.khar"Khar""Kharoshthi"));
1288             scripts.Add(new Script(ScriptId.khmr"Khmr""Khmer"));
1289             scripts.Add(new Script(ScriptId.khoj"Khoj""Khojki"));
1290             scripts.Add(new Script(ScriptId.knda"Knda""Kannada"));
1291             scripts.Add(new Script(ScriptId.kthi"Kthi""Kaithi"));
1292             scripts.Add(new Script(ScriptId.lana"Lana""Tai Tham"));
1293             scripts.Add(new Script(ScriptId.laoo"Laoo""Lao"));
1294             scripts.Add(new Script(ScriptId.latn"Latn""Latin"));
1295             scripts.Add(new Script(ScriptId.lepc"Lepc""Lepcha"));
1296             scripts.Add(new Script(ScriptId.limb"Limb""Limbu"));
1297             scripts.Add(new Script(ScriptId.lina"Lina""Linear A"));
1298             scripts.Add(new Script(ScriptId.linb"Linb""Linear B"));
1299             scripts.Add(new Script(ScriptId.lisu"Lisu""Lisu"));
1300             scripts.Add(new Script(ScriptId.lyci"Lyci""Lycian"));
1301             scripts.Add(new Script(ScriptId.lydi"Lydi""Lydian"));
1302             scripts.Add(new Script(ScriptId.mahj"Mahj""Mahajani"));
1303             scripts.Add(new Script(ScriptId.maka"Maka""Makasar"));
1304             scripts.Add(new Script(ScriptId.mand"Mand""Mandaic"));
1305             scripts.Add(new Script(ScriptId.mani"Mani""Manichaean"));
1306             scripts.Add(new Script(ScriptId.marc"Marc""Marchen"));
1307             scripts.Add(new Script(ScriptId.medf"Medf""Medefaidrin"));
1308             scripts.Add(new Script(ScriptId.mend"Mend""Mende Kikakui"));
1309             scripts.Add(new Script(ScriptId.merc"Merc""Meroitic Cursive"));
1310             scripts.Add(new Script(ScriptId.mero"Mero""Meroitic Hieroglyphs"));
1311             scripts.Add(new Script(ScriptId.mlym"Mlym""Malayalam"));
1312             scripts.Add(new Script(ScriptId.modi"Modi""Modi"));
1313             scripts.Add(new Script(ScriptId.mong"Mong""Mongolian"));
1314             scripts.Add(new Script(ScriptId.mroo"Mroo""Mro"));
1315             scripts.Add(new Script(ScriptId.mtei"Mtei""Meetei Mayak"));
1316             scripts.Add(new Script(ScriptId.mult"Mult""Multani"));
1317             scripts.Add(new Script(ScriptId.mymr"Mymr""Myanmar"));
1318             scripts.Add(new Script(ScriptId.nand"Nand""Nandinagari"));
1319             scripts.Add(new Script(ScriptId.narb"Narb""Old North Arabian"));
1320             scripts.Add(new Script(ScriptId.nbat"Nbat""Nabataean"));
1321             scripts.Add(new Script(ScriptId.newa"Newa""Newa"));
1322             scripts.Add(new Script(ScriptId.nkoo"Nkoo""Nko"));
1323             scripts.Add(new Script(ScriptId.nshu"Nshu""Nushu"));
1324             scripts.Add(new Script(ScriptId.ogam"Ogam""Ogham"));
1325             scripts.Add(new Script(ScriptId.olck"Olck""Ol Chiki"));
1326             scripts.Add(new Script(ScriptId.orkh"Orkh""Old Turkic"));
1327             scripts.Add(new Script(ScriptId.orya"Orya""Oriya"));
1328             scripts.Add(new Script(ScriptId.osge"Osge""Osage"));
1329             scripts.Add(new Script(ScriptId.osma"Osma""Osmanya"));
1330             scripts.Add(new Script(ScriptId.palm"Palm""Palmyrene"));
1331             scripts.Add(new Script(ScriptId.pauc"Pauc""Pau Cin Hau"));
1332             scripts.Add(new Script(ScriptId.perm"Perm""Old Permic"));
1333             scripts.Add(new Script(ScriptId.phag"Phag""Phags Pa"));
1334             scripts.Add(new Script(ScriptId.phli"Phli""Inscriptional Pahlavi"));
1335             scripts.Add(new Script(ScriptId.phlp"Phlp""Psalter Pahlavi"));
1336             scripts.Add(new Script(ScriptId.phnx"Phnx""Phoenician"));
1337             scripts.Add(new Script(ScriptId.plrd"Plrd""Miao"));
1338             scripts.Add(new Script(ScriptId.prti"Prti""Inscriptional Parthian"));
1339             scripts.Add(new Script(ScriptId.rjng"Rjng""Rejang"));
1340             scripts.Add(new Script(ScriptId.rohg"Rohg""Hanifi Rohingya"));
1341             scripts.Add(new Script(ScriptId.runr"Runr""Runic"));
1342             scripts.Add(new Script(ScriptId.samr"Samr""Samaritan"));
1343             scripts.Add(new Script(ScriptId.sarb"Sarb""Old South Arabian"));
1344             scripts.Add(new Script(ScriptId.saur"Saur""Saurashtra"));
1345             scripts.Add(new Script(ScriptId.sgnw"Sgnw""SignWriting"));
1346             scripts.Add(new Script(ScriptId.shaw"Shaw""Shawian"));
1347             scripts.Add(new Script(ScriptId.shrd"Shrd""Sharada"));
1348             scripts.Add(new Script(ScriptId.sidd"Sidd""Shiddham"));
1349             scripts.Add(new Script(ScriptId.sind"Sind""Khudawadi"));
1350             scripts.Add(new Script(ScriptId.sinh"Sinh""Sinhala"));
1351             scripts.Add(new Script(ScriptId.sogd"Sogd""Sogdian"));
1352             scripts.Add(new Script(ScriptId.sogo"Sogo""Old Sogdian"));
1353             scripts.Add(new Script(ScriptId.sora"Sora""Sora Sompeng"));
1354             scripts.Add(new Script(ScriptId.soyo"Soyo""Soyombo"));
1355             scripts.Add(new Script(ScriptId.sund"Sund""Sundanese"));
1356             scripts.Add(new Script(ScriptId.sylo"Sylo""Syloti Nagri"));
1357             scripts.Add(new Script(ScriptId.syrc"Syrc""Syriac"));
1358             scripts.Add(new Script(ScriptId.tagb"Tagb""Tagbanwa"));
1359             scripts.Add(new Script(ScriptId.takr"Takr""Takri"));
1360             scripts.Add(new Script(ScriptId.tale"Tale""Tai Le"));
1361             scripts.Add(new Script(ScriptId.talu"Talu""New Tai Lue"));
1362             scripts.Add(new Script(ScriptId.taml"Taml""Tamil"));
1363             scripts.Add(new Script(ScriptId.tang"Tang""Tangut"));
1364             scripts.Add(new Script(ScriptId.tavt"Tavt""Tai Viet"));
1365             scripts.Add(new Script(ScriptId.telu"Telu""Telugu"));
1366             scripts.Add(new Script(ScriptId.tfng"Tfng""Tifinag"));
1367             scripts.Add(new Script(ScriptId.tglg"Tglg""Tagalog"));
1368             scripts.Add(new Script(ScriptId.thaa"Thaa""Thaana"));
1369             scripts.Add(new Script(ScriptId.thai"Thai""Thai"));
1370             scripts.Add(new Script(ScriptId.tibt"Tibt""Tibetan"));
1371             scripts.Add(new Script(ScriptId.tirh"Tirh""Tirhuta"));
1372             scripts.Add(new Script(ScriptId.ugar"Ugar""Ugaritic"));
1373             scripts.Add(new Script(ScriptId.vaii"Vaii""Vai"));
1374             scripts.Add(new Script(ScriptId.wara"Wara""Warang Citi"));
1375             scripts.Add(new Script(ScriptId.wcho"Wcho""Wcho"));
1376             scripts.Add(new Script(ScriptId.xpeo"Xpeo""Old Persian"));
1377             scripts.Add(new Script(ScriptId.xsux"Xsux""Cuneiform"));
1378             scripts.Add(new Script(ScriptId.yiii"Yiii""Yi"));
1379             scripts.Add(new Script(ScriptId.zanb"Zanb""Zanabazar Square"));
1380             scripts.Add(new Script(ScriptId.zinh"Zinh""Inherited"));
1381             scripts.Add(new Script(ScriptId.zyyy"Zyyy""Common"));
1382             scripts.Add(new Script(ScriptId.zzzz"Zzzz""Unknown"));
1383             for (Script* script : scripts)
1384             {
1385                 scriptIdMap[cast<uint>(cast<byte>(script->Id()))] = script;
1386                 auto result = MakeCanonicalPropertyName(script->ShortName());
1387                 if (result.Error())
1388                 {
1389                     SetErrorId(result.GetErrorId());
1390                     return;
1391                 }
1392                 shortNameMap[result.Value()] = script;
1393                 result = MakeCanonicalPropertyName(script->LongName());
1394                 if (result.Error())
1395                 {
1396                     SetErrorId(result.GetErrorId());
1397                     return;
1398                 }
1399                 longNameMap[result.Value()] = script;
1400             }
1401         }
1402         public override ~ScriptTable()
1403         {
1404             for (Script* script : scripts)
1405             {
1406                 delete script;
1407             }
1408         }
1409         private static UniquePtr<ScriptTable> instance;
1410         private List<Script*> scripts;
1411         private Map<uintvoid*> scriptIdMap;
1412         private Map<stringvoid*> shortNameMap;
1413         private Map<stringvoid*> longNameMap;
1414     }
1415 
1416     [nodiscard]
1417     public Result<const Script*> GetScript(ScriptId id)
1418     {
1419         return ScriptTable.Instance().GetScript(id);
1420     }
1421 
1422     [nodiscard]
1423     public Result<const Script*> GetScriptByShortName(const string& shortName)
1424     {
1425         return ScriptTable.Instance().GetScriptByShortName(shortName);
1426     }
1427 
1428     [nodiscard]
1429     public Result<const Script*> GetScriptByLongName(const string& longName)
1430     {
1431         return ScriptTable.Instance().GetScriptByLongName(longName);
1432     }
1433 
1434     public class CharacterInfo
1435     {
1436         public CharacterInfo() : 
1437             binaryProperties(0u)generalCategory(GeneralCategoryId.none)upper(cast<uchar>(0u))lower(cast<uchar>(0u))title(cast<uchar>(0u))
1438             folding(cast<uchar>(0u))block(BlockId.none)age(AgeId.age_unassigned)script(ScriptId.none)
1439         {
1440         }
1441         public inline bool GetBinaryProperty(BinaryPropertyId binaryPropertyId) const
1442         {
1443             ulong mask = cast<ulong>(1u) << cast<ulong>(cast<byte>(binaryPropertyId));
1444             return (binaryProperties & mask) != 0u;
1445         }
1446         public inline bool HasGeneralCategory(GeneralCategoryId generalCategory_) const
1447         {
1448             return (generalCategory & generalCategory_) != GeneralCategoryId.none;
1449         }
1450         public inline GeneralCategoryId GeneralCategoryValue() const
1451         {
1452             return generalCategory;
1453         }
1454         public inline uchar Upper() const
1455         {
1456             return upper;
1457         }
1458         public inline uchar Lower() const
1459         {
1460             return lower;
1461         }
1462         public inline uchar Title() const
1463         {
1464             return title;
1465         }
1466         public inline uchar Folding() const
1467         {
1468             return folding;
1469         }
1470         public inline BlockId BlockValue() const
1471         {
1472             return block;
1473         }
1474         public inline AgeId AgeValue() const
1475         {
1476             return age;
1477         }
1478         public inline ScriptId ScriptValue() const
1479         {
1480             return script;
1481         }
1482         [nodiscard]
1483         public Result<bool> Read(BinaryReader& reader)
1484         {
1485             auto ulongResult = reader.ReadULong();
1486             if (ulongResult.Error())
1487             {
1488                 return Result<bool>(ErrorId(ulongResult.GetErrorId()));
1489             }
1490             binaryProperties = ulongResult.Value();
1491             auto uintResult = reader.ReadUInt();
1492             if (uintResult.Error())
1493             {
1494                 return Result<bool>(ErrorId(uintResult.GetErrorId()));
1495             }
1496             generalCategory = cast<GeneralCategoryId>(uintResult.Value());
1497             auto ucharResult = reader.ReadUChar();
1498             if (ucharResult.Error())
1499             {
1500                 return Result<bool>(ErrorId(ucharResult.GetErrorId()));
1501             }
1502             upper = ucharResult.Value();
1503             ucharResult = reader.ReadUChar();
1504             if (ucharResult.Error())
1505             {
1506                 return Result<bool>(ErrorId(ucharResult.GetErrorId()));
1507             }
1508             lower = ucharResult.Value();
1509             ucharResult = reader.ReadUChar();
1510             if (ucharResult.Error())
1511             {
1512                 return Result<bool>(ErrorId(ucharResult.GetErrorId()));
1513             }
1514             title = ucharResult.Value();
1515             ucharResult = reader.ReadUChar();
1516             if (ucharResult.Error())
1517             {
1518                 return Result<bool>(ErrorId(ucharResult.GetErrorId()));
1519             }
1520             folding = ucharResult.Value();
1521             auto ushortResult = reader.ReadUShort();
1522             if (ushortResult.Error())
1523             {
1524                 return Result<bool>(ErrorId(ushortResult.GetErrorId()));
1525             }
1526             block = cast<BlockId>(ushortResult.Value());
1527             auto byteResult = reader.ReadByte();
1528             if (byteResult.Error())
1529             {
1530                 return Result<bool>(ErrorId(byteResult.GetErrorId()));
1531             }
1532             age = cast<AgeId>(byteResult.Value());
1533             byteResult = reader.ReadByte();
1534             if (byteResult.Error())
1535             {
1536                 return Result<bool>(ErrorId(byteResult.GetErrorId()));
1537             }
1538             script = cast<ScriptId>(byteResult.Value());
1539             return Result<bool>(true);
1540         }
1541         private ulong binaryProperties;
1542         private GeneralCategoryId generalCategory;
1543         private uchar upper;
1544         private uchar lower;
1545         private uchar title;
1546         private uchar folding;
1547         private BlockId block;
1548         private AgeId age;
1549         private ScriptId script;
1550     }
1551 
1552     public const long numInfosInPage = 128u;
1553     public const uint characterInfoSize = 32u;
1554     public const uint characterInfoPageSize = cast<uint>(numInfosInPage) * characterInfoSize;
1555 
1556     public enum NumericTypeId : byte
1557     {
1558         none = 0u
1559         dedinu
1560     }
1561 
1562     public class NumericType
1563     {
1564         public NumericType(NumericTypeId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
1565         {
1566         }
1567         public inline NumericTypeId Id() const
1568         {
1569             return id;
1570         }
1571         public inline const string& ShortName() const
1572         {
1573             return shortName;
1574         }
1575         public inline const string& LongName() const
1576         {
1577             return longName;
1578         }
1579         private NumericTypeId id;
1580         private string shortName;
1581         private string longName;
1582     }
1583 
1584     public class NumericTypeTable : IOBase
1585     {
1586         static NumericTypeTable() : instance(new NumericTypeTable())
1587         {
1588         }
1589         public static NumericTypeTable& Instance()
1590         {
1591             return *instance;
1592         }
1593         [nodiscard]
1594         public Result<const NumericType*> GetNumericType(NumericTypeId id) const
1595         {
1596             if (Error())
1597             {
1598                 return Result<const NumericType*>(ErrorId(GetErrorId()));
1599             }
1600             auto it = numericTypeIdMap.CFind(cast<uint>(cast<byte>(id)));
1601             if (it != numericTypeIdMap.CEnd())
1602             {
1603                 return Result<const NumericType*>(cast<NumericType*>(it->second));
1604             }
1605             const NumericType* n = null;
1606             return Result<const NumericType*>(n);
1607         }
1608         [nodiscard]
1609         public Result<const NumericType*> GetNumericTypeByShortName(const string& shortName) const
1610         {
1611             if (Error())
1612             {
1613                 return Result<const NumericType*>(ErrorId(GetErrorId()));
1614             }
1615             auto result = MakeCanonicalPropertyName(shortName);
1616             if (result.Error())
1617             {
1618                 return Result<const NumericType*>(ErrorId(result.GetErrorId()));
1619             }
1620             auto it = shortNameMap.CFind(result.Value());
1621             if (it != shortNameMap.CEnd())
1622             {
1623                 return Result<const NumericType*>(cast<NumericType*>(it->second));
1624             }
1625             return Result<const NumericType*>(null);
1626         }
1627         [nodiscard]
1628         public Result<const NumericType*> GetNumericTypeByLongName(const string& longName) const
1629         {
1630             if (Error())
1631             {
1632                 return Result<const NumericType*>(ErrorId(GetErrorId()));
1633             }
1634             auto result = MakeCanonicalPropertyName(longName);
1635             if (result.Error())
1636             {
1637                 return Result<const NumericType*>(ErrorId(result.GetErrorId()));
1638             }
1639             auto it = longNameMap.CFind(result.Value());
1640             if (it != longNameMap.CEnd())
1641             {
1642                 return Result<const NumericType*>(cast<NumericType*>(it->second));
1643             }
1644             return Result<const NumericType*>(null);
1645         }
1646         private NumericTypeTable() : base()numericTypes()numericTypeIdMap()shortNameMap()longNameMap()
1647         {
1648             numericTypes.Add(new NumericType(NumericTypeId.none"None""None"));
1649             numericTypes.Add(new NumericType(NumericTypeId.de"De""Decimal"));
1650             numericTypes.Add(new NumericType(NumericTypeId.di"Di""Digit"));
1651             numericTypes.Add(new NumericType(NumericTypeId.nu"Nu""Numeric"));
1652             for (NumericType* numericType : numericTypes)
1653             {
1654                 numericTypeIdMap[cast<uint>(cast<byte>(numericType->Id()))] = numericType;
1655                 auto result = MakeCanonicalPropertyName(numericType->ShortName());
1656                 if (result.Error())
1657                 {
1658                     SetErrorId(result.GetErrorId());
1659                     return;
1660                 }
1661                 shortNameMap[result.Value()] = numericType;
1662                 result = MakeCanonicalPropertyName(numericType->LongName());
1663                 if (result.Error())
1664                 {
1665                     SetErrorId(result.GetErrorId());
1666                     return;
1667                 }
1668                 longNameMap[result.Value()] = numericType;
1669             }
1670         }
1671         public override ~NumericTypeTable()
1672         {
1673             for (NumericType* numericType : numericTypes)
1674             {
1675                 delete numericType;
1676             }
1677         }
1678         private List<NumericType*> numericTypes;
1679         private Map<uintvoid*> numericTypeIdMap;
1680         private Map<stringvoid*> shortNameMap;
1681         private Map<stringvoid*> longNameMap;
1682         private static UniquePtr<NumericTypeTable> instance;
1683     }
1684 
1685     [nodiscard]
1686     public Result<const NumericType*> GetNumericType(NumericTypeId id)
1687     {
1688         return NumericTypeTable.Instance().GetNumericType(id);
1689     }
1690 
1691     [nodiscard]
1692     public Result<const NumericType*> GetNumericTypeByShortName(const string& shortName)
1693     {
1694         return NumericTypeTable.Instance().GetNumericTypeByShortName(shortName);
1695     }
1696 
1697     [nodiscard]
1698     public Result<const NumericType*> GetNumericTypeByLongName(const string& longName)
1699     {
1700         return NumericTypeTable.Instance().GetNumericTypeByLongName(longName);
1701     }
1702 
1703     public enum BidiClassId : byte
1704     {
1705         none = 0u
1706         alanbbncsenesetfsillrelrilronsmonpdfpdirrlerlirlosws
1707     }
1708 
1709     public class BidiClass
1710     {
1711         public BidiClass(BidiClassId id_const string& shortName_const string& longName_) : id(id_)shortName(shortName_)longName(longName_)
1712         {
1713         }
1714         public inline BidiClassId Id() const
1715         {
1716             return id;
1717         }
1718         public inline const string& ShortName() const
1719         {
1720             return shortName;
1721         }
1722         public inline const string& LongName() const
1723         {
1724             return longName;
1725         }
1726         private BidiClassId id;
1727         private string shortName;
1728         private string longName;
1729     }
1730 
1731     public class BidiClassTable : IOBase
1732     {
1733         static BidiClassTable() : instance(new BidiClassTable())
1734         {
1735         }
1736         public static BidiClassTable& Instance()
1737         {
1738             return *instance;
1739         }
1740         [nodiscard]
1741         public Result<const BidiClass*> GetBidiClass(BidiClassId id) const
1742         {
1743             if (Error())
1744             {
1745                 return Result<const BidiClass*>(ErrorId(GetErrorId()));
1746             }
1747             auto it = bidiClassIdMap.CFind(cast<uint>(cast<byte>(id)));
1748             if (it != bidiClassIdMap.CEnd())
1749             {
1750                 return Result<const BidiClass*>(cast<BidiClass*>(it->second));
1751             }
1752             const BidiClass* n = null;
1753             return Result<const BidiClass*>(n);
1754         }
1755         [nodiscard]
1756         public Result<const BidiClass*> GetBidiClassByShortName(const string& shortName) const
1757         {
1758             if (Error())
1759             {
1760                 return Result<const BidiClass*>(ErrorId(GetErrorId()));
1761             }
1762             auto result = MakeCanonicalPropertyName(shortName);
1763             if (result.Error())
1764             {
1765                return Result<const BidiClass*>(ErrorId(result.GetErrorId()));
1766             }
1767             auto it = shortNameMap.CFind(result.Value());
1768             if (it != shortNameMap.CEnd())
1769             {
1770                 return Result<const BidiClass*>(cast<BidiClass*>(it->second));
1771             }
1772             return Result<const BidiClass*>(null);
1773         }
1774         [nodiscard]
1775         public Result<const BidiClass*> GetBidiClassByLongName(const string& longName) const
1776         {
1777             if (Error())
1778             {
1779                 return Result<const BidiClass*>(ErrorId(GetErrorId()));
1780             }
1781             auto result = MakeCanonicalPropertyName(longName);
1782             if (result.Error())
1783             {
1784                return Result<const BidiClass*>(ErrorId(result.GetErrorId()));
1785             }
1786             auto it = longNameMap.CFind(result.Value());
1787             if (it != longNameMap.CEnd())
1788             {
1789                 return Result<const BidiClass*>(cast<BidiClass*>(it->second));
1790             }
1791             return Result<const BidiClass*>(null);
1792         }
1793         private BidiClassTable() : base()bidiClasses()bidiClassIdMap()shortNameMap()longNameMap()
1794         {
1795             bidiClasses.Add(new BidiClass(BidiClassId.al"AL""Arabic Letter"));
1796             bidiClasses.Add(new BidiClass(BidiClassId.an"AN""Arabic Number"));
1797             bidiClasses.Add(new BidiClass(BidiClassId.b"B""Paragraph Separator"));
1798             bidiClasses.Add(new BidiClass(BidiClassId.bn"BN""Boundary Neutral"));
1799             bidiClasses.Add(new BidiClass(BidiClassId.cs"CS""Common Separator"));
1800             bidiClasses.Add(new BidiClass(BidiClassId.en"EN""European Number"));
1801             bidiClasses.Add(new BidiClass(BidiClassId.es"ES""European Separator"));
1802             bidiClasses.Add(new BidiClass(BidiClassId.et"ET""European Terminator"));
1803             bidiClasses.Add(new BidiClass(BidiClassId.fsi"FSI""First Strong Isolate"));
1804             bidiClasses.Add(new BidiClass(BidiClassId.l"L""Left To Right"));
1805             bidiClasses.Add(new BidiClass(BidiClassId.lre"LRE""Left To Right Embedding"));
1806             bidiClasses.Add(new BidiClass(BidiClassId.lri"LRI""Left To Right Isolate"));
1807             bidiClasses.Add(new BidiClass(BidiClassId.lro"LRO""Left To Right Override"));
1808             bidiClasses.Add(new BidiClass(BidiClassId.nsm"NSM""Nonspacing Mark"));
1809             bidiClasses.Add(new BidiClass(BidiClassId.on"ON""Other Neutral"));
1810             bidiClasses.Add(new BidiClass(BidiClassId.pdf"PDF""Pop Directional Format"));
1811             bidiClasses.Add(new BidiClass(BidiClassId.pdi"PDI""Pop Directional Isolate"));
1812             bidiClasses.Add(new BidiClass(BidiClassId.r"R""Right To Left"));
1813             bidiClasses.Add(new BidiClass(BidiClassId.rle"RLE""Right To Left Embedding"));
1814             bidiClasses.Add(new BidiClass(BidiClassId.rli"RLI""Right To Left Isolate"));
1815             bidiClasses.Add(new BidiClass(BidiClassId.rlo"RLO""Right To Left Override"));
1816             bidiClasses.Add(new BidiClass(BidiClassId.s"S""Segment Separator"));
1817             bidiClasses.Add(new BidiClass(BidiClassId.ws"WS""White Space"));
1818             for (BidiClass* bidiClass : bidiClasses)
1819             {
1820                 bidiClassIdMap[cast<uint>(cast<byte>(bidiClass->Id()))] = bidiClass;
1821                 auto result = MakeCanonicalPropertyName(bidiClass->ShortName());
1822                 if (result.Error())
1823                 {
1824                     SetErrorId(result.GetErrorId());
1825                     return;
1826                 }
1827                 shortNameMap[result.Value()] = bidiClass;
1828                 result = MakeCanonicalPropertyName(bidiClass->LongName());
1829                 if (result.Error())
1830                 {
1831                     SetErrorId(result.GetErrorId());
1832                     return;
1833                 }
1834                 longNameMap[result.Value()] = bidiClass;
1835             }
1836         }
1837         public override ~BidiClassTable()
1838         {
1839             for (BidiClass* bidiClass : bidiClasses)
1840             {
1841                 delete bidiClass;
1842             }
1843         }
1844         private static UniquePtr<BidiClassTable> instance;
1845         private List<BidiClass*> bidiClasses;
1846         private Map<uintvoid*> bidiClassIdMap;
1847         private Map<stringvoid*> shortNameMap;
1848         private Map<stringvoid*> longNameMap;
1849     }
1850 
1851     [nodiscard]
1852     public Result<const BidiClass*> GetBidiClass(BidiClassId id)
1853     {
1854         return BidiClassTable.Instance().GetBidiClass(id);
1855     }
1856 
1857     [nodiscard]
1858     public Result<const BidiClass*> GetBidiClassByShortName(const string& shortName)
1859     {
1860         return BidiClassTable.Instance().GetBidiClassByShortName(shortName);
1861     }
1862 
1863     [nodiscard]
1864     public Result<const BidiClass*> GetBidiClassByLongName(const string& longName)
1865     {
1866         return BidiClassTable.Instance().GetBidiClassByLongName(longName);
1867     }
1868 
1869     public enum BidiPairedBracketTypeId : byte
1870     {
1871         none = 0u
1872         oc
1873     }
1874 
1875     public class BidiPairedBracketType
1876     {
1877         public BidiPairedBracketType(BidiPairedBracketTypeId id_const string& shortName_const string& longName_) : 
1878             id(id_)shortName(shortName_)longName(longName_)
1879         {
1880         }
1881         public inline BidiPairedBracketTypeId Id() const
1882         {
1883             return id;
1884         }
1885         public inline const string& ShortName() const
1886         {
1887             return shortName;
1888         }
1889         public inline const string& LongName() const
1890         {
1891             return longName;
1892         }
1893         private BidiPairedBracketTypeId id;
1894         private string shortName;
1895         private string longName;
1896     }
1897 
1898     public class BidiPairedBracketTypeTable : IOBase
1899     {
1900         static BidiPairedBracketTypeTable() : instance(new BidiPairedBracketTypeTable())
1901         {
1902         }
1903         public static BidiPairedBracketTypeTable& Instance()
1904         {
1905             return *instance;
1906         }
1907         [nodiscard]
1908         public Result<const BidiPairedBracketType*> GetBidiPairedBracketType(BidiPairedBracketTypeId id) const
1909         {
1910             if (Error())
1911             {
1912                 return Result<const BidiPairedBracketType*>(ErrorId(GetErrorId()));
1913             }
1914             auto it = bidiPairedBracketTypeIdMap.CFind(cast<uint>(cast<byte>(id)));
1915             if (it != bidiPairedBracketTypeIdMap.CEnd())
1916             {
1917                 return Result<const BidiPairedBracketType*>(cast<BidiPairedBracketType*>(it->second));
1918             }
1919             const BidiPairedBracketType* n = null;
1920             return Result<const BidiPairedBracketType*>(n);
1921         }
1922         [nodiscard]
1923         public Result<const BidiPairedBracketType*> GetBidiPairedBracketTypeByShortName(const string& shortName) const
1924         {
1925             if (Error())
1926             {
1927                 return Result<const BidiPairedBracketType*>(ErrorId(GetErrorId()));
1928             }
1929             auto result = MakeCanonicalPropertyName(shortName);
1930             if (result.Error())
1931             {
1932                 return Result<const BidiPairedBracketType*>(ErrorId(result.GetErrorId()));
1933             }
1934             auto it = shortNameMap.CFind(result.Value());
1935             if (it != shortNameMap.CEnd())
1936             {
1937                 return Result<const BidiPairedBracketType*>(cast<BidiPairedBracketType*>(it->second));
1938             }
1939             return Result<const BidiPairedBracketType*>(null);
1940         }
1941         [nodiscard]
1942         public Result<const BidiPairedBracketType*> GetBidiPairedBracketTypeByLongName(const string& longName) const
1943         {
1944             if (Error())
1945             {
1946                 return Result<const BidiPairedBracketType*>(ErrorId(GetErrorId()));
1947             }
1948             auto result = MakeCanonicalPropertyName(longName);
1949             if (result.Error())
1950             {
1951                 return Result<const BidiPairedBracketType*>(ErrorId(result.GetErrorId()));
1952             }
1953             auto it = longNameMap.CFind(result.Value());
1954             if (it != longNameMap.CEnd())
1955             {
1956                 return Result<const BidiPairedBracketType*>(cast<BidiPairedBracketType*>(it->second));
1957             }
1958             return Result<const BidiPairedBracketType*>(null);
1959         }
1960         private BidiPairedBracketTypeTable() : base()bidiPairedBracketTypes()bidiPairedBracketTypeIdMap()shortNameMap()longNameMap()
1961         {
1962             bidiPairedBracketTypes.Add(new BidiPairedBracketType(BidiPairedBracketTypeId.o"O""Open"));
1963             bidiPairedBracketTypes.Add(new BidiPairedBracketType(BidiPairedBracketTypeId.c"C""Close"));
1964             bidiPairedBracketTypes.Add(new BidiPairedBracketType(BidiPairedBracketTypeId.none"N""None"));
1965             for (BidiPairedBracketType* bidiPairedBracketType : bidiPairedBracketTypes)
1966             {
1967                 bidiPairedBracketTypeIdMap[cast<uint>(cast<byte>(bidiPairedBracketType->Id()))] = bidiPairedBracketType;
1968                 auto result = MakeCanonicalPropertyName(bidiPairedBracketType->ShortName());
1969                 if (result.Error())
1970                 {
1971                     SetErrorId(result.GetErrorId());
1972                     return;
1973                 }
1974                 shortNameMap[result.Value()] = bidiPairedBracketType;
1975                 result = MakeCanonicalPropertyName(bidiPairedBracketType->LongName());
1976                 if (result.Error())
1977                 {
1978                     SetErrorId(result.GetErrorId());
1979                     return;
1980                 }
1981                 longNameMap[result.Value()] = bidiPairedBracketType;
1982             }
1983         }
1984         public override ~BidiPairedBracketTypeTable()
1985         {
1986             for (BidiPairedBracketType* bidiPairedBracketType : bidiPairedBracketTypes)
1987             {
1988                 delete bidiPairedBracketType;
1989             }
1990         }
1991         private static UniquePtr<BidiPairedBracketTypeTable> instance;
1992         private List<BidiPairedBracketType*> bidiPairedBracketTypes;
1993         private Map<uintvoid*> bidiPairedBracketTypeIdMap;
1994         private Map<stringvoid*> shortNameMap;
1995         private Map<stringvoid*> longNameMap;
1996     }
1997 
1998     [nodiscard]
1999     public Result<const BidiPairedBracketType*> GetBidiPairedBracketType(BidiPairedBracketTypeId id)
2000     {
2001         return BidiPairedBracketTypeTable.Instance().GetBidiPairedBracketType(id);
2002     }
2003 
2004     [nodiscard]
2005     public Result<const BidiPairedBracketType*> GetBidiPairedBracketTypeByShortName(const string& shortName)
2006     {
2007         return BidiPairedBracketTypeTable.Instance().GetBidiPairedBracketTypeByShortName(shortName);
2008     }
2009 
2010     [nodiscard]
2011     public Result<const BidiPairedBracketType*> GetBidiPairedBracketTypeByLongName(const string& longName)
2012     {
2013         return BidiPairedBracketTypeTable.Instance().GetBidiPairedBracketTypeByLongName(longName);
2014     }
2015 
2016     public enum AliasTypeId : byte
2017     {
2018         none = 0u
2019         correctioncontrolalternatefigmentabbreviation
2020     }
2021 
2022     public class AliasType
2023     {
2024         public AliasType(AliasTypeId id_const string& name_) : id(id_)name(name_)
2025         {
2026         }
2027         public inline AliasTypeId Id() const
2028         {
2029             return id;
2030         }
2031         public inline const string& Name() const
2032         {
2033             return name;
2034         }
2035         private AliasTypeId id;
2036         private string name;
2037     }
2038 
2039     public class AliasTypeTable
2040     {
2041         static AliasTypeTable() : instance(new AliasTypeTable())
2042         {
2043         }
2044         public static AliasTypeTable& Instance()
2045         {
2046             return *instance;
2047         }
2048         public const AliasType* GetAliasType(AliasTypeId id) const
2049         {
2050             auto it = aliasTypeIdMap.CFind(cast<uint>(cast<byte>(id)));
2051             if (it != aliasTypeIdMap.CEnd())
2052             {
2053                 return cast<AliasType*>(it->second);
2054             }
2055             return null;
2056         }
2057         public const AliasType* GetAliasType(const string& name) const
2058         {
2059             auto it = nameMap.CFind(name);
2060             if (it != nameMap.CEnd())
2061             {
2062                 return cast<AliasType*>(it->second);
2063             }
2064             return null;
2065         }
2066         private AliasTypeTable() : aliasTypes()aliasTypeIdMap()nameMap()
2067         {
2068             aliasTypes.Add(new AliasType(AliasTypeId.abbreviation"abbreviation"));
2069             aliasTypes.Add(new AliasType(AliasTypeId.alternate"alternate"));
2070             aliasTypes.Add(new AliasType(AliasTypeId.control"control"));
2071             aliasTypes.Add(new AliasType(AliasTypeId.correction"correction"));
2072             aliasTypes.Add(new AliasType(AliasTypeId.figment"figment"));
2073             for (AliasType* aliasType : aliasTypes)
2074             {
2075                 aliasTypeIdMap[cast<uint>(cast<byte>(aliasType->Id()))] = aliasType;
2076                 nameMap[aliasType->Name()] = aliasType;
2077             }
2078         }
2079         public ~AliasTypeTable()
2080         {
2081             for (AliasType* aliasType : aliasTypes)
2082             {
2083                 delete aliasType;
2084             }
2085         }
2086         private static UniquePtr<AliasTypeTable> instance;
2087         private List<AliasType*> aliasTypes;
2088         private Map<uintvoid*> aliasTypeIdMap;
2089         private Map<stringvoid*> nameMap;
2090     }
2091 
2092     public const AliasType* GetAliasType(AliasTypeId id)
2093     {
2094         return AliasTypeTable.Instance().GetAliasType(id);
2095     }
2096 
2097     public const AliasType* GetAliasType(const string& name)
2098     {
2099         return AliasTypeTable.Instance().GetAliasType(name);
2100     }
2101 
2102     public class Alias
2103     {
2104         public Alias() : typeId(AliasTypeId.none)name()
2105         {
2106         }
2107         public Alias(AliasTypeId typeId_const string& name_) : typeId(typeId_)name(name_)
2108         {
2109         }
2110         public inline AliasTypeId TypeId() const
2111         {
2112             return typeId;
2113         }
2114         public inline const string& Name() const
2115         {
2116             return name;
2117         }
2118         [nodiscard]
2119         public Result<bool> Read(BinaryReader& reader)
2120         {
2121             auto result = reader.ReadByte();
2122             if (result.Error())
2123             {
2124                 return Result<bool>(ErrorId(result.GetErrorId()));
2125             }
2126             typeId = cast<AliasTypeId>(result.Value());
2127             auto nameResult = reader.ReadString();
2128             if (nameResult.Error())
2129             {
2130                 return Result<bool>(ErrorId(nameResult.GetErrorId()));
2131             }
2132             name = nameResult.Value();
2133             return Result<bool>(true);
2134         }
2135         private AliasTypeId typeId;
2136         private string name;
2137     }
2138 
2139     public class ExtendedCharacterInfo
2140     {
2141         public ExtendedCharacterInfo() : 
2142             characterName()unicode1Name()canonicalCombiningClass(0u)fullUpper()fullLower()fullTitle()fullFolding()bidiClass(BidiClassId.none)
2143             numericType(NumericTypeId.none)numericValue()aliases()bidiMirroringGlyph(cast<uchar>(0u))bidiPairedBracketType(BidiPairedBracketTypeId.none)
2144             bidiPairedBracket(cast<uchar>(0u))
2145         {
2146         }
2147         public inline const string& CharacterName() const
2148         {
2149             return characterName;
2150         }
2151         public inline const string& Unicode1Name() const
2152         {
2153             return unicode1Name;
2154         }
2155         public inline byte CanonicalCombiningClass() const
2156         {
2157             return canonicalCombiningClass;
2158         }
2159         public inline const ustring& FullUpper() const
2160         {
2161             return fullUpper;
2162         }
2163         public inline const ustring& FullLower() const
2164         {
2165             return fullLower;
2166         }
2167         public inline const ustring& FullTitle() const
2168         {
2169             return fullTitle;
2170         }
2171         public inline const ustring& FullFolding() const
2172         {
2173             return fullFolding;
2174         }
2175         public inline BidiClassId BidiClassValue() const
2176         {
2177             return bidiClass;
2178         }
2179         public inline NumericTypeId NumericTypeValue() const
2180         {
2181             return numericType;
2182         }
2183         public inline const ustring& NumericValue() const
2184         {
2185             return numericValue;
2186         }
2187         public inline const List<Alias>& Aliases() const
2188         {
2189             return aliases;
2190         }
2191         public inline uchar BidiMirroringGlyph() const
2192         {
2193             return bidiMirroringGlyph;
2194         }
2195         public inline BidiPairedBracketTypeId BidiPairedBracketTypeValue() const
2196         {
2197             return bidiPairedBracketType;
2198         }
2199         public inline uchar BidiPairedBracket()
2200         {
2201             return bidiPairedBracket;
2202         }
2203         [nodiscard]
2204         public Result<bool> Read(BinaryReader& reader)
2205         {
2206             auto characterNameResult = reader.ReadString();
2207             if (characterNameResult.Error())
2208             {
2209                 return Result<bool>(ErrorId(characterNameResult.GetErrorId()));
2210             }
2211             characterName = characterNameResult.Value();
2212             auto unicode1NameResult = reader.ReadString();
2213             if (unicode1NameResult.Error())
2214             {
2215                 return Result<bool>(ErrorId(unicode1NameResult.GetErrorId()));
2216             }
2217             unicode1Name = unicode1NameResult.Value();
2218             auto canonicalCombiningClassResult = reader.ReadByte();
2219             if (canonicalCombiningClassResult.Error())
2220             {
2221                 return Result<bool>(ErrorId(canonicalCombiningClassResult.GetErrorId()));
2222             }
2223             canonicalCombiningClass = canonicalCombiningClassResult.Value();
2224             auto nuResult = reader.ReadByte();
2225             if (nuResult.Error())
2226             {
2227                 return Result<bool>(ErrorId(nuResult.GetErrorId()));
2228             }
2229             byte nu = nuResult.Value();
2230             for (byte i = 0u; i < nu; ++i;)
2231             {
2232                 auto result = reader.ReadUChar();
2233                 if (result.Error())
2234                 {
2235                     return Result<bool>(ErrorId(result.GetErrorId()));
2236                 }
2237                 fullUpper.Append(result.Value());
2238             }
2239             auto nlResult = reader.ReadByte();
2240             if (nlResult.Error())
2241             {
2242                 return Result<bool>(ErrorId(nlResult.GetErrorId()));
2243             }
2244             byte nl = nlResult.Value();
2245             for (byte i = 0u; i < nl; ++i;)
2246             {
2247                 auto result = reader.ReadUChar();
2248                 if (result.Error())
2249                 {
2250                     return Result<bool>(ErrorId(result.GetErrorId()));
2251                 }
2252                 fullLower.Append(result.Value());
2253             }
2254             auto ntResult = reader.ReadByte();
2255             if (ntResult.Error())
2256             {
2257                 return Result<bool>(ErrorId(ntResult.GetErrorId()));
2258             }
2259             byte nt = ntResult.Value();
2260             for (byte i = 0u; i < nt; ++i;)
2261             {
2262                 auto result = reader.ReadUChar();
2263                 if (result.Error())
2264                 {
2265                     return Result<bool>(ErrorId(result.GetErrorId()));
2266                 }
2267                 fullTitle.Append(result.Value());
2268             }
2269             auto nfResult = reader.ReadByte();
2270             if (nfResult.Error())
2271             {
2272                 return Result<bool>(ErrorId(nfResult.GetErrorId()));
2273             }
2274             byte nf = nfResult.Value();
2275             for (byte i = 0u; i < nf; ++i;)
2276             {
2277                 auto result = reader.ReadUChar();
2278                 if (result.Error())
2279                 {
2280                     return Result<bool>(ErrorId(result.GetErrorId()));
2281                 }
2282                 fullFolding.Append(result.Value());
2283             }
2284             auto bidiClassResult = reader.ReadByte();
2285             if (bidiClassResult.Error())
2286             {
2287                 return Result<bool>(ErrorId(bidiClassResult.GetErrorId()));
2288             }
2289             bidiClass = cast<BidiClassId>(bidiClassResult.Value());
2290             auto numericTypeResult = reader.ReadByte();
2291             if (numericTypeResult.Error())
2292             {
2293                 return Result<bool>(ErrorId(numericTypeResult.GetErrorId()));
2294             }
2295             numericType = cast<NumericTypeId>(numericTypeResult.Value());
2296             auto numericValueResult = reader.ReadUString();
2297             if (numericValueResult.Error())
2298             {
2299                 return Result<bool>(ErrorId(numericValueResult.GetErrorId()));
2300             }
2301             numericValue = numericValueResult.Value();
2302             auto naResult = reader.ReadByte();
2303             if (naResult.Error())
2304             {
2305                 return Result<bool>(ErrorId(naResult.GetErrorId()));
2306             }
2307             byte na = naResult.Value();
2308             for (byte i = 0u; i < na; ++i;)
2309             {
2310                 Alias alias;
2311                 auto aliasResult = alias.Read(reader);
2312                 if (aliasResult.Error())
2313                 {
2314                     return Result<bool>(ErrorId(aliasResult.GetErrorId()));
2315                 }
2316                 aliases.Add(alias);
2317             }
2318             auto bidiMirroringGlyphResult = reader.ReadUChar();
2319             if (bidiMirroringGlyphResult.Error())
2320             {
2321                 return Result<bool>(ErrorId(bidiMirroringGlyphResult.GetErrorId()));
2322             }
2323             bidiMirroringGlyph = bidiMirroringGlyphResult.Value();
2324             auto bidiPairedBracketTypeResult = reader.ReadByte();
2325             if (bidiPairedBracketTypeResult.Error())
2326             {
2327                 return Result<bool>(ErrorId(bidiPairedBracketTypeResult.GetErrorId()));
2328             }
2329             bidiPairedBracketType = cast<BidiPairedBracketTypeId>(bidiPairedBracketTypeResult.Value());
2330             auto bidiPairedBracketResult = reader.ReadUChar();
2331             if (bidiPairedBracketResult.Error())
2332             {
2333                 return Result<bool>(ErrorId(bidiPairedBracketResult.GetErrorId()));
2334             }
2335             bidiPairedBracket = bidiPairedBracketResult.Value();
2336             return Result<bool>(true);
2337         }
2338         private string characterName;
2339         private string unicode1Name;
2340         private byte canonicalCombiningClass;
2341         private ustring fullUpper;
2342         private ustring fullLower;
2343         private ustring fullTitle;
2344         private ustring fullFolding;
2345         private BidiClassId bidiClass;
2346         private NumericTypeId numericType;
2347         private ustring numericValue;
2348         private List<Alias> aliases;
2349         private uchar bidiMirroringGlyph;
2350         private BidiPairedBracketTypeId bidiPairedBracketType;
2351         private uchar bidiPairedBracket;
2352     }
2353 
2354     public class CharacterInfoPage
2355     {
2356         public CharacterInfoPage() : characterInfos()
2357         {
2358             characterInfos.Resize(numInfosInPage);
2359         }
2360         public const CharacterInfo& operator[](long index) const
2361         {
2362             return *characterInfos[index];
2363         }
2364         public const CharacterInfo* Get(long index) const
2365         {
2366             return characterInfos[index].Get();
2367         }
2368         [nodiscard]
2369         public Result<bool> Read(BinaryReader& reader)
2370         {
2371             for (long i = 0; i < numInfosInPage; ++i;)
2372             {
2373                 CharacterInfo* characterInfo = new CharacterInfo();
2374                 auto result = characterInfo->Read(reader);
2375                 if (result.Error())
2376                 {
2377                     return Result<bool>(ErrorId(result.GetErrorId()));
2378                 }
2379                 characterInfos[i].Reset(characterInfo);
2380             }
2381             return Result<bool>(true);
2382         }
2383         private List<UniquePtr<CharacterInfo>> characterInfos;
2384     }
2385 
2386     public class ExtendedCharacterInfoPage
2387     {
2388         public ExtendedCharacterInfoPage() : extendedCharacterInfos()
2389         {
2390             extendedCharacterInfos.Resize(numInfosInPage);
2391         }
2392         public const ExtendedCharacterInfo& operator[](long index) const
2393         {
2394             return *extendedCharacterInfos[index];
2395         }
2396         public const ExtendedCharacterInfo* Get(long index) const
2397         {
2398             return extendedCharacterInfos[index].Get();
2399         }
2400         [nodiscard]
2401         public Result<bool> Read(BinaryReader& reader)
2402         {
2403             for (long i = 0; i < numInfosInPage; ++i;)
2404             {
2405                 ExtendedCharacterInfo* extendedCharacterInfo = new ExtendedCharacterInfo();
2406                 auto result = extendedCharacterInfo->Read(reader);
2407                 if (result.Error())
2408                 {
2409                     return Result<bool>(ErrorId(result.GetErrorId()));
2410                 }
2411                 extendedCharacterInfos[i].Reset(extendedCharacterInfo);
2412             }
2413             return Result<bool>(true);
2414         }
2415         private List<UniquePtr<ExtendedCharacterInfo>> extendedCharacterInfos;
2416     }
2417 
2418     public class ExtendedCharacterInfoHeader
2419     {
2420         public ExtendedCharacterInfoHeader() : extendedPageStarts()
2421         {
2422         }
2423         public uint operator[](long index) const
2424         {
2425             return extendedPageStarts[index];
2426         }
2427         [nodiscard]
2428         public Result<bool> Read(BinaryReader& reader)
2429         {
2430             auto nResult = reader.ReadUInt();
2431             if (nResult.Error())
2432             {
2433                 return Result<bool>(ErrorId(nResult.GetErrorId()));
2434             }
2435             uint n = nResult.Value();
2436             extendedPageStarts.Resize(n);
2437             for (uint i = 0u; i < n; ++i;)
2438             {
2439                 auto result = reader.ReadUInt();
2440                 if (result.Error())
2441                 {
2442                     return Result<bool>(ErrorId(result.GetErrorId()));
2443                 }
2444                 extendedPageStarts[i] = result.Value();
2445             }
2446             return Result<bool>(true);
2447         }
2448         private List<uint> extendedPageStarts;
2449     }
2450 
2451     public const byte cmajor_ucd_version_1 = cast<byte>('1');
2452     public const byte cmajor_ucd_version_2 = cast<byte>('2');
2453     public const byte cmajor_ucd_version_3 = cast<byte>('3');
2454     public const byte current_cmajor_ucd_version = cmajor_ucd_version_3;
2455 
2456     public class CharacterTable
2457     {
2458         static CharacterTable() : instance(new CharacterTable())
2459         {
2460         }
2461         public static CharacterTable& Instance()
2462         {
2463             return *instance;
2464         }
2465         [nodiscard]
2466         public Result<const CharacterInfo*> GetCharacterInfo(uchar codePoint)
2467         {
2468             if (codePoint > cast<uchar>(1114111) )
2469             {
2470                 auto hexStringResult = ToHexString(cast<uint>(codePoint));
2471                 if (hexStringResult.Error())
2472                 {
2473                     return Result<const CharacterInfo*>(ErrorId(hexStringResult.GetErrorId()));
2474                 }
2475                 string errorMessage = "invalid Unicode code point " + hexStringResult.Value();
2476                 int errorId = AllocateError(errorMessage);
2477                 return Result<const CharacterInfo*>(ErrorId(errorId));
2478             }
2479             long pageIndex = cast<long>(codePoint) / numInfosInPage;
2480             if (pages.Count() <= pageIndex)
2481             {
2482                 LockGuard<RecursiveMutex> lock(characterTableLock);
2483                 while (pages.Count() <= pageIndex)
2484                 {
2485                     pages.Add(UniquePtr<CharacterInfoPage>());
2486                 }
2487             }
2488             CharacterInfoPage* page = pages[pageIndex].Get();
2489             if (page == null)
2490             {
2491                 LockGuard<RecursiveMutex> lock(characterTableLock);
2492                 if (page == null)
2493                 {
2494                     auto pathToUcdBinFileResult = PathToUcdBinFile();
2495                     if (pathToUcdBinFileResult.Error())
2496                     {
2497                         return Result<const CharacterInfo*>(ErrorId(pathToUcdBinFileResult.GetErrorId()));
2498                     }
2499                     Result<bool> ucdBinFileExistResult = File.Exists(pathToUcdBinFileResult.Value());
2500                     if (ucdBinFileExistResult.Error())
2501                     {
2502                         return Result<const CharacterInfo*>(ErrorId(ucdBinFileExistResult.GetErrorId()));
2503                     }
2504                     if (!ucdBinFileExistResult.Value())
2505                     {
2506                         string errorMessage = "Cmajor Unicode database file \'" + pathToUcdBinFileResult.Value() + "\' does not exist.";
2507                         int errorId = AllocateError(errorMessage);
2508                         return Result<const CharacterInfo*>(ErrorId(errorId));
2509                     }
2510                     auto binaryReaderResult = File.OpenBinary(pathToUcdBinFileResult.Value());
2511                     if (binaryReaderResult.Error())
2512                     {
2513                         return Result<const CharacterInfo*>(ErrorId(binaryReaderResult.GetErrorId()));
2514                     }
2515                     BinaryReader& reader = binaryReaderResult.Value();
2516                     if (!headerRead)
2517                     {
2518                         auto headerResult = ReadHeader(reader);
2519                         if (headerResult.Error())
2520                         {
2521                             return Result<const CharacterInfo*>(ErrorId(headerResult.GetErrorId()));
2522                         }
2523                     }
2524                     uint pageStart = headerSize + characterInfoPageSize * cast<uint>(pageIndex);
2525                     auto seekResult = reader.Seek(cast<long>(pageStart)Origin.seekSet);
2526                     if (seekResult.Error())
2527                     {
2528                         return Result<const CharacterInfo*>(ErrorId(seekResult.GetErrorId()));
2529                     }
2530                     page = new CharacterInfoPage();
2531                     auto readResult = page->Read(reader);
2532                     if (readResult.Error())
2533                     {
2534                         return Result<const CharacterInfo*>(ErrorId(readResult.GetErrorId()));
2535                     }
2536                     pages[pageIndex].Reset(page);
2537                 }
2538             }
2539             long infoIndex = cast<long>(codePoint) % numInfosInPage;
2540             const CharacterInfo* info = page->Get(infoIndex);
2541             return Result<const CharacterInfo*>(info);
2542         }
2543         [nodiscard]
2544         public Result<const ExtendedCharacterInfo*> GetExtendedCharacterInfo(uchar codePoint)
2545         {
2546             if (codePoint > cast<uchar>(1114111) )
2547             {
2548                 auto hexStringResult = ToHexString(cast<uint>(codePoint));
2549                 if (hexStringResult.Error())
2550                 {
2551                     return Result<const ExtendedCharacterInfo*>(hexStringResult.GetErrorId());
2552                 }
2553                 string errorMessage = "invalid Unicode code point " + hexStringResult.Value();
2554                 int errorId = AllocateError(errorMessage);
2555                 return Result<const ExtendedCharacterInfo*>(ErrorId(errorId));
2556             }
2557             long pageIndex = cast<long>(codePoint) / numInfosInPage;
2558             if (extendedPages.Count() <= pageIndex)
2559             {
2560                 LockGuard<RecursiveMutex> lock(characterTableLock);
2561                 while (extendedPages.Count() <= pageIndex)
2562                 {
2563                     extendedPages.Add(UniquePtr<ExtendedCharacterInfoPage>());
2564                 }
2565             }
2566             ExtendedCharacterInfoPage* extendedPage = extendedPages[pageIndex].Get();
2567             if (extendedPage == null)
2568             {
2569                 LockGuard<RecursiveMutex> lock(characterTableLock);
2570                 if (extendedPage == null)
2571                 {
2572                     auto pathToUcdBinFileResult = PathToUcdBinFile();
2573                     if (pathToUcdBinFileResult.Error())
2574                     {
2575                         return Result<const ExtendedCharacterInfo*>(ErrorId(pathToUcdBinFileResult.GetErrorId()));
2576                     }
2577                     Result<bool> ucdBinFileExistResult = File.Exists(pathToUcdBinFileResult.Value());
2578                     if (ucdBinFileExistResult.Error())
2579                     {
2580                         return Result<const ExtendedCharacterInfo*>(ErrorId(ucdBinFileExistResult.GetErrorId()));
2581                     }
2582                     if (!ucdBinFileExistResult.Value())
2583                     {
2584                         string errorMessage = "Cmajor Unicode database file \'" + pathToUcdBinFileResult.Value() + "\' does not exist.";
2585                         int errorId = AllocateError(errorMessage);
2586                         return Result<const ExtendedCharacterInfo*>(ErrorId(errorId));
2587                     }
2588                     auto readerResult = File.OpenBinary(pathToUcdBinFileResult.Value());
2589                     if (readerResult.Error())
2590                     {
2591                         return Result<const ExtendedCharacterInfo*>(ErrorId(readerResult.GetErrorId()));
2592                     }
2593                     BinaryReader& reader = readerResult.Value();
2594                     if (!headerRead)
2595                     {
2596                         auto headerResult = ReadHeader(reader);
2597                         if (headerResult.Error())
2598                         {
2599                             return Result<const ExtendedCharacterInfo*>(ErrorId(headerResult.GetErrorId()));
2600                         }
2601                     }
2602                     if (extendedHeader.IsNull())
2603                     {
2604                         auto seekResult = reader.Seek(cast<long>(extendedHeaderStart)Origin.seekSet);
2605                         if (seekResult.Error())
2606                         {
2607                             return Result<const ExtendedCharacterInfo*>(ErrorId(seekResult.GetErrorId()));
2608                         }
2609                         auto result = ReadExtendedHeader(reader);
2610                         if (result.Error())
2611                         {
2612                             return Result<const ExtendedCharacterInfo*>(ErrorId(result.GetErrorId()));
2613                         }
2614                     }
2615                     auto seekResult = reader.Seek(cast<long>((*extendedHeader)[pageIndex])Origin.seekSet);
2616                     if (seekResult.Error())
2617                     {
2618                         return Result<const ExtendedCharacterInfo*>(ErrorId(seekResult.GetErrorId()));
2619                     }
2620                     extendedPage = new ExtendedCharacterInfoPage();
2621                     auto readResult = extendedPage->Read(reader);
2622                     if (readResult.Error())
2623                     {
2624                         return Result<const ExtendedCharacterInfo*>(ErrorId(readResult.GetErrorId()));
2625                     }
2626                     extendedPages[pageIndex].Reset(extendedPage);
2627                 }
2628             }
2629             long infoIndex = cast<long>(codePoint) % numInfosInPage;
2630             const ExtendedCharacterInfo* info = extendedPage->Get(infoIndex);
2631             return Result<const ExtendedCharacterInfo*>(info);
2632         }
2633         private CharacterTable() : headerRead(false)pages()extendedHeaderStart(0u)extendedHeaderEnd(0u)extendedHeader()extendedPages()characterTableLock()
2634         {
2635             headerMagic.Resize(8);
2636             string hdrmgc = "CMAJUCD";
2637             for (long i = 0; i < 8; ++i;)
2638             {
2639                 if (i < 7)
2640                 {
2641                     headerMagic[i] = cast<byte>(hdrmgc[i]);
2642                 }
2643                 else
2644                 {
2645                     headerMagic[i] = current_cmajor_ucd_version;
2646                 }
2647             }
2648         }
2649         [nodiscard]
2650         private Result<bool> ReadHeader(BinaryReader& reader)
2651         {
2652             headerRead = true;
2653             List<byte> magic;
2654             magic.Resize(8);
2655             for (long i = 0; i < 8; ++i;)
2656             {
2657                 auto result = reader.ReadByte();
2658                 if (result.Error())
2659                 {
2660                     return Result<bool>(ErrorId(result.GetErrorId()));
2661                 }
2662                 magic[i] = result.Value();
2663             }
2664             for (long i = 0; i < 7; ++i;)
2665             {
2666                 if (magic[i] != cast<byte>(headerMagic[i]))
2667                 {
2668                     string errorMessage = "invalid cmajor_ucd.bin header magic: \'CMAJUCD\' expected";
2669                     int errorId = AllocateError(errorMessage);
2670                     return Result<bool>(ErrorId(errorId));
2671                 }
2672             }
2673             if (magic[7] != headerMagic[7])
2674             {
2675                 string errorMessage = "invalid cmajor_ucd.bin version: version " + 
2676                     string(cast<char>(headerMagic[7])1) + " expected, version " + 
2677                     string(cast<char>(magic[7])1) + " read";
2678                 int errorId = AllocateError(errorMessage);
2679                 return Result<bool>(ErrorId(errorId));
2680             }
2681             auto extendedHeaderStartResult = reader.ReadUInt();
2682             if (extendedHeaderStartResult.Error())
2683             {
2684                 return Result<bool>(ErrorId(extendedHeaderStartResult.GetErrorId()));
2685             }
2686             extendedHeaderStart = extendedHeaderStartResult.Value();
2687             auto extendedHeaderEndResult = reader.ReadUInt();
2688             if (extendedHeaderEndResult.Error())
2689             {
2690                 return Result<bool>(ErrorId(extendedHeaderEndResult.GetErrorId()));
2691             }
2692             extendedHeaderEnd = extendedHeaderEndResult.Value();
2693             return Result<bool>(true);
2694         }
2695         [nodiscard]
2696         private Result<bool> ReadExtendedHeader(BinaryReader& reader)
2697         {
2698             extendedHeader.Reset(new ExtendedCharacterInfoHeader());
2699             auto result = extendedHeader->Read(reader);
2700             if (result.Error())
2701             {
2702                 return Result<bool>(ErrorId(result.GetErrorId()));
2703             }
2704             return Result<bool>(true);
2705         }
2706         public ~CharacterTable()
2707         {
2708         }
2709         private const uint headerSize = 4096u;
2710         private static UniquePtr<CharacterTable> instance;
2711         private List<byte> headerMagic;
2712         private bool headerRead;
2713         private List<UniquePtr<CharacterInfoPage>> pages;
2714         private uint extendedHeaderStart;
2715         private uint extendedHeaderEnd;
2716         private UniquePtr<ExtendedCharacterInfoHeader> extendedHeader;
2717         private List<UniquePtr<ExtendedCharacterInfoPage>> extendedPages;
2718         private RecursiveMutex characterTableLock;
2719     }
2720 
2721     [nodiscard]
2722     public Result<const CharacterInfo*> GetCharacterInfo(uchar codePoint)
2723     {
2724         return CharacterTable.Instance().GetCharacterInfo(codePoint);
2725     }
2726 
2727     [nodiscard]
2728     public Result<const ExtendedCharacterInfo*> GetExtendedCharacterInfo(uchar codePoint)
2729     {
2730         return CharacterTable.Instance().GetExtendedCharacterInfo(codePoint);
2731     }
2732 
2733     [nodiscard]
2734     public Result<GeneralCategoryId> GetGeneralCategory(uchar c)
2735     {
2736         auto result = GetCharacterInfo(c);
2737         if (result.Error())
2738         {
2739             return Result<GeneralCategoryId>(ErrorId(result.GetErrorId()));
2740         }
2741         const CharacterInfo* characterInfo = result.Value();
2742         return Result<GeneralCategoryId>(characterInfo->GeneralCategoryValue());
2743     }
2744 
2745     [nodiscard]
2746     public Result<bool> HasGeneralCategory(uchar cGeneralCategoryId generalCategory)
2747     {
2748         auto result = GetCharacterInfo(c);
2749         if (result.Error())
2750         {
2751             return Result<bool>(ErrorId(result.GetErrorId()));
2752         }
2753         const CharacterInfo* characterInfo = result.Value();
2754         return Result<bool>(characterInfo->HasGeneralCategory(generalCategory));
2755     }