Subject: | Sorry to spoil the fun... |
If the slice is undef, nothing happens:
$ perl5.17.5 -Mblib -MString::Slice -e '$buffalo = "abcdefg"; slice($s, $buffalo, 0, 3); print
"$s", "\n"'
You need to do SvPOK_on and SvPOKp_on on the slice.
If the slice is a string, it leaks memory (watch memory usage):
$ perl5.17.5 -Mblib -MString::Slice -e 'warn $$; $buffalo = "abcdefg"; while(1){slice(my
$s="", $buffalo, 0, 3)};'
You need to do SvPV_free first, unless the slice-to-be is a copy-on-write scalar (SvIsCOW),
in which case you should do sv_force_normal and then SvPV_free (or, in perls that support it,
sv_force_normal_flags(SV_COW_DROP_PV) and then SvPV_free for good measure).
Also:
$ perl5.17.5 -Mblib -MString::Slice -e '$buffalo = (keys%{{"abcdefg"=>1}})[0]; slice($s="",
$buffalo, 0, 3); undef $buffalo; print "$s", "\n"'
abc
$ perl5.17.5 -Mblib -MString::Slice -e '$buffalo = (keys%{{"abcdefg"=>1}})[0]; slice($s="",
$buffalo, 0, 3); undef $buffalo; eval join ",", "a".."z"; print "$s", "\n"'
<nothing>
If the buffer is a shared hash key (i.e., copy-on-write) scalar, you can’t make it read-only. In
my penultimate example, $s is pointing to a freed string which just happens still to contain
abc. In my last example, the eval/join overwrites that memory.
You would have to do sv_force_normal first on the buffer (which would copy the string and
defeat the point of the slice). If you don’t mind violating encapsulation, you could reach
inside the string buffer using SvSHARED_HEK_FROM_PV (see sv.h) and do share_hek_hek (see
hv.h). Then you would need free magic to do unshare_hek when the slice is freed. But you
would have to update your module to account for the new copy-on-write mechanism I’m
working on, if that makes its way into perl 5.18. (See
<http://perl5.git.perl.org/perl.git/shortlog/refs/heads/sprout/ookow> and
<https://rt.perl.org/rt3/Ticket/Display.html?id=114820>.) That would involve fiddling with
reference counts inside the string buffer.