File Coverage

blib/lib/PerlIO/via/dynamic.pm
Criterion Covered Total %
statement 78 90 86.6
branch 19 30 63.3
condition 1 3 33.3
subroutine 15 18 83.3
pod 2 5 40.0
total 115 146 78.7


line stmt bran cond sub pod time code
1             package PerlIO::via::dynamic;
2 4     4   44645 use strict;
  4         9  
  4         230  
3             our $VERSION = '0.14';
4              
5             =head1 NAME
6              
7             PerlIO::via::dynamic - dynamic PerlIO layers
8              
9             =head1 SYNOPSIS
10              
11             open $fh, $fname;
12             $p = PerlIO::via::dynamic->new
13             (translate =>
14             sub { $_[1] =~ s/\$Filename[:\w\s\-\.\/\\]*\$/\$Filename: $fname\$/e},
15             untranslate =>
16             sub { $_[1] =~ s/\$Filename[:\w\s\-\.\/\\]*\$/\$Filename\$/});
17             $p->via ($fh);
18             binmode $fh, $p->via; # deprecated
19              
20             =head1 DESCRIPTION
21              
22             C is used for creating dynamic L
23             layers. It is useful when the behavior or the layer depends on
24             variables. You should not use this module as via layer directly (ie
25             :via(dynamic)).
26              
27             Use the constructor to create new layers, with two arguments:
28             translate and untranslate. Then use C<$p->via ($fh)> to wrap the
29             handle. Once <$fh> is destroyed, the temporary namespace for the IO
30             layer will be removed.
31              
32             Note that PerlIO::via::dynamic uses the scalar fields to reference to
33             the object representing the dynamic namespace.
34              
35             =head1 OPTIONS
36              
37             =over
38              
39             =item translate
40              
41             A function that translate buffer upon I.
42              
43             =item untranslate
44              
45             A function that translate buffer upon I.
46              
47             =item use_read
48              
49             Use C instead of C for the layer. Useful when caller
50             expect exact amount of data from read, and the C function
51             might return different length.
52              
53             By default C creates line-based layer to make
54             C implementation easier.
55              
56             =back
57              
58             =cut
59              
60 4     4   4027 use Symbol qw(delete_package gensym);
  4         3667  
  4         350  
61 4     4   24 use Scalar::Util qw(weaken);
  4         12  
  4         525  
62 4     4   4113 use IO::Handle;
  4         26151  
  4         581  
63              
64             sub PUSHED {
65 4 50   4 0 6418 die "this should not be via directly"
66             if $_[0] eq __PACKAGE__;
67 4         22 my $p = bless gensym(), $_[0];
68              
69 4 50 33     85 if ($] == 5.010000 && ref($_[-1]) eq 'GLOB') {
70             # This is to workaround a core bug in perl 5.10.0, see
71             # http://rt.perl.org/rt3/Public/Bug/Display.html?id=54934
72 0         0 require Internals;
73 0         0 Internals::SetRefCount($_[-1], Internals::GetRefCount($_[-1])+1);
74             }
75 4     4   32 no strict 'refs';
  4         9  
  4         1361  
76             # make sure the blessed glob is destroyed
77             # earlier than the object representing the namespace.
78 4         8 ${*$p} = ${"$_[0]::EGO"};
  4         31  
  4         16  
79              
80 4         90 return $p;
81             }
82              
83 1     1 1 2 sub translate {
84             }
85              
86 0     0 1 0 sub untranslate {
87             }
88              
89             sub _FILL {
90 6     6   180 my $line = readline( $_[1] );
91 6 100       30 $_[0]->untranslate ($line) if defined $line;
92 6         79 $line;
93             }
94              
95             sub READ {
96 0     0   0 my $ret = read $_[3], $_[1], $_[2];
97 0 0       0 return $ret unless $ret > 0;
98 0         0 $_[0]->untranslate ($_[1]);
99 0         0 return length ($_[1]);
100             }
101              
102             sub WRITE {
103 1     1   11 my $buf = $_[1];
104 1         6 $_[0]->translate($buf);
105 1         9 $_[2]->autoflush (1);
106 1 50       43 (print {$_[2]} $buf) ? length ($buf) : -1;
  1         84  
107             }
108              
109             sub SEEK {
110 0     0   0 seek ($_[3], $_[1], $_[2]);
111             }
112              
113             sub new {
114 4     4 0 673 my ($class, %arg) = @_;
115 4         9 my $self = {};
116 4         20 my $package = 'PerlIO::via::dynamic'.substr("$self", 7, -1);
117 4 50       471 eval qq|
118             package $package;
119             our \@ISA = qw($class);
120              
121             1;
122             | or die $@;
123              
124 4     4   21 no strict 'refs';
  4         7  
  4         1621  
125 4         23 for (qw/translate untranslate/) {
126 8 100       34 *{"$package\::$_"} = delete $arg{$_}
  7         46  
127             if exists $arg{$_}
128             }
129 4         14 %$self = %arg;
130 4 50       24 unless ($self->{use_read}) {
131 4         10 *{"$package\::FILL"} = *PerlIO::via::dynamic::_FILL;
  4         31  
132             }
133 4         12 bless $self, $package;
134 4         6 ${"$package\::EGO"} = $self;
  4         24  
135 4         18 weaken ${"$package\::EGO"};
  4         29  
136 4         14 return $self;
137             }
138              
139             sub via {
140 4     4 0 1424 my ($self, $fh) = @_;
141 4         16 my $via = ':via('.ref ($_[0]).')';
142 4 100       17 unless ($fh) {
143             # 0.01 compatibility
144 1         8 $self->{nogc} = 1;
145 1         32 return $via;
146             }
147 3 50   2   98 binmode ($fh, $via) or die $!;
  2         17  
  2         4  
  2         16  
148 3 50       17 if (defined *$fh{SCALAR}) {
149 3 50       10 if (defined *$fh{ARRAY}) {
150 0         0 warn "handle $fh cannot hold references, namespace won't be cleaned";
151 0         0 $self->{nogc} = 1;
152             }
153             else {
154 3         46 ${*$fh}[0] = $self;
  3         13  
155             }
156             }
157             else {
158 0         0 ${*$fh} = $self;
  0         0  
159             }
160             }
161              
162             sub DESTROY {
163 8     8   2570 my ($self) = @_;
164 8 100       97 return unless UNIVERSAL::isa ($self, 'HASH');
165 4 100       135 return if $self->{nogc};
166              
167 4     4   26 no strict 'refs';
  4         7  
  4         605  
168 3         6 my $ref = ref($self);
169 3         24 my ($leaf) = ($ref =~ /([^:]+)$/);
170 3         8 $leaf .= '::';
171              
172 3         5 for my $sym (keys %{$ref.'::'}) {
  3         22  
173 45 50       78 undef ${$ref.'::'}{$sym}
  45         156  
174             if $sym;
175             }
176              
177 3         65 delete $PerlIO::via::{$leaf};
178             }
179              
180             =head1 AUTHORS
181              
182             Chia-liang Kao Eclkao@clkao.orgE
183              
184             =head1 COPYRIGHT
185              
186             Copyright 2004 by Chia-liang Kao Eclkao@clkao.orgE.
187              
188             This program is free software; you can redistribute it and/or modify it
189             under the same terms as Perl itself.
190              
191             See L
192              
193             =cut
194              
195             1;