Data-Section
view release on metacpan or search on metacpan
lib/Data/Section.pm view on Meta::CPAN
#pod
#pod =cut
sub _mk_reader_group {
my ($mixin, $name, $arg, $col) = @_;
my $base = $col->{INIT}{into};
my $default_header_re = qr/
\A # start
_+\[ # __[
\s* # any whitespace
([^\]]+?) # this is the actual name of the section
\s* # any whitespace
\]_+ # ]__
[\x0d\x0a]{1,2} # possible cariage return for windows files
\z # end
/x;
my $header_re = $arg->{header_re} || $default_header_re;
$arg->{inherit} = 1 unless exists $arg->{inherit};
my $default_encoding = defined $arg->{encoding} ? $arg->{encoding} : 'UTF-8';
my %export;
my %stash = ();
$export{local_section_data} = sub {
my ($self) = @_;
my $pkg = ref $self ? ref $self : $self;
return $stash{ $pkg } if $stash{ $pkg };
my $template = $stash{ $pkg } = { };
my $dh = do { no strict 'refs'; \*{"$pkg\::DATA"} }; ## no critic Strict
return $stash{ $pkg } unless defined fileno *$dh;
binmode( $dh, ":raw :bytes" );
my ($current, $current_line);
if ($arg->{default_name}) {
$current = $arg->{default_name};
$template->{ $current } = \(my $blank = q{});
}
LINE: while (my $line = <$dh>) {
if ($line =~ $header_re) {
$current = $1;
$current_line = 0;
$template->{ $current } = \(my $blank = q{});
next LINE;
}
last LINE if $line =~ /^__END__/;
next LINE if !defined $current and $line =~ /^\s*$/;
Carp::confess("bogus data section: text outside of named section")
unless defined $current;
$current_line++;
unless ($default_encoding eq 'bytes') {
my $decoded_line = eval { decode($default_encoding, $line, Encode::FB_CROAK) }
or warn "Invalid character encoding in $current, line $current_line\n";
$line = $decoded_line if defined $decoded_line;
}
$line =~ s/\A\\//;
${$template->{$current}} .= $line;
}
return $stash{ $pkg };
};
$export{local_section_data_names} = sub {
my ($self) = @_;
my $method = $export{local_section_data};
return keys %{ $self->$method };
};
$export{merged_section_data} =
!$arg->{inherit} ? $export{local_section_data} : sub {
my ($self) = @_;
my $pkg = ref $self ? ref $self : $self;
my $lsd = $export{local_section_data};
my %merged;
for my $class (@{ mro::get_linear_isa($pkg) }) {
# in case of c3 + non-$base item showing up
next unless $class->isa($base);
my $sec_data = $class->$lsd;
# checking for truth is okay, since things must be undef or a ref
# -- rjbs, 2008-06-06
$merged{ $_ } ||= $sec_data->{$_} for keys %$sec_data;
}
return \%merged;
};
$export{merged_section_data_names} = sub {
my ($self) = @_;
my $method = $export{merged_section_data};
return keys %{ $self->$method };
};
$export{section_data} = sub {
my ($self, $name) = @_;
my $pkg = ref $self ? ref $self : $self;
my $prefix = $arg->{inherit} ? 'merged' : 'local';
my $method = "$prefix\_section_data";
my $data = $self->$method;
return $data->{ $name };
};
$export{section_data_names} = sub {
my ($self) = @_;
my $prefix = $arg->{inherit} ? 'merged' : 'local';
my $method = "$prefix\_section_data_names";
( run in 2.056 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )