File Coverage

blib/lib/Data/Section/Seekable/Reader.pm
Criterion Covered Total %
statement 52 52 100.0
branch 15 16 93.7
condition 2 2 100.0
subroutine 8 8 100.0
pod 4 4 100.0
total 81 82 98.7


line stmt bran cond sub pod time code
1             package Data::Section::Seekable::Reader;
2              
3             our $DATE = '2016-02-19'; # DATE
4             our $VERSION = '0.09'; # VERSION
5              
6 2     2   76927 use 5.010001;
  2         4  
7 2     2   6 use strict;
  2         3  
  2         29  
8 2     2   5 use warnings;
  2         3  
  2         53  
9              
10             sub new {
11 2     2   6 no strict 'refs';
  2         2  
  2         739  
12              
13 10     10 1 6513 my $class = shift;
14              
15 10         37 my $caller = caller;
16 10         212 my $self = bless {@_}, $class;
17              
18 10   100     34 $self->{handle} //= \*{"$caller\::DATA"};
  1         6  
19              
20             {
21 10         10 my $fh = $self->{handle};
  10         12  
22              
23             # BEGIN_BLOCK: read_dss_toc
24              
25 10         10 my $header_line;
26             my $header_found;
27 10         8 while (1) {
28 14         63 my $header_line = <$fh>;
29 14 100       94 defined($header_line)
30             or die "Unexpected end of data section while reading header line";
31 12         13 chomp($header_line);
32 12 100       21 if ($header_line eq 'Data::Section::Seekable v1') {
33 8         8 $header_found++;
34 8         9 last;
35             }
36             }
37 8 50       14 die "Can't find header 'Data::Section::Seekable v1'"
38             unless $header_found;
39              
40 8         9 my %toc;
41 8         8 my $i = 0;
42 8         5 while (1) {
43 15         10 $i++;
44 15         20 my $toc_line = <$fh>;
45 15 100       103 defined($toc_line)
46             or die "Unexpected end of data section while reading TOC line #$i";
47 13         12 chomp($toc_line);
48 13 100       33 $toc_line =~ /\S/ or last;
49 8 100       45 $toc_line =~ /^([^,]+),(\d+),(\d+)(?:,(.*))?$/
50             or die "Invalid TOC line #$i in data section: $toc_line";
51 7         36 $toc{$1} = [$2, $3, $4];
52             }
53 5         21 my $pos = tell $fh;
54 5         27 $toc{$_}[0] += $pos for keys %toc;
55              
56             # END_BLOCK: read_dss_toc
57              
58 5         8 $self->{_toc} = \%toc;
59             }
60              
61 5         10 $self;
62             }
63              
64             sub parts {
65 3     3 1 8 my $self = shift;
66 3         4 sort keys %{$self->{_toc}};
  3         21  
67             }
68              
69             sub read_part {
70 7     7 1 42 my ($self, $name) = @_;
71              
72 7 100       28 defined($self->{_toc}{$name})
73             or die "Unknown part '$name'";
74              
75 6         21 seek $self->{handle}, $self->{_toc}{$name}[0], 0;
76 6         61 read $self->{handle}, my($content), $self->{_toc}{$name}[1];
77              
78 6         46 $content;
79             }
80              
81             sub read_extra {
82 3     3 1 20 my ($self, $name) = @_;
83              
84 3 100       18 defined($self->{_toc}{$name})
85             or die "Unknown part '$name'";
86              
87 2         7 $self->{_toc}{$name}[2];
88             }
89              
90             1;
91             # ABSTRACT: Read parts from data section
92              
93             __END__
94              
95             =pod
96              
97             =encoding UTF-8
98              
99             =head1 NAME
100              
101             Data::Section::Seekable::Reader - Read parts from data section
102              
103             =head1 VERSION
104              
105             This document describes version 0.09 of Data::Section::Seekable::Reader (from Perl distribution Data-Section-Seekable), released on 2016-02-19.
106              
107             =head1 SYNOPSIS
108              
109             In your script:
110              
111             use Data::Section::Seekable::Reader;
112              
113             my $reader = Data::Section::Seekable::Reader->new;
114              
115             my $p2 = $reader->read_part('part2'); # -> "This is part\ntwo\n"
116             my $p1 = $reader->read_part('part1'); # -> "This is part1\n"
117             my $p3 = $reader->read_part('part3'); # dies, unknown part
118              
119             my $e1 = $reader->read_extra('part1'); # -> undef
120             my $e2 = $reader->read_extra('part2'); # -> "important"
121             my $e3 = $reader->read_extra('part3'); # dies, unknown part
122              
123             __DATA__
124             Data::Section::Seekable v1
125             part1,0,14
126             part2,14,17,important
127              
128             This is part1
129             This is part
130             two
131              
132             =head1 DESCRIPTION
133              
134             This class lets you read parts from __DATA__ section. Data section should
135             contain data in the format described by L<Data::Section::Seekable>.
136              
137             =head1 METHODS
138              
139             =head2 new(%attrs) => obj
140              
141             Constructor. Attributes:
142              
143             =over
144              
145             =item * handle => filehandle (default: C<DATA>)
146              
147             To access another package's data section, you can do:
148              
149             my $reader = Data::Section::Seekable::Reader->new(handle => \*Another::Package::DATA);
150              
151             =back
152              
153             The constructor will also read the header and TOC in the data section. Will die
154             on failure.
155              
156             =head2 $reader->parts($name) => list
157              
158             Return list of all known parts in the data section, sorted lexicographically.
159              
160             =head2 $reader->read_part($name) => str
161              
162             Read the content of a part named C<$name>. Will die if part is unknown.
163              
164             =head2 $reader->read_extra($name) => str
165              
166             Read the extra information field (the fourth field of TOC line) of a part named
167             C<$name>. Will die if part is unknown.
168              
169             =head1 HOMEPAGE
170              
171             Please visit the project's homepage at L<https://metacpan.org/release/Data-Section-Seekable>.
172              
173             =head1 SOURCE
174              
175             Source repository is at L<https://github.com/perlancar/perl-Data-Section-Seekable>.
176              
177             =head1 BUGS
178              
179             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-Section-Seekable>
180              
181             When submitting a bug or request, please include a test-file or a
182             patch to an existing test-file that illustrates the bug or desired
183             feature.
184              
185             =head1 SEE ALSO
186              
187             L<Data::Section::Seekable> for the description of the data format.
188              
189             L<Data::Section::Seekable::Writer> to generate the data section.
190              
191             =head1 AUTHOR
192              
193             perlancar <perlancar@cpan.org>
194              
195             =head1 COPYRIGHT AND LICENSE
196              
197             This software is copyright (c) 2016 by perlancar@cpan.org.
198              
199             This is free software; you can redistribute it and/or modify it under
200             the same terms as the Perl 5 programming language system itself.
201              
202             =cut