File Coverage

blib/lib/Tie/Watch.pm
Criterion Covered Total %
statement 130 176 73.8
branch 31 60 51.6
condition n/a
subroutine 48 72 66.6
pod 5 7 71.4
total 214 315 67.9


line stmt bran cond sub pod time code
1             $Tie::Watch::VERSION = '1.2';
2              
3             package Tie::Watch;
4              
5             =head1 NAME
6              
7             Tie::Watch - place watchpoints on Perl variables.
8              
9             =head1 SYNOPSIS
10              
11             use Tie::Watch;
12              
13             $watch = Tie::Watch->new(
14             -variable => \$frog,
15             -debug => 1,
16             -shadow => 0,
17             -fetch => [\&fetch, 'arg1', 'arg2', ..., 'argn'],
18             -store => \&store,
19             -destroy => sub {print "Final value=$frog.\n"},
20             }
21             %vinfo = $watch->Info;
22             $args = $watch->Args(-fetch);
23             $val = $watch->Fetch;
24             print "val=", $watch->Say($val), ".\n";
25             $watch->Store('Hello');
26             $watch->Unwatch;
27              
28             =head1 DESCRIPTION
29              
30             This class module binds one or more subroutines of your devising to a
31             Perl variable. All variables can have B, B and
32             B callbacks. Additionally, arrays can define B,
33             B, B, B, B, B, B,
34             B, B, B and B callbacks, and hashes
35             can define B, B, B, B and B
36             callbacks. If these term are unfamiliar to you, I I suggest
37             you read L.
38              
39             With Tie::Watch you can:
40              
41             . alter a variable's value
42             . prevent a variable's value from being changed
43             . invoke a Perl/Tk callback when a variable changes
44             . trace references to a variable
45              
46             Callback format is patterned after the Perl/Tk scheme: supply either a
47             code reference, or, supply an array reference and pass the callback
48             code reference in the first element of the array, followed by callback
49             arguments. (See examples in the Synopsis, above.)
50              
51             Tie::Watch provides default callbacks for any that you fail to
52             specify. Other than negatively impacting performance, they perform
53             the standard action that you'd expect, so the variable behaves
54             "normally". Once you override a default callback, perhaps to insert
55             debug code like print statements, your callback normally finishes by
56             calling the underlying (overridden) method. But you don't have to!
57              
58             To map a tied method name to a default callback name simply lowercase
59             the tied method name and uppercase its first character. So FETCH
60             becomes Fetch, NEXTKEY becomes Nextkey, etcetera.
61              
62             Here are two callbacks for a scalar. The B (read) callback does
63             nothing other than illustrate the fact that it returns the value to
64             assign the variable. The B (write) callback uppercases the
65             variable and returns it. In all cases the callback I return the
66             correct read or write value - typically, it does this by invoking the
67             underlying method.
68              
69             my $fetch_scalar = sub {
70             my($self) = @_;
71             $self->Fetch;
72             };
73              
74             my $store_scalar = sub {
75             my($self, $new_val) = @_;
76             $self->Store(uc $new_val);
77             };
78              
79             Here are B and B callbacks for either an array or hash.
80             They do essentially the same thing as the scalar callbacks, but
81             provide a little more information.
82              
83             my $fetch = sub {
84             my($self, $key) = @_;
85             my $val = $self->Fetch($key);
86             print "In fetch callback, key=$key, val=", $self->Say($val);
87             my $args = $self->Args(-fetch);
88             print ", args=('", join("', '", @$args), "')" if $args;
89             print ".\n";
90             $val;
91             };
92              
93             my $store = sub {
94             my($self, $key, $new_val) = @_;
95             my $val = $self->Fetch($key);
96             $new_val = uc $new_val;
97             $self->Store($key, $new_val);
98             print "In store callback, key=$key, val=", $self->Say($val),
99             ", new_val=", $self->Say($new_val);
100             my $args = $self->Args(-store);
101             print ", args=('", join("', '", @$args), "')" if $args;
102             print ".\n";
103             $new_val;
104             };
105              
106             In all cases, the first parameter is a reference to the Watch object,
107             used to invoke the following class methods.
108              
109             =head1 METHODS
110              
111             =over 4
112              
113             =item $watch = Tie::Watch->new(-options => values);
114              
115             The watchpoint constructor method that accepts option/value pairs to
116             create and configure the Watch object. The only required option is
117             B<-variable>.
118              
119             B<-variable> is a I to a scalar, array or hash variable.
120              
121             B<-debug> (default 0) is 1 to activate debug print statements internal
122             to Tie::Watch.
123              
124             B<-shadow> (default 1) is 0 to disable array and hash shadowing. To
125             prevent infinite recursion Tie::Watch maintains parallel variables for
126             arrays and hashes. When the watchpoint is created the parallel shadow
127             variable is initialized with the watched variable's contents, and when
128             the watchpoint is deleted the shadow variable is copied to the original
129             variable. Thus, changes made during the watch process are not lost.
130             Shadowing is on my default. If you disable shadowing any changes made
131             to an array or hash are lost when the watchpoint is deleted.
132              
133             Specify any of the following relevant callback parameters, in the
134             format described above: B<-fetch>, B<-store>, B<-destroy>.
135             Additionally for arrays: B<-clear>, B<-extend>, B<-fetchsize>,
136             B<-pop>, B<-push>, B<-shift>, B<-splice>, B<-storesize> and
137             B<-unshift>. Additionally for hashes: B<-clear>, B<-delete>,
138             B<-exists>, B<-firstkey> and B<-nextkey>.
139              
140             =item $args = $watch->Args(-fetch);
141              
142             Returns a reference to a list of arguments for the specified callback,
143             or undefined if none.
144              
145             =item $watch->Fetch(); $watch->Fetch($key);
146              
147             Returns a variable's current value. $key is required for an array or
148             hash.
149              
150             =item %vinfo = $watch->Info();
151              
152             Returns a hash detailing the internals of the Watch object, with these
153             keys:
154              
155             %vinfo = {
156             -variable => SCALAR(0x200737f8)
157             -debug => '0'
158             -shadow => '1'
159             -value => 'HELLO SCALAR'
160             -destroy => ARRAY(0x200f86cc)
161             -fetch => ARRAY(0x200f8558)
162             -store => ARRAY(0x200f85a0)
163             -legible => above data formatted as a list of string, for printing
164             }
165              
166             For array and hash Watch objects, the B<-value> key is replaced with a
167             B<-ptr> key which is a reference to the parallel array or hash.
168             Additionally, for an array or hash, there are key/value pairs for
169             all the variable specific callbacks.
170              
171             =item $watch->Say($val);
172              
173             Used mainly for debugging, it returns $val in quotes if required, or
174             the string "undefined" for undefined values.
175              
176             =item $watch->Store($new_val); $watch->Store($key, $new_val);
177              
178             Store a variable's new value. $key is required for an array or hash.
179              
180             =item $watch->Unwatch();
181              
182             Stop watching the variable.
183              
184             =back
185              
186             =head1 EFFICIENCY CONSIDERATIONS
187              
188             If you can live using the class methods provided, please do so. You
189             can meddle with the object hash directly and improved watch
190             performance, at the risk of your code breaking in the future.
191              
192             =head1 AUTHOR
193              
194             Stephen O. Lidie
195              
196             =head1 HISTORY
197              
198             lusol@Lehigh.EDU, LUCC, 96/05/30
199             . Original version 0.92 release, based on the Trace module from Hans Mulder,
200             and ideas from Tim Bunce.
201              
202             lusol@Lehigh.EDU, LUCC, 96/12/25
203             . Version 0.96, release two inner references detected by Perl 5.004.
204              
205             lusol@Lehigh.EDU, LUCC, 97/01/11
206             . Version 0.97, fix Makefile.PL and MANIFEST (thanks Andreas Koenig).
207             Make sure test.pl doesn't fail if Tk isn't installed.
208              
209             Stephen.O.Lidie@Lehigh.EDU, Lehigh University Computing Center, 97/10/03
210             . Version 0.98, implement -shadow option for arrays and hashes.
211              
212             Stephen.O.Lidie@Lehigh.EDU, Lehigh University Computing Center, 98/02/11
213             . Version 0.99, finally, with Perl 5.004_57, we can completely watch arrays.
214             With tied array support this module is essentially complete, so its been
215             optimized for speed at the expense of clarity - sorry about that. The
216             Delete() method has been renamed Unwatch() because it conflicts with the
217             builtin delete().
218              
219             Stephen.O.Lidie@Lehigh.EDU, Lehigh University Computing Center, 99/04/04
220             . Version 1.0, for Perl 5.005_03, update Makefile.PL for ActiveState, and
221             add two examples (one for Perl/Tk).
222              
223             sol0@lehigh.edu, Lehigh University Computing Center, 2003/06/07
224             . Version 1.1, for Perl 5.8, can trace a reference now, patch from Slaven
225             Rezic.
226              
227             sol0@lehigh.edu, Lehigh University Computing Center, 2005/05/17
228             . Version 1.2, for Perl 5.8, per Rob Seegel's suggestion, support array
229             DELETE and EXISTS.
230              
231             =head1 COPYRIGHT
232              
233             Copyright (C) 1996 - 2005 Stephen O. Lidie. All rights reserved.
234              
235             This program is free software; you can redistribute it and/or modify it under
236             the same terms as Perl itself.
237              
238             =cut
239              
240 1     1   787 use 5.004_57;;
  1         3  
  1         34  
