| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# $Id: DateRange.pm,v 1.2 2005/04/19 15:33:02 dk Exp $ |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Regexp::Log::DateRange; |
|
4
|
1
|
|
|
1
|
|
919
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
35
|
|
|
5
|
1
|
|
|
1
|
|
7
|
use vars qw($VERSION %templates); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
1386
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
$VERSION = '0.02'; |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
%templates = ( |
|
10
|
|
|
|
|
|
|
syslog => [ |
|
11
|
|
|
|
|
|
|
[ '\\s+', 1, 12, [ qw(. jan feb mar apr may jun jul aug sep oct nov dec)]], |
|
12
|
|
|
|
|
|
|
[ '\\s+', 1, 31, undef, '0?'], |
|
13
|
|
|
|
|
|
|
[ '\\:', 0, 23, undef, '0?' ], |
|
14
|
|
|
|
|
|
|
[ '\\:', 0, 59, undef, '0?' ], |
|
15
|
|
|
|
|
|
|
], |
|
16
|
|
|
|
|
|
|
); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub new |
|
19
|
|
|
|
|
|
|
{ |
|
20
|
200
|
|
|
200
|
0
|
10897864
|
my ( $class, $template, $date1, $date2) = @_; |
|
21
|
|
|
|
|
|
|
|
|
22
|
200
|
50
|
|
|
|
1132
|
unless ( ref($template)) { |
|
23
|
200
|
50
|
|
|
|
1066
|
die "Template '$template' doesn't exist\n" |
|
24
|
|
|
|
|
|
|
unless $templates{$template}; |
|
25
|
200
|
|
|
|
|
478
|
$template = $templates{$template}; |
|
26
|
|
|
|
|
|
|
} |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# some sanity checks |
|
29
|
200
|
|
|
|
|
407
|
my $n = @$template; |
|
30
|
200
|
50
|
|
|
|
716
|
die "template is empty\n" unless $n; |
|
31
|
200
|
50
|
|
|
|
615
|
die "date [@$date1] is not valid\n" unless $n == @$date1; |
|
32
|
200
|
50
|
|
|
|
609
|
die "date [@$date2] is not valid\n" unless $n == @$date2; |
|
33
|
|
|
|
|
|
|
|
|
34
|
200
|
|
|
|
|
866
|
for ( my $i = 0; $i < $n; $i++) { |
|
35
|
217
|
100
|
|
|
|
703
|
next if $date1->[$i] == $date2->[$i]; |
|
36
|
200
|
50
|
|
|
|
800
|
last if $date1->[$i] < $date2->[$i]; |
|
37
|
0
|
|
|
|
|
0
|
( $date2, $date1) = ( $date1, $date2); |
|
38
|
0
|
|
|
|
|
0
|
last; |
|
39
|
|
|
|
|
|
|
} |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# build 'alignment' vectors; for example, for the right range, |
|
42
|
|
|
|
|
|
|
# 2499 would give 0111, for the left, 1150 would give 0001 |
|
43
|
200
|
|
|
|
|
295
|
my ( @w1, @w2); |
|
44
|
200
|
|
|
|
|
531
|
my ( $last1, $last2) = ( 1, 1); |
|
45
|
200
|
|
|
|
|
879
|
for ( my $i = $#$date1; $i > 0; $i--) { |
|
46
|
600
|
100
|
|
|
|
2261
|
$w1[$i-1] = $last1 & (( $date1->[$i] == $template->[$i]->[1] ) ? 1 : 0); |
|
47
|
600
|
100
|
|
|
|
1842
|
$w2[$i-1] = $last2 & (( $date2->[$i] == $template->[$i]->[2] ) ? 1 : 0); |
|
48
|
600
|
|
|
|
|
920
|
$last1 = $w1[$i-1]; |
|
49
|
600
|
|
|
|
|
1463
|
$last2 = $w2[$i-1]; |
|
50
|
|
|
|
|
|
|
} |
|
51
|
200
|
|
|
|
|
1156
|
my $tree = range2tree( $template, $date1, $date2, \@w1, \@w2, 0); |
|
52
|
200
|
|
|
|
|
780
|
return tree2re( $template, $tree, 0); |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# 1,2,3 => (?:1|2|3) |
|
56
|
|
|
|
|
|
|
sub re_group |
|
57
|
|
|
|
|
|
|
{ |
|
58
|
1959
|
50
|
|
1959
|
0
|
4953
|
if ( 0 == @_) { |
|
|
|
100
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
0
|
return ''; |
|
60
|
|
|
|
|
|
|
} elsif ( 1 == @_) { |
|
61
|
775
|
|
|
|
|
2414
|
return $_[0]; |
|
62
|
|
|
|
|
|
|
} else { |
|
63
|
1184
|
|
|
|
|
11224
|
return '(?:'.join('|', @_).')'; |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# 8 .. 13 => (?:0?8|9)|1[0123] |
|
68
|
|
|
|
|
|
|
sub match_range |
|
69
|
|
|
|
|
|
|
{ |
|
70
|
981
|
|
|
981
|
0
|
2250
|
my ( $from, $to, $digit_prefix) = @_; |
|
71
|
|
|
|
|
|
|
|
|
72
|
981
|
|
|
|
|
1053
|
my @tens; |
|
73
|
981
|
|
|
|
|
1897
|
for my $x ( $from .. $to) { |
|
74
|
11702
|
|
|
|
|
14944
|
my $ten = int( $x / 10); |
|
75
|
11702
|
100
|
|
|
|
19367
|
unless ( defined $tens[$ten]) { |
|
76
|
1931
|
|
|
|
|
2702
|
my $mod = int( $x % 10); |
|
77
|
1931
|
|
|
|
|
5702
|
$tens[$ten] = [ $mod, $mod]; |
|
78
|
|
|
|
|
|
|
} else { |
|
79
|
9771
|
|
|
|
|
14833
|
$tens[$ten]->[1]++; |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
981
|
|
|
|
|
1482
|
my @q; |
|
84
|
981
|
|
|
|
|
1284
|
my $last_range = ''; |
|
85
|
981
|
|
|
|
|
1138
|
my @branges; |
|
86
|
981
|
|
|
|
|
2834
|
for ( my $i = 0; $i < @tens; $i++) { |
|
87
|
2780
|
100
|
|
|
|
7076
|
next unless defined $tens[$i]; |
|
88
|
1931
|
100
|
|
|
|
6818
|
my $range = ( $tens[$i]->[0] == $tens[$i]->[1] ) ? |
|
89
|
|
|
|
|
|
|
$tens[$i]->[0] : |
|
90
|
|
|
|
|
|
|
"[$tens[$i]->[0]-$tens[$i]->[1]]"; |
|
91
|
1931
|
100
|
|
|
|
8970
|
if ( $i) { |
|
92
|
1439
|
100
|
|
|
|
2744
|
if ( $range eq $last_range) { |
|
93
|
306
|
|
|
|
|
624
|
push @branges, $i; |
|
94
|
306
|
|
|
|
|
1367
|
$q[-1] = "[$branges[0]-$branges[-1]]$range"; |
|
95
|
|
|
|
|
|
|
} else { |
|
96
|
1133
|
|
|
|
|
1407
|
$last_range = $range; |
|
97
|
1133
|
|
|
|
|
2026
|
push @q, "$i$range"; |
|
98
|
1133
|
|
|
|
|
4128
|
@branges = ($i); |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
} else { |
|
101
|
492
|
|
|
|
|
1829
|
push @q, "$digit_prefix$range"; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
|
|
106
|
981
|
|
|
|
|
2123
|
my $ret = re_group(@q); |
|
107
|
981
|
|
|
|
|
2906
|
$ret =~ s/\[0-9\]/\\d/g; |
|
108
|
981
|
|
|
|
|
4670
|
return $ret; |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# Convert date range into a max-3-branch tree, where each branch is an alternative |
|
112
|
|
|
|
|
|
|
# expansion rule, and is either a range or a value leaf; the value leaves can |
|
113
|
|
|
|
|
|
|
# point deeper. For example, if matching date range 1 Apr - 3 June, the corresponding |
|
114
|
|
|
|
|
|
|
# structure would be something like |
|
115
|
|
|
|
|
|
|
# |
|
116
|
|
|
|
|
|
|
# range (Apr-May) |
|
117
|
|
|
|
|
|
|
# value (June, |
|
118
|
|
|
|
|
|
|
# range(1-3) |
|
119
|
|
|
|
|
|
|
# ) |
|
120
|
|
|
|
|
|
|
# |
|
121
|
|
|
|
|
|
|
sub range2tree |
|
122
|
|
|
|
|
|
|
{ |
|
123
|
795
|
|
|
795
|
0
|
1398
|
my ( $template, $d1, $d2, $w1, $w2, $depth) = @_; |
|
124
|
|
|
|
|
|
|
|
|
125
|
795
|
|
|
|
|
1139
|
my ( $i, $left, $center, $right); |
|
126
|
795
|
|
|
|
|
1494
|
my ( $r1, $r2) = ( $d1-> [$depth], $d2-> [$depth]); |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# print +(' ' x $depth), "$depth: $r1 $r2\n"; |
|
129
|
|
|
|
|
|
|
|
|
130
|
795
|
100
|
100
|
|
|
6494
|
if ( |
|
|
|
100
|
100
|
|
|
|
|
|
131
|
|
|
|
|
|
|
( $w1->[$depth] and $w2->[$depth]) |
|
132
|
|
|
|
|
|
|
or $depth >= $#$d1 |
|
133
|
|
|
|
|
|
|
) { |
|
134
|
200
|
|
|
|
|
1275
|
$center = { |
|
135
|
|
|
|
|
|
|
range => [ $r1 , $r2 ], |
|
136
|
|
|
|
|
|
|
}; |
|
137
|
|
|
|
|
|
|
# print +(' ' x $depth), "T\n"; |
|
138
|
|
|
|
|
|
|
} elsif ( $r1 < $r2) { |
|
139
|
569
|
|
|
|
|
788
|
my ( @d1, @d2); |
|
140
|
|
|
|
|
|
|
# if, say, in '123' vs '145', '2' < '4' where depth = 1, |
|
141
|
|
|
|
|
|
|
# then d1 = 129 and d2 = 140 |
|
142
|
569
|
|
|
|
|
2000
|
for ( $i = 0; $i <= $depth; $i++) { |
|
143
|
1144
|
|
|
|
|
1877
|
$d1[$i] = $d1->[$i]; |
|
144
|
1144
|
|
|
|
|
2946
|
$d2[$i] = $d2->[$i]; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
569
|
|
|
|
|
1585
|
for ( $i = $depth + 1; $i < @$d1; $i++) { |
|
147
|
1132
|
|
|
|
|
1908
|
$d1[$i] = $template-> [$i]->[2]; |
|
148
|
1132
|
|
|
|
|
2989
|
$d2[$i] = $template-> [$i]->[1]; |
|
149
|
|
|
|
|
|
|
} |
|
150
|
569
|
100
|
|
|
|
1402
|
if ( $w1->[$depth]) { |
|
151
|
287
|
|
|
|
|
362
|
$r1--; |
|
152
|
|
|
|
|
|
|
# print +(' ' x $depth), "LT\n"; |
|
153
|
|
|
|
|
|
|
} else { |
|
154
|
|
|
|
|
|
|
# print +(' ' x $depth), "$depth L > @$d1 : @d1 [@$w1]\n"; |
|
155
|
282
|
|
|
|
|
1947
|
$left = { |
|
156
|
|
|
|
|
|
|
next => range2tree( $template, $d1, \@d1, $w1, [(1) x @d1], $depth + 1), |
|
157
|
|
|
|
|
|
|
value => $r1, |
|
158
|
|
|
|
|
|
|
}; |
|
159
|
|
|
|
|
|
|
# print +(' ' x $depth), "$depth L <\n"; |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
|
|
162
|
569
|
100
|
|
|
|
1333
|
if ( $w2->[$depth]) { |
|
163
|
|
|
|
|
|
|
# print +(' ' x $depth), "RT\n"; |
|
164
|
282
|
|
|
|
|
455
|
$r2++; |
|
165
|
|
|
|
|
|
|
} else { |
|
166
|
|
|
|
|
|
|
# print +(' ' x $depth), "$depth R > @d2 : @$d2 [@$w2]\n"; |
|
167
|
287
|
|
|
|
|
1609
|
$right = { |
|
168
|
|
|
|
|
|
|
next => range2tree( $template, \@d2, $d2, [(1) x @d2], $w2, $depth + 1), |
|
169
|
|
|
|
|
|
|
value => $r2, |
|
170
|
|
|
|
|
|
|
}; |
|
171
|
|
|
|
|
|
|
# print +(' ' x $depth), "$depth R <\n"; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
569
|
50
|
|
|
|
1560
|
if ( $r1 + 1 < $r2) { |
|
174
|
569
|
|
|
|
|
2463
|
$center = { |
|
175
|
|
|
|
|
|
|
range => [ $r1 + 1 , $r2 - 1 ], |
|
176
|
|
|
|
|
|
|
}; |
|
177
|
|
|
|
|
|
|
# print +(' ' x $depth), "$depth CT [ ", $r1+1, ' .. ', $r2-1, " ]\n"; |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
} else { |
|
180
|
26
|
|
|
|
|
119
|
$center = { |
|
181
|
|
|
|
|
|
|
next => range2tree( $template, $d1, $d2, $w1, $w2, $depth + 1), |
|
182
|
|
|
|
|
|
|
value => $r1, |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
return [ |
|
187
|
795
|
100
|
|
|
|
5226
|
$left ? $left : (), |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
$center ? $center : (), |
|
189
|
|
|
|
|
|
|
$right ? $right : () |
|
190
|
|
|
|
|
|
|
]; |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# converts a tree into a regexp |
|
194
|
|
|
|
|
|
|
sub tree2re |
|
195
|
|
|
|
|
|
|
{ |
|
196
|
795
|
|
|
795
|
0
|
1220
|
my ( $template, $tree, $depth) = @_; |
|
197
|
795
|
|
|
|
|
853
|
my @q; |
|
198
|
795
|
|
|
|
|
1206
|
my $t = $template-> [$depth]; |
|
199
|
795
|
|
|
|
|
1582
|
for my $hash ( @$tree) { |
|
200
|
1364
|
100
|
|
|
|
2947
|
if ( exists $hash-> {value}) { |
|
201
|
595
|
100
|
|
|
|
2267
|
my $v = $t->[3] ? |
|
202
|
|
|
|
|
|
|
$t->[3]->[$hash->{value}] : |
|
203
|
|
|
|
|
|
|
match_range( $hash->{value}, $hash->{value}, $t->[4]); |
|
204
|
595
|
|
|
|
|
2499
|
push @q, $v . |
|
205
|
|
|
|
|
|
|
$t->[0] . |
|
206
|
|
|
|
|
|
|
tree2re( $template, $hash-> {next}, $depth + 1); |
|
207
|
|
|
|
|
|
|
} else { |
|
208
|
1059
|
|
|
|
|
2478
|
my $r = $t->[3] ? |
|
209
|
586
|
|
|
|
|
1655
|
re_group( map { $t->[3]->[$_] } |
|
210
|
|
|
|
|
|
|
$hash-> {range}-> [0] .. $hash-> {range}-> [1] ) : |
|
211
|
769
|
100
|
|
|
|
2677
|
match_range( @{$hash-> {range}}, $t->[4]); |
|
212
|
769
|
|
|
|
|
2946
|
push @q, $r . $t->[0]; |
|
213
|
|
|
|
|
|
|
} |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
795
|
|
|
|
|
1954
|
return re_group(@q); |
|
217
|
|
|
|
|
|
|
} |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
1; |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
__END__ |