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