File Coverage

blib/lib/Tie/Util.pm
Criterion Covered Total %
statement 115 117 98.2
branch 90 98 91.8
condition 22 35 62.8
subroutine 15 15 100.0
pod 7 7 100.0
total 249 272 91.5


line stmt bran cond sub pod time code
1             package Tie::Util;
2              
3 1     1   19803 use 5.008;
  1         4  
  1         47  
4              
5             $VERSION = '0.03';
6              
7             # B doesn't export this. I *hope* it doesn't change!
8 1     1   4 use constant SVprv_WEAKREF => 0x80000000; # from sv.h
  1         2  
  1         108  
9              
10 1     1   5 use Exporter 5.57 'import';
  1         20  
  1         30  
11 1     1   5 use Scalar::Util 1.09 qw 'reftype blessed weaken';
  1         16  
  1         1131  
12              
13             @EXPORT = qw 'is_tied weak_tie weaken_tie is_weak_tie tie tied';
14             @EXPORT_OK = 'fix_tie';
15             %EXPORT_TAGS = (all=>[@EXPORT,@EXPORT_OK]);
16              
17             {
18             my ($ref, $class);
19             sub _underload($) {
20 221     221   627 $ref = shift;
21 221         630 my $type = reftype $ref;
22             # This assumes that no one is overloading without loading
23             # overload.pm. I suppose I could change this to call
24             # UNIVERSAL::can($ref, "($sigil\{}") (at the risk of trig-
25             # ering negative reactions from OO-purists perusing
26             # this code :-).
27 221 100 66     1646 if(defined blessed $ref && $INC{'overload.pm'}) {
28 170 100 66     1278 my $sigil = $type eq 'GLOB' || $type eq 'IO' ? '*'
    100          
    100          
29             :$type eq 'HASH' ? '%'
30             :$type eq 'ARRAY' ? '@'
31             : '$';
32 170 50       649 if(defined overload::Method($ref,"$sigil\{}")) {
33 170         21272 $class = ref $ref;
34 170         317 bless $ref;
35             }
36             }
37 221         6245 return $ref;
38             }
39             sub _restore() {
40 221 100   221   942 defined $class and bless $ref, $class;
41 221         4180 undef $ref, undef $class
42             }
43             }
44              
45             sub expand($) {
46             local *_ = \do{my $x = shift};
47             my $done_type;
48             s<<<<(.*?)>>>><
49             my $code = $1;
50             my $type_decl = '';
51             unless($done_type++) {
52             $code =~ /\*(?:(\$\w+)|\{(.*?)})/;
53             $type_decl = "my \$type = reftype " . ($1||$2);
54             }
55             my $subst = "
56             $type_decl;
57             if(\$type eq 'GLOB' || \$type eq 'IO') {
58             $code
59             } elsif(\$type eq 'HASH') {
60             ";
61             (my $copy = $code) =~ y @*@%@;
62             $subst .= qq!
63             $copy
64             } elsif(\$type eq 'ARRAY') {
65             !;
66             ($copy = $code) =~ y ~*~@~;
67             $subst .= "
68             $copy
69             } else {
70             ";
71             $code =~ y&*&$&;
72             "$subst$code}";
73             >gse;
74             #local $SIG{__WARN__} = sub { warn shift;die $_ };
75 1 100 66 1 1 18 eval "$_}1" or die $@, "\n", $_;
  1 100 66 97 1 2  
  1 100 66 29 1 123  
  97 100 66 42 1 208  
  97 100 50 14   269  
  97 100 50     434  
  97 100 50     585  
  26 100 100     121  
  13 100 66     64  
  14 100 66     76  
  44 100       171  
  43 100       113  
  43 100       77  
  43 100       244  
  12 100       96  
  6 100       48  
  6 100       47  
  19 100       158  
  43 100       125  
  43 50       1030  
  29 50       1461  
  22 100       85  
  22 100       75  
  22 100       573  
  6 100       15  
  6 100       39  
  3 100       7  
  3 100       21  
  3 100       5  
  3 100       196  
  10 100       17  
  10 100       59  
  14 50       26  
  14 100       45  
  14 100       42  
  14 100       218  
  14         132  
  14         224  
  0         0  
  42         2380  
  42         123  
  42         89  
  42         114  
  42         268  
  10         60  
  5         37  
  6         60  
  21         812  
  42         874  
  42         204  
  42         215  
  14         53  
  14         26  
  14         38  
  14         88  
  4         9  
  2         6  
  2         6  
  6         13  
  14         31  
  0         0  
  14         17  
  14         223  
  14         73  
  4         16  
  2         9  
  2         10  
  6         32  
  14         46  
76             #warn $_;
77             }
78              
79             # This is what I first intended, but I realised that a to:: package allowed
80             # a weak tie as well, without requiring Yet Another function.
81             #expand<<'}';
82             #sub tie_to (\[%$@*]$) {
83             # my ($var, $obj) = @_;
84             # my $class = _underload $var;
85             # <<>>
86             # _restore;
87             # $obj
88             #}
89              
90             #*TIEARRAY = *TIESCALAR = *TIEHANDLE = *TIEHASH = sub { $_[1] };
91 34     34   1435 *to'TIEARRAY = *to'TIESCALAR = *to'TIEHANDLE = *to'TIEHASH = sub { $_[1] };
92              
93              
94             # :lvalue makes the following sub return the same scalar, as is evidenced
95             # by the following one-liner:
96             #
97             # perl -MScalar::Util=refaddr -le 'print refaddr \sub:lvalue { \
98             # print refaddr \my $x; $x}->()'
99             #
100             # (Remove the :lvalue and you get two different refaddrs.)
101              
102             expand<<'}';
103             sub tie(\[%$@*]$@):lvalue {
104             my($var,$class,@args) = @_; _underload $var;
105             #warn "$class: $args[0]";
106             my $ref_thereto;
107             <<<$ref_thereto =
108             \tie *$var, $class,
109             $class eq 'to'
110             ? $dummy ||= bless\my $dummy
111             : @args;>>>
112             _restore;
113             $$ref_thereto = $args[0], if $class eq 'to';
114             $$ref_thereto;
115             }
116              
117             expand<<'}';
118             sub is_tied (\[%$@*]) {
119             my ($var) = @_;
120             my $class = _underload $var;
121             <<>>
122             # If tied returns undef, it might still be tied, in which case all
123             # tie methods will die.
124             local *@;
125             eval {
126             if( $type eq 'GLOB' || $type eq 'IO' ){
127             no warnings 'unopened';
128             ()= tell $var
129             } elsif($type eq 'HASH') {
130             #()= %$var # We can't use this, because it might
131             # be an untied hash with a stale tied
132             # element, and we could get a
133             # false positive.
134             ()= scalar keys %$var
135             } elsif($type eq 'ARRAY') {
136             #()= @$var # same here
137             ()= $#$var;
138             } else {
139             ()= $$var
140             }
141             };
142             _restore;
143             return !!$@;
144             }
145              
146             sub weak_tie(\[%@$*]$@):lvalue{
147 9     9 1 574 my($var,$class,@args) = @_;
148 9         263 my $ref =\ &tie($var, $class, @args);
149 9         31 weaken $$ref;
150 9         25 $$ref;
151             }
152              
153             expand<<'}';
154             sub weaken_tie(\[%@$*]){
155             my $var = _underload shift;
156             my $obj;
157             <<<$obj = CORE::tied *$var;>>>
158             if(!defined $obj) {
159             _restore, return
160             }
161             # I have to re-tie it, since 'weaken tied' doesn't work.
162             local *{ref($obj).'::UNTIE'};
163             << $obj>>>;
164             _restore, return;
165             }
166              
167             expand<<'}';
168             sub is_weak_tie(\[%@$*]){
169             return undef unless &is_tied($_[0]);
170             _underload $_[0];
171             <<<
172             _restore,return !1 if not defined reftype CORE::tied *{$_[0]};
173             >>>
174              
175             # We have to use B here because 'isweak tied' fails.
176              
177             # From pp_sys.c in the perl source code:
178             # /* For tied filehandles, we apply tiedscalar magic to the IO
179             # slot of the GP rather than the GV itself. AMS 20010812 */
180             my $thing = shift;
181             $type eq 'GLOB' and $thing = *$thing{IO};
182             _restore;
183              
184             exists & svref_2object or require(B), B->import('svref_2object');
185             for(svref_2object($thing)->MAGIC) {
186             $_->TYPE =~ /^[qPp]\z/ and
187             return !!($_->OBJ->FLAGS & SVprv_WEAKREF);
188             }
189             die "Tie::Util internal error: This tied variable has no tie magic! Bug reports welcome.";
190             }
191              
192             sub tied(\[%@$*]):lvalue{
193 46 50   46 1 3649 return undef unless &is_tied($_[0]);
194              
195             # From pp_sys.c in the perl source code:
196             # /* For tied filehandles, we apply tiedscalar magic to the IO
197             # slot of the GP rather than the GV itself. AMS 20010812 */
198 46         86 my $thing = shift;
199 46         238 _underload $thing;
200 46 100       320 reftype $thing eq 'GLOB' and $thing = *$thing{IO};
201 46         85 _restore;
202              
203 46 100       169 exists & svref_2object or require(B), B->import('svref_2object');
204 46         402 for(svref_2object($thing)->MAGIC) {
205 54 100       736 $_->TYPE =~ /^[qPp]\z/ and
206             $thing = $_->OBJ->object_2svref;
207             }
208 46 50       184 $thing or die "Tie::Util internal error: " .
209             "This tied variable has no tie magic! Bug reports welcome.";
210 46         374 $$thing;
211             }
212              
213             sub fix_tie($):lvalue {
214 2     2 1 1786 for my $tie ($_[0]) {
215             return
216 2 50 33     21 unless ref \$tie eq REF and defined( my $tie_obj = CORE::tied $tie);
217 2         5 my $pkg = ref $tie_obj;
218 2 50       8 length $pkg or $pkg = $tie_obj;
219 2         3 local *{"$pkg:\:STORE"};
  2         12  
220 2         4 undef *{"$pkg:\:STORE"};
  2         8  
221 2         5 eval { $tie = undef }
  2         40  
222             }
223 2         7 $_[0];
224             }
225              
226             undef *expand;
227              
228             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!()__END__()!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229              
230             =head1 NAME
231              
232             Tie::Util - Utility functions for fiddling with tied variables
233              
234             =head1 VERSION
235              
236             Version 0.03
237              
238             This is a beta version. If you could please test it and report any bugs
239             (via e-mail), I would be grateful.
240              
241             =head1 SYNOPSIS
242              
243             use Tie::Util;
244            
245             use Tie::RefHash;
246             tie %hash, 'Tie::RefHash';
247            
248             $obj = tied %hash;
249             tie %another_hash, to => $obj; # two hashes now tied to the same object
250             Tie::Util::tie @whatever, to => "MyClass"; # tie @whatever to a class
251            
252             is_tied %hash; # returns true
253            
254             $obj = weak_tie %hash3, 'Tie::RefHash';
255             # %hash3 now holds a weak reference to the Tie::RefHash object.
256            
257             weaken_tie %another_hash; # weaken an existing tie
258            
259             is_weak_tie %hash3; # returns true
260             is_weak_tie %hash; # returns false but defined
261             is_weak_tie %hash4; # returns undef (not tied)
262              
263              
264             =head1 DESCRIPTION
265              
266             This module provides a few subroutines for examining and modifying
267             tied variables, including those that hold weak references to the
268             objects to which they are tied (weak ties).
269              
270             It also provides tie constructors in the C namespace, so that you can
271             tie variables to existing objects, like this:
272              
273             tie $var, to => $obj;
274             weak_tie @var, to => $another_obj; # for a weak tie
275              
276             It also allows one to tie a variable to a package, instead of an object
277             (see below).
278              
279             =for comment
280             This is how it would read if perl let me override tie
281             , if the C function is imported (which is done by default).
282              
283             =head1 FUNCTIONS
284              
285             All the following functions are exported by default, except for C.
286             You can choose to
287             import only a few, with C, or none at
288             all, with C.
289              
290             =over 4
291              
292             =item is_tied [*%@$]var
293              
294             Similar to the built-in L function, but it returns a
295             simple scalar.
296              
297             With this function you don't have to worry about whether the object to
298             which a variable is tied overloads its booleanness (like L
299             I), so you can simply write C instead
300             of C.
301              
302             Furthermore, it will still return true if it is a weak tie that has gone
303             stale (the object to which it was tied [without holding a reference count]
304             has lost all other references, so the variable is now tied to C),
305             whereas C returns C in such cases.
306              
307             =item tie [*%@$]var, $package, @args
308              
309             =item &tie( \$var, $package, @args );
310              
311             perl did not allow the built-in to be overridden until version 5.13.3, so,
312             for older perls, you have to
313             call this with the C prefix or use the C<&tie(...)> notation.
314              
315             This is just like the built-in function except that, when called with
316             'to' as the package, it allows you to tie the variable to I
317             (well,
318             any scalar at least). This is
319             probably only useful for tying a variable to a package, as opposed to an
320             object. (Believe it or not, it's just pure Perl; no XS trickery.)
321              
322             Otherwise the behaviour is identical to the core function.
323              
324             =item weak_tie [*%@$]var, $package, @args
325              
326             Like perl's L function, this calls C<$package>'s tie
327             constructor, passing
328             it the C<@args>, and ties the variable to the returned object. But the tie
329             that it creates is a weak one, i.e., the tied variable does not hold a
330             reference count on the object.
331              
332             Like C, above, it lets you tie the variable to anything, not just an
333             object.
334              
335             =item weaken_tie [*%@$]var
336              
337             This turns an existing tie into a weak one.
338              
339             =item is_weak_tie [*%@$]var
340              
341             Returns a defined true or false, indicating whether a tied variable is
342             weakly tied. Returns C if the variable is not tied.
343              
344             NOTE: This used to return true for a variable tied to C. Now (as of
345             version 0.02) it returns false, because the tie does not actually hold a
346             weak reference; it holds no reference at all.
347              
348             =item tied [*%@$]var
349              
350             =item &tied( \$var )
351              
352             Like perl's L function, this returns what the variable
353             is tied to, but, unlike the built-in, it returns the actual scalar that the
354             tie uses (instead of copying it), so you can, for instance, check to see
355             whether the variable is
356             tied to a tied variable with C.
357              
358             As with C, you need to use the C prefix or the ampersand
359             form if your perl
360             version is less than 5.13.3.
361              
362             =item fix_tie (scalar lvalue expression)
363              
364             This provides a work-around for a bug in perl that was introduced in 5.8.9
365             and 5.10.0, but was fixed in 5.13.2: If you assign a reference to a
366             tied scalar variable, some operators will operate on that reference,
367             instead of
368             calling C and using its return value.
369              
370             If you assign a reference to a tied variable, or a value that I be a
371             reference to a variable that I be tied, then you can 'fix' the tie
372             afterwards by called C on it. C is an lvalue function
373             that returns its first argument after fixing it, so you can replace code
374             like
375              
376             ($var = $value) =~ s/fror/dwat/;
377              
378             with
379              
380             fix_tie( $var = $value ) =~ s/fror/dwat/;
381              
382             =back
383              
384             =head1 THE to NAMESPACE
385              
386             Tie::Util installs tie constructors in the 'to' package to work its magic.
387             If anyone else wants to release a module named 'to', just let me know and
388             I'll give you comaint status, as long as you promise not to break
389             Tie::Util!
390              
391             =head1 PREREQUISITES
392              
393             perl 5.8.0 or later
394              
395             Exporter 5.57 or later
396              
397             Scalar::Util 1.09 or later
398              
399             =head1 BUGS
400              
401             =over 4
402              
403             =item *
404              
405             This module does not provide a single function to access the information
406             obscured by
407             a tie. For
408             that, you can simply untie a variable, access its contents, and re-tie it
409             (which is fairly trivial with the functions this module already provides).
410              
411             =back
412              
413             To report bugs, please e-mail the author.
414              
415             =head1 AUTHOR & COPYRIGHT
416              
417             Copyright (C) 2007-10 Father Chrysostomos
418             [dot] org>
419              
420             This program is free software; you may redistribute it and/or modify
421             it under the same terms as perl.
422              
423             =head1 SEE ALSO
424              
425             The L and L functions in the
426             L man page.
427              
428             The L man page.
429              
430             L's L function
431              
432             The L module.
433              
434             L, for which I wrote two of these functions.