CPANPLUS-YACSmoke

 view release on metacpan or  search on metacpan

lib/CPANPLUS/YACSmoke/IniFiles.pm  view on Meta::CPAN

If an error occurs while parsing the INI file the @Config::IniFiles::errors
array will contain messages that might help you figure out where the 
problem is in the file.

=cut

# Auxillary function to make deep (aliasing-free) copies of data
# structures.  Ignores blessed objects in tree (could be taught not
# to, if needed)
sub _deepcopy {
  my $ref=shift;

  if (! ref($ref)) { return $ref; }

  local $_;

  if (UNIVERSAL::isa($ref, "ARRAY")) {
          return [map {_deepcopy($_)} @$ref];
  }

  if (UNIVERSAL::isa($ref, "HASH")) {
          my $return={};
          foreach my $k (keys %$ref) {
                  $return->{$k}=_deepcopy($ref->{$k});
          }
          return $return;
  }

  carp "Unhandled data structure in $ref, cannot _deepcopy()";
}

# Internal method, gets the next line, taking proper care of line endings.
sub _nextline {
	my ($self, $fh)=@_;
	local $_;
	if (!exists $self->{line_ends}) {
		# no $self->{line_ends} is a hint set by caller that we are at
		# the first line (kludge kludge).
		{
			local $/=\1;
			my $nextchar;
			do {
				$nextchar=<$fh>;
				return undef if (!defined $nextchar);
				$_ .= $nextchar;
			} until (m/((\015|\012|\025|\n)$)/s);
			$self->{line_ends}=$1;
			if ($nextchar eq "\x0d") {
				# peek at the next char
				$nextchar = <$fh>;
				if ($nextchar eq "\x0a") {
					$self->{line_ends} .= "\x0a";
				} else {
					seek $fh, -1, 1;
				}
			}
		}

		# If there's a UTF BOM (Byte-Order-Mark) in the first
		# character of the first line then remove it before processing
		# (http://www.unicode.org/unicode/faq/utf_bom.html#22)
		s/^//;

		return $_;
	} else {
		local $/=$self->{line_ends};
		return scalar <$fh>;
	}
}

# Internal method, closes or resets the file handle. To be called
# whenever ReadConfig() returns.
sub _rollback {
	my ($self, $fh)=@_;
  # Only close if this is a filename, if it's
  # an open handle, then just roll back to the start
  if( !ref($self->{cf}) ) {
    close($fh);
  } else {
    # Attempt to rollback to beginning, no problem if this fails (e.g. STDIN)
    seek( $fh, 0, 0 );
  } # end if
}


sub ReadConfig {
  my $self = shift;

  my($lineno, $sect);
  my($group, $groupmem);
  my($parm, $val);
  my @cmts;

  @CPANPLUS::YACSmoke::IniFiles::errors = ( );

  # Initialize (and clear out) storage hashes
  $self->{sects}  = [];
  $self->{parms}  = {};
  $self->{group}  = {};
  $self->{v}      = {};
  $self->{sCMT}   = {};
  $self->{pCMT}   = {};
  $self->{EOT}    = {};
  $self->{mysects} = []; # A pair of hashes to remember which params are loaded
  $self->{myparms} = {}; # or set using the API vs. imported - useful for
  # import shadowing, see below, and WriteConfig(-delta=>1)

  if( defined $self->{imported} ) {
      # Run up the import tree to the top, then reload coming
      # back down, maintaining the imported file names and our 
      # file name.
      # This is only needed on a re-load though
	  $self->{imported}->ReadConfig() unless ($self->{firstload});

	  foreach my $field (qw(sects parms group v sCMT pCMT EOT)) {
		  $self->{$field} = _deepcopy($self->{imported}->{$field});
	  }
  } # end if
  
  return 1 if (
    (not exists $self->{cf}) or



( run in 1.053 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )