package LookFor; use Carp; use strict; our $AUTOLOAD; # it's a package global BEGIN { use Exporter (); our(@ISA,@EXPORT); @ISA = qw(Exporter); @EXPORT = qw(END_FIND FOUND DEBUG NOT_FOUND); } sub AUTOLOAD { my $self = shift; my $type = ref($self) or croak "<$self> is not an object"; my $name = $AUTOLOAD; $name =~ s/.*://; # strip fully-qualified portion unless (exists $self->{_permitted}->{$name} ) { croak "Can't access `$name' field in class $type"; } if (@_) { return $self->{$name} = shift; } else { return $self->{$name}; } } my %fields = ( #fields to inherit! data => undef, #Required in Class Init data_stream => undef, #" stream_name => undef, #" _data => undef, max_seeks => 1000, seek => \&_default_seek, _parent => undef, #don't inheret _data => undef, # _end_find => undef, type => undef, next_lookfor => undef, fnd_n_prc_data => undef, name => undef ); my @req_fields = qw/data data_stream stream_name/; sub new { my $objq = shift; my $class = ref($objq) || $objq; my %init = @_; my $self = { _permitted => \%fields, %fields, %init, }; bless $self, $class; if(ref($objq)) {$self->_inst_check($objq,\%init) } else { $self->_check()} return $self; } sub _end_chk { my $self = shift; $_ = $self->{sought}; return FOUND() if ("$_" eq undef); return NOT_FOUND(); } sub _check { my $self = shift; $self->{_end_find} = $self->new("fnd_n_prc_data"=> \&_end_chk,"name"=> "end"); } sub _inst_check { my ($self,$parent,$init) = @_; foreach (keys %fields) { if (!$$init{$_}) {$self->{$_} = $parent->{$_}} } $self->{_parent} = $parent; if ( ref($$init{fnd_n_prc_data}) ne "CODE" ) { $self->{_data}->{re} = $$init{fnd_n_prc_data}; $self->{fnd_n_prc_data} = \&_default_proc; } } sub change { my $self = shift; my %changes = @_; foreach my $param (keys %changes) { $self->{$param} = $changes{$param}; } } sub _default_proc { my ($self,$srch_str) = @_; $_ = $self->{sought}; if (/$self->{_data}->{re}/i) { if( $self->{type} & DEBUG() ) { print "{".$self->{stream_name}." ".$self->{name}."}->$_\n"; } return FOUND(); } return NOT_FOUND(); } sub _default_seek { my $self = shift; my $file = $self->{data_stream}; $self->{sought} = <$file>; return $self->{sought}; } # #Insert Code Diagraming stuff here;) # sub next_lookfor { my $self = shift; if (@_ > 1) { #multiple lookfors! $self->{next_lookfor} = _combined_lookfors($self, @_); } else { $self->{next_lookfor} = _check_for_end_find($self,shift); } } sub _check_for_end_find { my $self = shift; my $lookfor_in_question = shift; if ($lookfor_in_question eq "end_find" && ref($lookfor_in_question) ne "LookFor") { return $self->{_end_find}; } else { return $lookfor_in_question; } } sub _combined_fnd_n_prc_data { my $self = shift; #self will be the combined lookfor... my $chk; foreach my $lookfor ( @{$self->{_data}->{lookfors}}) { $lookfor->{sought} = $self->{sought}; #The data to search changes! if($lookfor->{fnd_n_prc_data}($lookfor) eq FOUND()) { $self->{next_lookfor} = $lookfor->{next_lookfor}; return FOUND(); } } return return NOT_FOUND(); } sub _combined_lookfors { my $self = shift; my $name; my @lookfors; while (@_) { my $lookfor = shift; $lookfor = _check_for_end_find($self,$lookfor); push @lookfors,$lookfor; $name .= "-{".$lookfor->{name}."}-"; } my $combined_lookfor = $self->new( "fnd_n_prc_data"=>\&_combined_fnd_n_prc_data, "name" => $name); $combined_lookfor->{_data}->{lookfors} = \@lookfors; return $combined_lookfor; } sub lookfor { my $self = shift; my $chk = NOT_FOUND(); my $sought = " "; my $debug = $self->{stream_name}." |".$self->{name}."|"; my $seek_count = 1; #foreach my $field (@req_fields) { # croak "$field is not defined in new()!" unless ($self->{$field}); #} while ($chk ne FOUND() && $sought ne undef && $seek_count < $self->{max_seeks}) { $sought = $self->{seek}($self); $chk = $self->{fnd_n_prc_data}($self); $seek_count++; } croak "$debug END FOUND before pattern" unless ($sought || $self->{name} eq "end"); croak "$debug: BROKEN LINK: Don't know what to do!" unless ($self->{next_lookfor} || $self->{name} eq "end" ); croak "$debug TOO MANY seeks!" if ($seek_count >= $self->{max_seeks}); $seek_count = 1; $self->{next_lookfor}->lookfor() if ($self->{next_lookfor}); return $self->{data}; } sub DEBUG {return 1} sub FOUND {return "found"} sub NOT_FOUND {return "not found"} sub END_FIND {return "end_find"} return 1;