Merged with master and am ready to merge back
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Sector / File / Scalar.pm
CommitLineData
2c70efe1 1package DBM::Deep::Sector::File::Scalar;
f0276afb 2
3use 5.006_000;
4
5use strict;
6use warnings FATAL => 'all';
616df1be 7no warnings 'recursion';
f0276afb 8
2c70efe1 9use base qw( DBM::Deep::Sector::File::Data );
f0276afb 10
5ae752e2 11my $STALE_SIZE = 2;
12
13# Please refer to the pack() documentation for further information
14my %StP = (
15 1 => 'C', # Unsigned char value (no order needed as it's just one byte)
16 2 => 'n', # Unsigned short in "network" (big-endian) order
17 4 => 'N', # Unsigned long in "network" (big-endian) order
18 8 => 'Q', # Usigned quad (no order specified, presumably machine-dependent)
19);
20
f0276afb 21sub free {
22 my $self = shift;
23
24 my $chain_loc = $self->chain_loc;
25
26 $self->SUPER::free();
27
28 if ( $chain_loc ) {
d6ecf579 29 $self->engine->load_sector( $chain_loc )->free;
f0276afb 30 }
31
32 return;
33}
34
35sub type { $_[0]{engine}->SIG_DATA }
36sub _init {
37 my $self = shift;
38
39 my $engine = $self->engine;
40
41 unless ( $self->offset ) {
42 my $data_section = $self->size - $self->base_size - $engine->byte_size - 1;
43
44 $self->{offset} = $engine->_request_data_sector( $self->size );
45
46 my $data = delete $self->{data};
47 my $dlen = length $data;
48 my $continue = 1;
49 my $curr_offset = $self->offset;
50 while ( $continue ) {
51
52 my $next_offset = 0;
53
54 my ($leftover, $this_len, $chunk);
55 if ( $dlen > $data_section ) {
56 $leftover = 0;
57 $this_len = $data_section;
58 $chunk = substr( $data, 0, $this_len );
59
60 $dlen -= $data_section;
61 $next_offset = $engine->_request_data_sector( $self->size );
62 $data = substr( $data, $this_len );
63 }
64 else {
65 $leftover = $data_section - $dlen;
66 $this_len = $dlen;
67 $chunk = $data;
68
69 $continue = 0;
70 }
71
72 $engine->storage->print_at( $curr_offset, $self->type ); # Sector type
73 # Skip staleness
74 $engine->storage->print_at( $curr_offset + $self->base_size,
75 pack( $StP{$engine->byte_size}, $next_offset ), # Chain loc
76 pack( $StP{1}, $this_len ), # Data length
77 $chunk, # Data to be stored in this sector
78 chr(0) x $leftover, # Zero-fill the rest
79 );
80
81 $curr_offset = $next_offset;
82 }
83
84 return;
85 }
86}
87
88sub data_length {
89 my $self = shift;
90
91 my $buffer = $self->engine->storage->read_at(
92 $self->offset + $self->base_size + $self->engine->byte_size, 1
93 );
94
95 return unpack( $StP{1}, $buffer );
96}
97
98sub chain_loc {
99 my $self = shift;
100 return unpack(
101 $StP{$self->engine->byte_size},
102 $self->engine->storage->read_at(
103 $self->offset + $self->base_size,
104 $self->engine->byte_size,
105 ),
106 );
107}
108
109sub data {
110 my $self = shift;
f0276afb 111
112 my $data;
113 while ( 1 ) {
114 my $chain_loc = $self->chain_loc;
115
116 $data .= $self->engine->storage->read_at(
117 $self->offset + $self->base_size + $self->engine->byte_size + 1, $self->data_length,
118 );
119
120 last unless $chain_loc;
121
d6ecf579 122 $self = $self->engine->load_sector( $chain_loc );
f0276afb 123 }
124
125 return $data;
126}
127
1281;
129__END__