#!/
# --------------------------------------
#
#   Title: Iterator
# Purpose: An iterator class.
#
#    Name: Iterator
#    File: Iterator.pm
# Created: August 17, 2007
#
# Copyright: Copyright 2007 by Mr. Shawn H. Corey.
#
# This program 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, version 3 of the License, or
# (at your option) any later version.
# 
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

# --------------------------------------
# Object
package Iterator;

# --------------------------------------
# Pragmas

require 5.8.0;

use strict;
use warnings;

# --------------------------------------
# Version
our $VERSION = '1.0.0';

# --------------------------------------
# Modules
use Carp;
use Data::Dumper;

# --------------------------------------
# Configuration Parameters

my %Default_Options = (
  inc => 1,
  value => 0,
  start => 0,
);

$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent   = 1;
$Data::Dumper::Maxdepth = 0;

# --------------------------------------
# Variables

# --------------------------------------
# Methods

# --------------------------------------
#        Usage: $iterator = Iterator->new( ; %options );
#      Purpose: To create a new iterator.
#      Returns: $iterator ref.
#   Parameters: A hash to initial key-value pairs.
# Side Effects: none
#       Throws: no exceptions
#     Comments: none
#     See Also: n/a
#
sub new {
  my $class = shift @_;
  my $self = { %Default_Options };

  $class = ( ref( $class ) or $class );
  bless $self, $class;
  $self->configure( @_ );

  # corrections for missing options
  my %opts = @_;
  if( exists $opts{value} ){
    $self->{start} = $self->{value};
  }elsif( exists $opts{start} ){
    $self->{value} = $self->{start};
  }

  return $self;
}

# --------------------------------------
#        Usage: $cloned_object = $iterator->clone( ; %options );
#      Purpose: Creates a clone iterator.
#               WARNING: only a surface-level clone is created.
#      Returns: $cloned_object -- The new iterator
#   Parameters:       %options -- Over-rides existing ones
# Side Effects: none
#       Throws: no exceptions
#     Comments: none
#     See Also: n/a
#
sub clone {
  my $self          = shift @_;
  my %options       = @_;
  my $cloned_object = $self->new();

  %{$cloned_object} = %{$self};
  $cloned_object->configure( %options );

  return $cloned_object;
}

# --------------------------------------
#        Usage: $iterator->configure( %options );
#      Purpose: To (re)set the initial key-values pairs of the iterator.
#      Returns: none
#   Parameters: A hash to initial key-value pairs.
# Side Effects: none
#       Throws: no exceptions
#     Comments: none
#     See Also: n/a
#
sub configure {
  my $self = shift @_;
  my %options = @_;

  for my $option ( keys %options ){
    croak "unknown option '$option'\n" unless exists $Default_Options{$option};
    $self->{$option} = $options{$option};
  }
}

# --------------------------------------
#        Usage: %options = $iterator->options( ; @options );
#      Purpose: To retrieve the current value(s) of the options.
#      Returns: %options -- option/value pairs.
#   Parameters: @options -- list of options
# Side Effects: none
#       Throws: no exceptions
#     Comments: none
#     See Also: n/a
#
sub options {
  my $self = shift @_;
  my @options = @_;
  my %options = ();

  if( @options ){
    for my $option ( @options ){
      $options{$option} = $self->{$option} if exists $Default_Options{$option};
    }
  }else{
    for my $option ( keys %Default_Options ){
      $options{$option} = $self->{$option};
    }
  }

  return %options;
}

# --------------------------------------
#        Usage: $value = $iterator->reset( ; $value, $inc );
#      Purpose: Rest the value and increment of the iterator.
#   Parameters: $value -- new starting value (optional)
#                 $inc -- new increment (optional)
# Side Effects: none
#       Throws: no exceptions
#     Comments: none
#     See Also: n/a
#
sub reset {
  my $self  = shift @_;

  if( @_ ){
    $self->configure( value => shift @_ );
    if( @_ ){
      $self->configure( inc => shift @_ );
    }
  }else{
    $self->configure( value => $self->{start} );
  }

  return $self->{value};
}

# --------------------------------------
#        Usage: $value = $iterator->next();
#      Purpose: Get the next value of the iterator.
#      Returns: $value -- the next value.
#   Parameters: none
# Side Effects: none
#       Throws: no exceptions
#     Comments: none
#     See Also: n/a
#
sub next {
  my $self  = shift @_;

  $self->{value} += $self->{inc};
  return $self->{value};
}

# --------------------------------------
#        Usage: $value = $iterator->same();
#      Purpose: Get the value of the iterator.
#      Returns: $value -- the value.
#   Parameters: none
# Side Effects: none
#       Throws: no exceptions
#     Comments: none
#     See Also: n/a
#
sub same {
  my $self  = shift @_;

  return $self->{value};
}

1;
__END__

=head1 NAME

Iterator - An iterator class.

=head1 VERSION

This document refers to Iterator, version 1.0.0

=head1 SYNOPSIS

  use Iterator;

  my $iter = new Iterator( start => 0 );
  while( <> ){
    printf 'line %03d: %s', $iter->next, $_;
  }

=head1 DESCRIPTION

Creates an iterator object.

=head2 Options

=over 4

=item start

The start value of the iterator.

=item value

The current value of the iterator.

=item inc

The amount the iterator increases.

=back

=head1 METHODS

=over 4

=item $iterator = new( ; %options )

Creates a new iterator object.
See L</Options> for details on the %options.

=item $cloned_iterator = $iterator->clone( ; %options )

Copies an iterator object.
See L</Options> for details on the %options.

=item $iterator->configure( %options )

Configures an iterator object.
See L</Options> for details on the %options.

=item %options = $iterator->options( ; @options )

Reutrns the options of an iterator object.
@options is a list of options to retrieve.
If empty, all options are retrieved.
See L</Options> for details on the %options.

=item $iterator->reset( ; $value, $increment )

Rest the iterator.
If $value is given, set its start to that value.
If $increment is given, set its increment to that value.
If no parmaters, reset it to its previous start value.

=item $value = $iterator->next()

Get the next value of the iterator.

=item $value = $iterator->same()

Get the current value of the iterator.

=back

=head1 ORIGINAL AUTHOR

Mr. Shawn H. Corey

=head2 Contributing Authors

(Insert your name here if you modified this program or its documentation.)

=head1 COPYRIGHT & LICENCES

Copyright 2007 by Mr. Shawn H. Corey.

=head2 Software Licence

This program 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, version 3 of the License, or
(at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

=head2 Document Licence

Permission is granted to copy, distribute and/or modify this document under the
terms of the GNU Free Documentation License, Version 1.2 or any later version
published by the Free Software Foundation; with the Invariant Sections being
ORIGINAL AUTHOR, COPYRIGHT & LICENCES, Software Licence, and Document Licence.

You should have received a copy of the GNU Free Documentation Licence
along with this document; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

=head1 ACKNOWLEDGEMENTS

=head1 HISTORY

  $Log$

=cut

