diff --git a/src/core.c/Supply.pm6 b/src/core.c/Supply.pm6 index b5816cef6d9..fe5077b65b3 100644 --- a/src/core.c/Supply.pm6 +++ b/src/core.c/Supply.pm6 @@ -697,7 +697,7 @@ my class Supply does Awaitable { # split the supply on the given string multi method split(Supply:D: Str(Cool) $the-needle, :$skip-empty!) { $skip-empty - ?? supply { + ?? supply { # skip empties my str $needle = $the-needle; my str $str; @@ -720,7 +720,91 @@ my class Supply does Awaitable { } } } - !! self.split($the-needle) + !! self.split($the-needle) # don't skip empties + } + + # split the supply on the given string for a limit + multi method split(Supply:D: Str(Cool) $the-needle, Whatever) { + self.split($the-needle, |%_) + } + multi method split(Supply:D: Str(Cool) $the-needle, Numeric(Cool) $the-limit) { + $the-limit == Inf + ?? self.split($the-needle, |%_) # there's no limit + !! $the-limit <= 0 # there *is* a limit + ?? supply { } # but it won't pass anything + !! supply { # need to pass stuff + my str $needle = $the-needle; + my int $limit = $the-limit.Int; + my int $emitted; + + my str $str; + whenever self -> str $val { + my $matches := nqp::split($needle,nqp::concat($str,$val)); + $str = nqp::pop($matches); # keep last for next batch + + my $iterator := nqp::iterator($matches); + nqp::while( + $iterator, + nqp::if( + nqp::isle_i(++$emitted,$limit), + emit(nqp::p6box_s(nqp::shift($iterator))), + done + ) + ); + + LAST { + emit nqp::p6box_s($str) if $emitted < $limit; + } + } + } + } + + # split the supply on the given string for a limit while skipping empty + multi method split(Supply:D: + Str(Cool) $the-needle, + Numeric(Cool) $the-limit, + :$skip-empty! + ) { + $the-limit == Inf + ?? self.split( # there's no limit + $the-needle, :$skip-empty, |%_ + ) + !! $the-limit <= 0 # there *is* a limit + ?? supply { } # nothing will pass + !! $skip-empty # will skip empties + ?? supply { + my str $needle = $the-needle; + my int $limit = $the-limit.Int; + + my str $emittee; + my int $emitted; + my str $str; + whenever self -> str $val { + my $matches := nqp::split($needle,nqp::concat($str,$val)); + $str = nqp::pop($matches); # keep last for next batch + + my $iterator := nqp::iterator($matches); + nqp::while( + $iterator, + nqp::if( + nqp::chars($emittee = nqp::shift($iterator)), + nqp::if( + nqp::isle_i(++$emitted,$limit), + emit(nqp::p6box_s($emittee)), + done + ) + ) + ); + + LAST { + emit nqp::p6box_s($str) + if nqp::chars($str) && $emitted < $limit; + } + } + } + !! self.split( # won't skip empties + $the-needle, $the-limit, |%_ + ) } ##