File Coverage

blib/lib/Data/Embed.pm
Criterion Covered Total %
statement 62 84 73.8
branch 20 32 62.5
condition 14 23 60.8
subroutine 12 14 85.7
pod 6 6 100.0
total 114 159 71.7


line stmt bran cond sub pod time code
1             package Data::Embed;
2              
3 9     9   141223 use strict;
  9         10  
  9         197  
4 9     9   27 use warnings;
  9         8  
  9         172  
5 9     9   3637 use English qw< -no_match_vars >;
  9         23008  
  9         37  
6 9     9   2360 use Exporter qw< import >;
  9         9  
  9         340  
7             { our $VERSION = '0.32'; }
8 9     9   4616 use Log::Log4perl::Tiny qw< :easy :dead_if_first >;
  9         45735  
  9         27  
9 9     9   1817 use Scalar::Util qw< blessed >;
  9         9  
  9         6120  
10              
11             our @EXPORT_OK =
12             qw< writer reader embed embedded generate_module_from_file reassemble >;
13             our @EXPORT = ();
14             our %EXPORT_TAGS = (
15             all => \@EXPORT_OK,
16             reading => [qw< reader embedded >],
17             writing => [qw< writer embed generate_module_from_file reassemble >],
18             );
19              
20             sub writer {
21 62     62 1 26024 require Data::Embed::Writer;
22 62         335 return Data::Embed::Writer->new(@_);
23             }
24              
25             sub reader {
26 10     10 1 1812 require Data::Embed::Reader;
27 10         88 return Data::Embed::Reader->new(@_);
28             }
29              
30             sub embed {
31 2 50 33 2 1 380 my %args = (@_ && ref($_[0])) ? %{$_[0]} : @_;
  0         0  
32              
33             my %constructor_args =
34 2         5 map { $_ => delete $args{$_} } qw< input output >;
  4         10  
35             $constructor_args{input} = $constructor_args{output} =
36             delete $args{container}
37 2 100       7 if exists $args{container};
38 2 50       8 my $writer = writer(%constructor_args)
39             or LOGCROAK 'could not get the writer object';
40              
41 2         7 return $writer->add(%args);
42             } ## end sub embed
43              
44             sub embedded {
45 1 50   1 1 1071 my $reader = reader(shift)
46             or LOGCROAK 'could not get the writer object';
47 1         3 return $reader->files();
48             }
49              
50             sub generate_module_from_file {
51 0     0 1 0 require Data::Embed::OneFileAsModule;
52 0         0 goto &Data::Embed::OneFileAsModule::generate_module_from_file;
53             }
54              
55             sub __compare_and_shift {
56 6     6   7 my ($l1, $l2) = @_;
57 6   100     16 while (scalar(@$l1) && scalar(@$l2)) {
58 4 50       11 last unless $l1->[0]->is_same_as($l2->[0]);
59 0         0 shift @$l1;
60 0         0 shift @$l2;
61             }
62 6         10 return ($l1, $l2);
63             } ## end sub __compare_and_shift
64              
65             sub __temporary_for {
66 0     0   0 my ($target, $previous) = @_;
67 0         0 require File::Temp;
68 0         0 require File::Basename;
69              
70 0         0 my $dir = File::Basename::dirname $target;
71 0         0 my $template = File::Basename::basename($target) . '.tmp-XXXXXXX';
72 0         0 my ($fh, $filename) = File::Temp::tempfile($template, DIR => $dir);
73 0         0 binmode $fh, ':raw';
74              
75 0         0 my $prefix = $previous->prefix();
76 0 0       0 if ($prefix->{length}) {
77 0         0 require Data::Embed::Util;
78 0         0 Data::Embed::Util::transfer($prefix->fh(), $fh);
79             }
80              
81 0         0 close $fh;
82              
83 0         0 return $filename;
84             } ## end sub __temporary_for
85              
86             sub reassemble {
87 7 50 33 7 1 1762 my %args = (@_ && ref($_[0])) ? %{$_[0]} : @_;
  0         0  
88              
89 7         8 my $target = $args{target};
90 7         5 my $interim_target;
91 7 50       6 my @sequence = @{$args{sequence} || []};
  7         16  
92              
93 7         4 my $writer;
94 7 100 66     20 if (ref($target) eq 'SCALAR' || (-e $target)) {
95 6         10 my $previous = reader($target);
96              
97 6         9 my ($rprevious, $rsequence) =
98             __compare_and_shift([$previous->files()], [@sequence]);
99              
100             # is it a nop?
101 6         6 my $nprevious = scalar @$rprevious;
102 6         3 my $nsequence = scalar @$rsequence;
103 6 50 66     15 return unless $nprevious || $nsequence;
104              
105             # if there's a residual in both, use a temporary something
106 6 100 66     25 if (
    50 66        
107             ($nprevious && $nsequence) # this is the real condition
108             || $nprevious # FIXME move into its own, see next condition...
109             )
110             {
111 4 50       5 if (ref $target) { # pointer to scalar... hopefully!
112 4         8 $interim_target = $previous->prefix()->contents();
113 4         9 $writer = writer(
114             input => \$interim_target,
115             output => \$interim_target,
116             );
117             } ## end if (ref $target)
118             else {
119 0         0 $interim_target = __temporary_for($target, $previous);
120 0         0 $writer = writer(
121             input => $interim_target,
122             output => $interim_target,
123             );
124             } ## end else [ if (ref $target) ]
125             } ## end if (($nprevious && $nsequence...))
126             elsif ($nprevious) { # we "just" have to get rid of stuff
127             # FIXME will implement later, let's just no-reuse here...
128             }
129             else { # append residual stuff in @$rsequence
130 2         4 @sequence = @$rsequence;
131 2         3 $writer = writer(output => $target, input => $target);
132             }
133             } ## end if (ref($target) eq 'SCALAR'...)
134             else {
135 1         2 $writer = writer(output => $target);
136             }
137              
138             $writer->add(
139             inputs => [
140             map {
141 7 100 66     48 if (blessed($_) && $_->isa('Data::Embed::File')) {
  13         44  
142             {
143 5         7 name => $_->name(),
144             fh => $_->fh(),
145             };
146             } ## end if (blessed($_) && $_->...)
147             else {
148 8         15 $_;
149             }
150             } @sequence
151             ]
152             );
153 7         15 $writer->write_index();
154              
155 7 100       9 if (defined $interim_target) {
156 4 50       9 if (ref $target) {
157 4         5 $$target = $interim_target;
158             }
159             else {
160 0         0 rename $interim_target, $target; # atomic
161             }
162             } ## end if (defined $interim_target)
163              
164 7         13 return;
165             } ## end sub reassemble
166              
167             1;