1
2
3
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<uint, void*> binaryPropertyIdMap;
294 private Map<string, void*> shortNameMap;
295 private Map<string, void*> 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 adlam, aegeanNumbers, ahom, alchemical, alphabeticPf, anatolianHieroglyphs, ancientGreekMusic, ancientGreekNumbers, ancientSymbols,
321 arabic, arabicExtA, arabicMath, arabicPfA, arabicPfB, arabicSup, armenian, arrows, ascii, avestan,
322 balinese, bamum, bamumSup, bassaVah, batak, bengali, bhaisuki, blockElements, bopomofo, bopomofoExt, boxDrawing,
323 brahmi, braille, buginese, buhid, byzantineMusic,
324 carian, caucasianAlbanian, chakma, cham, cherokee, cherokeeSup, chessSymbols,
325 cjk, cjkCompat, cjkCompatForms, cjkCompatIdeographs, cjkCompatIdeographsSup, cjkExtA, cjkExtB, cjkExtC, cjkExtD, cjkExtE, cjkExtF,
326 cjkRadicalsSup, cjkStrokes, cjkSymbols, compatJamo, controlPictures, coptic, copticEpactNumbers, countingRod, cuneiform,
327 cuneiformNumbers, currencySymbols, cypriotSyllabary, cyrillic, cyrillicExtA, cyrillicExtB, cyrillicExtC, cyrillicSup,
328 deseret, devanagari, devanagariExt, diacriticals, diariticalsForSymbols, diacriticalsSup, diacriticalsExt, dingbats, dogra, domino, duployan,
329 earlyDynasticCuneiform, egyptianHieroglyphs, egyptianHieroglyphFormatControls, elbasan, elymaic, emoticons, enclosedAlphanum, enclosedAlphanumSup, enclosedCjk, enclosedIdeographicSup,
330 ethiopic, ethiopicExt, ethiopicExtA, ethiopicSup,
331 geometricShapes, geometricShapesExt, georgian, georgianExt, georgianSup, glagolitic, glagoliticSup, gothic, grantha, greek, greekExt, gujarati, gunjalaGondi, gurmukhi,
332 halfAndFullForms, halfMarks, hangul, hanifiRohingya, hanunoo, hatran, hebrew, highPuSurrogates, highSurrogates, hiragana,
333 idc, ideographicSymbols, imperialAramaic, indicNumberForms, inscriptionalPahlavi, inscriptionalParthian, ipaExt, indicSiyaqNumbers,
334 jamo, jamoExtA, jamoExtB, javanese, kaithi, kanaExtA, smallKanaExt, kanaSup, kanbun, kangxi, kannada, katakana, katakanaExt, kayahLi, kharoshthi, khmer, khmerSymbols, khojki, khudawadi,
335 lao, latin1Sup, latinExtA, latinExtAdditional, latinExtB, latinExtC, latinExtD, latinExtE, lepcha, letterlikeSymbols, limbu,
336 linearA, linearBIdeograms, linearBSyllabary, lisu, lowSurrogates, lycian, lydian,
337 mahajani, mahjong, makasar, malayalam, mandaic, manichean, marchen, masaramGondi, mathAlphanum, mathOperators, mayanNumerals, medefaidrin, meeteiMayek, meeteiMayekExt, mendeKikakui, meroiticCursive, meroiticHieroglyphs,
338 miao, miscArrows, miscMathSymbolsA, miscMathSymbolsB, miscPictographs, miscSymbols, miscTechnical, modi, modifierLetters, modifierToneLetters, mongolian, mongolianSup,
339 mro, music, multani, myanmar, myanmarExtA, myanmarExtB,
340 nabataean, nb, nandinagari, newTaiLue, newa, nko, numberForms, nushu, nyiakengPuachueHmong,
341 ocr, ogham, olChiki, oldHungarian, oldItalic, oldNorthArabian, oldPermic, oldPersian, oldSogdian, oldSouthArabian, oldTurkic, oriya, ornamentalDingbats, osage, osmanya, ottomanSiyaqNumbers,
342 pahawhHmong, palmyrene, pauCinHau, phagsPa, phaistos, phoenician, phoneticExt, phoneticExtSup, playingCards, psalterPahlavi, pua, punctuation,
343 rejang, rumi, runic,
344 samaritan, saurashtra, sharada, shavian, shorthandFormatControls, siddham, sinhala, sinhalaArchaicNumbers, smallForms, sogdian, soraSompeng, soyombo, specials, sundanese, sundaneseSup,
345 supArrowsA, supArrowsB, supArrowsC, supMathOperators, supPuaA, supPuaB, supPunctuation, supSymbolsAndPictographs, superAndSub, suttonSignWriting, sylotiNagri, symbolsAndPictographsExtA, syriac,
346 syriacSup,
347 tagalog, tagbanwa, tags, taiLe, taiTham, taiViet, taiXuanJing, takri, tamil, tamilSup, tangut, tangutComponents, telugu, thaana, thai, tibetan, tifinagh, tirhuta, transportAndMap,
348 ucas, ucasExt, ugaritic, vai, vedicExt, verticalForms, vs, vsSup, wancho, warangCiti, yiRadicals, yiSyllables, yijing, zanabazarSquare
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<uint, void*> blockIdMap;
777 private Map<string, void*> shortNameMap;
778 private Map<string, void*> 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 << 0u, Ll = 1u << 1u, Lt = 1u << 2u, Lm = 1u << 3u, Lo = 1u << 4u,
803 LC = Lu | Ll | Lt,
804 L = Lu | Ll | Lt | Lm | Lo,
805 Mn = 1u << 5u, Mc = 1u << 6u, Me = 1u << 7u,
806 M = Mn | Mc | Me,
807 Nd = 1u << 8u, Nl = 1u << 9u, No = 1u << 10u,
808 N = Nd | Nl | No,
809 Pc = 1u << 11u, Pd = 1u << 12u, Ps = 1u << 13u, Pe = 1u << 14u, Pi = 1u << 15u, Pf = 1u << 16u, Po = 1u << 17u,
810 P = Pc | Pd | Ps | Pe | Pi | Pf | Po,
811 Sm = 1u << 18u, Sc = 1u << 19u, Sk = 1u << 20u, So = 1u << 21u,
812 S = Sm | Sc | Sk | So,
813 Zs = 1u << 22u, Zl = 1u << 23u, Zp = 1u << 24u,
814 Z = Zs | Zl | Zp,
815 Cc = 1u << 25u, Cf = 1u << 26u, Cs = 1u << 27u, Co = 1u << 28u, Cn = 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<uint, void*> generalCategoryIdMap;
976 private Map<string, void*> shortNameMap;
977 private Map<string, void*> 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_0, age_2_1,
1003 age_3_0, age_3_1, age_3_2,
1004 age_4_0, age_4_1,
1005 age_5_0, age_5_1, age_5_2,
1006 age_6_0, age_6_1, age_6_2, age_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_0, age_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<uint, void*> ageIdMap;
1099 private Map<string, void*> 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 adlm, aghb, ahom, arab, armi, armn, avst,
1116 bali, bamu, bass, batk, beng, bhks, bopo, brah, brai, bugi, buhd,
1117 cakm, cans, cari, cham, cher, copt, cprt, cyrl,
1118 deva, dogr, dsrt, dupl,
1119 elba, elym, egyp, ethi,
1120 geor, glag, gong, gonm, goth, gran, grek, gujr, guru,
1121 hang, hani, hano, hatr, hebr, hira, hluw, hmng, hmnp, hrkt, hung,
1122 ital,
1123 java,
1124 kali, kana, khar, khmr, khoj, knda, kthi,
1125 lana, laoo, latn, lepc, limb, lina, linb, lisu, lyci, lydi,
1126 mahj, maka, mand, mani, marc, medf, mend, merc, mero, mlym, modi, mong, mroo, mtei, mult, mymr,
1127 nand, narb, nbat, newa, nkoo, nshu,
1128 ogam, olck, orkh, orya, osge, osma,
1129 palm, pauc, perm, phag, phli, phlp, phnx, plrd, prti,
1130 qaai,
1131 rjng, rohg, runr,
1132 samr, sarb, saur, sgnw, shaw, shrd, sidd, sind, sinh, sogd, sogo, sora, soyo, sund, sylo, syrc,
1133 tagb, takr, tale, talu, taml, tang, tavt, telu, tfng, tglg, thaa, thai, tibt, tirh,
1134 ugar,
1135 vaii,
1136 wara,
1137 wcho,
1138 xpeo, xsux,
1139 yiii, zanb,
1140 zinh, zyyy, zzzz
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<uint, void*> scriptIdMap;
1412 private Map<string, void*> shortNameMap;
1413 private Map<string, void*> 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 de, di, nu
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<uint, void*> numericTypeIdMap;
1680 private Map<string, void*> shortNameMap;
1681 private Map<string, void*> 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 al, an, b, bn, cs, en, es, et, fsi, l, lre, lri, lro, nsm, on, pdf, pdi, r, rle, rli, rlo, s, ws
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<uint, void*> bidiClassIdMap;
1847 private Map<string, void*> shortNameMap;
1848 private Map<string, void*> 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 o, c
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<uint, void*> bidiPairedBracketTypeIdMap;
1994 private Map<string, void*> shortNameMap;
1995 private Map<string, void*> 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 correction, control, alternate, figment, abbreviation
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<uint, void*> aliasTypeIdMap;
2089 private Map<string, void*> 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 c, GeneralCategoryId 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 }