Config-INI-RefVars
view release on metacpan or search on metacpan
lib/Config/INI/RefVars.pm view on Meta::CPAN
$sect_vars->{$var_name} .= " "
. ($exp_flag ? $self->$_expand_value($curr_section, $value) : $value);
}
else {
$sect_vars->{$var_name} = $value;
}
}
elsif ($modifier eq '.') {
$sect_vars->{$var_name} = ($sect_vars->{$var_name} // "")
. ($exp_flag ? $self->$_expand_value($curr_section, $value) : $value);
}
elsif ($modifier eq ':') {
delete $expanded->{$x_var_name} if $exp_flag;
$sect_vars->{$var_name} = $self->$_expand_vars($curr_section, $var_name, $value, undef, 1);
}
elsif ($modifier eq '+>') {
if (exists($sect_vars->{$var_name})) {
$sect_vars->{$var_name} =
($exp_flag ? $self->$_expand_value($curr_section, $value) : $value)
. ' ' . $sect_vars->{$var_name};
}
else {
$sect_vars->{$var_name} = $value;
}
}
elsif ($modifier eq '.>') {
$sect_vars->{$var_name} = ($exp_flag ? $self->$_expand_value($curr_section, $value) : $value)
. ($sect_vars->{$var_name} // "");
}
else {
$_fatal->("'$modifier': unsupported modifier");
}
}
return ($tocopy_sec_declared, $curr_section);
};
sub parse_ini {
my $self = shift;
my %args = (cleanup => 1, @_);
state $allowed_keys = {
map { $_ => undef } qw(cleanup src src_name tocopy_section tocopy_vars not_tocopy)
};
state $dflt_src_name = "INI data";
_check_args(\%args, $allowed_keys);
foreach my $scalar_arg (qw(tocopy_section src_name)) {
croak("'$scalar_arg': must not be a reference") if ref($args{$scalar_arg});
}
delete $self->{+SRC_NAME} if exists($self->{+SRC_NAME});
$self->{+SRC_NAME} = $args{src_name} if exists($args{src_name});
my ($cleanup, $src, $tocopy_section, $tocopy_vars, $not_tocopy)
= @args{qw(cleanup src tocopy_section tocopy_vars not_tocopy)};
croak("'src': missing mandatory argument") if !defined($src);
my $backup = $self->{+BACKUP} //= {};
if (defined($tocopy_section)) {
$backup->{tocopy_section} = $self->{+TOCOPY_SECTION};
$self->{+TOCOPY_SECTION} = $tocopy_section;
}
else {
$tocopy_section = $self->{+TOCOPY_SECTION};
}
$self->{+CURR_TOCP_SECTION} = $tocopy_section;
$Globals{'=TO_CP_SEC'} = $tocopy_section;
if ($tocopy_vars) {
$backup->{tocopy_vars} = $self->{+TOCOPY_VARS};
$self->$_check_tocopy_vars($tocopy_vars, 1);
}
if ($not_tocopy) {
$backup->{not_tocopy} = $self->{+NOT_TOCOPY};
$self->$_check_not_tocopy($not_tocopy, 1);
}
$self->{+SECTIONS} = [];
$self->{+SECTIONS_H} = {};
$self->{+EXPANDED} = {};
$self->{+VARIABLES} = {
$tocopy_section => ($self->{+TOCOPY_VARS} ? {%{$self->{+TOCOPY_VARS}}} : {})
};
$self->{+FUNCTIONS} = {};
my $global_vars = $self->{+GLOBAL_VARS} = {%Globals};
my $variables = $self->{+VARIABLES};
my $tocopy_sec_vars = $variables->{$tocopy_section};
if (my $ref_src = ref($src)) {
$self->{+SRC_NAME} = $dflt_src_name if !exists($self->{+SRC_NAME});
if ($ref_src eq 'ARRAY') {
$src = [@$src];
foreach my $entry (@$src) {
croak("'src': unexpected ref type in array") if ref($entry);
if (!defined($entry)) {
carp("'src': undef entry - treated as empty string");
$entry = "";
}
}
}
else {
croak("'src': $ref_src: ref type not allowed");
}
}
else {
if (index($src, "\n") < 0) {
my $path = $src;
my $abs_path = abs_path($path) or croak("'$path': cannot resolve file name");
$src = $_read_ini_file->($abs_path);
$self->{+SRC_NAME} = $path if !exists($self->{+SRC_NAME});
my ($vol, $dirs, $file) = splitpath($abs_path);
@{$global_vars}{'=INIfile', '=INIdir'} = ($file,
catdir(length($vol // "") ? $vol : (), $dirs),
);
}
else {
$src = [split(/\n/, $src)];
$self->{+SRC_NAME} = $dflt_src_name if !exists($self->{+SRC_NAME});
}
}
$global_vars->{'=srcname'} = $self->{+SRC_NAME};
my $src_dir = '.';
my $include_stack = {};
if (!ref($args{src}) && index($args{src}, "\n") < 0) {
my $abs_path = abs_path($args{src})
or croak("'$args{src}': cannot resolve file name");
$include_stack->{$abs_path} = undef;
my ($vol, $dirs) = splitpath($abs_path);
$src_dir = catdir(length($vol // "") ? $vol : (), $dirs);
}
my ($tocopy_sec_declared, undef) = $self->$_parse_ini($src,
undef,
$include_stack,
$src_dir,
$self->{+SRC_NAME},
);
my @sections = ((exists($self->{+SECTIONS_H}{$tocopy_section}) ? () : $tocopy_section),
@{$self->{+SECTIONS}},
);
foreach my $section (@sections) {
my $sec_vars = $variables->{$section};
foreach my $variable (keys(%$sec_vars)) {
my $value = $sec_vars->{$variable};
$sec_vars->{$variable} = $self->$_expand_vars($section, $variable, $value);
}
}
if ($cleanup) {
foreach my $section (keys(%$variables)) {
my $sec_vars = $variables->{$section};
foreach my $var (keys(%$sec_vars)) {
delete $sec_vars->{$var} if index($var, '=') >= 0;
}
}
delete $variables->{$self->{+TOCOPY_SECTION}} if (!$tocopy_sec_declared && !%$tocopy_sec_vars);
}
else {
if ($self->{+GLOBAL_MODE}) {
foreach my $section (keys(%$variables)) {
my $sec_vars = $variables->{$section};
$sec_vars->{'='} = $section;
}
@{$tocopy_sec_vars}{keys(%$global_vars)} = values(%$global_vars);
}
else {
foreach my $section (keys(%$variables)) {
my $sec_vars = $variables->{$section};
$sec_vars->{'='} = $section;
@{$sec_vars}{keys(%$global_vars)} = values(%$global_vars);
}
}
}
$self->{+TOCOPY_SECTION} = $backup->{tocopy_section} if exists($backup->{tocopy_section});
$self->{+TOCOPY_VARS} = $backup->{tocopy_vars} if exists($backup->{tocopy_vars});
$self->{+NOT_TOCOPY} = $backup->{not_tocopy} if exists($backup->{not_tocopy});
$backup = {};
return $self;
}
sub current_tocopy_section { $_[0]->{+CURR_TOCP_SECTION} }
sub tocopy_section { $_[0]->{+TOCOPY_SECTION} }
sub global_mode { $_[0]->{+GLOBAL_MODE} }
sub sections {
return defined($_[0]->{+SECTIONS}) ? [@{$_[0]->{+SECTIONS}}] : undef;
}
sub sections_h {
return defined($_[0]->{+SECTIONS_H}) ? +{ %{$_[0]->{+SECTIONS_H}} } : undef;
}
sub separator { $_[0]->{+SEPARATOR} }
sub src_name { $_[0]->{+SRC_NAME} }
sub variables {
my $vars = $_[0]->{+VARIABLES} // return undef;
return { map { $_ => {%{$vars->{$_}}} } keys(%$vars) };
}
$_look_up = sub {
my ($self, $curr_sect, $variable) = @_;
my $matched = $variable =~ $self->{+VREF_RE};
my ($v_section, $v_basename) = $matched ? ($1, $2) : ($curr_sect, $variable);
my $v_value;
my $variables = $self->{+VARIABLES};
my $tocopy_section = $self->{+TOCOPY_SECTION};
if (!exists($variables->{$v_section})) {
$v_value = "";
}
elsif (exists($variables->{$v_section}{$v_basename})) {
$v_value = $variables->{$v_section}{$v_basename};
}
elsif ($v_basename !~ /\S/) {
$v_value = $v_basename;
}
elsif ($v_basename eq '=') {
$v_value = $v_section;
}
elsif ($v_basename =~ /^=(?:ENV|env):\s*(.*)$/) {
$v_value = $ENV{$1} // "";
}
elsif ($v_basename =~ /^=CONFIG:\s*(.*)$/) {
$v_value = $Config{$1} // "";
}
elsif (exists($self->{+GLOBAL_VARS}{$v_basename})) {
$v_value = $self->{+GLOBAL_VARS}{$v_basename};
}
elsif ($self->{+GLOBAL_MODE} && exists($variables->{$tocopy_section}{$v_basename})) {
if (!$matched
&& $curr_sect ne $tocopy_section
&& exists($self->{+NOT_TOCOPY}{$v_basename})
) {
( run in 2.367 seconds using v1.01-cache-2.11-cpan-aadc1410aed )