File:  [LON-CAPA] / loncom / types / HashIterator.pm
Revision 1.1: download - view: text, annotated - select for diffs
Fri Apr 18 02:40:24 2003 UTC (21 years ago) by foxr
Branches: MAIN
CVS tags: HEAD
Move these type implementing classes to the mainline cvs from the experimental
sandbox.

#
#  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;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>