#!/usr/bin/perl
use warnings;
use strict;
use feature qw/state/;
use Test::More tests => 4;
use Benchmark qw/cmpthese/;
my $length = 100_000;
my $string = join q(), map int rand 10, 1 .. $length;
my $mask = join q(), map int rand 2, 1 .. $length;
my $result = bitwise($string, $mask);
is arraywise ($string, $mask), $result, 'array';
is substrwise($string, $mask), $result, 'substr';
is packwise ($string, $mask), $result, 'pack';
is regexwise ($string, $mask), $result, 'regex';
sub bitwise {
my $string = shift;
state $mask;
($mask = shift) =~ y/01/\x00\xff/ unless defined $mask;
my $result = $string & $mask;
$result =~ tr/\x00//d;
return $result;
}
sub arraywise {
my $string = shift;
state $mask = shift;
my @chars = split //, $string;
return join q(), @chars[grep substr($mask, $_, 1), 0 .. length $ma
+sk];
}
sub regexwise {
my $string = shift;
state $regex;
unless (defined $regex) {
$regex = '^' . join(q(), map $_ ? '(.)' : '.', split //, shift
+) . '$';
}
my $result = join q(), $string =~ m/$regex/o;
return $result;
}
sub packwise {
my $string = shift;
state $mask;
unless (defined $mask) {
$mask = shift;
my $template;
while ($mask =~ /((.)\2*)/g) {
$template .= (qw(x a))[$2] . length $1;
}
$mask = $template;
}
return join q(), unpack $mask, $string;
}
sub substrwise {
my $string = shift;
state $mask;
my @mask;
unless (defined $mask) {
$mask = shift;
while ( $mask =~ /0+/g ) {
push @mask, [ $-[0], ( $+[0] - $-[0] ) ];
}
}
for (1 .. @mask) {
my $replace = ''; #'*' x $mask[-$_][1]; #check to see
substr $string, $mask[-$_][0], $mask[-$_][1], $replace;
}
return $string;
}
cmpthese(-3, {
bitwise => sub { bitwise ($string, $mask) },
arraywise => sub { arraywise ($string, $mask) },
substrwise => sub { substrwise($string, $mask) },
packwise => sub { packwise ($string, $mask) },
regexwise => sub { regexwise ($string, $mask) },
});