1. my class NFC is repr('VMArray') is array_type(uint32) { ... }
  2. my class NFD is repr('VMArray') is array_type(uint32) { ... }
  3. my class NFKC is repr('VMArray') is array_type(uint32) { ... }
  4. my class NFKD is repr('VMArray') is array_type(uint32) { ... }
  5. my class Uni does Positional[uint32] does Stringy is repr('VMArray') is array_type(uint32) {
  6. method new(*@codes) {
  7. my $uni := nqp::create(self);
  8. my int $n = @codes.elems;
  9. loop (my int $i = 0; $i < $n; $i = $i + 1) {
  10. nqp::bindpos_i($uni, $i, @codes.AT-POS($i));
  11. }
  12. $uni
  13. }
  14. method list(Uni:D:) {
  15. gather {
  16. my int $n = nqp::elems(self);
  17. loop (my int $i = 0; $i < $n; $i = $i + 1) {
  18. take nqp::atpos_i(self, $i);
  19. }
  20. }
  21. }
  22. method Uni(Uni:D:) {
  23. self
  24. }
  25. method NFC(Uni:D:) {
  26. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFC, nqp::create(NFC))
  27. }
  28. method NFD(Uni:D:) {
  29. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFD, nqp::create(NFD))
  30. }
  31. method NFKC(Uni:D:) {
  32. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFKC, nqp::create(NFKC))
  33. }
  34. method NFKD(Uni:D:) {
  35. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFKD, nqp::create(NFKD))
  36. }
  37. multi method Str(Uni:D:) {
  38. nqp::strfromcodes(self)
  39. }
  40. multi method Bool(Uni:D:) {
  41. nqp::p6bool(nqp::elems(self));
  42. }
  43. method codes(Uni:D:) { nqp::elems(self) }
  44. method elems(Uni:D:) { nqp::elems(self) }
  45. method Numeric(Uni:D:) { nqp::elems(self) }
  46. method Int(Uni:D:) { nqp::elems(self) }
  47. multi method EXISTS-POS(Uni:D: int \pos) {
  48. nqp::p6bool(
  49. nqp::islt_i(pos,nqp::elems(self)) && nqp::isge_i(pos,0)
  50. );
  51. }
  52. multi method EXISTS-POS(Uni:D: Int:D \pos) {
  53. pos < nqp::elems(self) && pos >= 0;
  54. }
  55. multi method AT-POS(Uni:D: int \pos) {
  56. nqp::isge_i(pos,nqp::elems(self)) || nqp::islt_i(pos,0)
  57. ?? Failure.new(X::OutOfRange.new(
  58. :what($*INDEX // 'Index'),
  59. :got(pos),
  60. :range("0..{nqp::elems(self)-1}")))
  61. !! nqp::atpos_i(self, pos)
  62. }
  63. multi method AT-POS(Uni:D: Int:D \pos) {
  64. my int $pos = nqp::unbox_i(pos);
  65. nqp::isge_i($pos,nqp::elems(self)) || nqp::islt_i($pos,0)
  66. ?? Failure.new(X::OutOfRange.new(
  67. :what($*INDEX // 'Index'),
  68. :got(pos),
  69. :range("0..{nqp::elems(self)-1}")))
  70. !! nqp::atpos_i(self,$pos)
  71. }
  72. multi method gist(Uni:D:) {
  73. self.^name ~ ':0x<' ~ self.list.fmt('%04x', ' ') ~ '>'
  74. }
  75. multi method perl(Uni:D:) {
  76. 'Uni.new(' ~ self.list.fmt('0x%04x', ', ') ~ ')' ~
  77. (self.WHAT === Uni ?? '' !! '.' ~ self.^name);
  78. }
  79. }
  80. my class NFD is Uni {
  81. method new(|) {
  82. die "Cannot create an NFD directly"; # XXX typed, better message
  83. }
  84. method NFD() { self }
  85. }
  86. my class NFC is Uni {
  87. method new(|) {
  88. die "Cannot create an NFD directly"; # XXX typed, better message
  89. }
  90. method NFC() { self }
  91. }
  92. my class NFKD is Uni {
  93. method new(|) {
  94. die "Cannot create an NFD directly"; # XXX typed, better message
  95. }
  96. method NFKD() { self }
  97. }
  98. my class NFKC is Uni {
  99. method NFKC() { self }
  100. method new(|) {
  101. die "Cannot create an NFD directly"; # XXX typed, better message
  102. }
  103. }