File Coverage

blib/lib/Regexp/Log.pm
Criterion Covered Total %
statement 92 92 100.0
branch 30 30 100.0
condition n/a
subroutine 15 15 100.0
pod 5 5 100.0
total 142 142 100.0


line stmt bran cond sub pod time code
1             package Regexp::Log;
2              
3 5     5   171428 use strict;
  5         11  
  5         234  
4 5     5   28 use Carp;
  5         11  
  5         431  
5 5     5   34 use vars qw( $VERSION );
  5         11  
  5         440  
6              
7             $VERSION = 0.06;
8              
9             sub new {
10 6     6 1 52 my $class = shift;
11 5     5   26 no strict 'refs';
  5         11  
  5         4510  
12 6         58 my $self = bless {
13             debug => 0,
14             comments => 0,
15             anchor_line => 1,
16             modifiers => '',
17 6         15 %{"${class}::DEFAULT"},
18             @_
19             }, $class;
20              
21             # some initialisation code
22 6 100       11 if ( my @capture = @{ $self->{capture} } ) {
  6         36  
23 5         9 $self->{capture} = [];
24 5         22 $self->capture(@capture);
25             }
26              
27 6         18 return $self;
28             }
29              
30             sub format {
31 9     9 1 6015 my $self = shift;
32 9 100       36 $self->{format} = shift if @_;
33 9         25 return $self->{format};
34             }
35              
36             sub capture {
37 12     12 1 2503 my $self = shift;
38              
39             # add the new tags to capture
40 12         27 for (@_) {
41              
42             # special tags
43 11 100       41 if ( $_ eq ':none' ) { $self->{capture} = [] }
  1 100       5  
44             elsif ( $_ eq ':all' ) {
45 3         13 $self->{capture} = [ $self->fields ];
46             }
47              
48             # normal tags
49 7         9 else { push @{ $self->{capture} }, $_ }
  7         27  
50             }
51              
52 12         17 my %capture = map { ( $_, 1 ) } @{ $self->{capture} };
  27         73  
  12         25  
53 12 100       57 $self->{capture} = [ keys %capture ] if @_;
54              
55             # compute what will be actually captured, in which order
56 12         40 $self->_regexp;
57 12         96 return grep { $capture{$_} } ( $self->{_regexp} =~ /\(\?\#=([-\w]+)\)/g );
  54         144  
58              
59             }
60              
61             # this internal method actually computes the correct regular expression
62             sub _regexp {
63 26     26   33 my $self = shift;
64 26         38 my $class = ref $self;
65              
66 26         50 $self->{_regexp} = $self->{format};
67              
68 26         69 $self->{_regexp} =~ s/([\\|()\[\]{}^\$*+?.])/\\$1/g;
69 26 100       143 $self->_preprocess if $self->can('_preprocess');
70              
71             # accept predefined formats
72 5     5   31 no strict 'refs';
  5         9  
  5         2516  
73 1         4 $self->{format} = ${"${class}::FORMAT"}{ $self->{format} }
  26         116  
74 26 100       163 if exists ${"${class}::FORMAT"}{ $self->{format} };
75              
76 26         32 my $convert = join '|', reverse sort keys %{"${class}::REGEXP"};
  26         158  
77 26         266 $self->{_regexp} =~ s/($convert)/${"${class}::REGEXP"}{$1}/g;
  69         305  
78              
79 26 100       124 $self->_postprocess if $self->can('_postprocess');
80             }
81              
82             sub regexp {
83 14     14 1 75 my $self = shift;
84 14         32 $self->_regexp;
85 14         34 my $regexp = $self->{_regexp};
86              
87 14         20 my %capture = map { ( $_, 1 ) } @{ $self->{capture} };
  48         88  
  14         30  
88              
89             # this is complicated, but handles multiple levels of imbrication
90 14         24 my $pos = 0;
91 14         49 while ( ( $pos = index( $regexp, "(?#=", $pos ) ) != -1 ) {
92 55         102 ( pos $regexp ) = $pos;
93 55         255 $regexp =~ s{\G\(\?\#=([-\w]+)\)(.*?)\(\?\#\!\1\)}
94 55 100       253 { exists $capture{$1} ? "((?#=$1)$2(?#!$1))"
95             : "(?:(?#=$1)$2(?#!$1))" }ex;
96 55         168 $pos += 4; # oh my! a magic constant!
97             }
98              
99             # for regexp debugging
100 14 100       42 if ( $self->debug ) {
101 1         44 $regexp =~ s/\(\?\#\!([-\w]+)\)/(?#!$1)(?{ print STDERR "$1 "})/g;
102 1         6 $regexp =~ s/^/(?{ print STDERR "\n"})/;
103             }
104              
105             # remove comments
106 14 100       39 $regexp =~ s{\(\?\#[=!][^)]*\)}{}g unless $self->comments;
107              
108             # include anchors
109 14 100       41 $regexp = qq{\^$regexp\$} if $self->anchor_line;
110              
111             # include modifiers
112 14 100       33 $regexp = join '', '(?', $self->modifiers, ":$regexp)"
113             if length $self->modifiers;
114              
115             # compute the regexp
116 5 100   5   32 if ( $self->debug ) { use re 'eval'; $regexp = qr/$regexp/; }
  5         11  
  5         817  
  14         29  
  1         195  
117 13         382 else { $regexp = qr/$regexp/ }
118              
119 14         91 return $regexp;
120             }
121              
122             *regex = \®exp;
123              
124             sub fields {
125 4     4 1 7 my $self = shift;
126 4         5 my $class = ref $self;
127 5     5   692 no strict 'refs';
  5         11  
  5         634  
128 4         8 return map { (/\(\?\#=([-\w]+)\)/g) } values %{"${class}::REGEXP"};
  16         98  
  4         21  
129             }
130              
131             for my $attr (qw( comments modifiers anchor_line debug )) {
132 5     5   30 no strict 'refs';
  5         9  
  5         410  
133             *$attr = sub {
134 84     84   2990 my $self = shift;
135 84 100       149 $self->{$attr} = shift if @_;
136 84         439 return $self->{$attr};
137             };
138             }
139              
140             1;
141              
142             __END__