[LON-CAPA-cvs] cvs: newloncapa /types HashIterator.pm

foxr lon-capa-cvs@mail.lon-capa.org
Wed, 09 Apr 2003 19:41:45 -0000


foxr		Wed Apr  9 15:41:45 2003 EDT

  Added files:                 
    /newloncapa/types	HashIterator.pm 
  Log:
  HashIterator - provides a way to iterate through hashes without making
  the actual hash available to the client.  The idea is that a class
  implementation might maintain a hash that should be data hidden from the client.
  The client may, however need to iterate through the hash.  The class can
  make available a HashIterator object and the user can then iterate through
  the hash through that.
  
  Exported interface:
     new{\%hash}          # generally called by an object with a hash.
     begin();  # Reset the iterator to collection start.
     end();    # True if iterator is at or off the end.
     get();    # Return current hash member, undef if end() is true.
     next();   # Advances the iterator.
   
  
  Initial draft, passes perl -c and that's about all we can vouch for at the 
  moment.
  
  

Index: newloncapa/types/HashIterator.pm
+++ newloncapa/types/HashIterator.pm
#
#  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:

=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.
=cut
sub new {
    my $class   = shift;	# Class name...
    my $hashref = shift;        # Maintain this hash.
    my $self  = [];		# We are an anonymous hash.

    my @keys = keys %$hashref;   
    my $keyref= \@keys;

    $self    = {  Hash      => $hashref,
		  Keylist   => $keyref,
		  KeyCount  => scalar @keys,
		  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 $keysref = $self->{Keylist};
    my @keys    = @$keysref;
    my $key     = $keys[$self->{Index}];

    return $$hashref{$key};
}
=pod
=head2 next
    Advances the iterator.
=cut
sub next {
    my $self = shift;		# Get us.
    $self->{Index} = $self->{Index}++;
}

1;