1package TAP::Parser::Iterator;
2
3use strict;
4use vars qw($VERSION @ISA);
5
6use TAP::Object ();
7
8@ISA = qw(TAP::Object);
9
10=head1 NAME
11
12TAP::Parser::Iterator - Base class for TAP source iterators
13
14=head1 VERSION
15
16Version 3.26
17
18=cut
19
20$VERSION = '3.26';
21
22=head1 SYNOPSIS
23
24  # to subclass:
25  use vars qw(@ISA);
26  use TAP::Parser::Iterator ();
27  @ISA = qw(TAP::Parser::Iterator);
28  sub _initialize {
29    # see TAP::Object...
30  }
31
32  sub next_raw { ... }
33  sub wait     { ... }
34  sub exit     { ... }
35
36=head1 DESCRIPTION
37
38This is a simple iterator base class that defines L<TAP::Parser>'s iterator
39API.  Iterators are typically created from L<TAP::Parser::SourceHandler>s.
40
41=head1 METHODS
42
43=head2 Class Methods
44
45=head3 C<new>
46
47Create an iterator.  Provided by L<TAP::Object>.
48
49=head2 Instance Methods
50
51=head3 C<next>
52
53 while ( my $item = $iter->next ) { ... }
54
55Iterate through it, of course.
56
57=head3 C<next_raw>
58
59B<Note:> this method is abstract and should be overridden.
60
61 while ( my $item = $iter->next_raw ) { ... }
62
63Iterate raw input without applying any fixes for quirky input syntax.
64
65=cut
66
67sub next {
68    my $self = shift;
69    my $line = $self->next_raw;
70
71    # vms nit:  When encountering 'not ok', vms often has the 'not' on a line
72    # by itself:
73    #   not
74    #   ok 1 - 'I hate VMS'
75    if ( defined($line) and $line =~ /^\s*not\s*$/ ) {
76        $line .= ( $self->next_raw || '' );
77    }
78
79    return $line;
80}
81
82sub next_raw {
83    require Carp;
84    my $msg = Carp::longmess('abstract method called directly!');
85    $_[0]->_croak($msg);
86}
87
88=head3 C<handle_unicode>
89
90If necessary switch the input stream to handle unicode. This only has
91any effect for I/O handle based streams.
92
93The default implementation does nothing.
94
95=cut
96
97sub handle_unicode { }
98
99=head3 C<get_select_handles>
100
101Return a list of filehandles that may be used upstream in a select()
102call to signal that this Iterator is ready. Iterators that are not
103handle-based should return an empty list.
104
105The default implementation does nothing.
106
107=cut
108
109sub get_select_handles {
110    return;
111}
112
113=head3 C<wait>
114
115B<Note:> this method is abstract and should be overridden.
116
117 my $wait_status = $iter->wait;
118
119Return the C<wait> status for this iterator.
120
121=head3 C<exit>
122
123B<Note:> this method is abstract and should be overridden.
124
125 my $wait_status = $iter->exit;
126
127Return the C<exit> status for this iterator.
128
129=cut
130
131sub wait {
132    require Carp;
133    my $msg = Carp::longmess('abstract method called directly!');
134    $_[0]->_croak($msg);
135}
136
137sub exit {
138    require Carp;
139    my $msg = Carp::longmess('abstract method called directly!');
140    $_[0]->_croak($msg);
141}
142
1431;
144
145=head1 SUBCLASSING
146
147Please see L<TAP::Parser/SUBCLASSING> for a subclassing overview.
148
149You must override the abstract methods as noted above.
150
151=head2 Example
152
153L<TAP::Parser::Iterator::Array> is probably the easiest example to follow.
154There's not much point repeating it here.
155
156=head1 SEE ALSO
157
158L<TAP::Object>,
159L<TAP::Parser>,
160L<TAP::Parser::Iterator::Array>,
161L<TAP::Parser::Iterator::Stream>,
162L<TAP::Parser::Iterator::Process>,
163
164=cut
165
166