File Coverage

blib/lib/Tie/SortHash.pm
Criterion Covered Total %
statement 24 60 40.0
branch 1 10 10.0
condition 2 9 22.2
subroutine 4 13 30.7
pod 1 2 50.0
total 32 94 34.0


line stmt bran cond sub pod time code
1             package Tie::SortHash;
2              
3 1     1   2067 use strict;
  1         2  
  1         67  
4 1     1   7 use vars qw($VERSION);
  1         2  
  1         4734  
5              
6             $VERSION = '1.01';
7              
8             sub iterate {
9 0     0 0 0 my( $hash, $sort, $lastkey ) = @_;
10 0         0 my $iwantthis = 0;
11              
12             # Iterate over sort order keys until we find what we want
13 0         0 foreach my $key ( eval "sort { $sort } keys %{\$hash}" ) {
14              
15 0 0 0     0 return( $hash->{$key}, $key ) if $iwantthis || ! defined $lastkey;
16              
17 0 0       0 $iwantthis = 1 if $key eq $lastkey;
18             }
19              
20             # If our sort block is screwed up, report
21 0 0       0 die $@ if $@;
22              
23             # We ran out of keys.
24 0         0 return undef;
25             } ## iterate()
26              
27             sub sortblock {
28 1     1 1 3 my( $self, $sort ) = @_;
29              
30             # Change default syntax to OO version
31 1         3 $sort =~ s/\$hash/\$hash->/gso;
32              
33             # Test the sort block
34 1         1 my $hash = $self->{DATA};
35 1         101 my @keys = eval "sort { $sort } keys %{\$hash}";
36              
37             # If there's an error, freak out
38 1 50       160 die $@ if $@;
39              
40 0         0 $self->{SORT} = $sort;
41              
42 0         0 return 1;
43             } ## sortblock()
44              
45             sub TIEHASH {
46 1     1   82 my $class = shift;
47              
48 1   50     3 my $hash = shift || {};
49              
50             # If there's no sort block, supply a good default,
51             # that's what this module's for, right?
52 1   50     6 my $sort = shift || '$a cmp $b || $a <=> $b';
53              
54 1         3 my( $keys, $vals, $i ) = ( {}, [], 1 );
55              
56             # Iterate over the hash, setting up info for the pheudo-hash
57 1         2 foreach my $key ( keys %{$hash} ) {
  1         4  
58 4         5 $keys->{$key} = $i;
59 4         4 push @{$vals}, $hash->{$key};
  4         7  
60 4         5 $i++;
61             }
62              
63             # Declare the data
64 1         4 my $self = {
65             DATA => [
66             $keys,
67 1         3 @{$vals},
68             ],
69             };
70              
71             # Add our sort block to the data
72 1         3 sortblock( $self, $sort );
73              
74 0           return bless $self, $class;
75             } # TIEHASH()
76              
77             sub CLEAR {
78 0     0     my $self = shift;
79 0           return $self->{DATA} = [{}];
80             } # CLEAR()
81              
82             sub DELETE {
83 0     0     my( $self, $key ) = @_;
84              
85             # Perl's garbage collection for Phseudo-Hashes stinks,
86             # I'm manually taking care of it, forcing me to _not_ be lazy
87              
88             # Find the index of the key to delete.
89 0           my $index = $self->{DATA}->[0]->{$key};
90              
91             # Decrement all indexes higher than the one we'll delete
92 0           foreach ( keys %{$self->{DATA}} ) {
  0            
93 0 0         $self->{DATA}->[0]->{$_}-- if $self->{DATA}->[0]->{$_} > $index;
94             }
95              
96             # Remove the value from the array
97 0           splice @{$self->{DATA}}, $index, 1;
  0            
98              
99             # Delete the key pointing to the just removed value
100 0           return delete $self->{DATA}->[0]->{$key};
101             } # DELETE()
102              
103 0     0     sub DESTROY {
104             # Nothing useful to do here, just commenting about that
105             } # DESTROY()
106              
107             sub EXISTS {
108 0     0     my( $self, $key ) = @_;
109 0           return exists $self->{DATA}->{$key};
110             } # EXISTS()
111              
112             sub FETCH {
113 0     0     my( $self, $key ) = @_;
114 0           return $self->{DATA}->{$key};
115             } # FETCH()
116              
117             sub FIRSTKEY {
118 0     0     my $self = shift;
119 0           keys %{$self->{DATA}};
  0            
120 0           return iterate( $self->{DATA}, $self->{SORT}, undef );
121             } # FIRSTKEY()
122              
123             sub NEXTKEY {
124 0     0     my( $self, $lastkey ) = @_;
125              
126             # Return undef if there's nothing left in our hash
127 0   0       return iterate( $self->{DATA}, $self->{SORT}, $lastkey ) || undef;
128             } # NEXTKEY()
129              
130             sub STORE {
131 0     0     my( $self, $key, $value ) = @_;
132              
133             # Add the key entry
134 0           $self->{DATA}->[0]->{$key} = @{$self->{DATA}};
  0            
135              
136             # Add the value
137 0           $self->{DATA}->{$key} = $value;
138              
139 0           return 1;
140             } # STORE()
141              
142             1;
143              
144             __END__