File Coverage

blib/lib/Tie/Array/Sorted.pm
Criterion Covered Total %
statement 38 49 77.5
branch 7 8 87.5
condition n/a
subroutine 11 17 64.7
pod n/a
total 56 74 75.6


line stmt bran cond sub pod time code
1             package Tie::Array::Sorted;
2              
3 1     1   891 use 5.006;
  1         4  
  1         41  
4              
5 1     1   6 use strict;
  1         2  
  1         31  
6 1     1   23 use warnings;
  1         2  
  1         34  
7              
8 1     1   5 use base 'Tie::Array';
  1         2  
  1         982  
9              
10             our $VERSION = '1.41';
11              
12             =head1 NAME
13              
14             Tie::Array::Sorted - An array which is kept sorted
15              
16             =head1 SYNOPSIS
17              
18             use Tie::Array::Sorted;
19              
20             tie @a, "Tie::Array::Sorted", sub { $_[0] <=> $_[1] };
21              
22             push @a, 10, 4, 7, 3, 4;
23             print "@a"; # "3 4 4 7 10"
24              
25             =head1 DESCRIPTION
26              
27             This presents an ordinary array, but is kept sorted. All pushes and
28             unshifts cause the elements in question to be inserted in the
29             appropriate location to maintain order.
30              
31             Direct stores (C<$a[10] = "wibble">) effectively splice out the original
32             value and insert the new element. It's not clear why you'd want to use
33             direct stores like that, but this module does the right thing if you do.
34              
35             If you don't like the ordinary lexical comparator, you can provide your
36             own; it should compare the two elements it is given. For instance, a
37             numeric comparator would look like this:
38              
39             tie @a, "Tie::Array::Sorted", sub { $_[0] <=> $_[1] }
40              
41             Whereas to compare a list of files by their sizes, you'd so something
42             like:
43              
44             tie @a, "Tie::Array::Sorted", sub { -s $_[0] <=> -s $_[1] }
45              
46             =head1 LAZY SORTING
47              
48             If you do more stores than fetches, you may find
49             L more efficient.
50              
51             =cut
52              
53             sub TIEARRAY {
54 3     3   1730 my ($class, $comparator) = @_;
55             bless {
56             array => [],
57 3     3   7 comp => (defined $comparator ? $comparator : sub { $_[0] cmp $_[1] })
58 3 100       28 }, $class;
59             }
60              
61             sub STORE {
62 0     0   0 my ($self, $index, $elem) = @_;
63 0         0 splice @{ $self->{array} }, $index, 0;
  0         0  
64 0         0 $self->PUSH($elem);
65             }
66              
67             sub PUSH {
68 12     12   778 my ($self, @elems) = @_;
69 12         25 ELEM: for my $elem (@elems) {
70 14         127 my ($lo, $hi) = (0, $#{ $self->{array} });
  14         30  
71 14         38 while ($hi >= $lo) {
72 19         35 my $mid = int(($lo + $hi) / 2);
73 19         33 my $mid_val = $self->{array}[$mid];
74 19         47 my $cmp = $self->{comp}($elem, $mid_val);
75 19 100       146 if ($cmp == 0) {
    100          
    50          
76 2         3 splice(@{ $self->{array} }, $mid, 0, $elem);
  2         5  
77 2         9 next ELEM;
78             } elsif ($cmp > 0) {
79 7         18 $lo = $mid + 1;
80             } elsif ($cmp < 0) {
81 10         27 $hi = $mid - 1;
82             }
83             }
84 12         13 splice(@{ $self->{array} }, $lo, 0, $elem);
  12         64  
85             }
86             }
87              
88 0     0   0 sub UNSHIFT { goto &PUSH }
89              
90 9     9   1207 sub FETCHSIZE { scalar @{ $_[0]->{array} } }
  9         48  
91 0     0   0 sub STORESIZE { $#{ $_[0]->{array} } = $_[1] - 1 }
  0         0  
92 34     34   5024 sub FETCH { $_[0]->{array}->[ $_[1] ] }
93 1     1   7 sub CLEAR { @{ $_[0]->{array} } = () }
  1         12  
94 1     1   320 sub POP { pop(@{ $_[0]->{array} }) }
  1         4  
95 0     0     sub SHIFT { shift(@{ $_[0]->{array} }) }
  0            
96              
97 0     0     sub EXISTS { exists $_[0]->{array}->[ $_[1] ] }
98 0     0     sub DELETE { delete $_[0]->{array}->[ $_[1] ] }
99              
100             1;
101              
102             =head1 AUTHOR
103              
104             Original author: Simon Cozens
105              
106             Current maintainer: Tony Bowden
107              
108             =head1 BUGS and QUERIES
109              
110             Please direct all correspondence regarding this module to:
111             bug-Tie-Array-Sorted@rt.cpan.org
112              
113             This module was originall written as part of the L project.
114             However, as Plucene no longer uses this, it is effectively unmaintained.
115              
116             =head1 COPYRIGHT AND LICENSE
117              
118             Copyright (C) 2003-2006 Simon Cozens and Tony Bowden.
119              
120             This program is free software; you can redistribute it and/or modify it under
121             the terms of the GNU General Public License; either version 2 of the License,
122             or (at your option) any later version.
123              
124             This program is distributed in the hope that it will be useful, but WITHOUT
125             ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
126             FOR A PARTICULAR PURPOSE.
127              
128              
129             =cut
130