File Coverage

blib/lib/Data/CompactReadonly/V0/Array.pm
Criterion Covered Total %
statement 59 59 100.0
branch 16 16 100.0
condition n/a
subroutine 10 10 100.0
pod 0 3 0.0
total 85 88 96.5


line stmt bran cond sub pod time code
1             package Data::CompactReadonly::V0::Array;
2             our $VERSION = '0.0.5';
3              
4 4     4   34 use warnings;
  4         9  
  4         137  
5 4     4   22 use strict;
  4         9  
  4         96  
6 4     4   18 use base qw(Data::CompactReadonly::V0::Collection Data::CompactReadonly::Array);
  4         8  
  4         2572  
7              
8 4     4   2127 use Data::CompactReadonly::V0::TiedArray;
  4         12  
  4         1969  
9              
10             sub _init {
11 51     51   187 my($class, %args) = @_;
12 51         143 my($root, $offset) = @args{qw(root offset)};
13              
14 51         227 my $object = bless({
15             root => $root,
16             offset => $offset
17             }, $class);
18              
19 51 100       173 if($root->_tied()) {
20 20         90 tie my @array, 'Data::CompactReadonly::V0::TiedArray', $object;
21 20         144 return \@array;
22             } else {
23 31         264 return $object;
24             }
25             }
26              
27             # write an Array to the file at the current offset
28             sub _create {
29 21     21   108 my($class, %args) = @_;
30 21         50 my $fh = $args{fh};
31 21         122 $class->_stash_already_seen(%args);
32 21         1702 (my $scalar_type = $class) =~ s/Array/Scalar/;
33              
34             # node header
35             print $fh $class->_type_byte_from_class().
36 21         121 $scalar_type->_get_bytes_from_word(1 + $#{$args{data}});
  21         142  
37              
38             # empty pointer table
39 21         182 my $table_start_ptr = tell($fh);
40 21         90 print $fh "\x00" x $args{ptr_size} x (1 + $#{$args{data}});
  21         196  
41 21         178 $class->_set_next_free_ptr(%args);
42              
43             # write a pointer to each item in turn, and if necessary also write
44             # item, which can be of any type
45 21         59 foreach my $index (0 .. $#{$args{data}}) {
  21         120  
46 81         232 my $this_data = $args{data}->[$index];
47 81         511 $class->_seek(%args, pointer => $table_start_ptr + $index * $args{ptr_size});
48 81 100       442 if(my $ptr = $class->_get_already_seen(%args, data => $this_data)) {
49 14         304 print $fh $class->_encode_ptr(%args, pointer => $ptr);
50             } else {
51 67         1111 print $fh $class->_encode_ptr(%args, pointer => $class->_get_next_free_ptr(%args));
52 67         485 $class->_seek(%args, pointer => $class->_get_next_free_ptr(%args));
53 66         393 Data::CompactReadonly::V0::Node->_create(%args, data => $this_data);
54             }
55             }
56             }
57              
58             sub exists {
59 7     7 0 105 my($self, $element) = @_;
60 7         14 eval { $self->element($element) };
  7         19  
61 7 100       49 if($@ =~ /out of range/) {
    100          
62 3         20 return 0;
63             } elsif($@) {
64 2         11 die($@);
65             } else {
66 2         15 return 1;
67             }
68             }
69              
70             sub element {
71 126     126 0 847 my($self, $element) = @_;
72 4     4   33 no warnings 'numeric';
  4         17  
  4         1044  
73 126 100       383 die("$self: Invalid element: $element: negative\n")
74             if($element < 0);
75 124 100       509 die("$self: Invalid element: $element: non-integer\n")
76             if($element =~ /[^0-9]/);
77 121 100       421 die("$self: Invalid element: $element: out of range\n")
78             if($element > $self->count() - 1);
79              
80 115         319 $self->_seek($self->_offset() + $self->_scalar_type_bytes() + $element * $self->_ptr_size());
81 115         460 my $ptr = $self->_decode_ptr(
82             $self->_bytes_at_current_offset($self->_ptr_size())
83             );
84 115         398 $self->_seek($ptr);
85 115         496 return $self->_node_at_current_offset();
86             }
87              
88             sub indices {
89 2     2 0 6 my $self = shift;
90            
91 2 100       10 return [] if($self->count() == 0);
92 1         5 return [(0 .. $self->count() - 1)];
93             }
94              
95             1;