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   36 use warnings;
  4         9  
  4         136  
5 4     4   23 use strict;
  4         8  
  4         113  
6 4     4   66 use base qw(Data::CompactReadonly::V0::Collection Data::CompactReadonly::Array);
  4         38  
  4         2446  
7              
8 4     4   2015 use Data::CompactReadonly::V0::TiedArray;
  4         12  
  4         2108  
9              
10             sub _init {
11 51     51   173 my($class, %args) = @_;
12 51         144 my($root, $offset) = @args{qw(root offset)};
13              
14 51         201 my $object = bless({
15             root => $root,
16             offset => $offset
17             }, $class);
18              
19 51 100       160 if($root->_tied()) {
20 20         108 tie my @array, 'Data::CompactReadonly::V0::TiedArray', $object;
21 20         169 return \@array;
22             } else {
23 31         246 return $object;
24             }
25             }
26              
27             # write an Array to the file at the current offset
28             sub _create {
29 21     21   96 my($class, %args) = @_;
30 21         53 my $fh = $args{fh};
31 21         131 $class->_stash_already_seen(%args);
32 21         1875 (my $scalar_type = $class) =~ s/Array/Scalar/;
33              
34             # node header
35             print $fh $class->_type_byte_from_class().
36 21         127 $scalar_type->_get_bytes_from_word(1 + $#{$args{data}});
  21         134  
37              
38             # empty pointer table
39 21         192 my $table_start_ptr = tell($fh);
40 21         95 print $fh "\x00" x $args{ptr_size} x (1 + $#{$args{data}});
  21         216  
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         77 foreach my $index (0 .. $#{$args{data}}) {
  21         135  
46 90         295 my $this_data = $args{data}->[$index];
47 90         589 $class->_seek(%args, pointer => $table_start_ptr + $index * $args{ptr_size});
48 90 100       528 if(my $ptr = $class->_get_already_seen(%args, data => $this_data)) {
49 20         411 print $fh $class->_encode_ptr(%args, pointer => $ptr);
50             } else {
51 70         1268 print $fh $class->_encode_ptr(%args, pointer => $class->_get_next_free_ptr(%args));
52 70         612 $class->_seek(%args, pointer => $class->_get_next_free_ptr(%args));
53 69         434 Data::CompactReadonly::V0::Node->_create(%args, data => $this_data);
54             }
55             }
56             }
57              
58             sub exists {
59 7     7 0 92 my($self, $element) = @_;
60 7         17 eval { $self->element($element) };
  7         17  
61 7 100       35 if($@ =~ /out of range/) {
    100          
62 3         20 return 0;
63             } elsif($@) {
64 2         10 die($@);
65             } else {
66 2         14 return 1;
67             }
68             }
69              
70             sub element {
71 134     134 0 1198 my($self, $element) = @_;
72 4     4   35 no warnings 'numeric';
  4         26  
  4         1203  
73 134 100       372 die("$self: Invalid element: $element: negative\n")
74             if($element < 0);
75 132 100       672 die("$self: Invalid element: $element: non-integer\n")
76             if($element =~ /[^0-9]/);
77 129 100       444 die("$self: Invalid element: $element: out of range\n")
78             if($element > $self->count() - 1);
79              
80 123         344 $self->_seek($self->_offset() + $self->_scalar_type_bytes() + $element * $self->_ptr_size());
81 123         525 my $ptr = $self->_decode_ptr(
82             $self->_bytes_at_current_offset($self->_ptr_size())
83             );
84 123         392 $self->_seek($ptr);
85 123         509 return $self->_node_at_current_offset();
86             }
87              
88             sub indices {
89 2     2 0 6 my $self = shift;
90            
91 2 100       8 return [] if($self->count() == 0);
92 1         4 return [(0 .. $self->count() - 1)];
93             }
94              
95             1;