Config-INI

 view release on metacpan or  search on metacpan

lib/Config/INI/Reader.pm  view on Meta::CPAN

#pod
#pod =head1 DESCRIPTION
#pod
#pod Config::INI::Reader is I<yet another> config module implementing I<yet another>
#pod slightly different take on the undeniably easy to read L<".ini" file
#pod format|Config::INI>.  Its default behavior is quite similar to that of
#pod L<Config::Tiny>, on which it is based.
#pod
#pod The chief difference is that Config::INI::Reader is designed to be subclassed
#pod to allow for side-effects and self-reconfiguration to occur during the course
#pod of reading its input.
#pod
#pod =cut

use Carp ();

our @CARP_NOT = qw(Mixin::Linewise::Readers);

#pod =head1 METHODS FOR READING CONFIG
#pod
#pod These methods are all that most users will need: they read configuration from a
#pod source of input, then they return the data extracted from that input.  There
#pod are three reader methods, C<read_string>, C<read_file>, and C<read_handle>.
#pod The first two are implemented in terms of the third.  It iterates over lines in
#pod a file, calling methods on the reader when events occur.  Those events are
#pod detailed below in the L</METHODS FOR SUBCLASSING> section.
#pod
#pod All of the reader methods return an unblessed reference to a hash.
#pod
#pod All throw an exception when they encounter an error.
#pod
#pod =head2 read_file
#pod
#pod   my $hash_ref = Config::INI::Reader->read_file($filename);
#pod
#pod Given a filename, this method returns a hashref of the contents of that file.
#pod
#pod =head2 read_string
#pod
#pod   my $hash_ref = Config::INI::Reader->read_string($string);
#pod
#pod Given a string, this method returns a hashref of the contents of that string.
#pod
#pod =head2 read_handle
#pod
#pod   my $hash_ref = Config::INI::Reader->read_handle($io_handle);
#pod
#pod Given an IO::Handle, this method returns a hashref of the contents of that
#pod handle.
#pod
#pod =cut

sub read_handle {
  my ($invocant, $handle) = @_;

  my $self = ref $invocant ? $invocant : $invocant->new;

  # parse the file
  LINE: while (my $line = $handle->getline) {
    if ($handle->input_line_number == 1 && $line =~ /\A\x{FEFF}/) {
      Carp::confess("input handle appears to start with a BOM");
    }

    $self->preprocess_line(\$line);

    next LINE if $self->can_ignore($line, $handle);

    # Handle section headers
    if (defined (my $name = $self->parse_section_header($line, $handle))) {
      # Create the sub-hash if it doesn't exist.
      # Without this sections without keys will not
      # appear at all in the completed struct.
      $self->change_section($name);
      next LINE;
    }

    if (my ($name, $value) = $self->parse_value_assignment($line, $handle)) {
      $self->set_value($name, $value);
      next LINE;
    }

    $self->handle_unparsed_line($line, $handle);
  }

  $self->finalize;

  return $self->{data};
}

#pod =head1 METHODS FOR SUBCLASSING
#pod
#pod These are the methods you need to understand and possibly change when
#pod subclassing Config::INI::Reader to handle a different format of input.
#pod
#pod =head2 current_section
#pod
#pod   my $section_name = $reader->current_section;
#pod
#pod This method returns the name of the current section.  If no section has yet
#pod been set, it returns the result of calling the C<starting_section> method.
#pod
#pod =cut

sub current_section {
  $_[0]->{section} // $_[0]->starting_section;
}

#pod =head2 parse_section_header
#pod
#pod   my $name = $reader->parse_section_header($line, $handle);
#pod
#pod Given a line of input, this method decides whether the line is a section-change
#pod declaration.  If it is, it returns the name of the section to which to change.
#pod If the line is not a section-change, the method returns false.
#pod
#pod =cut

sub parse_section_header {
  return $1 if $_[1] =~ /^\s*\[\s*(.+?)\s*\]\s*$/;
  return;
}



( run in 1.586 second using v1.01-cache-2.11-cpan-39bf76dae61 )