File Coverage

blib/lib/Devel/INC/Sorted.pm
Criterion Covered Total %
statement 79 87 90.8
branch 6 6 100.0
condition 6 8 75.0
subroutine 24 29 82.7
pod 0 5 0.0
total 115 135 85.1


line stmt bran cond sub pod time code
1             package Devel::INC::Sorted; # git description: Devel-INC-Sorted-0.02-7-geee6b42
2             # ABSTRACT: Keep your hooks in the beginning of @INC
3              
4 1     1   13568 use base 'Tie::Array';
  1         2  
  1         444  
5              
6 1     1   850 use strict;
  1         1  
  1         16  
7 1     1   4 use warnings;
  1         1  
  1         34  
8              
9 1     1   474 use sort 'stable';
  1         366  
  1         4  
10              
11 1     1   28 use Exporter;
  1         1  
  1         32  
12 1     1   3 use Scalar::Util qw(blessed reftype);
  1         1  
  1         64  
13 1     1   415 use Tie::RefHash;
  1         2345  
  1         286  
14              
15             our $VERSION = '0.03';
16              
17             our @EXPORT_OK = qw(inc_add_floating inc_float_entry inc_unfloat_entry untie_inc);
18              
19             tie our %floating, 'Tie::RefHash';
20              
21             sub import {
22 1     1   638 my ( $self, @args ) = @_;
23 1         2 $self->tie_inc( grep { ref } @args ); # if a code ref is given, pass it to TIEARRAY
  4         8  
24 1         56 goto &Exporter::import;
25             }
26              
27             sub _args {
28 7     7   7 my ( $self, @args );
29              
30 7 100 66     78 if (
      100        
31             ( blessed($_[0]) or defined($_[0]) && !ref($_[0]) ) # class or object
32             and
33             ( $_[0]->isa(__PACKAGE__) )
34             ) {
35 2         2 $self = shift;
36             } else {
37 5         6 $self = __PACKAGE__;
38             }
39              
40 7         14 return ( $self->tie_inc, @_ );
41             }
42              
43             sub inc_add_floating {
44 2     2 0 544 my ( $self, @args ) = &_args;
45              
46 2         5 $self->inc_float_entry(@args);
47              
48 2         4 $self->PUSH(@args);
49             }
50              
51             sub inc_float_entry {
52 3     3 0 281 my ( $self, @args ) = &_args;
53              
54 3         20 @floating{@args} = ( (1) x @args );
55              
56 3         33 $self->_fixup;
57             }
58              
59             sub inc_unfloat_entry {
60 1     1 0 271 my ( $self, @args ) = &_args;
61              
62 1         7 delete @floating{@args};
63              
64 1         9 $self->_fixup;
65             }
66              
67             sub tie_inc {
68 8     8 0 10 my ( $self, @args ) = @_;
69 8 100       16 return $self if ref $self;
70 6 100       16 return tied @INC if tied @INC;
71 1         7 tie @INC, $self, $args[0], @INC;
72             }
73              
74             sub untie_inc {
75 1     1 0 274 my ( $self ) = &_args;
76 1     1   5 no warnings 'untie'; # untying while tied() is referenced elsewhere warns
  1         1  
  1         431  
77 1         6 untie @INC;
78 1         1 @INC = @{ $self->{array} };
  1         11  
79             }
80              
81             # This code was adapted from Tie::Array::Sorted::Lazy
82             # the reason it's not a subclass is because neither ::Sorted nor ::Sorted::Lazy
83             # provide a stably sorted array, which is bad for our default comparison operator
84              
85             sub TIEARRAY {
86 1     1   2 my ( $class, $comparator, @orig ) = @_;
87              
88             $comparator ||= sub {
89 81     81   61 my ( $left, $right ) = @_;
90 81         114 exists $floating{$right} <=> exists $floating{$left};
91 1   50     12 };
92              
93 1         5 bless {
94             array => \@orig,
95             comp => $comparator,
96             }, $class;
97             }
98              
99             sub STORE {
100 6     6   11 my ($self, $index, $elem) = @_;
101 6         9 $self->{array}[$index] = $elem;
102 6         8 $self->_fixup();
103 6         15 $self->{array}[$index];
104             }
105              
106             sub PUSH {
107 3     3   274 my $self = shift;
108 3         3 my $ret = push @{ $self->{array} }, @_;
  3         6  
109 3         5 $self->_fixup();
110 3         3 $ret;
111             }
112              
113             sub UNSHIFT {
114 1     1   357 my $self = shift;
115 1         2 my $ret = unshift @{ $self->{array} }, @_;
  1         3  
116 1         3 $self->_fixup();
117 1         1 $ret;
118             }
119              
120             sub _fixup {
121 14     14   10 my $self = shift;
122 14         11 $self->{array} = [ sort { $self->{comp}->($a, $b) } @{ $self->{array} } ];
  81         355  
  14         33  
123 14         122 $self->{dirty} = 0;
124             }
125              
126             sub FETCH {
127 42     42   145 $_[0]->{array}->[ $_[1] ];
128             }
129              
130             sub FETCHSIZE {
131 44     44   1951 scalar @{ $_[0]->{array} }
  44         65  
132             }
133              
134             sub STORESIZE {
135 0     0   0 $#{ $_[0]->{array} } = $_[1] - 1;
  0         0  
136             }
137              
138             sub POP {
139 0     0   0 pop(@{ $_[0]->{array} });
  0         0  
140             }
141              
142             sub SHIFT {
143 0     0   0 shift(@{ $_[0]->{array} });
  0         0  
144             }
145              
146             sub EXISTS {
147 0     0   0 exists $_[0]->{array}->[ $_[1] ];
148             }
149              
150             sub DELETE {
151 0     0   0 delete $_[0]->{array}->[ $_[1] ];
152             }
153              
154             sub CLEAR {
155 1     1   21 @{ $_[0]->{array} } = ()
  1         15  
156             }
157              
158             __PACKAGE__
159              
160             __END__