241 1     1   5 use Carp;
  1         1  
  1         92  
242 1     1   5 use strict;
  1         11  
  1         35  
243 1     1   1266 use subs qw/normalize_callbacks/;
  1         23  
  1         5  
244 1     1   69 use vars qw/@array_callbacks @hash_callbacks @scalar_callbacks/;
  1         2  
  1         1742  
245              
246             @array_callbacks = qw/-clear -delete -destroy -exists -extend -fetch
247             -fetchsize -pop -push -shift -splice -store
248             -storesize -unshift/;
249             @hash_callbacks = qw/-clear -delete -destroy -exists -fetch -firstkey
250             -nextkey -store/;
251             @scalar_callbacks = qw/-destroy -fetch -store/;
252              
253             sub new {
254              
255             # Watch constructor. The *real* constructor is Tie::Watch->base_watch(),
256             # invoked by methods in other Watch packages, depending upon the variable's
257             # type. Here we supply defaulted parameter values and then verify them,
258             # normalize all callbacks and bind the variable to the appropriate package.
259              
260 5     5 1 94 my($class, %args) = @_;
261 5         11 my $version = $Tie::Watch::VERSION;
262 5         16 my (%arg_defaults) = (-debug => 0, -shadow => 1);
263 5         12 my $variable = $args{-variable};
264 5 50       14 croak "Tie::Watch::new(): -variable is required." if not defined $variable;
265              
266 5         11 my($type, $watch_obj) = (ref $variable, undef);
267 5 100       37 if ($type =~ /(SCALAR|REF)/) {
    100          
    50          
268 1         22 @arg_defaults{@scalar_callbacks} = (
269             [\&Tie::Watch::Scalar::Destroy], [\&Tie::Watch::Scalar::Fetch],
270             [\&Tie::Watch::Scalar::Store]);
271             } elsif ($type =~ /ARRAY/) {
272 2         56 @arg_defaults{@array_callbacks} = (
273             [\&Tie::Watch::Array::Clear], [\&Tie::Watch::Array::Delete],
274             [\&Tie::Watch::Array::Destroy], [\&Tie::Watch::Array::Exists],
275             [\&Tie::Watch::Array::Extend], [\&Tie::Watch::Array::Fetch],
276             [\&Tie::Watch::Array::Fetchsize], [\&Tie::Watch::Array::Pop],
277             [\&Tie::Watch::Array::Push], [\&Tie::Watch::Array::Shift],
278             [\&Tie::Watch::Array::Splice], [\&Tie::Watch::Array::Store],
279             [\&Tie::Watch::Array::Storesize], [\&Tie::Watch::Array::Unshift]);
280             } elsif ($type =~ /HASH/) {
281 2         44 @arg_defaults{@hash_callbacks} = (
282             [\&Tie::Watch::Hash::Clear], [\&Tie::Watch::Hash::Delete],
283             [\&Tie::Watch::Hash::Destroy], [\&Tie::Watch::Hash::Exists],
284             [\&Tie::Watch::Hash::Fetch], [\&Tie::Watch::Hash::Firstkey],
285             [\&Tie::Watch::Hash::Nextkey], [\&Tie::Watch::Hash::Store]);
286             } else {
287 0         0 croak "Tie::Watch::new() - not a variable reference.";
288             }
289 5         13 my(@margs, %ahsh, $args, @args);
290 5         43 @margs = grep ! defined $args{$_}, keys %arg_defaults;
291 5         18 %ahsh = %args; # argument hash
292 5         30 @ahsh{@margs} = @arg_defaults{@margs}; # fill in missing values
293 5         18 normalize_callbacks \%ahsh;
294              
295 5 100       37 if ($type =~ /(SCALAR|REF)/) {
    100          
    50          
296 1         10 $watch_obj = tie $$variable, 'Tie::Watch::Scalar', %ahsh;
297             } elsif ($type =~ /ARRAY/) {
298 2         17 $watch_obj = tie @$variable, 'Tie::Watch::Array', %ahsh;
299             } elsif ($type =~ /HASH/) {
300 2         13 $watch_obj = tie %$variable, 'Tie::Watch::Hash', %ahsh;
301             }
302 5         36 $watch_obj;
303              
304             } # end new, Watch constructor
305              
306             sub Args {
307              
308             # Return a reference to a list of callback arguments, or undef if none.
309             #
310             # $_[0] = self
311             # $_[1] = callback type
312              
313 0 0   0 1 0 defined $_[0]->{$_[1]}->[1] ? [@{$_[0]->{$_[1]}}[1 .. $#{$_[0]->{$_[1]}}]]
  0         0  
  0         0  
314             : undef;
315              
316             } # end Args
317              
318             sub Info {
319              
320             # Info() method subclassed by other Watch modules.
321             #
322             # $_[0] = self
323             # @_[1 .. $#_] = optional callback types
324              
325 0     0 1 0 my(%vinfo, @results);
326 0         0 my(@info) = (qw/-variable -debug -shadow/);
327 0 0       0 push @info, @_[1 .. $#_] if scalar @_ >= 2;
328 0         0 foreach my $type (@info) {
329 0         0 push @results, sprintf('%-10s: ', substr $type, 1) .
330             $_[0]->Say($_[0]->{$type});
331 0         0 $vinfo{$type} = $_[0]->{$type};
332             }
333 0         0 $vinfo{-legible} = [@results];
334 0         0 %vinfo;
335              
336             } # end Info
337              
338             sub Say {
339              
340             # For debugging, mainly.
341             #
342             # $_[0] = self
343             # $_[1] = value
344              
345 0 0   0 1 0 defined $_[1] ? (ref($_[1]) ne '' ? $_[1] : "'$_[1]'") : "undefined";
    0          
346              
347             } # end Say
348              
349             sub Unwatch {
350              
351             # Stop watching a variable by releasing the last reference and untieing it.
352             # Update the original variable with its shadow, if appropriate.
353             #
354             # $_[0] = self
355              
356 3     3 1 54 my $variable = $_[0]->{-variable};
357 3         8 my $type = ref $variable;
358 3 100       18 my $copy = $_[0]->{-ptr} if $type !~ /(SCALAR|REF)/;
359 3         7 my $shadow = $_[0]->{-shadow};
360 3         6 undef $_[0];
361 3 100       19 if ($type =~ /(SCALAR|REF)/) {
    100          
    50          
362 1         12 untie $$variable;
363             } elsif ($type =~ /ARRAY/) {
364 1         9 untie @$variable;
365 1 50       8 @$variable = @$copy if $shadow;
366             } elsif ($type =~ /HASH/) {
367 1         10 untie %$variable;
368 1 50       11 %$variable = %$copy if $shadow;
369             } else {
370 0         0 croak "Tie::Watch::Delete() - not a variable reference.";
371             }
372              
373             } # end Unwatch
374              
375             # Watch private methods.
376              
377             sub base_watch {
378              
379             # Watch base class constructor invoked by other Watch modules.
380              
381 5     5 0 35 my($class, %args) = @_;
382 5         42 my $watch_obj = {%args};
383 5         23 $watch_obj;
384              
385             } # end base_watch
386              
387             sub callback {
388            
389             # Execute a Watch callback, either the default or user specified.
390             # Note that the arguments are those supplied by the tied method,
391             # not those (if any) specified by the user when the watch object
392             # was instantiated. This is for performance reasons, and why the
393             # Args() method exists.
394             #
395             # $_[0] = self
396             # $_[1] = callback type
397             # $_[2] through $#_ = tied arguments
398              
399 38     38 0 74 &{$_[0]->{$_[1]}->[0]} ($_[0], @_[2 .. $#_]);
  38         134  
400              
401             } # end callback
402              
403             sub normalize_callbacks {
404              
405             # Ensure all callbacks are normalized in [\&code, @args] format.
406              
407 5     5   8 my($args_ref) = @_;
408 5         8 my($cb, $ref);
409 5         19 foreach my $arg (keys %$args_ref) {
410 62 100       205 next if $arg =~ /variable|debug|shadow/;
411 47         108 $cb = $args_ref->{$arg};
412 47         73 $ref = ref $cb;
413 47 50       186 if ($ref =~ /CODE/) {
    50          
414 0         0 $args_ref->{$arg} = [$cb];
415             } elsif ($ref !~ /ARRAY/) {
416 0         0 croak "Tie::Watch: malformed callback $arg=$cb.";
417             }
418             }
419              
420             } # end normalize_callbacks
421              
422             ###############################################################################
423              
424             package Tie::Watch::Scalar;
425              
426 1     1   8 use Carp;
  1         2  
  1         369  
427             @Tie::Watch::Scalar::ISA = qw/Tie::Watch/;
428              
429             sub TIESCALAR {
430              
431 1     1   5 my($class, %args) = @_;
432 1         3 my $variable = $args{-variable};
433 1         7 my $watch_obj = Tie::Watch->base_watch(%args);
434 1         4 $watch_obj->{-value} = $$variable;
435 1 50       5 print "WatchScalar new: $variable created, \@_=", join(',', @_), "!\n"
436             if $watch_obj->{-debug};
437 1         6 bless $watch_obj, $class;
438              
439             } # end TIESCALAR
440              
441 0     0   0 sub Info {$_[0]->SUPER::Info('-value', @Tie::Watch::scalar_callbacks)}
442              
443             # Default scalar callbacks.
444              
445 1     1   3 sub Destroy {undef %{$_[0]}}
  1         9  
446 1     1   5 sub Fetch {$_[0]->{-value}}
447 1     1   7 sub Store {$_[0]->{-value} = $_[1]}
448              
449             # Scalar access methods.
450              
451 1     1   5 sub DESTROY {$_[0]->callback('-destroy')}
452 1     1   8 sub FETCH {$_[0]->callback('-fetch')}
453 1     1   14 sub STORE {$_[0]->callback('-store', $_[1])}
454              
455             ###############################################################################
456              
457             package Tie::Watch::Array;
458              
459 1     1   5 use Carp;
  1         2  
  1         1161  
460             @Tie::Watch::Array::ISA = qw/Tie::Watch/;
461              
462             sub TIEARRAY {
463              
464 2     2   21 my($class, %args) = @_;
465 2         9 my($variable, $shadow) = @args{-variable, -shadow};
466 2 50       9 my @copy = @$variable if $shadow; # make a private copy of user's array
467 2 50       9 $args{-ptr} = $shadow ? \@copy : [];
468 2         13 my $watch_obj = Tie::Watch->base_watch(%args);
469 2 50       11 print "WatchArray new: $variable created, \@_=", join(',', @_), "!\n"
470             if $watch_obj->{-debug};
471 2         14 bless $watch_obj, $class;
472              
473             } # end TIEARRAY
474              
475 0     0   0 sub Info {$_[0]->SUPER::Info('-ptr', @Tie::Watch::array_callbacks)}
476              
477             # Default array callbacks.
478              
479 0     0   0 sub Clear {$_[0]->{-ptr} = ()}
480 0     0   0 sub Delete {delete $_[0]->{-ptr}->[$_[1]]}
481 1     1   2 sub Destroy {undef %{$_[0]}}
  1         18  
482 0     0   0 sub Exists {exists $_[0]->{-ptr}->[$_[1]]}
483 0     0   0 sub Extend {}
484 1     1   5 sub Fetch {$_[0]->{-ptr}->[$_[1]]}
485 2     2   3 sub Fetchsize {scalar @{$_[0]->{-ptr}}}
  2         9  
486 0     0   0 sub Pop {pop @{$_[0]->{-ptr}}}
  0         0  
487 1     1   3 sub Push {push @{$_[0]->{-ptr}}, @_[1 .. $#_]}
  1         8  
488 0     0   0 sub Shift {shift @{$_[0]->{-ptr}}}
  0         0  
489             sub Splice {
490 0     0   0 my $n = scalar @_; # splice() is wierd!
491 0 0       0 return splice @{$_[0]->{-ptr}}, $_[1] if $n == 2;
  0         0  
492 0 0       0 return splice @{$_[0]->{-ptr}}, $_[1], $_[2] if $n == 3;
  0         0  
493 0 0       0 return splice @{$_[0]->{-ptr}}, $_[1], $_[2], @_[3 .. $#_] if $n >= 4;
  0         0  
494             }
495 1     1   7 sub Store {$_[0]->{-ptr}->[$_[1]] = $_[2]}
496 1     1   3 sub Storesize {$#{@{$_[0]->{-ptr}}} = $_[1] - 1}
  1         2  
  1         0  
497 0     0   0 sub Unshift {unshift @{$_[0]->{-ptr}}, @_[1 .. $#_]}
  0         0  
498              
499             # Array access methods.
500              
501 0     0   0 sub CLEAR {$_[0]->callback('-clear')}
502 0     0   0 sub DELETE {$_[0]->callback('-delete', $_[1])}
503 1     1   5 sub DESTROY {$_[0]->callback('-destroy')}
504 0     0   0 sub EXISTS {$_[0]->callback('-exists', $_[1])}
505 0     0   0 sub EXTEND {$_[0]->callback('-extend', $_[1])}
506 1     1   11 sub FETCH {$_[0]->callback('-fetch', $_[1])}
507 2     2   16 sub FETCHSIZE {$_[0]->callback('-fetchsize')}
508 0     0   0 sub POP {$_[0]->callback('-pop')}
509 1     1   10 sub PUSH {$_[0]->callback('-push', @_[1 .. $#_])}
510 0     0   0 sub SHIFT {$_[0]->callback('-shift')}
511 0     0   0 sub SPLICE {$_[0]->callback('-splice', @_[1 .. $#_])}
512 1     1   15 sub STORE {$_[0]->callback('-store', $_[1], $_[2])}
513 1     1   10 sub STORESIZE {$_[0]->callback('-storesize', $_[1])}
514 0     0   0 sub UNSHIFT {$_[0]->callback('-unshift', @_[1 .. $#_])}
515              
516             ###############################################################################
517              
518             package Tie::Watch::Hash;
519              
520 1     1   6 use Carp;
  1         3  
  1         604  
521             @Tie::Watch::Hash::ISA = qw/Tie::Watch/;
522              
523             sub TIEHASH {
524              
525 2     2   10 my($class, %args) = @_;
526 2         25 my($variable, $shadow) = @args{-variable, -shadow};
527 2 50       11 my %copy = %$variable if $shadow; # make a private copy of user's hash
528 2 50       21 $args{-ptr} = $shadow ? \%copy : {};
529 2         12 my $watch_obj = Tie::Watch->base_watch(%args);
530 2 50       11 print "WatchHash new: $variable created, \@_=", join(',', @_), "!\n"
531             if $watch_obj->{-debug};
532 2         11 bless $watch_obj, $class;
533              
534             } # end TIEHASH
535              
536 0     0   0 sub Info {$_[0]->SUPER::Info('-ptr', @Tie::Watch::hash_callbacks)}
537              
538             # Default hash callbacks.
539              
540 0     0   0 sub Clear {$_[0]->{-ptr} = ()}
541 1     1   6 sub Delete {delete $_[0]->{-ptr}->{$_[1]}}
542 1     1   2 sub Destroy {undef %{$_[0]}}
  1         8  
543 2     2   18 sub Exists {exists $_[0]->{-ptr}->{$_[1]}}
544 7     7   28 sub Fetch {$_[0]->{-ptr}->{$_[1]}}
545 3     3   4 sub Firstkey {my $c = keys %{$_[0]->{-ptr}}; each %{$_[0]->{-ptr}}}
  3         11  
  3         4  
  3         18  
546 10     10   19 sub Nextkey {each %{$_[0]->{-ptr}}}
  10         46  
547 4     4   20 sub Store {$_[0]->{-ptr}->{$_[1]} = $_[2]}
548              
549             # Hash access methods.
550              
551 0     0   0 sub CLEAR {$_[0]->callback('-clear')}
552 1     1   11 sub DELETE {$_[0]->callback('-delete', $_[1])}
553 1     1   4 sub DESTROY {$_[0]->callback('-destroy')}
554 2     2   17 sub EXISTS {$_[0]->callback('-exists', $_[1])}
555 7     7   24 sub FETCH {$_[0]->callback('-fetch', $_[1])}
556 3     3   93 sub FIRSTKEY {$_[0]->callback('-firstkey')}
557 10     10   50 sub NEXTKEY {$_[0]->callback('-nextkey')}
558 4     4   38 sub STORE {$_[0]->callback('-store', $_[1], $_[2])}
559              
560             1;