Skip to content

Instantly share code, notes, and snippets.

@MasterDuke17
Created August 4, 2018 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MasterDuke17/1cf73f690e43c79c1ed0e4b197fe4c5c to your computer and use it in GitHub Desktop.
Save MasterDuke17/1cf73f690e43c79c1ed0e4b197fe4c5c to your computer and use it in GitHub Desktop.
diff --git a/src/core/Buf.pm6 b/src/core/Buf.pm6
index bd500edbc..07cb09b4f 100644
--- a/src/core/Buf.pm6
+++ b/src/core/Buf.pm6
@@ -170,11 +170,78 @@ my role Blob[::T = uint8] does Positional[T] does Stringy is repr('VMArray') is
self.^name ~ '.new(' ~ self.join(',') ~ ')';
}
- method subbuf(Blob:D: $from, $length?) {
+ proto method subbuf(|) {*}
+ multi method subbuf(Blob:D: $from) {
+ nqp::stmts(
+ (my int $elems = nqp::elems(self)),
+ nqp::stmts(
+ (my int $pos),
+ (my int $todo),
+ ($pos = nqp::istype($from, Callable) ?? $from($elems) !! $from.Int),
+ ($todo = $elems - $pos),
+ nqp::if(
+ nqp::islt_i($pos, 0),
+ X::OutOfRange.new(
+ :what('From argument to subbuf'), :got($from.gist), :range("0..$elems"),
+ :comment("use *-{abs $pos} if you want to index relative to the end"),
+ ).fail,
+ nqp::if(
+ nqp::isgt_i($pos, $elems),
+ X::OutOfRange.new(
+ :what('From argument to subbuf'), :got($from.gist), :range("0..$elems"),
+ ).fail,
+ nqp::if(
+ nqp::isle_i($todo, 0),
+ nqp::create(self), # we want zero elements; return empty Blob
+ nqp::stmts(
+ (my $subbuf := nqp::create(self)),
+ nqp::setelems($subbuf, $todo),
+ (my int $i = -1),
+ --$pos,
+ nqp::while(
+ nqp::islt_i(++$i,$todo),
+ nqp::bindpos_i($subbuf, $i, nqp::atpos_i(self, ++$pos))),
+ $subbuf))))))
+ }
+
+ multi method subbuf(Blob:D: Range $from) {
+ nqp::stmts(
+ (my int $elems = nqp::elems(self)),
+ nqp::stmts(
+ (my int $pos),
+ (my int $todo),
+ $from.int-bounds($pos, my int $max),
+ ($todo = nqp::add_i(nqp::sub_i($max, $pos), 1)),
+ nqp::if(
+ nqp::islt_i($pos, 0),
+ X::OutOfRange.new(
+ :what('From argument to subbuf'), :got($from.gist), :range("0..$elems"),
+ :comment("use *-{abs $pos} if you want to index relative to the end"),
+ ).fail,
+ nqp::if(
+ nqp::isgt_i($pos, $elems),
+ X::OutOfRange.new(
+ :what('From argument to subbuf'), :got($from.gist), :range("0..$elems"),
+ ).fail,
+ nqp::if(
+ nqp::isle_i($todo, 0),
+ nqp::create(self), # we want zero elements; return empty Blob
+ nqp::stmts(
+ (my $subbuf := nqp::create(self)),
+ nqp::setelems($subbuf, $todo),
+ (my int $i = -1),
+ --$pos,
+ nqp::while(
+ nqp::islt_i(++$i,$todo),
+ nqp::bindpos_i($subbuf, $i, nqp::atpos_i(self, ++$pos))),
+ $subbuf))))))
+ }
+
+ multi method subbuf(Blob:D: $from, $length) {
nqp::stmts(
(my int $elems = nqp::elems(self)),
nqp::if(
- $length.DEFINITE && $length < 0,
+ nqp::islt_i($length, 0),
X::OutOfRange.new(
:what('Len element to subbuf'), :got($length), :range("0..$elems"),
).fail,
@@ -188,7 +255,7 @@ my role Blob[::T = uint8] does Positional[T] does Stringy is repr('VMArray') is
($todo = nqp::add_i(nqp::sub_i($max, $pos), 1))),
nqp::stmts(
($pos = nqp::istype($from, Callable) ?? $from($elems) !! $from.Int),
- ($todo = $length.DEFINITE ?? $length.Int min $elems - $pos !! $elems - $pos))),
+ ($todo = $length.Int min $elems - $pos))),
nqp::if(
nqp::islt_i($pos, 0),
X::OutOfRange.new(
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment