File Coverage

blib/lib/Regex/Iterator.pm
Criterion Covered Total %
statement 54 54 100.0
branch 13 18 72.2
condition 2 3 66.6
subroutine 10 10 100.0
pod 7 7 100.0
total 86 92 93.4


line stmt bran cond sub pod time code
1             package Regex::Iterator;
2              
3 4     4   29943 use strict;
  4         10  
  4         168  
4 4     4   20 use vars qw($VERSION);
  4         7  
  4         2589  
5              
6             $VERSION = "0.4";
7              
8              
9             =pod
10              
11             =head1 NAME
12              
13             Regex::Iterator - provides an iterator interface to regexps
14              
15             =head1 SYNOPSIS
16              
17             my $string = 'string to search';
18             my $re = qr/[aeiou]/i;
19             # a plain string of 'aeiou' would work as well
20              
21            
22              
23             my $it = Regex::Iterator->new($regex, $string);
24              
25             while (my $match = $it->match) {
26             $it->replace('o');
27             }
28             print $it->result,"\n"; # 'strong to soorch'
29             print $it->string,"\n"; # 'string to search'
30              
31              
32             =head1 DESCRIPTION
33              
34             Inspired by Mark Jason Dominus' talk I
35             (available from http://perl.plover.com/yak/iterators/) this is an iterative regex
36             matcher based on the work I did for B
37              
38              
39             =head1 METHODS
40              
41             =head2 new
42            
43             Fairly self explanatory - takes a regex and a string to match it against.
44              
45             C can be the result of a C
46              
47             =cut
48              
49              
50             sub new {
51 5     5 1 2343 my ($class, $re, $string) = @_;
52              
53 5         15 my $self = bless {}, $class;
54            
55 5         21 $self->string($string);
56 5         14 $self->re($re);
57              
58              
59 5         33 return bless $self, $class;
60              
61             }
62              
63              
64             =head2 string [ string ]
65              
66             Gets the current string we're matching against.
67              
68             If a new string is optionally passed in then it will be set
69             as the string for the iterator to match on and the iterator
70             will be reset.
71              
72             Setting returns the object itself to allow chaining.
73              
74             =cut
75              
76             sub string {
77 15     15 1 22 my $self = shift;
78              
79 15 100       61 return $self->{_orig} unless @_;
80              
81 6         27 $self->{_orig} = $_[0];
82 6         17 $self->rewind;
83              
84 6         8 return $self;
85             }
86              
87              
88              
89             =head2 re [ regex ]
90              
91             Gets the current regex we're matching with.
92              
93             If a new regex is optionally passed in then it will be set
94             as the regex for the iterator to match with. Does not
95             reset the iterator so you can change patterns halfway through
96             an iteration if necessary. The regex will be automatically
97             compiled using C for speed.
98              
99             Setting returns the object itself to allow chaining.
100              
101             =cut
102              
103             sub re {
104 8     8 1 13 my $self = shift;
105              
106 8 100       29 return $self->{_re} unless @_;
107            
108 6         9 my $re = $_[0];
109 6 100       71 $re = qr/$re/ unless ref($re) eq 'Regexp';
110              
111              
112 6         16 $self->{_re} = $re;
113              
114 6         13 return $self;
115             }
116              
117             =head2 match
118              
119             Returns the current match as a string.
120              
121             It then advances to the next one.
122              
123             =cut
124              
125              
126             sub match {
127 14     14 1 1422 my $self = shift;
128 14 50       38 return undef unless defined $self->{_remain};
129              
130              
131              
132 14         26 local $1;
133 14         29 "null" =~ m!()!; # set $1 to ""
134 14         29 $self->_next();
135              
136 14         14 my $re = $self->{_re};
137              
138 14         137 $self->{_remain} =~ /(.*?)($re)(.*)/s;
139              
140              
141 14 100 66     86 return unless defined $2 and $2 ne "";
142              
143            
144 8         15 my $match = $2;
145 8 50       13 my $pre = $1; $pre = '' unless defined $pre;
  8         19  
146 8 50       14 my $post = $+; $post = '' unless defined $post;
  8         16  
147              
148 8         12 $self->{_result} .= $pre;
149 8         11 $self->{_remain} = $post;
150 8         10 $self->{_match} = $match;
151              
152 8         28 return $match;
153             }
154              
155              
156              
157             =head2 replace
158              
159             Replaces the current match with I
160              
161             =cut
162              
163             sub replace {
164 6     6 1 889 my ($self, $replace) = @_;
165 6 50       16 return 0 unless defined $self->{_match};
166 6         31 $self->{_match} = $replace;
167 6         17 return 1;
168             }
169              
170              
171             =head2 rewind
172              
173             Rewinds the object's state to the original string (as supplied by set_string),
174             this allows matching to begin from the beginning again
175              
176             =cut
177              
178             sub rewind {
179 7     7 1 10 my $self = shift;
180              
181 7         24 $self->{_remain} = $self->string;
182 7         34 $self->{$_} = '' for qw( _match _result );
183              
184 7         17 return $self;
185             }
186              
187              
188              
189              
190              
191             =head2 result
192              
193             Returns the string with all replacements.
194              
195             =cut
196              
197             sub result {
198 6     6 1 735 my $self = shift;
199              
200 6         19 return join '', grep { defined } @$self{qw/ _result _match _remain /};
  18         56  
201             }
202              
203              
204             # internal iterator method
205              
206             sub _next {
207 14     14   18 my $self = shift;
208 14 50       32 return undef unless defined $self->{_match};
209            
210 14         24 $self->{_result} .= $self->{_match};
211 14         27 $self->{_match} = undef;
212             }
213              
214              
215             =pod
216              
217             =head1 BUGS
218              
219             None that I know of but there are probably loads.
220              
221             =head1 COPYING
222              
223             Distributed under the same terms as Perl itself.
224              
225             =head1 AUTHOR
226              
227             Copyright (c) 2004,
228              
229             Simon Wistow
230              
231             Matt Lawrence
232              
233             =head1 SEE ALSO
234              
235             L, http://perl.plover.com/yak/iterators/
236              
237             =cut
238              
239             # keep perl happy
240             1;