# Implement iteration over a opaque hash. # # $Id: HashIterator.pm,v 1.1 2003/09/15 09:20:39 foxr Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # =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 use strict; 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;