File Coverage

blib/lib/Storable/AMF0.pm
Criterion Covered Total %
statement 77 78 98.7
branch 24 32 75.0
condition 4 4 100.0
subroutine 15 15 100.0
pod 6 6 100.0
total 126 135 93.3


line stmt bran cond sub pod time code
1             package Storable::AMF0;
2             # vim: ts=8 sw=4 sts=4 et
3 52     52   134073 use strict;
  52         66  
  52         1244  
4 52     52   177 use warnings;
  52         57  
  52         1186  
5 52     52   246 use Fcntl qw(:flock);
  52         58  
  52         5910  
6             our $VERSION = '1.23';
7 52     52   21081 use subs qw(freeze thaw);
  52         1009  
  52         220  
8 52     52   2250 use Exporter 'import';
  52         66  
  52         1438  
9 52     52   179 use Carp qw(croak);
  52         60  
  52         27442  
10             { our @Bool = (bless( do{\(my $o = 0)},'JSON::PP::Boolean'), bless( do{\(my $o = 1)},'JSON::PP::Boolean'));
11             local $@;
12             eval {
13             require Types::Serialiser;
14             @Bool = (Types::Serialiser::false(), Types::Serialiser::true());
15             1
16             } or
17             eval {
18             require JSON::XS;
19             @Bool = (JSON::XS::false(), JSON::XS::true());
20             1
21             };
22             };
23              
24             # Items to export into callers namespace by default. Note: do not export
25             # names by default without a very good reason. Use EXPORT_OK instead.
26             # Do not simply export all your public functions/methods/constants.
27              
28             our @EXPORT_TAGS_ALL = qw(
29             freeze thaw dclone
30             retrieve lock_retrieve lock_store lock_nstore store nstore
31             ref_lost_memory ref_clear
32             deparse_amf new_amfdate perl_date
33             new_date
34             parse_option
35             parse_serializator_option
36             );
37              
38             our %EXPORT_TAGS = ( 'all' => \@EXPORT_TAGS_ALL);
39             our @EXPORT_OK = ( @EXPORT_TAGS_ALL );
40              
41             sub retrieve($) {
42 32     32 1 61 my $file = shift;
43 32         37 my $lock = shift;
44              
45 32 50       1115 open my $fh, "<:raw", $file or croak "Fail on open file \"$file\" for reading $!";
46 32 100       98 flock $fh, LOCK_SH if $lock;
47 32         20 my $buf;
48 32         211 sysread $fh, $buf, (( sysseek $fh, 0, 2 ), sysseek $fh, 0,0)[0] ;
49 32         531 return thaw($buf);
50             }
51              
52             sub lock_retrieve($) {
53 6     6 1 12 $_[1] = 1;
54 6         12 goto &retrieve;
55             }
56              
57             sub store($$) {
58 15     15 1 41974 my ( $object, $file, $lock ) = @_;
59              
60 15         382 my $freeze = \freeze($object);
61 15 50       55 unless (defined $$freeze ){
62 0         0 croak "Bad object $@";
63             }
64             else {
65 15         19 my $fh;
66 15 100       28 if ($lock){
67 7 50       428 open $fh, ">>:raw", $file or croak "Fail on open file \"$file\" for writing $!";
68 7 50       251612 flock $fh, LOCK_EX if $lock;
69 7         204 truncate $fh, 0;
70 7         26 seek $fh,0,0;
71             }
72             else {
73 8 50       630 open $fh, ">:raw", $file or croak "Fail on open file \"$file\" for writing $!";
74             }
75 15 50       155 print $fh $$freeze if defined $$freeze;
76 15         502 close $fh;
77             };
78             }
79              
80             sub lock_store($$) {
81 7     7 1 21 $_[2] = 1;
82 7         41 goto &store;
83             }
84             sub ref_lost_memory($);
85             sub ref_clear($);
86             {{
87             require XSLoader;
88             XSLoader::load( 'Storable::AMF', $VERSION );
89 52     52   303 no warnings 'once';
  52         72  
  52         3037  
90             *nstore = \&store;
91             *lock_nstore = \&lock_store;
92              
93 52     52   200 no strict 'refs';
  52         65  
  52         29854  
94              
95             my $my_package = __PACKAGE__ . "::";
96             for my $other_package ( "Storable::AMF::", "Storable::AMF3::" ){
97             *{ $other_package . $_ } = *{ $my_package . $_} for qw(ref_clear ref_lost_memory VERSION);
98             }
99             *{"Storable::AMF::$_"} = *{"Storable::AMF0::$_"} for grep m/retrieve|store/, @EXPORT_OK;
100             }};
101              
102             *refaddr = \&Scalar::Util::refaddr;
103             *reftype = \&Scalar::Util::reftype;
104              
105             sub _ref_selfref($$);
106             sub _ref_selfref($$){
107 1447     1447   3883 require Scalar::Util;
108 1447         1143 my $obj_addr = shift;
109 1447         1229 my $value = shift;
110 1447         1733 my $addr = refaddr($value);
111 1447 100       3142 return unless defined $addr;
112 673 100       1653 if ( reftype($value) eq 'ARRAY' ) {
    50          
113              
114 364 100       854 return $$obj_addr{$addr} if exists $$obj_addr{$addr};
115 268         419 $$obj_addr{$addr} = 1;
116 268   100     503 _ref_selfref( $obj_addr, $_ ) && return 1 for @$value;
117 214         226 $$obj_addr{$addr} = 0;
118             }
119             elsif ( reftype($value) eq 'HASH' ) {
120              
121 309 100       659 return $$obj_addr{$addr} if exists $$obj_addr{$addr};
122 231         326 $$obj_addr{$addr} = 1;
123 231   100     581 _ref_selfref( $obj_addr, $_ ) && return 1 for values %$value;
124 213         217 $$obj_addr{$addr} = 0;
125             }
126              
127 427         948 return;
128             }
129              
130             sub ref_clear($) {
131 1581     1581 1 631595 my $ref = shift;
132 1581         1098 my %addr;
133 1581         3916 require Scalar::Util;
134 1581 100       3707 return unless ( refaddr($ref));
135 726         473 my @r;
136 726 100       1681 if ( reftype($ref) eq 'ARRAY' ) {
    50          
137 399         508 @r = @$ref;
138 399         413 @$ref = ();
139 399         795 ref_clear($_) for @r;
140             }
141             elsif ( reftype($ref) eq 'HASH' ) {
142 327         618 @r = values %$ref;
143 327         370 %$ref = ();
144 327         668 ref_clear($_) for @r;
145             }
146             }
147              
148             sub ref_lost_memory($) {
149 533     533 1 209206 my $ref = shift;
150 533         422 my %obj_addr;
151 533         738 return _ref_selfref( \%obj_addr, $ref );
152             }
153              
154             1;
155             __END__