X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBM%2FDeep%2FArray.pm;h=73babc58ccc7553f4d4e21ad52391aec8afbc117;hb=065b45be4e413444714f0b35aa9653e10753118b;hp=65af4a7e4bff1d8b2efb215ece6a14a4cba64fac;hpb=86867f3a6f23efdf7c7290f5a0b7a69f5f39834f;p=dbsrgits%2FDBM-Deep.git diff --git a/lib/DBM/Deep/Array.pm b/lib/DBM/Deep/Array.pm index 65af4a7..73babc5 100644 --- a/lib/DBM/Deep/Array.pm +++ b/lib/DBM/Deep/Array.pm @@ -1,11 +1,9 @@ package DBM::Deep::Array; -use 5.6.0; +use 5.006_000; use strict; -use warnings; - -our $VERSION = '0.99_01'; +use warnings FATAL => 'all'; # This is to allow DBM::Deep::Array to handle negative indices on # its own. Otherwise, Perl would intercept the call to negative @@ -20,21 +18,8 @@ sub _get_self { eval { local $SIG{'__DIE__'}; tied( @{$_[0]} ) } || $_[0] } -sub _repr { shift;[ @_ ] } - -sub _import { - my $self = shift; - my ($struct) = @_; +sub _repr { [] } - eval { - local $SIG{'__DIE__'}; - $self->push( @$struct ); - }; if ($@) { - $self->_throw_error("Cannot import: type mismatch"); - } - - return 1; -} sub TIEARRAY { my $class = shift; my $args = $class->_get_args( @_ ); @@ -50,9 +35,11 @@ sub FETCH { $self->lock( $self->LOCK_SH ); -# my $orig_key = $key eq 'length' ? undef : $key; - my $orig_key = $key; - if ( $key =~ /^-?\d+$/ ) { + if ( !defined $key ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use an undefined array index." ); + } + elsif ( $key =~ /^-?\d+$/ ) { if ( $key < 0 ) { $key += $self->FETCHSIZE; unless ( $key >= 0 ) { @@ -60,11 +47,13 @@ sub FETCH { return; } } - - $key = pack($self->{engine}{long_pack}, $key); + } + elsif ( $key ne 'length' ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use '$key' as an array index." ); } - my $rv = $self->SUPER::FETCH( $key, $orig_key ); + my $rv = $self->SUPER::FETCH( $key ); $self->unlock; @@ -77,30 +66,33 @@ sub STORE { $self->lock( $self->LOCK_EX ); -# my $orig = $key eq 'length' ? undef : $key; - my $orig_key = $key; - my $size; - my $numeric_idx; - if ( $key =~ /^\-?\d+$/ ) { - $numeric_idx = 1; + my $idx_is_numeric; + if ( !defined $key ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use an undefined array index." ); + } + elsif ( $key =~ /^-?\d+$/ ) { + $idx_is_numeric = 1; if ( $key < 0 ) { $size = $self->FETCHSIZE; - $key += $size; - if ( $key < 0 ) { - die( "Modification of non-creatable array value attempted, subscript $orig_key" ); + if ( $key + $size < 0 ) { + die( "Modification of non-creatable array value attempted, subscript $key" ); } + $key += $size } - - $key = pack($self->{engine}{long_pack}, $key); + } + elsif ( $key ne 'length' ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use '$key' as an array index." ); } - my $rv = $self->SUPER::STORE( $key, $value, $orig_key ); + my $rv = $self->SUPER::STORE( $key, $value ); - if ( $numeric_idx ) { + if ( $idx_is_numeric ) { $size = $self->FETCHSIZE unless defined $size; - if ( $orig_key >= $size ) { - $self->STORESIZE( $orig_key + 1 ); + if ( $key >= $size ) { + $self->STORESIZE( $key + 1 ); } } @@ -115,7 +107,11 @@ sub EXISTS { $self->lock( $self->LOCK_SH ); - if ( $key =~ /^\-?\d+$/ ) { + if ( !defined $key ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use an undefined array index." ); + } + elsif ( $key =~ /^-?\d+$/ ) { if ( $key < 0 ) { $key += $self->FETCHSIZE; unless ( $key >= 0 ) { @@ -123,8 +119,10 @@ sub EXISTS { return; } } - - $key = pack($self->{engine}{long_pack}, $key); + } + elsif ( $key ne 'length' ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use '$key' as an array index." ); } my $rv = $self->SUPER::EXISTS( $key ); @@ -137,14 +135,16 @@ sub EXISTS { sub DELETE { my $self = shift->_get_self; my ($key) = @_; - - my $unpacked_key = $key; - my $orig = $key eq 'length' ? undef : $key; + warn "ARRAY::DELETE($self,$key)\n" if DBM::Deep::DEBUG; $self->lock( $self->LOCK_EX ); my $size = $self->FETCHSIZE; - if ( $key =~ /^-?\d+$/ ) { + if ( !defined $key ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use an undefined array index." ); + } + elsif ( $key =~ /^-?\d+$/ ) { if ( $key < 0 ) { $key += $size; unless ( $key >= 0 ) { @@ -152,14 +152,16 @@ sub DELETE { return; } } - - $key = pack($self->{engine}{long_pack}, $key); + } + elsif ( $key ne 'length' ) { + $self->unlock; + DBM::Deep->_throw_error( "Cannot use '$key' as an array index." ); } - my $rv = $self->SUPER::DELETE( $key, $orig ); + my $rv = $self->SUPER::DELETE( $key ); - if ($rv && $unpacked_key == $size - 1) { - $self->STORESIZE( $unpacked_key ); + if ($rv && $key == $size - 1) { + $self->STORESIZE( $key ); } $self->unlock; @@ -167,25 +169,24 @@ sub DELETE { return $rv; } +# Now that we have a real Reference sector, we should store arrayzize there. However, +# arraysize needs to be transactionally-aware, so a simple location to store it isn't +# going to work. sub FETCHSIZE { my $self = shift->_get_self; $self->lock( $self->LOCK_SH ); - my $SAVE_FILTER = $self->_fileobj->{filter_fetch_value}; - $self->_fileobj->{filter_fetch_value} = undef; + my $SAVE_FILTER = $self->_storage->{filter_fetch_value}; + $self->_storage->{filter_fetch_value} = undef; - my $packed_size = $self->FETCH('length'); + my $size = $self->FETCH('length') || 0; - $self->_fileobj->{filter_fetch_value} = $SAVE_FILTER; + $self->_storage->{filter_fetch_value} = $SAVE_FILTER; $self->unlock; - if ($packed_size) { - return int(unpack($self->{engine}{long_pack}, $packed_size)); - } - - return 0; + return $size; } sub STORESIZE { @@ -194,12 +195,12 @@ sub STORESIZE { $self->lock( $self->LOCK_EX ); - my $SAVE_FILTER = $self->_fileobj->{filter_store_value}; - $self->_fileobj->{filter_store_value} = undef; + my $SAVE_FILTER = $self->_storage->{filter_store_value}; + $self->_storage->{filter_store_value} = undef; - my $result = $self->STORE('length', pack($self->{engine}{long_pack}, $new_length), 'length'); + my $result = $self->STORE('length', $new_length, 'length'); - $self->_fileobj->{filter_store_value} = $SAVE_FILTER; + $self->_storage->{filter_store_value} = $SAVE_FILTER; $self->unlock; @@ -244,29 +245,42 @@ sub PUSH { return $length; } +# XXX This really needs to be something more direct within the file, not a +# fetch and re-store. -RobK, 2007-09-20 +sub _move_value { + my $self = shift; + my ($old_key, $new_key) = @_; + + return $self->_engine->make_reference( $self, $old_key, $new_key ); +} + sub SHIFT { my $self = shift->_get_self; + warn "SHIFT($self)\n" if DBM::Deep::DEBUG; $self->lock( $self->LOCK_EX ); my $length = $self->FETCHSIZE(); - if ($length) { - my $content = $self->FETCH( 0 ); + if ( !$length ) { + $self->unlock; + return; + } + + my $content = $self->DELETE( 0 ); + # Unless the deletion above has cleared the array ... + if ( $length > 1 ) { for (my $i = 0; $i < $length - 1; $i++) { - $self->STORE( $i, $self->FETCH($i + 1) ); + $self->_move_value( $i+1, $i ); } + $self->DELETE( $length - 1 ); + } - $self->unlock; + $self->unlock; - return $content; - } - else { - $self->unlock; - return; - } + return $content; } sub UNSHIFT { @@ -280,8 +294,10 @@ sub UNSHIFT { if ($length) { for (my $i = $length - 1; $i >= 0; $i--) { - $self->STORE( $i + $new_size, $self->FETCH($i) ); + $self->_move_value( $i, $i+$new_size ); } + + $self->STORESIZE( $length + $new_size ); } for (my $i = 0; $i < $new_size; $i++) { @@ -328,12 +344,13 @@ sub SPLICE { if ( $new_size != $splice_length ) { if ($new_size > $splice_length) { for (my $i = $length - 1; $i >= $offset + $splice_length; $i--) { - $self->STORE( $i + ($new_size - $splice_length), $self->FETCH($i) ); + $self->_move_value( $i, $i + ($new_size - $splice_length) ); } + $self->STORESIZE( $length + $new_size - $splice_length ); } else { for (my $i = $offset + $splice_length; $i < $length; $i++) { - $self->STORE( $i + ($new_size - $splice_length), $self->FETCH($i) ); + $self->_move_value( $i, $i + ($new_size - $splice_length) ); } for (my $i = 0; $i < $splice_length - $new_size; $i++) { $self->DELETE( $length - 1 ); @@ -357,7 +374,7 @@ sub SPLICE { return wantarray ? @old_elements : $old_elements[-1]; } -# We don't need to define it, yet. +# We don't need to populate it, yet. # It will be useful, though, when we split out HASH and ARRAY sub EXTEND { ## @@ -372,8 +389,7 @@ sub _copy_node { my $length = $self->length(); for (my $index = 0; $index < $length; $index++) { - my $value = $self->get($index); - $self->_copy_value( \$db_temp->[$index], $value ); + $self->_copy_value( \$db_temp->[$index], $self->get($index) ); } return 1;