File Coverage

blib/lib/Class/Hash.pm
Criterion Covered Total %
statement 127 134 94.7
branch 48 52 92.3
condition n/a
subroutine 18 19 94.7
pod 11 11 100.0
total 204 216 94.4


line stmt bran cond sub pod time code
1             package Class::Hash;
2              
3 13     13   3640767 use 5.008;
  13         58  
  13         614  
4 13     13   79 use strict;
  13         35  
  13         641  
5 13     13   79 use warnings;
  13         31  
  13         457  
6              
7 13     13   78 use Carp;
  13         37  
  13         1547  
8 13     13   20091 use Tie::Hash;
  13         20687  
  13         35589  
9              
10             our $VERSION = '1.01';
11              
12             =head1 NAME
13              
14             Class::Hash - Perl extension for hashes that look like classes
15              
16             =head1 SYNOPSIS
17              
18             use Class::Hash ALL_METHODS => 1;
19              
20             $hash = Class::Hash->new(foo => 'bar');
21              
22             print "foo: ",$hash->foo,"\n"; # prints "foo: bar"
23              
24             $hash->hello = "World";
25             print "Hello ",$hash->hello,"!\n"; # prints "Hello World!"
26              
27             # Other accessor methods
28             $hash->store("foo", "something else");
29             $foo = $hash->fetch("foo");
30              
31             # Or just use it like a plain hash ref!
32             $stuff->{foo} = "whoa dude!";
33              
34             =head1 ABSTRACT
35              
36             This component provides a method-based interface to a hash. Occasionally, it's
37             more convenient to have named methods to access a hash than hash keys. This
38             module generalizes this behavior.
39              
40             =head1 DESCRIPTION
41              
42             This component provides a method-based interface to a hash. Occasionally, it's
43             more convenient to have named methods to access a hash than hash keys. This
44             module generalizes this behavior. It tries to work the tied hash interface
45             inside-out.
46              
47             This module tries to do as much or as little for you as you want and provides a
48             number of configuration options. The options allow you to determine what kind
49             of interface the object has. The interface may also be altered after-the-fact.
50             See L for details.
51              
52             =head1 METHODS
53              
54             =over
55              
56             =item use Class::Hash [ %default_options ];
57              
58             When telling Perl to C C, you may specify any default options
59             that should be made available. By default, all options are I--giving you
60             the simplest set of features. The default options can be modified per-instance
61             and options can be modified after instantiation via C.
62              
63             For more information on the options, see L.
64              
65             =cut
66              
67             our $AUTOLOAD;
68             my %meta_options = (
69             METHOD_BASED => [ qw( no_named_accessors fetch store delete clear exists each keys values ) ],
70             ALL_METHODS => [ qw( fetch store delete clear exists each keys values ) ],
71             );
72              
73             # We don't want this to be exposed in the Class::Hash package
74             my $process_options = sub {
75             my ($options) = @_;
76              
77             for my $key (keys %meta_options) {
78             if (defined $$options{$key}) {
79             $$options{$_} = $$options{$key} for (@{$meta_options{$key}});
80             delete $$options{$key};
81             }
82             }
83              
84             $options;
85             };
86              
87             my %defaults;
88             sub import : lvalue {
89 13 50   13   179 if (ref $_[0]) {
90 0         0 $AUTOLOAD = (ref $_[0]).'::import';
91 0         0 return shift->AUTOLOAD(@_);
92             }
93            
94 13         31 my $class = shift;
95 13         29 my %options;
96 13 50       69 if (ref $_[0] eq 'HASH') {
97 0         0 %options = %{$_[0]};
  0         0  
98             } else {
99 13         42 %options = @_;
100             }
101              
102 13         24 %defaults = %{ &$process_options(\%options) };
  13         168  
103             }
104              
105             =item $hash = Class::Hash-Enew( [ %hash ] [, \%options ] )
106              
107             This initializes a particular "hash". The first list of arguments are the
108             initial key/value pairs to set in the hash. If none are given, the hash is
109             initially empty.
110              
111             The second argument is also optional. It is a hash reference containing the
112             optiosn to set on this instance of the hash. If not options are given, then the
113             defaults set during import are used. FOr more information on the options, see
114             L.
115              
116             I: It should be noted that:
117              
118             $hash = Class::Hash->new;
119              
120             is not the same as:
121              
122             $hash2 = $hash->new;
123              
124             The first will be treated as a constructor and the second as an accessor.
125              
126             =cut
127              
128             sub new : lvalue {
129 15 50   15 1 1211 if (ref $_[0]) {
130 0         0 $AUTOLOAD = (ref $_[0]).'::new';
131 0         0 return shift->AUTOLOAD(@_);
132             }
133              
134 15         65 my ($class, @args) = @_;
135              
136 15         62 my $options = { %defaults };
137 15         169 tie my %self, 'Tie::ExtraHash', $options;
138 15         177 for (my $i = 0; $i < @args;) {
139 45 100       134 if (ref $args[$i] eq 'HASH') {
140 12         50 my $opts = &$process_options($args[$i]);
141 12         72 while (my ($k, $v) = each %$opts) {
142 36         127 $$options{$k} = $v;
143             }
144              
145 12         42 ++$i;
146             } else {
147 33         193 $self{$args[$i]} = $args[$i + 1];
148 33         296 $i += 2;
149             }
150             }
151              
152 15         104 my $result = bless \%self, $class;
153             }
154              
155             =item $value = $hash-EI [ ($new_value) ]
156              
157             =item $value = Class::Hash-EI [ ($hash, $new_value) ]
158              
159             This method is the accessor for the hash-key named I. This can be any
160             valid Perl symbol and is the simplest way of accessing values in the hash. The
161             current value is returned by the accessor--which is first set to C<$new_value>
162             if specified.
163              
164             It is possible to disable the named accessor syntax by setting the
165             "no_named_accessors" option. See the L section for details.
166              
167             =cut
168              
169             sub AUTOLOAD : lvalue {
170 23     23   262 my ($sub) = $AUTOLOAD =~ /([^:]+)$/;
171 23 100       129 if (ref $_[0]) {
172 17         1821 croak "Undefined subroutine &$AUTOLOAD called"
173 17 100       40 if (tied %{$_[0]})->[1]{no_named_accessors};
174              
175 9         16 my $self = shift;
176 9 100       30 $self->{$sub} = pop if @_ > 0;
177 9         67 return $self->{$sub};
178             } else {
179 6         7 my $class = shift;
180 6         9 my $self = shift;
181 6 100       18 $self->{$sub} = pop if @_ > 0;
182 6         33 return $self->{$sub};
183             }
184             }
185              
186 0     0   0 sub DESTROY { }
187              
188             =item $value = $hash-Efetch($name)
189              
190             =item $value = Class::Hash-Efetch [ ($hash, $new_value) ]
191              
192             This is the get accessor for the hash key named C<$name>. This fetches the
193             current value stored in C<$name>. This accessor is only available when the
194             "fetch" option is set. See the L section for details.
195              
196             =cut
197              
198             sub fetch : lvalue {
199 7 100   7 1 487 if (ref $_[0]) {
200 4         5 my $self = shift;
201 4 100       17 if ((tied %$self)->[1]{fetch}) {
202 3         4 my $name = shift;
203 3         22 return $self->{$name};
204             } else {
205 1         3 $AUTOLOAD = (ref $self).'::get';
206 1         5 return $self->AUTOLOAD(@_);
207             }
208             } else {
209 3         7 my ($class, $self, $name) = @_;
210 3         58 return $self->{$name};
211             }
212             }
213              
214             =item $hash-Estore($name, $new_value)
215              
216             =item $hash-Estore($name) = $new_value
217              
218             =item Class::Hash-Estore($hash, $name, $new_value)
219              
220             =item Class::Hash-Estore($hash, $name) = $new_value
221              
222             This is the set accessor for the hash key named C<$name>. This sets the current
223             value to be stored in C<$name>. This accessor is only available when the
224             "store" option is set. See the L section for details.
225              
226             =cut
227              
228             sub store : lvalue {
229 7 100   7 1 585 if (ref $_[0]) {
230 3         4 my $self = shift;
231 3 100       14 if ((tied %$self)->[1]{store}) {
232 2         4 my $name = shift;
233 2 100       9 $self->{$name} = pop if @_ > 0;
234 2         13 return $self->{$name};
235             } else {
236 1         3 $AUTOLOAD = (ref $self).'::store';
237 1         23 return $self->AUTOLOAD(@_);
238             }
239             } else {
240 4         10 my ($class, $self, $name, @values) = @_;
241 4 50       26 $self->{$name} = pop if @_ > 0;
242 4         33 return $self->{$name};
243             }
244             }
245              
246             =item $old_value = $hash-Edelete($name)
247              
248             =item $old_value = Class::Hash-Edelete($hash, $name)
249              
250             Deletes the value associated with the given key C<$name>. This method is only
251             available when the "delete" option is set. See the L section for
252             details.
253              
254             =cut
255              
256             sub delete : lvalue {
257 4 100   4 1 357 if (ref $_[0]) {
258 2         4 my $self = shift;
259 2 100       12 if ((tied %$self)->[1]{'delete'}) {
260 1         7 return my @deleted = delete @$self{@_};
261             } else {
262 1         4 $AUTOLOAD = (ref $self).'::delete';
263 1         4 return $self->AUTOLOAD(@_);
264             }
265             } else {
266 2         4 my $class = shift;
267 2         4 my $self = shift;
268 2         10 return my @deleted = delete @$self{@_};
269             }
270             }
271              
272             =item $hash-Eclear
273              
274             =item Class::Hash-Eclear($hash)
275              
276             Clears all values from the hash. This method is only available when the "clear"
277             option is set. See L for details.
278              
279             =cut
280              
281             sub clear : lvalue {
282 3 100   3 1 497 if (ref $_[0]) {
283 2         3 my $self = shift;
284 2 100       14 if ((tied %$self)->[1]{clear}) {
285 1         7 return %$self = ();
286             } else {
287 1         5 $AUTOLOAD = (ref $self).'::clear';
288 1         6 return $self->AUTOLOAD(@_);
289             }
290             } else {
291 1         4 my $class = shift;
292 1         3 my $self = shift;
293 1         5 return %$self = ();
294             }
295             }
296              
297             =item $hash-Eexists($name)
298              
299             =item Class::Hash-Eexists($hash, $name)
300              
301             Determines whether the given hash key has been set--even if it has been set to
302             C. This method is only available when the "exists" option is set. See
303             L for details.
304              
305             =cut
306              
307             sub exists : lvalue {
308 5 100   5 1 1749 if (ref $_[0]) {
309 3         5 my $self = shift;
310 3 100       14 if ((tied %$self)->[1]{'exists'}) {
311 2         4 my $name = shift;
312 2         12 return my $test = exists $self->{$name};
313             } else {
314 1         4 $AUTOLOAD = (ref $self).'::exists';
315 1         5 return $self->AUTOLOAD(@_);
316             }
317             } else {
318 2         5 my $class = shift;
319 2         3 my $self = shift;
320 2         3 my $name = shift;
321 2         10 return my $test = exists $self->{$name};
322             }
323             }
324              
325             =item ($key, $value) = $hash-Eeach
326              
327             =item ($key, $value) = Class::Hash-Eeach($hash)
328              
329             Iterates through all pairs in the hash. This method is only available when the
330             "each" option is set. See L for details.
331              
332             =cut
333              
334             sub each : lvalue {
335 9 100   9 1 626 if (ref $_[0]) {
336 5         7 my $self = shift;
337 5 100       19 if ((tied %$self)->[1]{'each'}) {
338 4         19 return my @pair = each %$self;
339             } else {
340 1         4 $AUTOLOAD = (ref $self).'::nextkey';
341 1         6 return $self->AUTOLOAD(@_);
342             }
343             } else {
344 4         26 my $class = shift;
345 4         5 my $self = shift;
346 4         18 return my @pair = each %$self;
347             }
348             }
349              
350             =item @keys = $hash-Ekeys
351              
352             =item @keys = $hash-Ekeys($hash)
353              
354             Returns all keys for the hash. This method is only available when the "keys"
355             option is set. See L for details.
356              
357             =cut
358              
359             sub keys : lvalue {
360 4 100   4 1 1364 if (ref $_[0]) {
361 2         3 my $self = shift;
362 2 100       10 if ((tied %$self)->[1]{'keys'}) {
363 1         5 return my @keys = keys %$self;
364             } else {
365 1         3 $AUTOLOAD = (ref $self).'::keys';
366 1         7 return $self->AUTOLOAD(@_);
367             }
368             } else {
369 2         3 my $class = shift;
370 2         3 my $self = shift;
371 2         7 return my @keys = keys %$self;
372             }
373             }
374              
375             =item @values = $hash-Evalues
376              
377             =item @values = $hash-Evalues($hash)
378              
379             Returns all values for the hash. This method is only available when the
380             "values" option is set. See L for details.
381              
382             =cut
383              
384             sub values : lvalue {
385 4 100   4 1 1410 if (ref $_[0]) {
386 2         3 my $self = shift;
387 2 100       9 if ((tied %$self)->[1]{'values'}) {
388 1         6 return my @values = values %$self;
389             } else {
390 1         4 $AUTOLOAD = (ref $self).'::values';
391 1         5 return $self->AUTOLOAD(@_);
392             }
393             } else {
394 2         3 my $class = shift;
395 2         4 my $self = shift;
396 2         7 return my @values = values %$self;
397             }
398             }
399              
400             =item $options = Class::Hash-Eoptions($hash)
401              
402             =item Class::Hash-Eoptions($hash)-E{option} = $option
403              
404             This returns the options currently set on the hash. See L for
405             details.
406              
407             =cut
408              
409             sub options : lvalue {
410 11     11 1 6641 my $class = shift;
411 11         25 my $self = shift;
412 11         257 return (tied %$self)->[1];
413             }
414              
415             =item $options = Class::Hash-Edefaults
416              
417             =item Class::Hash-Edefaults-E{option} = $option
418              
419             This returns the default options set on the hash. Making changes to the
420             returned value will effect all instances of Class::Hash constructed after
421             the change is made. Any existing instances are not modified.
422              
423             =cut
424              
425             sub defaults : lvalue {
426 1     1 1 14 my $class = shift;
427 1         12 return my $defaults = \%defaults;
428             }
429              
430             =back
431              
432             =head1 OPTIONS
433              
434             There are two types of options that may be set on Class::Hash objects: method
435             options and aggregate options. The method options determine the presence or
436             absence of various methods that may be defined in the Class::Hash object--see
437             L because this isn't strictly correct. The aggregate options alter the
438             settings of more than one other options.
439              
440             =head2 METHOD OPTIONS
441              
442             It should be noted that there are two possible syntaxes for calling most of the
443             Class::Hash methods. The first is the typical object syntax and the other is a
444             class/object syntax. The object syntax is available for all methods but
445             C. However, the object syntax is only available when it is turned on
446             by the matching option. The class/object syntax (always listed second when both
447             are possible) is always available regardless of option settings--but is far
448             less pretty.
449              
450             =over
451              
452             =item no_named_accessors
453              
454             When set, this option eliminates the use of named accessors. This will result in
455             an exception being raiesed when access is attempted. For example:
456              
457             $bob = new Class::Hash(foo => 'bar');
458             $foo = $bob->foo; # works!
459              
460             $fred = new Class::Hash(bar => 'foo', { no_named_accessors => 1 });
461             $bar = $fred->bar; ### <--- ERROR! Undefined subroutine &Class::Hash::bar called
462              
463             =item fetch
464              
465             When set, this option adds the use of the C accessor.
466              
467             =item store
468              
469             When set, this option adds the use of the C accessor.
470              
471             =item delete
472              
473             When set, this option adds the use of the C method.
474              
475             =item clear
476              
477             When set, this option adds the use of the C method.
478              
479             =item exists
480              
481             When set, this option adds the use of the C method.
482              
483             =item each
484              
485             When set, this option adds the use of the C method.
486              
487             =item keys
488              
489             When set, this option adds the use of the C method.
490              
491             =item values
492              
493             When set, this option adds the use of the C method.
494              
495             =back
496              
497             =head2 AGGREGATE OPTIONS
498              
499             All aggregate option names are in all caps to suggest that you're turning on or
500             off lots of stuff at once. Aggregate options always work one way, they do not
501             have the effect of turning some things on and some stuff off. This would be too
502             confusing.
503              
504             =item METHOD_BASED
505              
506             This option affects the following: C, C, C,
507             C, C, C, C, C, and C.
508              
509             =item ALL_METHODS
510              
511             This option affects the following: C, C, C, C,
512             C, C, C, and C.
513              
514             =head1 BUGS
515              
516             The nastiest part of this module is the way C and other methods are
517             made available. All the methods defined that aren't named accessors (such as
518             C, C, C, C, etc.) are defined as subroutines
519             whether they are "turned on" via options or not. This won't make a difference
520             99% of the time as the methods Do-The-Right-Thing(tm). However, when attempting
521             to use L, everything will be screwed up.
522              
523             I would like to modify the system to have the methods only defined
524             per-instance, but that would require the ability to load and unload method
525             definitions on-the-fly per-instance. Something that might be possible, but
526             would require some very odd finagling to achieve it, so I've stuck with the
527             It-Works-For-Me(tm) method or
528             It-Works-If-You-Just-Use-It-And-Don't-Try-To-Be-Funny(tm) method. :-)
529              
530             Another problem is that this is currently set to require Perl 5.8.0. I don't
531             know if this is really necessary, but I'm too lazy to find out right now.
532             Because of the lvalue attribute set on C, it does require 5.7.1,
533             which is almost the same as requiring 5.8.0.
534              
535             There are probably some nasty documentation bugs. I didn't go back through
536             and carefully proofread the documentation after I changed the implementation
537             mid-way through.
538              
539             =head1 AUTHOR
540              
541             Andrew Sterling Hanenkamp, Ehanenkamp@users.sourceforge.netE
542              
543             =head1 COPYRIGHT AND LICENSE
544              
545             Copyright 2003 by Andrew Sterling Hanenkamp
546              
547             This library is free software; you can redistribute it and/or modify
548             it under the same terms as Perl itself.
549              
550             =cut
551              
552             1