# # Implement iteration over a opaque hash. # =pod =head1 HashIterator A hash iterator is an object that alows iteration over a hash in a manner analagous to the way that STL iterators allow iteration over those containers. The HashIterator has the effect of hiding the existence of the hash from the caller and instead presenting an iteratable collection to the caller. The intent is for a hash iterator to be an object returned by another object or class to support iteration over some internal hash maintained by the object. Passing the hash itself back breaks data hiding and protection. =head1 Typical usage: use HashIterator; ... $i = HashIterator::new(\%myhash); ... $i->begin(); while(! $i->end()) { $itemref = $i->get(); $i->next(); } =head1 Member Functions: =cut package HashIterator; =pod =head2 new(hash) Create a new HashIterator object and return a reference to it. Data members of the HashIterator include: =over 4 =item Hash Reference to the hash being iterated over. =item Keylist The set of keys in the underlying hash (an anonymous array ref). =item KeyCount The number of keys in the underlying hash. =item Index Position of the iterator within the keylist/hash table. =back =cut sub new { my $class = shift; # Class name... my $hashref = shift; # Maintain this hash. my @keylist = keys(%$hashref); my $keyref= \@keylist; my $keycount = scalar @keylist; my $self = { Hash => $hashref, Keylist => $keyref, KeyCount => $keycount, Index => 0}; bless($self, $class); # Type ourself... return $self; } =pod =head2 begin Reset the iterator to the start of iteration. =cut sub begin { my $self = shift; # Get object... $self->{Index} = 0; } =pod =head2 end Return true if the iterator is off the end of the hash. =cut sub end { my $self = shift; # Retrieve self as object. return ($self->{Index} >= $self->{KeyCount}); } =pod =head2 get Return the contents of the hash at the current key. If the key is off the end of the hash, undef is returned. What is returned is a copy of the element. If the index is off the end of the iteration, undef is returned. =cut sub get { my $self = shift; if ($self->end()) { return undef; } my $hashref = $self->{Hash}; my $key = $self->{Keylist}->[$self->{Index}]; return $$hashref{$key}; } =pod =head2 next Advances the iterator. =cut sub next { my $self = shift; # Get us. $self->{Index} = $self->{Index} + 1; } 1;