File Coverage

blib/lib/Array/Stream/Transactional/Matcher.pm
Criterion Covered Total %
statement 69 71 97.1
branch 17 24 70.8
condition 2 5 40.0
subroutine 12 13 92.3
pod 4 4 100.0
total 104 117 88.8


line stmt bran cond sub pod time code
1             # $Id: Matcher.pm,v 1.11 2004/06/11 21:50:53 claes Exp $
2              
3             package Array::Stream::Transactional::Matcher;
4              
5 5     5   178979 use Array::Stream::Transactional::Matcher::Rule;
  5         118  
  5         394  
6 5     5   3237 use Array::Stream::Transactional::Matcher::Logical;
  5         13  
  5         162  
7 5     5   3123 use Array::Stream::Transactional::Matcher::Value;
  5         11  
  5         140  
8 5     5   3538 use Array::Stream::Transactional::Matcher::Flow;
  5         15  
  5         143  
9              
10 5     5   135 use 5.006001;
  5         17  
  5         200  
11 5     5   23 use Carp qw(croak confess);
  5         10  
  5         252  
12 5     5   28 use strict;
  5         10  
  5         135  
13 5     5   31 use warnings;
  5         9  
  5         4419  
14              
15             require Exporter;
16              
17             our @ISA = qw(Exporter);
18              
19             our %EXPORT_TAGS = ( 'all' => [ qw(mkrule) ] );
20             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
21             our @EXPORT = qw();
22              
23             our $VERSION = '1.00';
24              
25             sub mkrule {
26 53     53 1 8338 my $type = shift;
27 53         98 $type =~ s/-/::/g;
28 53 50       134 unless($type =~ /^Array::Stream::Transactional::Matcher::/) {
29 53         112 $type = "Array::Stream::Transactional::Matcher::${type}";
30             }
31 53         444 return $type->new(@_);
32             }
33              
34             sub new {
35 20     20 1 181 my $class = shift;
36 20         59 my %args = @_;
37 20 50 33     153 croak "Missing mandatory argument 'rules'" unless(exists $args{rules} && ref $args{rules} eq 'ARRAY');
38 20         110 my $self = bless {}, $class;
39              
40 20         33 my $default = undef;
41 20 100       54 if(exists $args{call}) {
42 1 50       5 croak "Argument 'call' must be a CODE reference" unless(ref $args{call} eq 'CODE');
43 1         2 $default = $args{call};
44             } else {
45 19     0   61 $default = sub {};
  0         0  
46             }
47            
48 20         32 my @rules;
49 20         26 foreach(@{$args{rules}}) {
  20         55  
50 22 100       67 if(ref $_ eq 'ARRAY') {
    50          
51 19         24 my ($rule, $callback) = @{$_};
  19         63  
52 19 50       113 croak "Rule match object must be an Array::Stream::Transactional::Matcher::Rule subclass" unless(UNIVERSAL::isa($rule, 'Array::Stream::Transactional::Matcher::Rule'));
53 19 50       59 croak "Rule callback must be a CODE reference" unless(ref $callback eq 'CODE');
54 19         74 push @rules, [ $rule, $callback ];
55             } elsif (UNIVERSAL::isa($_, 'Array::Stream::Transactional::Matcher::Rule')) {
56 3         25 push @rules, [ $_, $default ];
57             } else {
58 0         0 croak "Rule entry must be an Array::Stream::Transactional::Matcher::Rule or an ARRAY reference";
59             }
60             }
61              
62 20         104 $self->{rules} = \@rules;
63 20         107 return $self;
64             }
65              
66             sub rules {
67 140     140 1 192 my $self = shift;
68 140   50     491 return $self->{rules} || [];
69             }
70              
71             sub match {
72 20     20 1 112 my ($self, $stream) = @_;
73 20 50       85 croak "Can't match a non Array::Stream::Transactional stream" unless(UNIVERSAL::isa($stream, 'Array::Stream::Transactional'));
74              
75 20         26 my @matches;
76              
77 20         29 my $match = 0;
78 20         75 MATCH: while($stream->has_more) {
79 140         1024 my $start = $stream->pos;
80 140         480 for my $rule (@{$self->rules}) {
  140         259  
81 149         459 $match = $rule->[0]->match($stream);
82 149 100       638 if($match) {
83 47 100       134 my $end = $start == $stream->pos ? $start : $stream->pos - 1;
84 47         405 push @matches, { rule => $rule, start => $start, end => $end };
85 47         149 $rule->[1]->($rule->[0], $start, $end);
86 47         195 next MATCH;
87             }
88             }
89             } continue {
90 140 100       560 $stream->next unless($match == -1);
91 140         1055 $match = 0;
92             }
93              
94 20         198 return @matches;
95             }
96              
97             1;
98              
99             __END__