File Coverage

blib/lib/Class/MakeMethods/Standard/Hash.pm
Criterion Covered Total %
statement 74 86 86.0
branch 32 44 72.7
condition 19 39 48.7
subroutine 13 13 100.0
pod 5 5 100.0
total 143 187 76.4


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Class::MakeMethods::Standard::Hash - Standard hash methods
4              
5             =head1 SYNOPSIS
6              
7             package MyObject;
8             use Class::MakeMethods::Standard::Hash (
9             new => 'new',
10             scalar => [ 'foo', 'bar' ],
11             array => 'my_list',
12             hash => 'my_index',
13             );
14             ...
15            
16             my $obj = MyObject->new( foo => 'Foozle' );
17             print $obj->foo();
18            
19             $obj->bar('Barbados');
20             print $obj->bar();
21            
22             $obj->my_list(0 => 'Foozle', 1 => 'Bang!');
23             print $obj->my_list(1);
24            
25             $obj->my_index('broccoli' => 'Blah!', 'foo' => 'Fiddle');
26             print $obj->my_index('foo');
27              
28             =head1 DESCRIPTION
29              
30             The Standard::Hash suclass of MakeMethods provides a basic constructor and accessors for blessed-hash object instances.
31              
32             =head2 Calling Conventions
33              
34             When you C this package, the method names you provide
35             as arguments cause subroutines to be generated and installed in
36             your module.
37              
38             See L for more information.
39              
40             =head2 Declaration Syntax
41              
42             To declare methods, pass in pairs of a method-type name followed
43             by one or more method names.
44              
45             Valid method-type names for this package are listed in L<"METHOD
46             GENERATOR TYPES">.
47              
48             See L and L for more information.
49              
50             =cut
51              
52             package Class::MakeMethods::Standard::Hash;
53              
54             $VERSION = 1.000;
55 9     9   25688 use strict;
  9         19  
  9         394  
56 9     9   5142 use Class::MakeMethods::Standard '-isasubclass';
  9         23  
  9         316  
57 9     9   6037 use Class::MakeMethods::Utility::ArraySplicer 'array_splicer';
  9         21  
  9         70  
