$self->create_tag(
$obj, $obj->_base_offset, $obj->_type,
- chr(0) x $self->{index_size},
+ chr(0)x$self->{index_size},
);
# Flush the filehandle
##
my $self = shift;
my ($obj, $offset, $sig, $content) = @_;
- my $size = length($content);
+ my $size = length( $content );
my $fh = $obj->_fh;
- seek($fh, $offset + $obj->_root->{file_offset}, SEEK_SET);
+ if ( defined $offset ) {
+ seek($fh, $offset + $obj->_root->{file_offset}, SEEK_SET);
+ }
+
print( $fh $sig . pack($self->{data_pack}, $size) . $content );
+ return unless defined $offset;
+
return {
signature => $sig,
size => $size,
sub _length_needed {
my $self = shift;
- my ($obj, $value) = @_;
+ my ($obj, $value, $key) = @_;
my $is_dbm_deep = eval {
local $SIG{'__DIE__'};
$value->isa( 'DBM::Deep' );
};
- my $internal_ref = $is_dbm_deep && ($value->_root eq $obj->_root);
+ my $len = SIG_SIZE + $self->{data_size}
+ + $self->{data_size} + length( $key );
- if ( $internal_ref ) {
- return $self->{long_size};
+ if ( $is_dbm_deep && $value->_root eq $obj->_root ) {
+ return $len + $self->{long_size};
}
my $r = Scalar::Util::reftype( $value ) || '';
unless ( $r eq 'HASH' || $r eq 'ARRAY' ) {
- return length( $value );
+ if ( defined $value ) {
+ $len += length( $value );
+ }
+ return $len;
}
- my $actual_length = $self->{index_size};
+ $len += $self->{index_size};
# if autobless is enabled, must also take into consideration
- # the class name, as it is stored along with key/value.
+ # the class name as it is stored after the key.
if ( $obj->_root->{autobless} ) {
+ # This is for the bit saying whether or not this thing is blessed.
+ $len += 1;
+
my $value_class = Scalar::Util::blessed($value);
- if ( defined $value_class && !$value->isa('DBM::Deep') ) {
- $actual_length += length($value_class);
+ if ( defined $value_class && !$is_dbm_deep ) {
+ $len += $self->{data_size} + length($value_class);
}
}
- return $actual_length;
+ return $len;
}
sub add_bucket {
my $result = 2;
my $root = $obj->_root;
+ my $fh = $obj->_fh;
- my $fh = $obj->_fh;
+ my $actual_length = $self->_length_needed( $obj, $value, $plain_key );
my ($subloc, $offset) = $self->_find_in_buckets( $tag, $md5 );
read( $fh, $size, $self->{data_size});
$size = unpack($self->{data_pack}, $size);
- my $actual_length = $self->_length_needed( $obj, $value );
-
if ($actual_length <= $size) {
$location = $subloc;
}
else {
- $location = $root->{end};
+ $location = $self->_request_space( $obj, $actual_length );
seek(
$fh,
$tag->{offset} + $offset + $self->{hash_size} + $root->{file_offset},
}
# Adding a new md5
elsif ( defined $offset ) {
- $location = $root->{end};
+ $location = $self->_request_space( $obj, $actual_length );
seek( $fh, $tag->{offset} + $offset + $root->{file_offset}, SEEK_SET );
print( $fh $md5 . pack($self->{long_pack}, $location) );
else {
$self->split_index( $obj, $md5, $tag );
- $location = $root->{end};
+ $location = $self->_request_space( $obj, $actual_length );
}
$self->write_value( $obj, $location, $plain_key, $value );
# actual value.
##
my $r = Scalar::Util::reftype($value) || '';
- my $content_length;
if ( $internal_ref ) {
- print( $fh SIG_INTERNAL );
- print( $fh pack($self->{data_pack}, $self->{long_size}) );
- print( $fh pack($self->{long_pack}, $value->_base_offset) );
- $content_length = $self->{long_size};
+ $self->create_tag( $obj, undef, SIG_INTERNAL,pack($self->{long_pack}, $value->_base_offset) );
+ }
+ elsif ($r eq 'HASH') {
+ $self->create_tag( $obj, undef, SIG_HASH, chr(0)x$self->{index_size} );
+ }
+ elsif ($r eq 'ARRAY') {
+ $self->create_tag( $obj, undef, SIG_ARRAY, chr(0)x$self->{index_size} );
+ }
+ elsif (!defined($value)) {
+ $self->create_tag( $obj, undef, SIG_INTERNAL, '' );
}
else {
- if ($r eq 'HASH') {
- print( $fh SIG_HASH );
- print( $fh pack($self->{data_pack}, $self->{index_size}) . chr(0) x $self->{index_size} );
- $content_length = $self->{index_size};
- }
- elsif ($r eq 'ARRAY') {
- print( $fh SIG_ARRAY );
- print( $fh pack($self->{data_pack}, $self->{index_size}) . chr(0) x $self->{index_size} );
- $content_length = $self->{index_size};
- }
- elsif (!defined($value)) {
- print( $fh SIG_NULL );
- print( $fh pack($self->{data_pack}, 0) );
- $content_length = 0;
- }
- else {
- print( $fh SIG_DATA );
- print( $fh pack($self->{data_pack}, length($value)) . $value );
- $content_length = length($value);
- }
+ $self->create_tag( $obj, undef, SIG_DATA, $value );
}
##
##
if ( $root->{autobless} ) {
my $value_class = Scalar::Util::blessed($value);
- if ( defined $value_class && !$value->isa( 'DBM::Deep' ) ) {
- ##
- # Blessed ref -- will restore later
- ##
+ if ( defined $value_class && !$is_dbm_deep ) {
print( $fh chr(1) );
print( $fh pack($self->{data_pack}, length($value_class)) . $value_class );
- $content_length += 1;
- $content_length += $self->{data_size} + length($value_class);
}
else {
print( $fh chr(0) );
- $content_length += 1;
}
}
##
- # If this is a new content area, advance EOF counter
- ##
- if ($location == $root->{end}) {
- $root->{end} += SIG_SIZE;
- $root->{end} += $self->{data_size} + $content_length;
- $root->{end} += $self->{data_size} + length($key);
- }
-
- ##
# If content is a hash or array, create new child DBM::Deep object and
# pass each key or element to it.
##
- if ( ! $internal_ref ) {
+ if ( !$internal_ref ) {
if ($r eq 'HASH') {
my $branch = DBM::Deep->new(
type => DBM::Deep->TYPE_HASH,
my $index_tag = $self->create_tag(
$obj, $loc, SIG_INDEX,
- chr(0) x $self->{index_size},
+ chr(0)x$self->{index_size},
);
my @offsets = ();
my $blist_tag = $self->create_tag(
$obj, $loc, SIG_BLIST,
- chr(0) x $self->{bucket_list_size},
+ chr(0)x$self->{bucket_list_size},
);
seek($fh, $blist_tag->{offset} + $root->{file_offset}, SEEK_SET);
$tag = $self->create_tag(
$obj, $loc, SIG_BLIST,
- chr(0) x $self->{bucket_list_size},
+ chr(0)x$self->{bucket_list_size},
);
$tag->{ref_loc} = $ref_loc;