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.1.0';
3              
4 4     4   44 use warnings;
  4         8  
  4         275  
5 4     4   27 use strict;
  4         11  
  4         210  
6 4     4   24 use base qw(Data::CompactReadonly::V0::Collection Data::CompactReadonly::Array);
  4         8  
  4         3700  
7              
8 4     4   3054 use Data::CompactReadonly::V0::TiedArray;
  4         16  
  4         2835  
9              
10             sub _init {
11 51     51   207 my($class, %args) = @_;
12 51         165 my($root, $offset) = @args{qw(root offset)};
13              
14 51         214 my $object = bless({
15             root => $root,
16             offset => $offset
17             }, $class);
18              
19 51 100       191 if($root->_tied()) {
20 20         97 tie my @array, 'Data::CompactReadonly::V0::TiedArray', $object;
21 20         161 return \@array;
22             } else {
23 31         350 return $object;
24             }
25             }
26              
27             # write an Array to the file at the current offset
28             sub _create {
29 21     21   102 my($class, %args) = @_;
30 21         49 my $fh = $args{fh};
31 21         145 $class->_stash_already_seen(%args);
32 21         2322 (my $scalar_type = $class) =~ s/Array/Scalar/;
33              
34             # node header
35             print $fh $class->_type_byte_from_class().
36 21         143 $scalar_type->_get_bytes_from_word(1 + $#{$args{data}});
  21         152  
37              
38             # empty pointer table
39 21         136 my $table_start_ptr = tell($fh);
40 21         83 print $fh "\x00" x $args{ptr_size} x (1 + $#{$args{data}});
  21         300  
41 21         200 $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         48 foreach my $index (0 .. $#{$args{data}}) {
  21         148  
46 90         280 my $this_data = $args{data}->[$index];
47 90         730 $class->_seek(%args, pointer => $table_start_ptr + $index * $args{ptr_size});
48 90 100       446 if(my $ptr = $class->_get_already_seen(%args, data => $this_data)) {
49 17         472 print $fh $class->_encode_ptr(%args, pointer => $ptr);
50             } else {
51 73         1477 print $fh $class->_encode_ptr(%args, pointer => $class->_get_next_free_ptr(%args));
52 73         632 $class->_seek(%args, pointer => $class->_get_next_free_ptr(%args));
53 72         424 Data::CompactReadonly::V0::Node->_create(%args, data => $this_data);
54             }
55             }
56             }
57              
58             sub exists {
59 7     7 0 130 my($self, $element) = @_;
60 7         18 eval { $self->element($element) };
  7         22  
61 7 100       47 if($@ =~ /out of range/) {
    100          
62 3         27 return 0;
63             } elsif($@) {
64 2         14 die($@);
65             } else {
66 2         21 return 1;
67             }
68             }
69              
70             sub element {
71 140     140 0 4377 my($self, $element) = @_;
72 4     4   39 no warnings 'numeric';
  4         9  
  4         1385  
73 140 100       2016 die("$self: Invalid element: $element: negative\n")
74             if($element < 0);
75 138 100       682 die("$self: Invalid element: $element: non-integer\n")
76             if($element =~ /[^0-9]/);
77 135 100       569 die("$self: Invalid element: $element: out of range\n")
78             if($element > $self->count() - 1);
79              
80 129         436 $self->_seek($self->_offset() + $self->_scalar_type_bytes() + $element * $self->_ptr_size());
81 129         509 my $ptr = $self->_decode_ptr(
82             $self->_bytes_at_current_offset($self->_ptr_size())
83             );
84 129         445 $self->_seek($ptr);
85 129         461 return $self->_node_at_current_offset();
86             }
87              
88             sub indices {
89 2     2 0 7 my $self = shift;
90            
91 2 100       16 return [] if($self->count() == 0);
92 1         8 return [(0 .. $self->count() - 1)];
93             }
94              
95             1;