1
2
3
4
5
6 using System.IO;
7 using System.Collections;
8 using System.Unicode;
9
10 namespace System
11 {
12 [nodiscard]
13 public Result<ustring> ToUtf32(const string& utf8Str)
14 {
15 ustring result;
16 const char* p = utf8Str.Chars();
17 long bytesRemaining = utf8Str.Length();
18 while (bytesRemaining > 0)
19 {
20 char c = *p;
21 byte x = cast<byte>(c);
22 if ((x & 128u) == 0u)
23 {
24 result.Append(cast<uchar>(cast<uint>(x)));
25 --bytesRemaining;
26 ++p;
27 }
28 else if ((x & 224u) == 192u )
29 {
30 if (bytesRemaining < 2)
31 {
32 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
33 return Result<ustring>(ErrorId(errorId));
34 }
35 uchar u = cast<uchar>(cast<uint>(0u));
36 byte b1 = cast<byte>(p[1]);
37 if ((b1 & 192u) != 128u )
38 {
39 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
40 return Result<ustring>(ErrorId(errorId));
41 }
42 byte shift = 0u;
43 for (byte i = 0u; i < 6u; ++i;)
44 {
45 byte bit = b1 & 1u;
46 b1 = b1 >> 1u;
47 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
48 ++shift;
49 }
50 byte b0 = x;
51 for (byte i = 0u; i < 5u; ++i;)
52 {
53 byte bit = b0 & 1u;
54 b0 = b0 >> 1u;
55 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
56 ++shift;
57 }
58 result.Append(u);
59 bytesRemaining = bytesRemaining - 2;
60 p = p + 2;
61 }
62 else if ((x & 240u) == 224u )
63 {
64 if (bytesRemaining < 3)
65 {
66 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
67 return Result<ustring>(ErrorId(errorId));
68 }
69 uchar u = cast<uchar>(cast<uint>(0u));
70 byte b2 = cast<byte>(p[2]);
71 if ((b2 & 192u) != 128u )
72 {
73 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
74 return Result<ustring>(ErrorId(errorId));
75 }
76 byte shift = 0u;
77 for (byte i = 0u; i < 6u; ++i;)
78 {
79 byte bit = b2 & 1u;
80 b2 = b2 >> 1u;
81 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
82 ++shift;
83 }
84 byte b1 = cast<byte>(p[1]);
85 if ((b1 & 192u) != 128u )
86 {
87 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
88 return Result<ustring>(ErrorId(errorId));
89 }
90 for (byte i = 0u; i < 6u; ++i;)
91 {
92 byte bit = b1 & 1u;
93 b1 = b1 >> 1u;
94 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
95 ++shift;
96 }
97 byte b0 = x;
98 for (byte i = 0u; i < 4u; ++i;)
99 {
100 byte bit = b0 & 1u;
101 b0 = b0 >> 1u;
102 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
103 ++shift;
104 }
105 result.Append(u);
106 bytesRemaining = bytesRemaining - 3;
107 p = p + 3;
108 }
109 else if ((x & 248u) == 240u )
110 {
111 if (bytesRemaining < 4)
112 {
113 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
114 return Result<ustring>(ErrorId(errorId));
115 }
116 uchar u = cast<uchar>(cast<uint>(0u));
117 byte b3 = cast<byte>(p[3]);
118 if ((b3 & 192u) != 128u )
119 {
120 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
121 return Result<ustring>(ErrorId(errorId));
122 }
123 byte shift = 0u;
124 for (byte i = 0u; i < 6u; ++i;)
125 {
126 byte bit = b3 & 1u;
127 b3 = b3 >> 1u;
128 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
129 ++shift;
130 }
131 byte b2 = cast<byte>(p[2]);
132 if ((b2 & 192u) != 128u )
133 {
134 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
135 return Result<ustring>(ErrorId(errorId));
136 }
137 for (byte i = 0u; i < 6u; ++i;)
138 {
139 byte bit = b2 & 1u;
140 b2 = b2 >> 1u;
141 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
142 ++shift;
143 }
144 byte b1 = cast<byte>(p[1]);
145 if ((b1 & 192u) != 128u )
146 {
147 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
148 return Result<ustring>(ErrorId(errorId));
149 }
150 for (byte i = 0u; i < 6u; ++i;)
151 {
152 byte bit = b1 & 1u;
153 b1 = b1 >> 1u;
154 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
155 ++shift;
156 }
157 byte b0 = x;
158 for (byte i = 0u; i < 3u; ++i;)
159 {
160 byte bit = b0 & 1u;
161 b0 = b0 >> 1u;
162 u = cast<uchar>(cast<uint>(u) | (cast<uint>(bit) << shift));
163 ++shift;
164 }
165 result.Append(u);
166 bytesRemaining = bytesRemaining - 4;
167 p = p + 4;
168 }
169 else
170 {
171 int errorId = AllocateError("invalid UTF-8 sequence: index=" + ToString(p - utf8Str.Chars()));
172 return Result<ustring>(ErrorId(errorId));
173 }
174 }
175 return Result<ustring>(result);
176 }
177
178 [nodiscard]
179 public Result<ustring> ToUtf32(const wstring& utf16Str)
180 {
181 ustring result;
182 const wchar* w = utf16Str.Chars();
183 long remaining = utf16Str.Length();
184 while (remaining > 0)
185 {
186 wchar w1 = *w++;
187 --remaining;
188 if (cast<ushort>(w1) < 55296u || cast<ushort>(w1) > 57343u )
189 {
190 result.Append(w1);
191 }
192 else
193 {
194 if (cast<ushort>(w1) < 55296u || cast<ushort>(w1) > 56319u )
195 {
196 int errorId = AllocateError("invalid UTF-16 sequence: index=" + ToString(w - utf16Str.Chars()));
197 return Result<ustring>(ErrorId(errorId));
198 }
199 if (remaining > 0)
200 {
201 wchar w2 = *w++;
202 --remaining;
203 if (cast<ushort>(w2) < 56320u || cast<ushort>(w2) > 57343u )
204 {
205 int errorId = AllocateError("invalid UTF-16 sequence: index=" + ToString(w - utf16Str.Chars()));
206 return Result<ustring>(ErrorId(errorId));
207 }
208 else
209 {
210 uchar uprime = cast<uchar>(((1023u & cast<uint>(w1)) << 10u) | (1023u & cast<uint>(w2)));
211 uchar u = cast<uchar>(cast<uint>(uprime) + 65536u);
212 result.Append(u);
213 }
214 }
215 else
216 {
217 int errorId = RtmAllocateError("invalid UTF-16 sequence");
218 return Result<ustring>(ErrorId(errorId));
219 }
220 }
221 }
222 return Result<ustring>(result);
223 }
224
225 [nodiscard]
226 public Result<wstring> ToUtf16(const ustring& utf32Str)
227 {
228 wstring result;
229 int index = 0;
230 for (uchar u : utf32Str)
231 {
232 if (cast<uint>(u) > 1114111u )
233 {
234 int errorId = AllocateError("invalid UTF-32 code point: index=" + ToString(index));
235 return Result<wstring>(ErrorId(errorId));
236 }
237 if (cast<uint>(u) < 65536u )
238 {
239 if (cast<uint>(u) >= 55296u && cast<uint>(u) <= 57343u)
240 {
241 int errorId = AllocateError("invalid UTF-32 code point (reserved for UTF-16): index=" + ToString(index));
242 return Result<wstring>(ErrorId(errorId));
243 }
244 wchar x = cast<wchar>(u);
245 result.Append(x);
246 }
247 else
248 {
249 uchar uprime = cast<uchar>(cast<uint>(u) - 65536u);
250 wchar w1 = cast<wchar>(55296u);
251 wchar w2 = cast<wchar>(56320u);
252 for (ushort i = 0u; i < 10u; ++i;)
253 {
254 ushort bit = cast<ushort>(cast<uint>(uprime) & (cast<uint>(1u) << i));
255 w2 = cast<wchar>(cast<ushort>(w2) | bit);
256 }
257 for (ushort i = 10u; i < 20u; ++i;)
258 {
259 ushort bit = cast<ushort>((cast<uint>(uprime) & (cast<uint>(1u) << i)) >> 10u);
260 w1 = cast<wchar>(cast<ushort>(w1) | bit);
261 }
262 result.Append(w1);
263 result.Append(w2);
264 }
265 ++index;
266 }
267 return Result<wstring>(result);
268 }
269
270 [nodiscard]
271 public Result<wstring> ToUtf16(const string& utf8Str)
272 {
273 auto result = ToUtf32(utf8Str);
274 if (result.Error())
275 {
276 return Result<wstring>(ErrorId(result.GetErrorId()));
277 }
278 return ToUtf16(result.Value());
279 }
280
281 [nodiscard]
282 public Result<string> ToUtf8(const ustring& utf32Str)
283 {
284 string result;
285 int index = 0;
286 for (uchar c : utf32Str)
287 {
288 uint x = cast<uint>(c);
289 if (x < 128u )
290 {
291 result.Append(cast<char>(x & 127u));
292 }
293 else if (x < 2048u )
294 {
295 byte b1 = 128u;
296 for (byte i = 0u; i < 6u; ++i;)
297 {
298 b1 = b1 | (cast<byte>(x & 1u) << i);
299 x = x >> 1u;
300 }
301 byte b0 = 192u;
302 for (byte i = 0u; i < 5u; ++i;)
303 {
304 b0 = b0 | (cast<byte>(x & 1u) << i);
305 x = x >> 1u;
306 }
307 result.Append(cast<char>(b0));
308 result.Append(cast<char>(b1));
309 }
310 else if (x < 65536u )
311 {
312 byte b2 = 128u;
313 for (byte i = 0u; i < 6u; ++i;)
314 {
315 b2 = b2 | (cast<byte>(x & 1u) << i);
316 x = x >> 1u;
317 }
318 byte b1 = 128u;
319 for (byte i = 0u; i < 6u; ++i;)
320 {
321 b1 = b1 | (cast<byte>(x & 1u) << i);
322 x = x >> 1u;
323 }
324 byte b0 = 224u;
325 for (byte i = 0u; i < 4u; ++i;)
326 {
327 b0 = b0 | (cast<byte>(x & 1u) << i);
328 x = x >> 1u;
329 }
330 result.Append(cast<char>(b0));
331 result.Append(cast<char>(b1));
332 result.Append(cast<char>(b2));
333 }
334 else if (x < 1114112u )
335 {
336 byte b3 = 128u;
337 for (byte i = 0u; i < 6u; ++i;)
338 {
339 b3 = b3 | (cast<byte>(x & 1u) << i);
340 x = x >> 1u;
341 }
342 byte b2 = 128u;
343 for (byte i = 0u; i < 6u; ++i;)
344 {
345 b2 = b2 | (cast<byte>(x & 1u) << i);
346 x = x >> 1u;
347 }
348 byte b1 = 128u;
349 for (byte i = 0u; i < 6u; ++i;)
350 {
351 b1 = b1 | (cast<byte>(x & 1u) << i);
352 x = x >> 1u;
353 }
354 byte b0 = 240u;
355 for (byte i = 0u; i < 3u; ++i;)
356 {
357 b0 = b0 | (cast<byte>(x & 1u) << i);
358 x = x >> 1u;
359 }
360 result.Append(cast<char>(b0));
361 result.Append(cast<char>(b1));
362 result.Append(cast<char>(b2));
363 result.Append(cast<char>(b3));
364 }
365 else
366 {
367 int errorId = AllocateError("invalid UTF-32 code point (" + ToString(x) + "): index=" + ToString(index));
368 return Result<string>(ErrorId(errorId));
369 }
370 ++index;
371 }
372 return Result<string>(result);
373 }
374
375 [nodiscard]
376 public Result<string> ToUtf8(const wstring& utf16Str)
377 {
378 auto result = ToUtf32(utf16Str);
379 if (result.Error())
380 {
381 return Result<string>(ErrorId(result.GetErrorId()));
382 }
383 return ToUtf8(result.Value());
384 }
385
386 [nodiscard]
387 public Result<bool> IsUpperLetter(uchar c)
388 {
389 auto result = GetGeneralCategory(c);
390 if (result.Error())
391 {
392 return Result<bool>(ErrorId(result.GetErrorId()));
393 }
394 return Result<bool>(result.Value() == GeneralCategoryId.Lu);
395 }
396
397 [nodiscard]
398 public Result<bool> IsLowerLetter(uchar c)
399 {
400 auto result = GetGeneralCategory(c);
401 if (result.Error())
402 {
403 return Result<bool>(ErrorId(result.GetErrorId()));
404 }
405 return Result<bool>(result.Value() == GeneralCategoryId.Ll);
406 }
407
408 [nodiscard]
409 public Result<bool> IsTitleLetter(uchar c)
410 {
411 auto result = GetGeneralCategory(c);
412 if (result.Error())
413 {
414 return Result<bool>(ErrorId(result.GetErrorId()));
415 }
416 return Result<bool>(result.Value() == GeneralCategoryId.Lt);
417 }
418
419 [nodiscard]
420 public Result<bool> IsModifierLetter(uchar c)
421 {
422 auto result = GetGeneralCategory(c);
423 if (result.Error())
424 {
425 return Result<bool>(ErrorId(result.GetErrorId()));
426 }
427 return Result<bool>(result.Value() == GeneralCategoryId.Lm);
428 }
429
430 [nodiscard]
431 public Result<bool> IsOtherLetter(uchar c)
432 {
433 auto result = GetGeneralCategory(c);
434 if (result.Error())
435 {
436 return Result<bool>(ErrorId(result.GetErrorId()));
437 }
438 return Result<bool>(result.Value() == GeneralCategoryId.Lo);
439 }
440
441 [nodiscard]
442 public Result<bool> IsCasedLetter(uchar c)
443 {
444 return HasGeneralCategory(c, GeneralCategoryId.LC);
445 }
446
447 [nodiscard]
448 public Result<bool> IsLetter(uchar c)
449 {
450 return HasGeneralCategory(c, GeneralCategoryId.L);
451 }
452
453 [nodiscard]
454 public Result<bool> IsNonspacingMark(uchar c)
455 {
456 auto result = GetGeneralCategory(c);
457 if (result.Error())
458 {
459 return Result<bool>(ErrorId(result.GetErrorId()));
460 }
461 return Result<bool>(result.Value() == GeneralCategoryId.Mn);
462 }
463
464 [nodiscard]
465 public Result<bool> IsSpacingMark(uchar c)
466 {
467 auto result = GetGeneralCategory(c);
468 if (result.Error())
469 {
470 return Result<bool>(ErrorId(result.GetErrorId()));
471 }
472 return Result<bool>(result.Value() == GeneralCategoryId.Mc);
473 }
474
475 [nodiscard]
476 public Result<bool> IsEnclosingMark(uchar c)
477 {
478 auto result = GetGeneralCategory(c);
479 if (result.Error())
480 {
481 return Result<bool>(ErrorId(result.GetErrorId()));
482 }
483 return Result<bool>(result.Value() == GeneralCategoryId.Me);
484 }
485
486 [nodiscard]
487 public Result<bool> IsMark(uchar c)
488 {
489 return HasGeneralCategory(c, GeneralCategoryId.M);
490 }
491
492 [nodiscard]
493 public Result<bool> IsDecimalNumber(uchar c)
494 {
495 auto result = GetGeneralCategory(c);
496 if (result.Error())
497 {
498 return Result<bool>(ErrorId(result.GetErrorId()));
499 }
500 return Result<bool>(result.Value() == GeneralCategoryId.Nd);
501 }
502
503 [nodiscard]
504 public Result<bool> IsLetterNumber(uchar c)
505 {
506 auto result = GetGeneralCategory(c);
507 if (result.Error())
508 {
509 return Result<bool>(ErrorId(result.GetErrorId()));
510 }
511 return Result<bool>(result.Value() == GeneralCategoryId.Nl);
512 }
513
514 [nodiscard]
515 public Result<bool> IsOtherNumber(uchar c)
516 {
517 auto result = GetGeneralCategory(c);
518 if (result.Error())
519 {
520 return Result<bool>(ErrorId(result.GetErrorId()));
521 }
522 return Result<bool>(result.Value() == GeneralCategoryId.No);
523 }
524
525 [nodiscard]
526 public Result<bool> IsNumber(uchar c)
527 {
528 return HasGeneralCategory(c, GeneralCategoryId.N);
529 }
530
531 [nodiscard]
532 public Result<bool> IsConnectorPunctuation(uchar c)
533 {
534 auto result = GetGeneralCategory(c);
535 if (result.Error())
536 {
537 return Result<bool>(ErrorId(result.GetErrorId()));
538 }
539 return Result<bool>(result.Value() == GeneralCategoryId.Pc);
540 }
541
542 [nodiscard]
543 public Result<bool> IsDashPunctuation(uchar c)
544 {
545 auto result = GetGeneralCategory(c);
546 if (result.Error())
547 {
548 return Result<bool>(ErrorId(result.GetErrorId()));
549 }
550 return Result<bool>(result.Value() == GeneralCategoryId.Pd);
551 }
552
553 [nodiscard]
554 public Result<bool> IsOpenPunctuation(uchar c)
555 {
556 auto result = GetGeneralCategory(c);
557 if (result.Error())
558 {
559 return Result<bool>(ErrorId(result.GetErrorId()));
560 }
561 return Result<bool>(result.Value() == GeneralCategoryId.Ps);
562 }
563
564 [nodiscard]
565 public Result<bool> IsClosePunctuation(uchar c)
566 {
567 auto result = GetGeneralCategory(c);
568 if (result.Error())
569 {
570 return Result<bool>(ErrorId(result.GetErrorId()));
571 }
572 return Result<bool>(result.Value() == GeneralCategoryId.Pe);
573 }
574
575 [nodiscard]
576 public Result<bool> IsInitialPunctuation(uchar c)
577 {
578 auto result = GetGeneralCategory(c);
579 if (result.Error())
580 {
581 return Result<bool>(ErrorId(result.GetErrorId()));
582 }
583 return Result<bool>(result.Value() == GeneralCategoryId.Pi);
584 }
585
586 [nodiscard]
587 public Result<bool> IsFinalPunctuation(uchar c)
588 {
589 auto result = GetGeneralCategory(c);
590 if (result.Error())
591 {
592 return Result<bool>(ErrorId(result.GetErrorId()));
593 }
594 return Result<bool>(result.Value() == GeneralCategoryId.Pf);
595 }
596
597 [nodiscard]
598 public Result<bool> IsOtherPunctuation(uchar c)
599 {
600 auto result = GetGeneralCategory(c);
601 if (result.Error())
602 {
603 return Result<bool>(ErrorId(result.GetErrorId()));
604 }
605 return Result<bool>(result.Value() == GeneralCategoryId.Po);
606 }
607
608 [nodiscard]
609 public Result<bool> IsPunctuation(uchar c)
610 {
611 return HasGeneralCategory(c, GeneralCategoryId.P);
612 }
613
614 [nodiscard]
615 public Result<bool> IsMathSymbol(uchar c)
616 {
617 auto result = GetGeneralCategory(c);
618 if (result.Error())
619 {
620 return Result<bool>(ErrorId(result.GetErrorId()));
621 }
622 return Result<bool>(result.Value() == GeneralCategoryId.Sm);
623 }
624
625 [nodiscard]
626 public Result<bool> IsCurrencySymbol(uchar c)
627 {
628 auto result = GetGeneralCategory(c);
629 if (result.Error())
630 {
631 return Result<bool>(ErrorId(result.GetErrorId()));
632 }
633 return Result<bool>(result.Value() == GeneralCategoryId.Sc);
634 }
635
636 [nodiscard]
637 public Result<bool> IsModifierSymbol(uchar c)
638 {
639 auto result = GetGeneralCategory(c);
640 if (result.Error())
641 {
642 return Result<bool>(ErrorId(result.GetErrorId()));
643 }
644 return Result<bool>(result.Value() == GeneralCategoryId.Sk);
645 }
646
647 [nodiscard]
648 public Result<bool> IsOtherSymbol(uchar c)
649 {
650 auto result = GetGeneralCategory(c);
651 if (result.Error())
652 {
653 return Result<bool>(ErrorId(result.GetErrorId()));
654 }
655 return Result<bool>(result.Value() == GeneralCategoryId.So);
656 }
657
658 [nodiscard]
659 public Result<bool> IsSymbol(uchar c)
660 {
661 return HasGeneralCategory(c, GeneralCategoryId.S);
662 }
663
664 [nodiscard]
665 public Result<bool> IsSpaceSeparator(uchar c)
666 {
667 auto result = GetGeneralCategory(c);
668 if (result.Error())
669 {
670 return Result<bool>(ErrorId(result.GetErrorId()));
671 }
672 return Result<bool>(result.Value() == GeneralCategoryId.Zs);
673 }
674
675 [nodiscard]
676 public Result<bool> IsLineSeparator(uchar c)
677 {
678 auto result = GetGeneralCategory(c);
679 if (result.Error())
680 {
681 return Result<bool>(ErrorId(result.GetErrorId()));
682 }
683 return Result<bool>(result.Value() == GeneralCategoryId.Zl);
684 }
685
686 [nodiscard]
687 public Result<bool> IsParagraphSeparator(uchar c)
688 {
689 auto result = GetGeneralCategory(c);
690 if (result.Error())
691 {
692 return Result<bool>(ErrorId(result.GetErrorId()));
693 }
694 return Result<bool>(result.Value() == GeneralCategoryId.Zp);
695 }
696
697 [nodiscard]
698 public Result<bool> IsSeparator(uchar c)
699 {
700 return HasGeneralCategory(c, GeneralCategoryId.Z);
701 }
702
703 [nodiscard]
704 public Result<bool> IsControl(uchar c)
705 {
706 auto result = GetGeneralCategory(c);
707 if (result.Error())
708 {
709 return Result<bool>(ErrorId(result.GetErrorId()));
710 }
711 return Result<bool>(result.Value() == GeneralCategoryId.Cc);
712 }
713
714 [nodiscard]
715 public Result<bool> IsFormat(uchar c)
716 {
717 auto result = GetGeneralCategory(c);
718 if (result.Error())
719 {
720 return Result<bool>(ErrorId(result.GetErrorId()));
721 }
722 return Result<bool>(result.Value() == GeneralCategoryId.Cf);
723 }
724
725 [nodiscard]
726 public Result<bool> IsSurrogate(uchar c)
727 {
728 auto result = GetGeneralCategory(c);
729 if (result.Error())
730 {
731 return Result<bool>(ErrorId(result.GetErrorId()));
732 }
733 return Result<bool>(result.Value() == GeneralCategoryId.Cs);
734 }
735
736 [nodiscard]
737 public Result<bool> IsPrivateUse(uchar c)
738 {
739 auto result = GetGeneralCategory(c);
740 if (result.Error())
741 {
742 return Result<bool>(ErrorId(result.GetErrorId()));
743 }
744 return Result<bool>(result.Value() == GeneralCategoryId.Co);
745 }
746
747 [nodiscard]
748 public Result<bool> IsUnassigned(uchar c)
749 {
750 auto result = GetGeneralCategory(c);
751 if (result.Error())
752 {
753 return Result<bool>(ErrorId(result.GetErrorId()));
754 }
755 return Result<bool>(result.Value() == GeneralCategoryId.Cn);
756 }
757
758 [nodiscard]
759 public Result<bool> IsOther(uchar c)
760 {
761 return HasGeneralCategory(c, GeneralCategoryId.C);
762 }
763
764 [nodiscard]
765 public Result<bool> IsGraphic(uchar c)
766 {
767 return HasGeneralCategory(c, GeneralCategoryId.G);
768 }
769
770 [nodiscard]
771 public Result<bool> IsBaseChar(uchar c)
772 {
773 return HasGeneralCategory(c, GeneralCategoryId.B);
774 }
775
776 [nodiscard]
777 public Result<bool> IsCombining(uchar c)
778 {
779 return IsMark(c);
780 }
781
782 [nodiscard]
783 public Result<uchar> ToUpper(uchar c)
784 {
785 auto result = GetCharacterInfo(c);
786 if (result.Error())
787 {
788 return Result<uchar>(ErrorId(result.GetErrorId()));
789 }
790 const CharacterInfo* characterInfo = result.Value();
791 return Result<uchar>(characterInfo->Upper());
792 }
793
794 [nodiscard]
795 public Result<uchar> ToLower(uchar c)
796 {
797 auto result = GetCharacterInfo(c);
798 if (result.Error())
799 {
800 return Result<uchar>(ErrorId(result.GetErrorId()));
801 }
802 const CharacterInfo* characterInfo = result.Value();
803 return Result<uchar>(characterInfo->Lower());
804 }
805
806 [nodiscard]
807 public Result<uchar> ToTitle(uchar c)
808 {
809 auto result = GetCharacterInfo(c);
810 if (result.Error())
811 {
812 return Result<uchar>(ErrorId(result.GetErrorId()));
813 }
814 const CharacterInfo* characterInfo = result.Value();
815 return Result<uchar>(characterInfo->Title());
816 }
817
818 [nodiscard]
819 public Result<uchar> ToFolding(uchar c)
820 {
821 auto result = GetCharacterInfo(c);
822 if (result.Error())
823 {
824 return Result<uchar>(ErrorId(result.GetErrorId()));
825 }
826 const CharacterInfo* characterInfo = result.Value();
827 return Result<uchar>(characterInfo->Folding());
828 }
829
830 [nodiscard]
831 public Result<ustring> FullUpper(uchar c)
832 {
833 auto result = GetExtendedCharacterInfo(c);
834 if (result.Error())
835 {
836 return Result<ustring>(ErrorId(result.GetErrorId()));
837 }
838 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
839 return Result<ustring>(extendedCharacterInfo->FullUpper());
840 }
841
842 [nodiscard]
843 public Result<ustring> FullLower(uchar c)
844 {
845 auto result = GetExtendedCharacterInfo(c);
846 if (result.Error())
847 {
848 return Result<ustring>(ErrorId(result.GetErrorId()));
849 }
850 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
851 return Result<ustring>(extendedCharacterInfo->FullLower());
852 }
853
854 [nodiscard]
855 public Result<ustring> FullTitle(uchar c)
856 {
857 auto result = GetExtendedCharacterInfo(c);
858 if (result.Error())
859 {
860 return Result<ustring>(ErrorId(result.GetErrorId()));
861 }
862 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
863 return Result<ustring>(extendedCharacterInfo->FullTitle());
864 }
865
866 [nodiscard]
867 public Result<ustring> FullFolding(uchar c)
868 {
869 auto result = GetExtendedCharacterInfo(c);
870 if (result.Error())
871 {
872 return Result<ustring>(ErrorId(result.GetErrorId()));
873 }
874 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
875 return Result<ustring>(extendedCharacterInfo->FullFolding());
876 }
877
878 [nodiscard]
879 public Result<bool> IsWhiteSpace(uchar c)
880 {
881 auto result = GetCharacterInfo(c);
882 if (result.Error())
883 {
884 return Result<bool>(ErrorId(result.GetErrorId()));
885 }
886 const CharacterInfo* characterInfo = result.Value();
887 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.whiteSpace));
888 }
889
890 [nodiscard]
891 public Result<bool> IsAlphabetic(uchar c)
892 {
893 auto result = GetCharacterInfo(c);
894 if (result.Error())
895 {
896 return Result<bool>(ErrorId(result.GetErrorId()));
897 }
898 const CharacterInfo* characterInfo = result.Value();
899 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.alphabetic));
900 }
901
902 [nodiscard]
903 public Result<bool> IsAsciiHexDigit(uchar c)
904 {
905 auto result = GetCharacterInfo(c);
906 if (result.Error())
907 {
908 return Result<bool>(ErrorId(result.GetErrorId()));
909 }
910 const CharacterInfo* characterInfo = result.Value();
911 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.asciiHexDigit));
912 }
913
914 [nodiscard]
915 public bool IsAsciiDigit(uchar c)
916 {
917 return cast<uint>(c) < 256u && IsDigit(cast<char>(c));
918 }
919
920 [nodiscard]
921 public Result<bool> IsUppercase(uchar c)
922 {
923 auto result = GetCharacterInfo(c);
924 if (result.Error())
925 {
926 return Result<bool>(ErrorId(result.GetErrorId()));
927 }
928 const CharacterInfo* characterInfo = result.Value();
929 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.uppercase));
930 }
931
932 [nodiscard]
933 public Result<bool> IsLowercase(uchar c)
934 {
935 auto result = GetCharacterInfo(c);
936 if (result.Error())
937 {
938 return Result<bool>(ErrorId(result.GetErrorId()));
939 }
940 const CharacterInfo* characterInfo = result.Value();
941 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.lowercase));
942 }
943
944 [nodiscard]
945 public Result<bool> IsIdStart(uchar c)
946 {
947 auto result = GetCharacterInfo(c);
948 if (result.Error())
949 {
950 return Result<bool>(ErrorId(result.GetErrorId()));
951 }
952 const CharacterInfo* characterInfo = result.Value();
953 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.idStart));
954 }
955
956 [nodiscard]
957 public Result<bool> IsIdCont(uchar c)
958 {
959 auto result = GetCharacterInfo(c);
960 if (result.Error())
961 {
962 return Result<bool>(ErrorId(result.GetErrorId()));
963 }
964 const CharacterInfo* characterInfo = result.Value();
965 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.idContinue));
966 }
967
968 [nodiscard]
969 public Result<bool> IsGraphemeBase(uchar c)
970 {
971 auto result = GetCharacterInfo(c);
972 if (result.Error())
973 {
974 return Result<bool>(ErrorId(result.GetErrorId()));
975 }
976 const CharacterInfo* characterInfo = result.Value();
977 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.graphemeBase));
978 }
979
980 [nodiscard]
981 public Result<bool> IsGraphemeExtender(uchar c)
982 {
983 auto result = GetCharacterInfo(c);
984 if (result.Error())
985 {
986 return Result<bool>(ErrorId(result.GetErrorId()));
987 }
988 const CharacterInfo* characterInfo = result.Value();
989 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.graphemeExtend));
990 }
991
992 [nodiscard]
993 public Result<bool> IsOtherLower(uchar c)
994 {
995 auto result = GetCharacterInfo(c);
996 if (result.Error())
997 {
998 return Result<bool>(ErrorId(result.GetErrorId()));
999 }
1000 const CharacterInfo* characterInfo = result.Value();
1001 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.otherLowercase));
1002 }
1003
1004 [nodiscard]
1005 public Result<bool> IsOtherUpper(uchar c)
1006 {
1007 auto result = GetCharacterInfo(c);
1008 if (result.Error())
1009 {
1010 return Result<bool>(ErrorId(result.GetErrorId()));
1011 }
1012 const CharacterInfo* characterInfo = result.Value();
1013 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.otherUppercase));
1014 }
1015
1016 [nodiscard]
1017 public Result<string> GetCharacterName(uchar c)
1018 {
1019 auto result = GetExtendedCharacterInfo(c);
1020 if (result.Error())
1021 {
1022 return Result<string>(ErrorId(result.GetErrorId()));
1023 }
1024 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1025 return Result<string>(extendedCharacterInfo->CharacterName());
1026 }
1027
1028 [nodiscard]
1029 public Result<string> GetUnicode1Name(uchar c)
1030 {
1031 auto result = GetExtendedCharacterInfo(c);
1032 if (result.Error())
1033 {
1034 return Result<string>(ErrorId(result.GetErrorId()));
1035 }
1036 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1037 return Result<string>(extendedCharacterInfo->Unicode1Name());
1038 }
1039
1040 [nodiscard]
1041 public Result<NumericTypeId> GetNumericType(uchar c)
1042 {
1043 auto result = GetExtendedCharacterInfo(c);
1044 if (result.Error())
1045 {
1046 return Result<NumericTypeId>(ErrorId(result.GetErrorId()));
1047 }
1048 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1049 return Result<NumericTypeId>(extendedCharacterInfo->NumericTypeValue());
1050 }
1051
1052 [nodiscard]
1053 public Result<ustring> GetNumericValue(uchar c)
1054 {
1055 auto result = GetExtendedCharacterInfo(c);
1056 if (result.Error())
1057 {
1058 return Result<ustring>(ErrorId(result.GetErrorId()));
1059 }
1060 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1061 return Result<ustring>(extendedCharacterInfo->NumericValue());
1062 }
1063
1064 [nodiscard]
1065 public Result<bool> IsBidiMirrored(uchar c)
1066 {
1067 auto result = GetCharacterInfo(c);
1068 if (result.Error())
1069 {
1070 return Result<bool>(ErrorId(result.GetErrorId()));
1071 }
1072 const CharacterInfo* characterInfo = result.Value();
1073 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.bidiMirrored));
1074 }
1075
1076 [nodiscard]
1077 public Result<bool> IsBidiControl(uchar c)
1078 {
1079 auto result = GetCharacterInfo(c);
1080 if (result.Error())
1081 {
1082 return Result<bool>(ErrorId(result.GetErrorId()));
1083 }
1084 const CharacterInfo* characterInfo = result.Value();
1085 return Result<bool>(characterInfo->GetBinaryProperty(BinaryPropertyId.bidiControl));
1086 }
1087
1088 [nodiscard]
1089 public Result<uchar> GetBidiMirroringGlyph(uchar c)
1090 {
1091 auto result = GetExtendedCharacterInfo(c);
1092 if (result.Error())
1093 {
1094 return Result<uchar>(ErrorId(result.GetErrorId()));
1095 }
1096 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1097 return Result<uchar>(extendedCharacterInfo->BidiMirroringGlyph());
1098 }
1099
1100 [nodiscard]
1101 public Result<BidiPairedBracketTypeId> GetBidiPairedBracketType(uchar c)
1102 {
1103 auto result = GetExtendedCharacterInfo(c);
1104 if (result.Error())
1105 {
1106 return Result<BidiPairedBracketTypeId>(ErrorId(result.GetErrorId()));
1107 }
1108 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1109 return Result<BidiPairedBracketTypeId>(extendedCharacterInfo->BidiPairedBracketTypeValue());
1110 }
1111
1112 [nodiscard]
1113 public Result<uchar> GetBidiPairedBracket(uchar c)
1114 {
1115 auto result = GetExtendedCharacterInfo(c);
1116 if (result.Error())
1117 {
1118 return Result<uchar>(ErrorId(result.GetErrorId()));
1119 }
1120 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1121 return Result<uchar>(extendedCharacterInfo->BidiPairedBracket());
1122 }
1123
1124 [nodiscard]
1125 public Result<List<Alias>> Aliases(uchar c)
1126 {
1127 auto result = GetExtendedCharacterInfo(c);
1128 if (result.Error())
1129 {
1130 return Result<List<Alias>>(ErrorId(result.GetErrorId()));
1131 }
1132 const ExtendedCharacterInfo* extendedCharacterInfo = result.Value();
1133 return Result<List<Alias>>(extendedCharacterInfo->Aliases());
1134 }