File Coverage

blib/lib/Devel/INC/Sorted.pm
Criterion Covered Total %
statement 76 84 90.4
branch 6 6 100.0
condition 7 8 87.5
subroutine 23 28 82.1
pod 0 5 0.0
total 112 131 85.5


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