File Coverage

blib/lib/String/Filter.pm
Criterion Covered Total %
statement 39 43 90.7
branch 7 12 58.3
condition 2 5 40.0
subroutine 6 8 75.0
pod 4 4 100.0
total 58 72 80.5


line stmt bran cond sub pod time code
1             package String::Filter;
2              
3 1     1   787 use strict;
  1         2  
  1         38  
4 1     1   4 use warnings;
  1         2  
  1         53  
5              
6 1     1   1232 use Regexp::Assemble;
  1         21427  
  1         460  
7              
8             our $VERSION = '0.01';
9              
10             sub new {
11 1     1 1 398 my $klass = shift;
12 1 50       6 my $args = @_ == 1 ? $_[0] : +{ @_ };
13             my $self = bless {
14             rules => [],
15 0     0   0 default_rule => $args->{default_rule} || sub { $_[0] },
16 1   50     10 _ra => Regexp::Assemble->new(),
17             _re => undef,
18             };
19 1 50       119 $self->add_rule(@{$args->{rules}})
  1         6  
20             if $args->{rules};
21 1         4 return $self;
22             }
23              
24             sub add_rule {
25 1     1 1 2 my $self = shift;
26 1 50       6 die "# of arguments is not even"
27             unless @_ % 2 == 0;
28 1         4 while (@_) {
29 3         4 my $pattern = shift;
30 3         5 my $subref = shift;
31 3         13 $self->{_ra}->add($pattern);
32 3         789 push @{$self->{rules}}, [ qr/^$pattern/, $subref ];
  3         66  
33 3         11 $self->{_re} = undef;
34             }
35             }
36              
37             sub default_rule {
38 0     0 1 0 my $self = shift;
39 0 0       0 $self->{default_rule} = shift
40             if @_;
41 0         0 return $self->{default_rule};
42             }
43              
44             sub filter {
45 1     1 1 7 my ($self, $text) = @_;
46 1   33     5 $self->{_re} ||= do {
47 1         5 my $assembled = $self->{_ra}->re;
48 1         892 qr/($assembled)/;
49             };
50 1         3 my @ret;
51 1         12 for my $token (split /$self->{_re}/, $text) {
52 8 100       15 next if $token eq '';
53             # FIXME do we have to do this O(n) every time?
54 6         6 for my $rule (@{$self->{rules}}) {
  6         11  
55 14 100       48 if ($token =~ /$rule->[0]/) {
56 4         11 push @ret, $rule->[1]->($token);
57 4         134 goto NEXT_TOKEN;
58             }
59             }
60 2         6 push @ret, $self->{default_rule}->($token);
61             NEXT_TOKEN:
62 6         39 ;
63             }
64 1         7 return join '', @ret;
65             }
66              
67             1;
68             __END__