File Coverage

blib/lib/Data/Section.pm
Criterion Covered Total %
statement 93 93 100.0
branch 31 38 81.5
condition 6 9 66.6
subroutine 13 13 100.0
pod n/a
total 143 153 93.4


line stmt bran cond sub pod time code
1 2     2   71490 use strict;
  2         14  
  2         45  
2 2     2   9 use warnings;
  2         3  
  2         79  
3             package Data::Section 0.200008;
4             # ABSTRACT: read multiple hunks of data out of your DATA section
5              
6 2     2   545 use Encode qw/decode/;
  2         8526  
  2         115  
7 2     2   724 use MRO::Compat 0.09;
  2         2837  
  2         119  
8             use Sub::Exporter 0.979 -setup => {
9             groups => { setup => \'_mk_reader_group' },
10 11         10858 collectors => { INIT => sub { $_[0] = { into => $_[1]->{into} } } },
11 2     2   1016 };
  2         21091  
  2         18  
12              
13             #pod =head1 SYNOPSIS
14             #pod
15             #pod package Letter::Resignation;
16             #pod use Data::Section -setup;
17             #pod
18             #pod sub quit {
19             #pod my ($class, $angry, %arg) = @_;
20             #pod
21             #pod my $template = $class->section_data(
22             #pod ($angry ? "angry_" : "professional_") . "letter"
23             #pod );
24             #pod
25             #pod return fill_in($$template, \%arg);
26             #pod }
27             #pod
28             #pod __DATA__
29             #pod __[ angry_letter ]__
30             #pod Dear jerks,
31             #pod
32             #pod I quit!
33             #pod
34             #pod --
35             #pod {{ $name }}
36             #pod __[ professional_letter ]__
37             #pod Dear {{ $boss }},
38             #pod
39             #pod I quit, jerks!
40             #pod
41             #pod
42             #pod --
43             #pod {{ $name }}
44             #pod
45             #pod =head1 DESCRIPTION
46             #pod
47             #pod Data::Section provides an easy way to access multiple named chunks of
48             #pod line-oriented data in your module's DATA section. It was written to allow
49             #pod modules to store their own templates, but probably has other uses.
50             #pod
51             #pod =head1 WARNING
52             #pod
53             #pod You will need to use C<__DATA__> sections and not C<__END__> sections. Yes, it
54             #pod matters. Who knew!
55             #pod
56             #pod =head1 EXPORTS
57             #pod
58             #pod To get the methods exported by Data::Section, you must import like this:
59             #pod
60             #pod use Data::Section -setup;
61             #pod
62             #pod Optional arguments may be given to Data::Section like this:
63             #pod
64             #pod use Data::Section -setup => { ... };
65             #pod
66             #pod Valid arguments are:
67             #pod
68             #pod encoding - if given, gives the encoding needed to decode bytes in
69             #pod data sections; default; UTF-8
70             #pod
71             #pod the special value "bytes" will leave the bytes in the string
72             #pod verbatim
73             #pod
74             #pod inherit - if true, allow packages to inherit the data of the packages
75             #pod from which they inherit; default: true
76             #pod
77             #pod header_re - if given, changes the regex used to find section headers
78             #pod in the data section; it should leave the section name in $1
79             #pod
80             #pod default_name - if given, allows the first section to has no header and set
81             #pod its name
82             #pod
83             #pod Three methods are exported by Data::Section:
84             #pod
85             #pod =head2 section_data
86             #pod
87             #pod my $string_ref = $pkg->section_data($name);
88             #pod
89             #pod This method returns a reference to a string containing the data from the name
90             #pod section, either in the invocant's C section or in that of one of its
91             #pod ancestors. (The ancestor must also derive from the class that imported
92             #pod Data::Section.)
93             #pod
94             #pod By default, named sections are delimited by lines that look like this:
95             #pod
96             #pod __[ name ]__
97             #pod
98             #pod You can use as many underscores as you want, and the space around the name is
99             #pod optional. This pattern can be configured with the C option (see
100             #pod above). If present, a single leading C<\> is removed, so that sections can
101             #pod encode lines that look like section delimiters.
102             #pod
103             #pod When a line containing only C<__END__> is reached, all processing of sections
104             #pod ends.
105             #pod
106             #pod =head2 section_data_names
107             #pod
108             #pod my @names = $pkg->section_data_names;
109             #pod
110             #pod This returns a list of all the names that will be recognized by the
111             #pod C method.
112             #pod
113             #pod =head2 merged_section_data
114             #pod
115             #pod my $data = $pkg->merged_section_data;
116             #pod
117             #pod This method returns a hashref containing all the data extracted from the
118             #pod package data for all the classes from which the invocant inherits -- as long as
119             #pod those classes also inherit from the package into which Data::Section was
120             #pod imported.
121             #pod
122             #pod In other words, given this inheritance tree:
123             #pod
124             #pod A
125             #pod \
126             #pod B C
127             #pod \ /
128             #pod D
129             #pod
130             #pod ...if Data::Section was imported by A, then when D's C is
131             #pod invoked, C's data section will not be considered. (This prevents the read
132             #pod position of C's data handle from being altered unexpectedly.)
133             #pod
134             #pod The keys in the returned hashref are the section names, and the values are
135             #pod B the strings extracted from the data sections.
136             #pod
137             #pod =head2 merged_section_data_names
138             #pod
139             #pod my @names = $pkg->merged_section_data_names;
140             #pod
141             #pod This returns a list of all the names that will be recognized by the
142             #pod C method.
143             #pod
144             #pod =head2 local_section_data
145             #pod
146             #pod my $data = $pkg->local_section_data;
147             #pod
148             #pod This method returns a hashref containing all the data extracted from the
149             #pod package on which the method was invoked. If called on an object, it will
150             #pod operate on the package into which the object was blessed.
151             #pod
152             #pod This method needs to be used carefully, because it's weird. It returns only
153             #pod the data for the package on which it was invoked. If the package on which it
154             #pod was invoked has no data sections, it returns an empty hashref.
155             #pod
156             #pod =head2 local_section_data_names
157             #pod
158             #pod my @names = $pkg->local_section_data_names;
159             #pod
160             #pod This returns a list of all the names that will be recognized by the
161             #pod C method.
162             #pod
163             #pod =cut
164              
165             sub _mk_reader_group {
166 11     11   570 my ($mixin, $name, $arg, $col) = @_;
167 11         19 my $base = $col->{INIT}{into};
168              
169 11         32 my $default_header_re = qr/
170             \A # start
171             _+\[ # __[
172             \s* # any whitespace
173             ([^\]]+?) # this is the actual name of the section
174             \s* # any whitespace
175             \]_+ # ]__
176             [\x0d\x0a]{1,2} # possible cariage return for windows files
177             \z # end
178             /x;
179              
180 11   66     41 my $header_re = $arg->{header_re} || $default_header_re;
181 11 100       30 $arg->{inherit} = 1 unless exists $arg->{inherit};
182              
183 11 100       25 my $default_encoding = defined $arg->{encoding} ? $arg->{encoding} : 'UTF-8';
184              
185 11         11 my %export;
186 11         14 my %stash = ();
187              
188             $export{local_section_data} = sub {
189 47     47   8002 my ($self) = @_;
190              
191 47 50       84 my $pkg = ref $self ? ref $self : $self;
192              
193 47 100       167 return $stash{ $pkg } if $stash{ $pkg };
194              
195 15         31 my $template = $stash{ $pkg } = { };
196              
197 2     2   1074 my $dh = do { no strict 'refs'; \*{"$pkg\::DATA"} }; ## no critic Strict
  2         4  
  2         1389  
  15         16  
  15         19  
  15         46  
198 15 100       47 return $stash{ $pkg } unless defined fileno *$dh;
199 14         154 binmode( $dh, ":raw :bytes" );
200              
201 14         26 my ($current, $current_line);
202 14 100       35 if ($arg->{default_name}) {
203 1         4 $current = $arg->{default_name};
204 1         2 $template->{ $current } = \(my $blank = q{});
205             }
206 14         140 LINE: while (my $line = <$dh>) {
207 57 100       259 if ($line =~ $header_re) {
208 27         61 $current = $1;
209 27         34 $current_line = 0;
210 27         54 $template->{ $current } = \(my $blank = q{});
211 27         89 next LINE;
212             }
213              
214 30 100       49 last LINE if $line =~ /^__END__/;
215 29 100 66     72 next LINE if !defined $current and $line =~ /^\s*$/;
216              
217 26 50       37 Carp::confess("bogus data section: text outside of named section")
218             unless defined $current;
219              
220 26         29 $current_line++;
221 26 50       47 unless ($default_encoding eq 'bytes') {
222 26 50       31 my $decoded_line = eval { decode($default_encoding, $line, Encode::FB_CROAK) }
  26         65  
223             or warn "Invalid character encoding in $current, line $current_line\n";
224 26 50       1820 $line = $decoded_line if defined $decoded_line;
225             }
226 26         79 $line =~ s/\A\\//;
227              
228 26         27 ${$template->{$current}} .= $line;
  26         171  
229             }
230              
231 14         85 return $stash{ $pkg };
232 11         41 };
233              
234             $export{local_section_data_names} = sub {
235 6     6   14 my ($self) = @_;
236 6         8 my $method = $export{local_section_data};
237 6         6 return keys %{ $self->$method };
  6         12  
238 11         32 };
239              
240             $export{merged_section_data} =
241             !$arg->{inherit} ? $export{local_section_data} : sub {
242              
243 12     12   19 my ($self) = @_;
244 12 50       22 my $pkg = ref $self ? ref $self : $self;
245              
246 12         18 my $lsd = $export{local_section_data};
247              
248 12         14 my %merged;
249 12         13 for my $class (@{ mro::get_linear_isa($pkg) }) {
  12         43  
250             # in case of c3 + non-$base item showing up
251 25 100       89 next unless $class->isa($base);
252 20         28 my $sec_data = $class->$lsd;
253              
254             # checking for truth is okay, since things must be undef or a ref
255             # -- rjbs, 2008-06-06
256 20   66     120 $merged{ $_ } ||= $sec_data->{$_} for keys %$sec_data;
257             }
258              
259 12         57 return \%merged;
260 11 100       44 };
261              
262             $export{merged_section_data_names} = sub {
263 6     6   12 my ($self) = @_;
264 6         8 my $method = $export{merged_section_data};
265 6         7 return keys %{ $self->$method };
  6         12  
266 11         27 };
267              
268             $export{section_data} = sub {
269 11     11   2136 my ($self, $name) = @_;
270 11 50       24 my $pkg = ref $self ? ref $self : $self;
271              
272 11 100       27 my $prefix = $arg->{inherit} ? 'merged' : 'local';
273 11         22 my $method = "$prefix\_section_data";
274              
275 11         31 my $data = $self->$method;
276              
277 11         44 return $data->{ $name };
278 11         47 };
279              
280             $export{section_data_names} = sub {
281 4     4   10 my ($self) = @_;
282              
283 4 100       12 my $prefix = $arg->{inherit} ? 'merged' : 'local';
284 4         9 my $method = "$prefix\_section_data_names";
285 4         13 return $self->$method;
286 11         27 };
287              
288 11         30 return \%export;
289             }
290              
291             #pod =head1 TIPS AND TRICKS
292             #pod
293             #pod =head2 MooseX::Declare and namespace::autoclean
294             #pod
295             #pod The L library automatically cleans
296             #pod foreign routines from a class, including those imported by Data::Section.
297             #pod
298             #pod L does the same thing, and can also cause your
299             #pod C<__DATA__> section to appear outside your class's package.
300             #pod
301             #pod These are easy to address. The
302             #pod L library provides an
303             #pod installer that will cause installed methods to appear to come from the class
304             #pod and avoid autocleaning. Using an explicit C statement will keep the
305             #pod data section in the correct package.
306             #pod
307             #pod package Foo;
308             #pod
309             #pod use MooseX::Declare;
310             #pod class Foo {
311             #pod
312             #pod # Utility to tell Sub::Exporter modules to export methods.
313             #pod use Sub::Exporter::ForMethods qw( method_installer );
314             #pod
315             #pod # method_installer returns a sub.
316             #pod use Data::Section { installer => method_installer }, -setup;
317             #pod
318             #pod method my_method {
319             #pod my $content_ref = $self->section_data('SectionA');
320             #pod
321             #pod print $$content_ref;
322             #pod }
323             #pod }
324             #pod
325             #pod __DATA__
326             #pod __[ SectionA ]__
327             #pod Hello, world.
328             #pod
329             #pod =head1 SEE ALSO
330             #pod
331             #pod =begin :list
332             #pod
333             #pod * L
334             #pod
335             #pod * L does something that is at first look similar,
336             #pod but it works with source filters, and contains the warning:
337             #pod
338             #pod It is possible that this module may overwrite the source code in files that
339             #pod use it. To protect yourself against this possibility, you are strongly
340             #pod advised to use the -backup option described in "Safety first".
341             #pod
342             #pod Enough said.
343             #pod
344             #pod =end :list
345             #pod
346             #pod =cut
347              
348             1;
349              
350             __END__