Skip to content

Commit

Permalink
Make Buf.subbuf between 1.5x and 4x as fast
Browse files Browse the repository at this point in the history
Also implement .subbuf(^10), just like with .substr
  • Loading branch information
lizmat committed Nov 14, 2015
1 parent 9f14995 commit 032e02e
Showing 1 changed file with 38 additions and 44 deletions.
82 changes: 38 additions & 44 deletions src/core/Buf.pm
Original file line number Diff line number Diff line change
Expand Up @@ -97,55 +97,49 @@ my role Blob[::T = uint8] does Positional[T] does Stringy is repr('VMArray') is
self.^name ~ '.new(' ~ self.list.join(', ') ~ ')';
}

method subbuf(Blob:D: $from = 0, $len is copy = self.elems - $from) {
method subbuf(Blob:D: $from, $length?) {

if ($len < 0) {
X::OutOfRange.new(
what => "Len element to subbuf",
got => $len,
range => (0..self.elems)).fail;
}


my $ret := nqp::create(self);

my int $ifrom = nqp::unbox_i(
nqp::istype($from, Callable)
?? $from(nqp::p6box_i(self.elems))
!! $from.Int);

if ($ifrom < 0) {
X::OutOfRange.new(
what => 'From argument to subbuf',
got => $from.gist,
range => (0..self.elems),
comment => "use *{$ifrom} if you want to index relative to the end"
).fail;
my int $elems = self.elems;
X::OutOfRange.new(
what => "Len element to subbuf",
got => $length,
range => "0..$elems",
).fail if $length.DEFINITE && $length < 0;

my int $pos;
my int $todo;
if nqp::istype($from,Range) {
($pos,my int $max) = $from.int-bounds;
$todo = $max - $pos + 1;
}

if ($ifrom > self.elems) {
X::OutOfRange.new(
what => 'From argument to subbuf',
got => $from.gist,
range => (0..self.elems),
).fail;
else {
$pos = nqp::istype($from, Callable) ?? $from($elems) !! $from.Int;
$todo = $length.DEFINITE
?? $length.Int min $elems - $pos
!! $elems - $pos;
}

return $ret
if $ifrom == self.elems;

$len = self.elems - $ifrom
if $ifrom + $len > self.elems;

my int $llen = $len.Int;
nqp::setelems($ret, $llen);
my int $i = 0;
while $i < $llen {
nqp::bindpos_i($ret, $i, nqp::atpos_i(self, $ifrom));
$i = $i + 1;
$ifrom = $ifrom + 1;
X::OutOfRange.new(
what => 'From argument to subbuf',
got => $from.gist,
range => "0..$elems",
comment => "use *{$pos} if you want to index relative to the end",
).fail if $pos < 0;
X::OutOfRange.new(
what => 'From argument to subbuf',
got => $from.gist,
range => "0..$elems",
).fail if $pos > $elems;

my $subbuf := nqp::create(self);
if $todo {
nqp::setelems($subbuf, $todo);
my int $i = -1;
$pos = $pos - 1;
nqp::bindpos_i($subbuf,$i,nqp::atpos_i(self,($pos = $pos + 1)))
while ($i = $i + 1) < $todo;
}
$ret
$subbuf
}

method unpack(Blob:D: $template) {
Expand Down

0 comments on commit 032e02e

Please sign in to comment.