File Coverage

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


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