Created
February 21, 2015 22:50
-
-
Save lizmat/695c8187f5279ab41c88 to your computer and use it in GitHub Desktop.
make substr-rw work like substr, but make substr 2.5x as slow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/core/Str.pm b/src/core/Str.pm | |
index 0cb832a..57bf2cf 100644 | |
--- a/src/core/Str.pm | |
+++ b/src/core/Str.pm | |
@@ -1556,64 +1556,79 @@ sub chrs(*@c) returns Str:D { | |
@c.map({.chr}).join; | |
} | |
-sub substr(Str() \what, \from, $chars?) { | |
- my str $str = nqp::unbox_s(what); | |
- my int $max = nqp::chars($str); | |
- my int $from = nqp::unbox_i( | |
- nqp::istype(from, Callable) ?? (from)(nqp::p6box_i($max)) !! from.Int | |
+sub SUBSTR-SANITY(Str \what, \start, \chars, \from, \length) { | |
+ my str $str = nqp::unbox_s(what); | |
+ my int $max = nqp::chars($str); | |
+ from = nqp::unbox_i( | |
+ nqp::istype(start, Callable) ?? (start)(nqp::p6box_i($max)) !! start.Int | |
); | |
- if $from < 0 { | |
- if nqp::istype(from, Callable) || -$from > $max { | |
+ if from < 0 { | |
+ if nqp::istype(from, Callable) || -from > $max { | |
X::OutOfRange.new( | |
- :what<Start argument to substr>,:got($from),:range("0..$max"), | |
+ :what<Start argument to substr>,:got(from),:range("0..$max"), | |
).fail; | |
} | |
else { | |
X::OutOfRange.new( | |
:what<Start argument to substr>,:got(from),:range<0..Inf>, | |
- :comment("use *$from if you want to index relative to the end") | |
+ :comment("use *{from} if you want to index relative to the end") | |
).fail; | |
} | |
} | |
- elsif $from > $max { | |
+ elsif from > $max { | |
X::OutOfRange.new( | |
- :what<Start of substr>,:got($from),:range("0..$max"), | |
+ :what<Start of substr>,:got(from),:range("0..$max"), | |
).fail; | |
} | |
- my int $length = nqp::unbox_i( | |
- $chars.defined | |
- ?? $chars === Inf | |
- ?? $max - $from | |
- !! nqp::istype($chars,Callable) | |
- ?? $chars($max - $from) | |
- !! (nqp::istype($chars,Int) ?? $chars !! $chars.Int) | |
- !! $max - $from | |
+ length = nqp::unbox_i( | |
+ chars.defined | |
+ ?? chars === Inf | |
+ ?? $max - from | |
+ !! nqp::istype(chars,Callable) | |
+ ?? (chars)($max - from) | |
+ !! (nqp::istype(chars,Int) ?? chars !! chars.Int) | |
+ !! $max - from | |
); | |
X::OutOfRange.new( | |
- :what<Length argument to substr>,:got($chars),:range<0..Inf>, | |
- :comment("use *$length if you want to index relative to the end") | |
- ).fail if $length < 0; | |
+ :what<Length argument to substr>,:got(chars),:range<0..Inf>, | |
+ :comment("use *{length} if you want to index relative to the end") | |
+ ).fail if length < 0; | |
+ 1; | |
+} | |
- nqp::p6box_s(nqp::substr($str, $from, $length)); | |
+sub substr(Str() \what, \from, $chars?) { | |
+ | |
+ # should really be int, but \ then doesn't work for rw access | |
+ my $r := SUBSTR-SANITY( what, from, $chars, my Int $from, my Int $length); | |
+ return $r.defined | |
+ ?? nqp::p6box_s(nqp::substr( | |
+ nqp::unbox_s(what),nqp::unbox_i($from),nqp::unbox_i($length) | |
+ )) | |
+ !! $r; | |
} | |
-sub substr-rw(Str() $s is rw, $from, $length?) { | |
- my str $str = nqp::unbox_s($s); | |
- my int $chars = nqp::unbox_i( | |
- nqp::defined($length) ?? $length !! $from - nqp::chars($str) | |
- ); | |
- my str $substr = nqp::substr($str,$from,$chars); | |
+sub substr-rw(Str() \what, \from, $chars?) { | |
+ | |
+ # should really be int, but \ then doesn't work for rw access | |
+ my $r := SUBSTR-SANITY( what, from, $chars, my Int $from, my Int $length); | |
+ return $r unless $r.defined; | |
+ | |
Proxy.new( | |
- FETCH => sub ($) { nqp::p6box_s($substr) }, | |
- STORE => sub ($, $new) { | |
- $s = nqp::p6box_s( | |
- nqp::substr($str,0,$from) | |
- ~ nqp::unbox_s($new) | |
- ~ nqp::substr($str,$from + $chars) | |
- ); | |
- } | |
+ FETCH => sub ($) { | |
+ nqp::p6box_s(nqp::substr( | |
+ nqp::unbox_s(what), nqp::unbox_i($from), nqp::unbox_i($length) | |
+ )); | |
+ }, | |
+ STORE => sub ($, $new) { | |
+ my $str = nqp::unbox_s(what); | |
+ what = nqp::p6box_s( | |
+ nqp::substr($str,0,$from) | |
+ ~ nqp::unbox_s($new) | |
+ ~ nqp::substr($str,$from + $length) | |
+ ); | |
+ }, | |
); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment