Fix fatal recursion warnings (plus tests)
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Engine / Sector / Scalar.pm
index 332e849..f045f51 100644 (file)
@@ -1,13 +1,22 @@
-#TODO: Add chaining back in.
 package DBM::Deep::Engine::Sector::Scalar;
 
 use 5.006_000;
 
 use strict;
 use warnings FATAL => 'all';
+no warnings 'recursion';
 
-use DBM::Deep::Engine::Sector::Data;
-our @ISA = qw( DBM::Deep::Engine::Sector::Data );
+use base qw( DBM::Deep::Engine::Sector::Data );
+
+my $STALE_SIZE = 2;
+
+# Please refer to the pack() documentation for further information
+my %StP = (
+    1 => 'C', # Unsigned char value (no order needed as it's just one byte)
+    2 => 'n', # Unsigned short in "network" (big-endian) order
+    4 => 'N', # Unsigned long in "network" (big-endian) order
+    8 => 'Q', # Usigned quad (no order specified, presumably machine-dependent)
+);
 
 sub free {
     my $self = shift;
@@ -30,24 +39,48 @@ sub _init {
     my $engine = $self->engine;
 
     unless ( $self->offset ) {
+        my $data_section = $self->size - $self->base_size - $engine->byte_size - 1;
+
         $self->{offset} = $engine->_request_data_sector( $self->size );
+
         my $data = delete $self->{data};
         my $dlen = length $data;
-
-        my $data_section = $self->size - $self->base_size - $engine->byte_size - 1;
-        my $next_offset = 0;
-
-        if ( $dlen > $data_section ) {
-            DBM::Deep->_throw_error( "Storage of values longer than $data_section not supported." );
+        my $continue = 1;
+        my $curr_offset = $self->offset;
+        while ( $continue ) {
+
+            my $next_offset = 0;
+
+            my ($leftover, $this_len, $chunk);
+            if ( $dlen > $data_section ) {
+                $leftover = 0;
+                $this_len = $data_section;
+                $chunk = substr( $data, 0, $this_len );
+
+                $dlen -= $data_section;
+                $next_offset = $engine->_request_data_sector( $self->size );
+                $data = substr( $data, $this_len );
+            }
+            else {
+                $leftover = $data_section - $dlen;
+                $this_len = $dlen;
+                $chunk = $data;
+
+                $continue = 0;
+            }
+
+            $engine->storage->print_at( $curr_offset, $self->type ); # Sector type
+            # Skip staleness
+            $engine->storage->print_at( $curr_offset + $self->base_size,
+                pack( $StP{$engine->byte_size}, $next_offset ),  # Chain loc
+                pack( $StP{1}, $this_len ),                      # Data length
+                $chunk,                                          # Data to be stored in this sector
+                chr(0) x $leftover,                              # Zero-fill the rest
+            );
+
+            $curr_offset = $next_offset;
         }
 
-        $self->write( 0, $self->type );
-        $self->write( $self->base_size,
-            pack( $engine->StP($engine->byte_size), $next_offset ) # Chain loc
-          . pack( $engine->StP(1), $dlen )                         # Data length
-          . $data
-        );
-
         return;
     }
 }
@@ -55,18 +88,19 @@ sub _init {
 sub data_length {
     my $self = shift;
 
-    return unpack(
-        $self->engine->StP(1),
-        $self->read( $self->base_size + $self->engine->byte_size, 1 ),
+    my $buffer = $self->engine->storage->read_at(
+        $self->offset + $self->base_size + $self->engine->byte_size, 1
     );
+
+    return unpack( $StP{1}, $buffer );
 }
 
 sub chain_loc {
     my $self = shift;
     return unpack(
-        $self->engine->StP($self->engine->byte_size),
-        $self->read(
-            $self->base_size,
+        $StP{$self->engine->byte_size},
+        $self->engine->storage->read_at(
+            $self->offset + $self->base_size,
             $self->engine->byte_size,
         ),
     );
@@ -74,12 +108,16 @@ sub chain_loc {
 
 sub data {
     my $self = shift;
+#    my ($args) = @_;
+#    $args ||= {};
 
     my $data;
     while ( 1 ) {
         my $chain_loc = $self->chain_loc;
 
-        $data .= $self->read( $self->base_size + $self->engine->byte_size + 1, $self->data_length );
+        $data .= $self->engine->storage->read_at(
+            $self->offset + $self->base_size + $self->engine->byte_size + 1, $self->data_length,
+        );
 
         last unless $chain_loc;