Assignment to a negative value within the bounds of the array works
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Hash.pm
1 package DBM::Deep::Hash;
2
3 use strict;
4
5 use base 'DBM::Deep';
6
7 sub _get_self {
8     eval { tied( %{$_[0]} ) } || $_[0]
9 }
10
11 sub TIEHASH {
12     ##
13     # Tied hash constructor method, called by Perl's tie() function.
14     ##
15     my $class = shift;
16     my $args;
17     if (scalar(@_) > 1) {
18         if ( @_ % 2 ) {
19             $class->_throw_error( "Odd number of parameters to TIEHASH" );
20         }
21         $args = {@_};
22     }
23         elsif ( my $type = Scalar::Util::reftype($_[0]) ) {
24         if ( $type ne 'HASH' ) {
25             $class->_throw_error( "Not a hashref in TIEHASH" );
26         }
27         $args = $_[0];
28     }
29     else { $args = { file => shift }; }
30     
31     $args->{type} = $class->TYPE_HASH;
32
33     return $class->_init($args);
34 }
35
36 sub FETCH {
37     my $self = shift->_get_self;
38     my $key = ($self->root->{filter_store_key})
39         ? $self->root->{filter_store_key}->($_[0])
40         : $_[0];
41
42     return $self->SUPER::FETCH( $key );
43 }
44
45 sub STORE {
46     my $self = shift->_get_self;
47         my $key = ($self->root->{filter_store_key})
48         ? $self->root->{filter_store_key}->($_[0])
49         : $_[0];
50     my $value = $_[1];
51
52     return $self->SUPER::STORE( $key, $value );
53 }
54
55 sub FIRSTKEY {
56         ##
57         # Locate and return first key (in no particular order)
58         ##
59     my $self = $_[0]->_get_self;
60
61         ##
62         # Make sure file is open
63         ##
64         if (!defined($self->fh)) { $self->_open(); }
65         
66         ##
67         # Request shared lock for reading
68         ##
69         $self->lock( $self->LOCK_SH );
70         
71         my $result = $self->_get_next_key();
72         
73         $self->unlock();
74         
75         return ($result && $self->root->{filter_fetch_key})
76         ? $self->root->{filter_fetch_key}->($result)
77         : $result;
78 }
79
80 sub NEXTKEY {
81         ##
82         # Return next key (in no particular order), given previous one
83         ##
84     my $self = $_[0]->_get_self;
85
86         my $prev_key = ($self->root->{filter_store_key})
87         ? $self->root->{filter_store_key}->($_[1])
88         : $_[1];
89
90         my $prev_md5 = $DBM::Deep::DIGEST_FUNC->($prev_key);
91
92         ##
93         # Make sure file is open
94         ##
95         if (!defined($self->fh)) { $self->_open(); }
96         
97         ##
98         # Request shared lock for reading
99         ##
100         $self->lock( $self->LOCK_SH );
101         
102         my $result = $self->_get_next_key( $prev_md5 );
103         
104         $self->unlock();
105         
106         return ($result && $self->root->{filter_fetch_key})
107         ? $self->root->{filter_fetch_key}->($result)
108         : $result;
109 }
110
111 ##
112 # Public method aliases
113 ##
114 *first_key = *FIRSTKEY;
115 *next_key = *NEXTKEY;
116
117 1;
118 __END__