58              
59             ########################################################################
60              
61             =head1 METHOD GENERATOR TYPES
62              
63             =head2 new - Constructor
64              
65             For each method name passed, returns a subroutine with the following characteristics:
66              
67             =over 4
68              
69             =item *
70              
71             Has a reference to a sample item to copy. This defaults to a reference to an empty hash, but you may override this with the C<'defaults' => I> method parameter.
72              
73             =item *
74              
75             If called as a class method, makes a new hash and blesses it into that class.
76              
77             =item *
78              
79             If called on a hash-based instance, makes a copy of it and blesses the copy into the same class as the original instance.
80              
81             =item *
82              
83             If passed a list of key-value pairs, appends them to the new hash. These arguments override any copied values, and later arguments with the same name will override earlier ones.
84              
85             =item *
86              
87             Returns the new instance.
88              
89             =back
90              
91             Sample declaration and usage:
92              
93             package MyObject;
94             use Class::MakeMethods::Standard::Hash (
95             new => 'new',
96             );
97             ...
98            
99             # Bare constructor
100             my $empty = MyObject->new();
101            
102             # Constructor with initial values
103             my $obj = MyObject->new( foo => 'Foozle', bar => 'Barbados' );
104            
105             # Copy with overriding value
106             my $copy = $obj->new( bar => 'Bob' );
107              
108             =cut
109              
110             sub new {
111 8         23 map {
112 8     8 1 71 my $name = $_->{name};
113 8   50     54 my $defaults = $_->{defaults} || {};
114             $name => sub {
115 18     18   2718 my $callee = shift;
116 18 100       130 my $self = ref($callee) ? bless( { %$callee }, ref $callee )
117             : bless( { %$defaults }, $callee );
118 18         68 while ( scalar @_ ) {
119 33         45 my $method = shift;
120 33 50 0     156 UNIVERSAL::can( $self, $method )
121             or Carp::croak("Can't call method '$method' in constructor for " . ( ref($callee) || $callee ));
122 33         3678 $self->$method( shift );
123             }
124 18         73 return $self;
125             }
126 8         75 } (shift)->_get_declarations(@_)
127             }
128              
129             ########################################################################
130              
131             =head2 scalar - Instance Accessor
132              
133             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
134              
135             =over 4
136              
137             =item *
138              
139             Must be called on a hash-based instance.
140              
141             =item *
142              
143             Has a specific hash key to use to access the related value for each instance.
144             This defaults to the method name, but you may override this with the C<'hash_key' => I> method parameter.
145              
146             =item *
147              
148             If called without any arguments returns the current value.
149              
150             =item *
151              
152             If called with an argument, stores that as the value, and returns it,
153              
154             =back
155              
156             Sample declaration and usage:
157              
158             package MyObject;
159             use Class::MakeMethods::Standard::Hash (
160             scalar => 'foo',
161             );
162             ...
163            
164             # Store value
165             $obj->foo('Foozle');
166            
167             # Retrieve value
168             print $obj->foo;
169              
170             =cut
171              
172             sub scalar {
173 34         62 map {
174 31     31 1 109 my $name = $_->{name};
175 34   66     151 my $hash_key = $_->{hash_key} || $_->{name};
176             $name => sub {
177 103     103   217 my $self = shift;
178 103 100       259 if ( scalar(@_) == 0 ) {
179 60         299 $self->{$hash_key};
180             } else {
181 43         410 $self->{$hash_key} = shift;
182             }
183             }
184 34         286 } (shift)->_get_declarations(@_)
185             }
186              
187             ########################################################################
188              
189             =head2 array - Instance Ref Accessor
190              
191             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
192              
193             =over 4
194              
195             =item *
196              
197             Must be called on a hash-based instance.
198              
199             =item *
200              
201             Has a specific hash key to use to access the related value for each instance.
202             This defaults to the method name, but you may override this with the C<'hash_key' => I> method parameter.
203              
204             =item *
205              
206             The value for each instance will be a reference to an array (or undef).
207              
208             =item *
209              
210             If called without any arguments, returns the contents of the array in list context, or an array reference in scalar context (or undef).
211              
212             =item *
213              
214             If called with a single array ref argument, sets the contents of the array to match the contents of the provided one.
215              
216             =item *
217              
218             If called with a single numeric argument, uses that argument as an index to retrieve from the referenced array, and returns that value (or undef).
219              
220             =item *
221              
222             If called with a two arguments, the first undefined and the second an array ref argument, uses that array's contents as a list of indexes to return a slice of the referenced array.
223              
224             =item *
225              
226             If called with a list of argument pairs, each with a numeric index and an associated value, stores the value at the given index in the referenced array. If the instance's value was previously undefined, a new array is autovivified. The current value in each position will be overwritten, and later arguments with the same index will override earlier ones. Returns the current array-ref value.
227              
228             =item *
229              
230             If called with a list of argument pairs, each with the first item being a reference to an array of up to two numbers, loops over each pair and uses those numbers to splice the value array.
231              
232             The first controlling number is the position at which the splice will begin. Zero will start before the first item in the list. Negative numbers count backwards from the end of the array.
233              
234             The second number is the number of items to be removed from the list. If it is omitted, or undefined, or zero, no items are removed. If it is a positive integer, that many items will be returned.
235              
236             If both numbers are omitted, or are both undefined, they default to containing the entire value array.
237              
238             If the second argument is undef, no values will be inserted; if it is a non-reference value, that one value will be inserted; if it is an array-ref, its values will be copied.
239              
240             The method returns the items that removed from the array, if any.
241              
242             =back
243              
244             Sample declaration and usage:
245            
246             package MyObject;
247             use Class::MakeMethods::Standard::Hash (
248             array => 'bar',
249             );
250             ...
251            
252             # Clear and set contents of list
253             print $obj->bar([ 'Spume', 'Frost' ] );
254            
255             # Set values by position
256             $obj->bar(0 => 'Foozle', 1 => 'Bang!');
257            
258             # Positions may be overwritten, and in any order
259             $obj->bar(2 => 'And Mash', 1 => 'Blah!');
260            
261             # Retrieve value by position
262             print $obj->bar(1);
263            
264             # Direct access to referenced array
265             print scalar @{ $obj->bar() };
266              
267             There are also calling conventions for slice and splice operations:
268              
269             # Retrieve slice of values by position
270             print join(', ', $obj->bar( undef, [0, 2] ) );
271            
272             # Insert an item at position in the array
273             $obj->bar([3], 'Potatoes' );
274            
275             # Remove 1 item from position 3 in the array
276             $obj->bar([3, 1], undef );
277            
278             # Set a new value at position 2, and return the old value
279             print $obj->bar([2, 1], 'Froth' );
280              
281             =cut
282              
283             sub array {
284 2         5 map {
285 2     2 1 8 my $name = $_->{name};
286 2   33     12 my $hash_key = $_->{hash_key} || $_->{name};
287 2         4 my $init = $_->{auto_init};
288             $name => sub {
289 9     9   14 my $self = shift;
290 9 100 100     56 if ( scalar(@_) == 0 ) {
    100          
291 4 50 66     19 if ( $init and ! defined $self->{$hash_key} ) {
292 0         0 $self->{$hash_key} = [];
293             }
294 0         0 ( ! $self->{$hash_key} ) ? () :
295 4 50       30 ( wantarray ) ? @{ $self->{$hash_key} } :
    100          
296             $self->{$hash_key}
297             } elsif ( scalar(@_) == 1 and ref $_[0] eq 'ARRAY' ) {
298 1         3 $self->{$hash_key} = [ @{ $_[0] } ];
  1         4  
299 0         0 ( ! $self->{$hash_key} ) ? () :
300 1 50       9 ( wantarray ) ? @{ $self->{$hash_key} } :
    50          
301             $self->{$hash_key}
302             } else {
303 4   100     17 $self->{$hash_key} ||= [];
304 4         17 return array_splicer( $self->{$hash_key}, @_ );
305             }
306             }
307 2         12 } (shift)->_get_declarations(@_)
308             }
309              
310             ########################################################################
311              
312             =head2 hash - Instance Ref Accessor
313              
314             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
315              
316             =over 4
317              
318             =item *
319              
320             Must be called on a hash-based instance.
321              
322             =item *
323              
324             Has a specific hash key to use to access the related value for each instance.
325             This defaults to the method name, but you may override this with the C<'hash_key' => I> method parameter.
326              
327             =item *
328              
329             The value for each instance will be a reference to a hash (or undef).
330              
331             =item *
332              
333             If called without any arguments, returns the contents of the hash in list context, or a hash reference in scalar context (or undef).
334              
335             =item *
336              
337             If called with one non-ref argument, uses that argument as an index to retrieve from the referenced hash, and returns that value (or undef).
338              
339             =item *
340              
341             If called with one array-ref argument, uses the contents of that array to retrieve a slice of the referenced hash.
342              
343             =item *
344              
345             If called with one hash-ref argument, sets the contents of the referenced hash to match that provided.
346              
347             =item *
348              
349             If called with a list of key-value pairs, stores the value under the given key in the referenced hash. If the instance's value was previously undefined, a new hash is autovivified. The current value under each key will be overwritten, and later arguments with the same key will override earlier ones. Returns the contents of the hash in list context, or a hash reference in scalar context.
350              
351             =back
352              
353             Sample declaration and usage:
354              
355             package MyObject;
356             use Class::MakeMethods::Standard::Hash (
357             hash => 'baz',
358             );
359             ...
360            
361             # Set values by key
362             $obj->baz('foo' => 'Foozle', 'bar' => 'Bang!');
363            
364             # Values may be overwritten, and in any order
365             $obj->baz('broccoli' => 'Blah!', 'foo' => 'Fiddle');
366            
367             # Retrieve value by key
368             print $obj->baz('foo');
369            
370             # Retrive slice of values by position
371             print join(', ', $obj->baz( ['foo', 'bar'] ) );
372            
373             # Direct access to referenced hash
374             print keys %{ $obj->baz() };
375            
376             # Reset the hash contents to empty
377             %{ $obj->baz() } = ();
378              
379             =cut
380              
381             sub hash {
382 2         4 map {
383 2     2 1 22 my $name = $_->{name};
384 2   33     21 my $hash_key = $_->{hash_key} || $_->{name};
385 2         3 my $init = $_->{auto_init};
386             $name => sub {
387 9     9   15 my $self = shift;
388 9 100       36 if ( scalar(@_) == 0 ) {
    100          
    50          
389 4 50 66     26 if ( $init and ! defined $self->{$hash_key} ) {
390 0         0 $self->{$hash_key} = {};
391             }
392 0         0 ( ! $self->{$hash_key} ) ? () :
393 4 50       33 ( wantarray ) ? %{ $self->{$hash_key} } :
    100          
394             $self->{$hash_key}
395             } elsif ( scalar(@_) == 1 ) {
396 4 100       20 if ( ref($_[0]) eq 'HASH' ) {
    50          
397 1         2 $self->{$hash_key} = { %{$_[0]} };
  1         9  
398             } elsif ( ref($_[0]) eq 'ARRAY' ) {
399 0         0 return @{$self->{$hash_key}}{ @{$_[0]} }
  0         0  
  0         0  
400             } else {
401 3         17 return $self->{$hash_key}->{ $_[0] }
402             }
403             } elsif ( scalar(@_) % 2 ) {
404 0         0 Carp::croak "Odd number of items in assigment to $name";
405             } else {
406 1         3 while ( scalar(@_) ) {
407 1         3 my $key = shift();
408 1         5 $self->{$hash_key}->{ $key } = shift();
409             }
410 1         4 return $self->{$hash_key};
411             }
412             }
413 2         15 } (shift)->_get_declarations(@_)
414             }
415              
416             ########################################################################
417              
418             =head2 object - Instance Ref Accessor
419              
420             For each method name passed, uses a closure to generate a subroutine with the following characteristics:
421              
422             =over 4
423              
424             =item *
425              
426             Must be called on a hash-based instance.
427              
428             =item *
429              
430             Has a specific hash key to use to access the related value for each instance.
431             This defaults to the method name, but you may override this with the C<'hash_key' => I> method parameter.
432              
433             =item *
434              
435             The value for each instance will be a reference to an object (or undef).
436              
437             =item *
438              
439             If called without any arguments returns the current value.
440              
441             =item *
442              
443             If called with an argument, stores that as the value, and returns it,
444              
445             =back
446              
447             Sample declaration and usage:
448              
449             package MyObject;
450             use Class::MakeMethods::Standard::Hash (
451             object => 'foo',
452             );
453             ...
454            
455             # Store value
456             $obj->foo( Foozle->new() );
457            
458             # Retrieve value
459             print $obj->foo;
460              
461             =cut
462              
463             sub object {
464 1         4 map {
465 1     1 1 4 my $name = $_->{name};
466 1   33     6 my $hash_key = $_->{hash_key} || $_->{name};
467 1         2 my $class = $_->{class};
468 1         2 my $init = $_->{auto_init};
469 1 50 33     6 if ( $init and ! $class ) {
470 0         0 Carp::croak("Use of auto_init requires value for class parameter")
471             }
472 1   50     15 my $new_method = $_->{new_method} || 'new';
473             $name => sub {
474 3     3   5 my $self = shift;
475 3 100       6 if ( scalar @_ ) {
476 1         1 my $value = shift;
477 1 50 33     15 if ( $class and ! UNIVERSAL::isa( $value, $class ) ) {
478 0         0 Carp::croak "Wrong argument type ('$value') in assigment to $name";
479             }
480 1         6 $self->{$hash_key} = $value;
481             } else {
482 2 50 33     12 if ( $init and ! defined $self->{$hash_key} ) {
483 0         0 $self->{$hash_key} = $class->$new_method();
484             }
485 2         13 $self->{$hash_key};
486             }
487             }
488 1         7 } (shift)->_get_declarations(@_)
489             }
490              
491             ########################################################################
492              
493             =head1 SEE ALSO
494              
495             See L for general information about this distribution.
496              
497             See L for more about this family of subclasses.
498              
499             =cut
500              
501             1;