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. Seq.new: class :: does Iterator {
  16. has $!uni;
  17. has int $!els;
  18. has int $!i;
  19. method !SET-SELF(\uni) {
  20. $!uni := uni;
  21. $!i = -1;
  22. $!els = nqp::elems(uni);
  23. self
  24. }
  25. method new (\uni) { nqp::create(self)!SET-SELF: uni }
  26. method pull-one {
  27. nqp::if(
  28. nqp::islt_i(($!i = nqp::add_i($!i, 1)), $!els),
  29. nqp::atpos_i($!uni, $!i),
  30. IterationEnd)
  31. }
  32. method push-all($target --> IterationEnd) {
  33. nqp::stmts(
  34. (my $uni := $!uni), # lexicals faster than attrs
  35. (my int $els = $!els),
  36. (my int $i = $!i),
  37. nqp::while(
  38. nqp::islt_i(($i = nqp::add_i($i, 1)), $els),
  39. $target.push: nqp::atpos_i($uni, $i)),
  40. ($!i = $i))
  41. }
  42. method count-only {
  43. nqp::p6box_i(
  44. nqp::if(
  45. nqp::islt_i($!i, nqp::elems($!uni)),
  46. nqp::sub_i(nqp::elems($!uni), nqp::add_i($!i, 1)),
  47. 0))
  48. }
  49. method bool-only { nqp::p6bool(self.count-only) }
  50. }.new: self
  51. }
  52. method Uni(Uni:D:) {
  53. self
  54. }
  55. method NFC(Uni:D:) {
  56. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFC, nqp::create(NFC))
  57. }
  58. method NFD(Uni:D:) {
  59. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFD, nqp::create(NFD))
  60. }
  61. method NFKC(Uni:D:) {
  62. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFKC, nqp::create(NFKC))
  63. }
  64. method NFKD(Uni:D:) {
  65. nqp::normalizecodes(self, nqp::const::NORMALIZE_NFKD, nqp::create(NFKD))
  66. }
  67. multi method Str(Uni:D:) {
  68. nqp::strfromcodes(self)
  69. }
  70. multi method Bool(Uni:D:) {
  71. nqp::p6bool(nqp::elems(self));
  72. }
  73. method codes(Uni:D:) { nqp::elems(self) }
  74. method elems(Uni:D:) { nqp::elems(self) }
  75. method Numeric(Uni:D:) { nqp::elems(self) }
  76. method Int(Uni:D:) { nqp::elems(self) }
  77. multi method EXISTS-POS(Uni:D: int \pos) {
  78. nqp::p6bool(
  79. nqp::islt_i(pos,nqp::elems(self)) && nqp::isge_i(pos,0)
  80. );
  81. }
  82. multi method EXISTS-POS(Uni:D: Int:D \pos) {
  83. pos < nqp::elems(self) && pos >= 0;
  84. }
  85. multi method AT-POS(Uni:D: int \pos) {
  86. nqp::isge_i(pos,nqp::elems(self)) || nqp::islt_i(pos,0)
  87. ?? Failure.new(X::OutOfRange.new(
  88. :what($*INDEX // 'Index'),
  89. :got(pos),
  90. :range("0..{nqp::elems(self)-1}")))
  91. !! nqp::atpos_i(self, pos)
  92. }
  93. multi method AT-POS(Uni:D: Int:D \pos) {
  94. my int $pos = nqp::unbox_i(pos);
  95. nqp::isge_i($pos,nqp::elems(self)) || nqp::islt_i($pos,0)
  96. ?? Failure.new(X::OutOfRange.new(
  97. :what($*INDEX // 'Index'),
  98. :got(pos),
  99. :range("0..{nqp::elems(self)-1}")))
  100. !! nqp::atpos_i(self,$pos)
  101. }
  102. multi method gist(Uni:D:) {
  103. self.^name ~ ':0x<' ~ self.list.fmt('%04x', ' ') ~ '>'
  104. }
  105. multi method perl(Uni:D:) {
  106. 'Uni.new(' ~ self.list.fmt('0x%04x', ', ') ~ ')' ~
  107. (self.WHAT === Uni ?? '' !! '.' ~ self.^name);
  108. }
  109. }
  110. my class NFD is Uni {
  111. method new(|) {
  112. die "Cannot create an NFD directly"; # XXX typed, better message
  113. }
  114. method NFD() { self }
  115. }
  116. my class NFC is Uni {
  117. method new(|) {
  118. die "Cannot create an NFC directly"; # XXX typed, better message
  119. }
  120. method NFC() { self }
  121. }
  122. my class NFKD is Uni {
  123. method new(|) {
  124. die "Cannot create an NFKD directly"; # XXX typed, better message
  125. }
  126. method NFKD() { self }
  127. }
  128. my class NFKC is Uni {
  129. method NFKC() { self }
  130. method new(|) {
  131. die "Cannot create an NFKC directly"; # XXX typed, better message
  132. }
  133. }