File Coverage

blib/lib/Data/MultiValuedHash.pm
Criterion Covered Total %
statement 228 234 97.4
branch 100 128 78.1
condition 21 27 77.7
subroutine 33 33 100.0
pod 28 28 100.0
total 410 450 91.1


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Data::MultiValuedHash - Hash whose keys have multiple ordered values
4              
5             =cut
6              
7             ######################################################################
8              
9             package Data::MultiValuedHash;
10             require 5.004;
11              
12             # Copyright (c) 1999-2003, Darren R. Duncan. All rights reserved. This module
13             # is free software; you can redistribute it and/or modify it under the same terms
14             # as Perl itself. However, I do request that this copyright information and
15             # credits remain attached to the file. If you modify this module and
16             # redistribute a changed version then please attach a note listing the
17             # modifications. This module is available "as-is" and the author can not be held
18             # accountable for any problems resulting from its use.
19              
20 1     1   1820 use strict;
  1         1  
  1         36  
21 1     1   5 use warnings;
  1         2  
  1         32  
22 1     1   5 use vars qw($VERSION);
  1         4  
  1         3032  
23             $VERSION = '1.081';
24              
25             ######################################################################
26              
27             =head1 DEPENDENCIES
28              
29             =head2 Perl Version
30              
31             5.004
32              
33             =head2 Standard Modules
34              
35             I
36              
37             =head2 Nonstandard Modules
38              
39             I
40              
41             =head1 SYNOPSIS
42              
43             use Data::MultiValuedHash;
44              
45             $mvh = Data::MultiValuedHash->new(); # make empty, case-sensitive (norm)
46             $mvh = Data::MultiValuedHash->new( 1 ); # make empty, case-insensitive
47             $mvh = Data::MultiValuedHash->new( 0, {
48             name => 'John',
49             age => 17,
50             color => 'green',
51             siblings => ['Laura', 'Andrew', 'Julia'],
52             pets => ['Cat', 'Bird'],
53             } ); # make new with initial values, case-sensitive keys
54              
55             $mvh->store( age => 18 ); # celebrate a birthday
56              
57             $mvh->push( siblings => 'Tandy' ); # add a family member, returns 4
58              
59             $mvh->unshift( pets => ['Dog', 'Hamster'] ); # more pets
60              
61             $does_it = $mvh->exists( 'color' ); # returns true
62              
63             $name = $mvh->fetch_value( 'siblings' ); # returns 'Laura'
64             $name = $mvh->fetch_value( 'siblings', 2 ); # returns 'Julia'
65             $name = $mvh->fetch_value( 'siblings', -1 ); # returns 'Tandy'
66             $rname = $mvh->fetch( 'siblings' ); # returns all 4 in array ref
67             @names = $mvh->fetch( 'siblings' ); # returns all 4 as list
68              
69             $name = $mvh->fetch_value( 'Siblings' ); # returns nothing, wrong case
70             $mv2 = Data::MultiValuedHash->new( 1, $mvh ); # conv to case inse
71             $name = $mv2->fetch_value( 'Siblings' ); # returns 'Laura' this time
72             $is_it = $mvh->ignores_case(); # returns false; like normal hashes
73             $is_it = $mv2->ignores_case(); # returns true
74              
75             $color = $mvh->shift( 'color' ); # returns 'green'; none remain
76              
77             $animal = $mvh->pop( 'pets' ); # returns 'Bird'; three remain
78              
79             %list = $mvh->fetch_all(); # want all keys, all values
80             # returns ( name => ['John'], age => [18], color => [],
81             # siblings => ['Laura', 'Andrew', 'Julia', 'Tandy'],
82             # pets => ['Dog', 'Hamster', 'Cat'] )
83              
84             %list = $mvh->fetch_first(); # want all keys, first values of each
85             # returns ( name => 'John', age => 18, color => undef,
86             # siblings => 'Laura', pets => 'Dog' )
87              
88             %list = $mvh->fetch_last(); # want all keys, last values of each
89             # returns ( name => 'John', age => 18, color => undef,
90             # siblings => 'Tandy', pets => 'Cat' )
91              
92             %list = $mvh->fetch_last( ['name', 'siblings'] ); # want named keys only
93             # returns ( name => 'John', siblings => 'Tandy' )
94              
95             %list = $mvh->fetch_last( ['name', 'siblings'], 1 ); # want complement
96             # returns ( age => 18, color => undef, pets => 'Cat' )
97              
98             $mv3 = $mvh->clone(); # make a duplicate of myself
99             $mv4 = $mvh->fetch_mvh( 'pets', 1 ); # leave out the pets in this "clone"
100              
101             @list = $mv3->keys();
102             # returns ('name','age','color','siblings','pets')
103             $num = $mv3->keys(); # whoops, doesn't do what we expect; returns array ref
104             $num = $mv3->keys_count(); # returns 5
105              
106             @list = $mv3->values();
107             # returns ( 'John', 18, 'Laura', 'Andrew', 'Julia', 'Tandy',
108             # 'Dog', 'Hamster', 'Cat' )
109             @num = $mv3->values_count(); # returns 9
110              
111             @list = $mvh->splice( 'Siblings', 2, 1, ['James'] );
112             # replaces 'Julia' with 'James'; returns ( 'Julia' )
113              
114             $mv3->store_all( {
115             songs => ['this', 'that', 'and the other'],
116             pets => 'Fish',
117             } ); # adds key 'songs' with values, replaces list of pets with 'fish'
118              
119             $mv3->store_value( 'pets', 'turtle' ); # replaces 'fish' with 'turtle'
120             $mv3->store_value( 'pets', 'rabbit', 1 ); # pets is now ['turtle','rabbit']
121              
122             $oldval = $mv3->delete( 'color' ); # gets rid of color for good
123             $rdump = $mv3->delete_all(); # return everything as hash of arrays, clear
124              
125             =head1 DESCRIPTION
126              
127             This Perl 5 object class implements a simple data structure that is similar to a
128             hash except that each key can have several values instead of just one. There are
129             many places that such a structure is useful, such as database records whose
130             fields may be multi-valued, or when parsing results of an html form that contains
131             several fields with the same name. This class can export a wide variety of
132             key/value subsets of its data when only some keys are needed.
133              
134             While you could do tasks similar to this class by making your own hash with array
135             refs for values, you will need to repeat some messy-looking code everywhere you
136             need to use that data, creating a lot of redundant access or parsing code and
137             increasing the risk of introducing errors.
138              
139             One optional feature that this class provides is case-insensitive keys.
140             Case-insensitivity simplifies matching form field names whose case may have been
141             changed by the web browser while in transit (I have seen it happen).
142              
143             =cut
144              
145             ######################################################################
146              
147             # Names of properties for objects of this class are declared here:
148             my $KEY_MAIN_HASH = 'main_hash'; # this is a hash of arrays
149             my $KEY_CASE_INSE = 'case_inse'; # are our keys case insensitive?
150              
151             ######################################################################
152              
153             =head1 SYNTAX
154              
155             This class does not export any functions or methods, so you need to call them
156             using object notation. This means using Bfunction()> for functions
157             and B<$object-Emethod()> for methods. If you are inheriting this class for
158             your own modules, then that often means something like B<$self-Emethod()>.
159              
160             All method arguments and results are passed by value (where appropriate) such
161             that subsequent editing of them will not change values internal to the MVH
162             object; this is the generally accepted behaviour.
163              
164             Most methods take either KEY or VALUES arguments. KEYs are always treated as
165             scalars and VALUES are taken as a list. Value lists can be passed either as an
166             ARRAY ref, whereupon they are internally flattened, or as an ordinary LIST. If
167             the first VALUES argument is an ARRAY ref, it is interpreted as being the entire
168             list and subsequent arguments are ignored. If you want to store an actual ARRAY
169             ref as a value, make sure to put it inside another ARRAY ref first, or it will be
170             flattened.
171              
172             Any method which returns a list will check if it is being called in scalar or
173             list context. If the context wants a scalar then the method returns its list in
174             an ARRAY ref; otherwise, the list is returned as a list. This behaviour is the
175             same whether the returned list is an associative list (hash) or an ordinary list
176             (array). Failures are returned as "undef" in scalar context and "()" in list
177             context. Scalar results are returned as themselves, of course.
178              
179             When case-insensitivity is used, all operations involving hash keys operate with
180             lowercased versions, and these are also what is stored. The default setting of
181             the "ignores case" property is false, like with a normal hash.
182              
183             =head1 FUNCTIONS AND METHODS
184              
185             =head2 new([ CASE[, SOURCE] ])
186              
187             This function creates a new Data::MultiValuedHash (or subclass) object and
188             returns it. All of the method arguments are passed to initialize() as is; please
189             see the POD for that method for an explanation of them.
190              
191             =cut
192              
193             ######################################################################
194              
195             sub new {
196 24     24 1 4269 my $class = CORE::shift( @_ );
197 24   33     139 my $self = bless( {}, ref($class) || $class );
198 24         57 $self->initialize( @_ );
199 24         73 return( $self );
200             }
201              
202             ######################################################################
203              
204             =head2 initialize([ CASE[, SOURCE] ])
205              
206             This method is used by B to set the initial properties of objects that it
207             creates. Calling it yourself will empty the internal hash. If you provide
208             arguments to this method then the first one, CASE, will initialize the
209             case-insensitivity attribute, and any subsequent arguments will provide initial
210             keys and values for the internal hash. Nothing is returned.
211              
212             The first optional argument CASE (boolean) specifies whether this object uses
213             case-insensitive keys; the default value is false.
214              
215             The second optional argument, SOURCE is used as initial keys and values for this
216             object. If it is a Hash Ref (normal or of arrays), then the store_all( SOURCE )
217             method is called to handle it. If the same argument is a MVH object, then its
218             keys and values are similarly given to store_all( SOURCE ). Otherwise, SOURCE
219             is ignored and this object starts off empty.
220              
221             =cut
222              
223             ######################################################################
224              
225             sub initialize {
226 24     24 1 28 my $self = CORE::shift( @_ );
227 24         63 $self->{$KEY_MAIN_HASH} = {};
228 24         46 $self->{$KEY_CASE_INSE} = 0;
229 24 100       52 if( scalar( @_ ) ) {
230 23         39 $self->{$KEY_CASE_INSE} = CORE::shift( @_ );
231 23         23 my $initializer = CORE::shift( @_ );
232 23 100 100     159 if( UNIVERSAL::isa($initializer,'Data::MultiValuedHash') or
233             ref($initializer) eq 'HASH' ) {
234 20         44 $self->store_all( $initializer );
235             } else {
236 3         9 $self->_set_hash_with_nonhash_source( $initializer, @_ );
237             }
238             }
239             }
240              
241             # method can be overloaded by subclass; assumes main hash empty
242 3     3   6 sub _set_hash_with_nonhash_source {
243             }
244              
245             ######################################################################
246              
247             =head2 clone([ CLONE ])
248              
249             This method initializes a new object to have all of the same properties of the
250             current object and returns it. This new object can be provided in the optional
251             argument CLONE (if CLONE is an object of the same class as the current object);
252             otherwise, a brand new object of the current class is used. Only object
253             properties recognized by Data::MultiValuedHash are set in the clone; other
254             properties are not changed.
255              
256             =cut
257              
258             ######################################################################
259              
260             sub clone {
261 2     2 1 397 my ($self, $clone, @args) = @_;
262 2 50       20 ref($clone) eq ref($self) or $clone = bless( {}, ref($self) );
263              
264 2         4 my $rh_main_hash = $self->{$KEY_MAIN_HASH};
265 5         6 $clone->{$KEY_MAIN_HASH} = { map { ( $_, [@{$rh_main_hash->{$_}}] ) }
  5         13  
  2         7  
266 2         3 CORE::keys %{$rh_main_hash} };
267              
268 2         5 $clone->{$KEY_CASE_INSE} = $self->{$KEY_CASE_INSE};
269              
270 2         5 return( $clone );
271             }
272              
273             ######################################################################
274              
275             =head2 ignores_case([ VALUE ])
276              
277             This method is an accessor for the boolean "case insensitive" property of this
278             object, which it returns. If VALUE is defined, this property is set to it.
279              
280             If the property is being changed from false to true, then any existing keys will
281             be lowercased, and where name collisions occur, the values will be combined.
282             The order of these new values is determined by iterating over the original
283             case-sensitive keys in the order of "sort keys()".
284              
285             =cut
286              
287             ######################################################################
288              
289             sub ignores_case {
290 27     27 1 2251 my $self = CORE::shift( @_ );
291 27 100       58 if( defined( my $new_value = CORE::shift( @_ ) ) ) {
292 4         8 my $old_value = $self->{$KEY_CASE_INSE};
293 4         6 $self->{$KEY_CASE_INSE} = $new_value;
294 4 100 100     14 if( !$old_value and $new_value ) { # if conv from sensitiv to insens
295 1         2 my $rh_main_hash = $self->{$KEY_MAIN_HASH};
296 1         3 $self->{$KEY_MAIN_HASH} = {};
297 1         3 $self->store_all( $rh_main_hash );
298             }
299             }
300 27         69 return( $self->{$KEY_CASE_INSE} );
301             }
302              
303             ######################################################################
304              
305             =head2 keys()
306              
307             This method returns a list of all this object's keys.
308              
309             =cut
310              
311             ######################################################################
312              
313             sub keys {
314 2     2 1 14 my $self = CORE::shift( @_ );
315 2         3 my @keys_list = CORE::keys %{$self->{$KEY_MAIN_HASH}};
  2         9  
316 2 50       37 return( wantarray ? @keys_list : \@keys_list );
317             }
318              
319             ######################################################################
320              
321             =head2 keys_count()
322              
323             This method returns a count of this object's keys.
324              
325             =cut
326              
327             ######################################################################
328              
329             sub keys_count {
330 2     2 1 372 my $self = CORE::shift( @_ );
331 2         4 return( scalar( CORE::keys %{$self->{$KEY_MAIN_HASH}} ) );
  2         9  
332             }
333              
334             ######################################################################
335              
336             =head2 values()
337              
338             This method returns a flattened list of all this object's values.
339              
340             =cut
341              
342             ######################################################################
343              
344             sub values {
345 2     2 1 344 my $self = CORE::shift( @_ );
346 2         5 my @values_list = map { @{$_} } CORE::values %{$self->{$KEY_MAIN_HASH}};
  10         12  
  10         26  
  2         8  
347 2 50       22 return( wantarray ? @values_list : \@values_list );
348             }
349              
350             ######################################################################
351              
352             =head2 values_count()
353              
354             This method returns a count of all this object's values.
355              
356             =cut
357              
358             ######################################################################
359              
360             sub values_count {
361 2     2 1 380 my $self = CORE::shift( @_ );
362 2         5 my $count = 0;
363 2         3 map { $count += scalar( @{$_} ) } CORE::values %{$self->{$KEY_MAIN_HASH}};
  10         7  
  10         14  
  2         6  
364 2         8 return( $count );
365             }
366              
367             ######################################################################
368              
369             =head2 exists( KEY )
370              
371             This method returns true if KEY is in the hash, although it may not have any
372             values.
373              
374             =cut
375              
376             ######################################################################
377              
378             sub exists {
379 9     9 1 1506 my $self = CORE::shift( @_ );
380 9 100       30 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
381 9 100       21 defined( $key ) or $key = '';
382 9         45 return( CORE::exists( $self->{$KEY_MAIN_HASH}->{$key} ) );
383             }
384              
385             ######################################################################
386              
387             =head2 count( KEY )
388              
389             This method returns a count of the values that KEY has. It returns failure if
390             KEY doesn't exist.
391              
392             =cut
393              
394             ######################################################################
395              
396             sub count {
397 4     4 1 560 my $self = CORE::shift( @_ );
398 4 50       12 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
399 4 100       9 defined( $key ) or $key = '';
400 4 100       14 CORE::exists( $self->{$KEY_MAIN_HASH}->{$key} ) or return( undef );
401 2         3 return( scalar( @{$self->{$KEY_MAIN_HASH}->{$key}} ) );
  2         8  
402             }
403              
404             ######################################################################
405              
406             =head2 fetch_value( KEY[, INDEX] )
407              
408             This method returns a single value of KEY, which is at INDEX position in the
409             internal array of values; the default INDEX is 0. It returns failure if KEY
410             doesn't exist.
411              
412             =cut
413              
414             ######################################################################
415              
416             sub fetch_value {
417 15     15 1 2348 my $self = CORE::shift( @_ );
418 15 100       42 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
419 15 100       31 defined( $key ) or $key = '';
420 15 100       42 CORE::exists( $self->{$KEY_MAIN_HASH}->{$key} ) or return( undef );
421 13   100     41 my $index = CORE::shift( @_ ) || 0;
422 13         58 return( $self->{$KEY_MAIN_HASH}->{$key}->[$index] );
423             }
424              
425             ######################################################################
426              
427             =head2 fetch( KEY[, INDEXES] )
428              
429             This method returns a list of all values that KEY has. It returns failure if KEY
430             doesn't exist. The first optional argument, INDEXES, is an array ref that specifies
431             a subset of all this key's values that we want returned instead of all of them.
432              
433             =cut
434              
435             ######################################################################
436              
437             sub fetch {
438 37     37 1 6308 my $self = CORE::shift( @_ );
439 37 100       109 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
440 37 100       83 defined( $key ) or $key = '';
441 37 50       102 CORE::exists( $self->{$KEY_MAIN_HASH}->{$key} ) or
    100          
442             return( wantarray ? () : undef );
443 33         33 my @values = @{$self->{$KEY_MAIN_HASH}->{$key}};
  33         108  
444 33 100       78 if( defined( $_[0] ) ) {
445 4         8 my @indexes =
446 10 100       25 ref( $_[0] ) eq 'ARRAY' ? @{CORE::shift( @_ )} : CORE::shift( @_ );
447 10         18 my %indexes = map { ($_ + 0, 1) } @indexes; # clean up input
  16         51  
448 10         33 @indexes = sort (CORE::keys %indexes);
449 10         34 @values = @values[@indexes];
450             }
451 33 50       170 return( wantarray ? @values : \@values );
452             }
453              
454             ######################################################################
455              
456             =head2 fetch_hash([ INDEX[, KEYS[, COMPLEMENT]] ])
457              
458             This method returns a hash with all this object's keys and a single value of
459             each key, which is at INDEX position in the internal array of values for the
460             key; the default INDEX is 0. The first optional argument, KEYS, is an array ref
461             that specifies a subset of all this object's keys that we want returned. If the
462             second optional boolean argument, COMPLEMENT, is true, then the complement of
463             the keys listed in KEYS is returned instead.
464              
465             =cut
466              
467             ######################################################################
468              
469             sub fetch_hash {
470 19     19 1 2008 my $self = CORE::shift( @_ );
471 19   100     58 my $index = CORE::shift( @_ ) || 0;
472 19         28 my $rh_main_hash = $self->{$KEY_MAIN_HASH};
473 95         198 my %hash_copy = map { ( $_, $rh_main_hash->{$_}->[$index] ) }
  19         53  
474 19         21 CORE::keys %{$rh_main_hash};
475 19 100       52 if( defined( $_[0] ) ) {
476 10         30 $self->_reduce_hash_to_subset( \%hash_copy, @_ );
477             }
478 19 50       83 return( wantarray ? %hash_copy : \%hash_copy );
479             }
480              
481             ######################################################################
482              
483             =head2 fetch_first([ KEYS[, COMPLEMENT] ])
484              
485             This method returns a hash with all this object's keys, but only the first value
486             for each key. The first optional argument, KEYS, is an array ref that specifies
487             a subset of all this object's keys that we want returned. If the second optional
488             boolean argument, COMPLEMENT, is true, then the complement of the keys listed in
489             KEYS is returned instead.
490              
491             =cut
492              
493             ######################################################################
494              
495             sub fetch_first {
496 4     4 1 675 my $self = CORE::shift( @_ );
497 4         10 my $rh_output = $self->fetch_hash( 0, @_ );
498 4 50       17 return( wantarray ? %{$rh_output} : $rh_output );
  0         0  
499             }
500              
501             ######################################################################
502              
503             =head2 fetch_last([ KEYS[, COMPLEMENT] ])
504              
505             This method returns a hash with all this object's keys, but only the last value
506             for each key. The first optional argument, KEYS, is an array ref that specifies
507             a subset of all this object's keys that we want returned. If the second optional
508             boolean argument, COMPLEMENT, is true, then the complement of the keys listed in
509             KEYS is returned instead.
510              
511             =cut
512              
513             ######################################################################
514              
515             sub fetch_last {
516 4     4 1 689 my $self = CORE::shift( @_ );
517 4         11 my $rh_output = $self->fetch_hash( -1, @_ );
518 4 50       33 return( wantarray ? %{$rh_output} : $rh_output );
  0         0  
519             }
520              
521             ######################################################################
522              
523             =head2 fetch_all([ KEYS[, COMPLEMENT[, INDEXES]] ])
524              
525             This method returns a hash with all this object's keys and values. The values
526             for each key are contained in an ARRAY ref. The first optional argument, KEYS,
527             is an array ref that specifies a subset of all this object's keys that we want
528             returned. If the second optional boolean argument, COMPLEMENT, is true, then the
529             complement of the keys listed in KEYS is returned instead. The third optional
530             argument, INDEXES, is an array ref that specifies a subset of all of each key's
531             values that we want returned instead of all of them.
532              
533             =cut
534              
535             ######################################################################
536              
537             sub fetch_all {
538 57     57 1 8631 my $self = CORE::shift( @_ );
539 57         88 my $rh_main_hash = $self->{$KEY_MAIN_HASH};
540 239         667 my %hash_copy =
541 57         76 map { ( $_, [@{$rh_main_hash->{$_}}] ) } CORE::keys %{$rh_main_hash};
  239         210  
  57         160  
542 57 100       168 if( defined( $_[0] ) ) {
543 25         102 $self->_reduce_hash_to_subset( \%hash_copy, @_ );
544             }
545 57 100       123 if( defined( $_[2] ) ) {
546 23 100       58 my @indexes = ref( $_[2] ) eq 'ARRAY' ? @{$_[2]} : $_[2];
  8         16  
547 23         33 my %indexes = map { ($_ + 0, 1) } @indexes; # clean up input
  33         90  
548 23         71 @indexes = sort (CORE::keys %indexes);
549 23         43 %hash_copy = map { ($_, [@{$hash_copy{$_}}[@indexes]]) }
  53         52  
  53         247  
550             CORE::keys %hash_copy;
551             }
552 57 50       812 return( wantarray ? %hash_copy : \%hash_copy );
553             }
554              
555             ######################################################################
556              
557             =head2 fetch_mvh([ KEYS[, COMPLEMENT[, INDEXES]] ])
558              
559             This method returns a new MVH object with all or a subset of this object's keys
560             and values. It has the same calling conventions as fetch_all() except that an MVH
561             object is returned instead of a literal hash. The case-insensitivity attribute
562             of the new MVH is the same as the current one.
563              
564             =cut
565              
566             ######################################################################
567              
568             sub fetch_mvh {
569 2     2 1 209 my $self = CORE::shift( @_ );
570 2         7 my $new_mvh = bless( {}, ref($self) );
571 2         5 $new_mvh->{$KEY_MAIN_HASH} = $self->fetch_all( @_ );
572 2         4 $new_mvh->{$KEY_CASE_INSE} = $self->{$KEY_CASE_INSE};
573 2         5 return( $new_mvh );
574             }
575              
576             ######################################################################
577              
578             =head2 store_value( KEY, VALUE[, INDEX] )
579              
580             This method adds a new KEY to this object, if it doesn't already exist. The
581             VALUE replaces any that may have existed before at INDEX position in the
582             internal array of values; the default INDEX is 0. This method returns the new
583             count of values that KEY has, which may be more than one greater than before.
584              
585             =cut
586              
587             ######################################################################
588              
589             sub store_value {
590 2     2 1 196 my $self = CORE::shift( @_ );
591 2 50       7 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
592 2         3 my $value = CORE::shift( @_ );
593 2   100     9 my $index = CORE::shift( @_ ) || 0;
594 2   50     7 $self->{$KEY_MAIN_HASH}->{$key} ||= [];
595 2         3 $self->{$KEY_MAIN_HASH}->{$key}->[$index] = $value;
596 2         3 return( scalar( @{$self->{$KEY_MAIN_HASH}->{$key}} ) );
  2         5  
597             }
598              
599             ######################################################################
600              
601             =head2 store( KEY, VALUES )
602              
603             This method adds a new KEY to this object, if it doesn't already exist. The
604             VALUES replace any that may have existed before. This method returns the new
605             count of values that KEY has. The best way to get a key which has no values is
606             to pass an empty ARRAY ref as the VALUES.
607              
608             =cut
609              
610             ######################################################################
611              
612             sub store {
613 4     4 1 695 my $self = CORE::shift( @_ );
614 4 50       17 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
615 4 100       15 my @values = (ref( $_[0] ) eq 'ARRAY') ? @{CORE::shift( @_ )} : @_;
  2         5  
616 4         10 $self->{$KEY_MAIN_HASH}->{$key} = \@values;
617 4         5 return( scalar( @{$self->{$KEY_MAIN_HASH}->{$key}} ) );
  4         18  
618             }
619              
620             ######################################################################
621              
622             =head2 store_all( HASH )
623              
624             This method takes one argument, HASH, which is an associative list or hash ref
625             or MVH object containing new keys and values to store in this object. The value
626             associated with each key can be either scalar or an array. Symantics are the
627             same as for calling store() multiple times, once for each KEY. Existing keys and
628             values with the same names are replaced. New keys are added in the order of
629             "sort CORE::keys %hash". This method returns a count of new keys added.
630              
631             =cut
632              
633             ######################################################################
634              
635             sub store_all {
636 24     24 1 769 my $self = CORE::shift( @_ );
637 3         14 my %new = UNIVERSAL::isa( $_[0], 'Data::MultiValuedHash' ) ?
638 19         104 (%{CORE::shift( @_ )->{$KEY_MAIN_HASH}}) :
639 24 100       91 (ref( $_[0] ) eq 'HASH') ? (%{CORE::shift( @_ )}) : @_;
    100          
640 24         49 my $rh_main_hash = $self->{$KEY_MAIN_HASH};
641 24         31 my $case_inse = $self->{$KEY_CASE_INSE};
642 24         90 foreach my $key (sort (CORE::keys %new)) {
643 93 100       415 my @values = (ref($new{$key}) eq 'ARRAY') ? @{$new{$key}} : $new{$key};
  47         98  
644 93 100       182 $key = lc($key) if( $case_inse );
645 93         235 $rh_main_hash->{$key} = \@values;
646             }
647 24         86 return( scalar( CORE::keys %new ) );
648             }
649              
650             ######################################################################
651              
652             =head2 push( KEY, VALUES )
653              
654             This method adds a new KEY to this object, if it doesn't already exist. The
655             VALUES are appended to the list of any that existed before. This method returns
656             the new count of values that KEY has.
657              
658             =cut
659              
660             ######################################################################
661              
662             sub push {
663 5     5 1 942 my $self = CORE::shift( @_ );
664 5 50       21 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
665 5 100       17 defined( $key ) or $key = '';
666 5 100       16 my @values = (ref( $_[0] ) eq 'ARRAY') ? @{CORE::shift( @_ )} : @_;
  2         5  
667 5   100     22 $self->{$KEY_MAIN_HASH}->{$key} ||= [];
668 5         5 CORE::push( @{$self->{$KEY_MAIN_HASH}->{$key}}, @values );
  5         13  
669 5         7 return( scalar( @{$self->{$KEY_MAIN_HASH}->{$key}} ) );
  5         19  
670             }
671              
672             ######################################################################
673              
674             =head2 unshift( KEY, VALUES )
675              
676             This method adds a new KEY to this object, if it doesn't already exist. The
677             VALUES are prepended to the list of any that existed before. This method returns
678             the new count of values that KEY has.
679              
680             =cut
681              
682             ######################################################################
683              
684             sub unshift {
685 1     1 1 228 my $self = CORE::shift( @_ );
686 1 50       9 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
687 1 50       6 my @values = (ref( $_[0] ) eq 'ARRAY') ? @{CORE::shift( @_ )} : @_;
  0         0  
688 1   50     5 $self->{$KEY_MAIN_HASH}->{$key} ||= [];
689 1         2 CORE::unshift( @{$self->{$KEY_MAIN_HASH}->{$key}}, @values );
  1         4  
690 1         2 return( scalar( @{$self->{$KEY_MAIN_HASH}->{$key}} ) );
  1         5  
691             }
692              
693             ######################################################################
694              
695             =head2 pop( KEY )
696              
697             This method removes the last value associated with KEY and returns it. It
698             returns failure if KEY doesn't exist.
699              
700             =cut
701              
702             ######################################################################
703              
704             sub pop {
705 2     2 1 372 my $self = CORE::shift( @_ );
706 2 50       9 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
707 2 100       63 CORE::exists( $self->{$KEY_MAIN_HASH}->{$key} ) or return( undef );
708 1         2 return( CORE::pop( @{$self->{$KEY_MAIN_HASH}->{$key}} ) );
  1         6  
709             }
710              
711             ######################################################################
712              
713             =head2 shift( KEY )
714              
715             This method removes the last value associated with KEY and returns it. It
716             returns failure if KEY doesn't exist.
717              
718             =cut
719              
720             ######################################################################
721              
722             sub shift {
723 2     2 1 344 my $self = CORE::shift( @_ );
724 2 50       9 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
725 2 50       8 CORE::exists( $self->{$KEY_MAIN_HASH}->{$key} ) or return( undef );
726 2         4 return( CORE::shift( @{$self->{$KEY_MAIN_HASH}->{$key}} ) );
  2         10  
727             }
728              
729             ######################################################################
730              
731             =head2 splice( KEY, OFFSET[, LENGTH[, VALUES]] )
732              
733             This method adds a new KEY to this object, if it doesn't already exist. The
734             values for KEY at index positions designated by OFFSET and LENGTH are removed,
735             and replaced with any VALUES that there may be. This method returns the elements
736             removed from the list of values for KEY, which grows or shrinks as necessary. If
737             LENGTH is omitted, the method returns everything from OFFSET onward.
738              
739             =cut
740              
741             ######################################################################
742              
743             sub splice {
744 6     6 1 1201 my $self = CORE::shift( @_ );
745 6 50       19 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
746 6   100     20 my $offset = CORE::shift( @_ ) || 0;
747 6         10 my $length = CORE::shift( @_ );
748 6 100       15 my @values = (ref( $_[0] ) eq 'ARRAY') ? @{CORE::shift( @_ )} : @_;
  1         3  
749 6   50     19 $self->{$KEY_MAIN_HASH}->{$key} ||= [];
750             # yes, an undef or () for $length is diff than it not being there at all
751 3         10 my @output = defined( $length ) ? CORE::splice(
752 3         12 @{$self->{$KEY_MAIN_HASH}->{$key}}, $offset, $length, @values ) :
753 6 100       12 CORE::splice( @{$self->{$KEY_MAIN_HASH}->{$key}}, $offset );
754 6 50       33 return( wantarray ? @output : \@output );
755             }
756              
757             ######################################################################
758              
759             =head2 delete( KEY )
760              
761             This method removes KEY and returns its values. It returns failure if KEY
762             doesn't previously exist.
763              
764             =cut
765              
766             ######################################################################
767              
768             sub delete {
769 2     2 1 217 my $self = CORE::shift( @_ );
770 2 50       9 my $key = $self->{$KEY_CASE_INSE} ? lc(CORE::shift(@_)) : CORE::shift(@_);
771 2 50       22 CORE::exists( $self->{$KEY_MAIN_HASH}->{$key} ) or
    100          
772             return( wantarray ? () : undef );
773 1         4 my $ra_values = CORE::delete( $self->{$KEY_MAIN_HASH}->{$key} );
774 1 50       8 return( wantarray ? @{$ra_values} : $ra_values );
  0         0  
775             }
776              
777             ######################################################################
778              
779             =head2 delete_all()
780              
781             This method deletes all this object's keys and values and returns them in a hash.
782             The values for each key are contained in an ARRAY ref.
783              
784             =cut
785              
786             ######################################################################
787              
788             sub delete_all {
789 2     2 1 59 my $self = CORE::shift( @_ );
790 2         5 my $rh_main_hash = $self->{$KEY_MAIN_HASH};
791 2         5 $self->{$KEY_MAIN_HASH} = {};
792 2 50       12 return( wantarray ? %{$rh_main_hash} : $rh_main_hash );
  0         0  
793             }
794              
795             ######################################################################
796              
797             =head2 batch_new( CASE, SOURCE[, *] )
798              
799             This batch function creates a list of new Data::MultiValuedHash (or subclass)
800             objects and returns them. The symantecs are like calling new() multiple times,
801             except that the argument SOURCE is required. SOURCE is an array and this
802             function creates as many MVH objects as there are elements in SOURCE. The list
803             is returned as an array ref in scalar context and a list in list context.
804             CASE defaults to false if undefined. Any arguments following SOURCE are passed
805             to new() as is.
806              
807             =cut
808              
809             ######################################################################
810              
811             sub batch_new {
812 1     1 1 88 my $class = CORE::shift( @_ );
813 1   50     10 my $case_inse = CORE::shift( @_ ) || 0;
814 1         5 my @initializers =
815 1 50       6 ref($_[0]) eq 'ARRAY' ? @{CORE::shift(@_)} : CORE::shift(@_);
816 1         4 my @new_mvh = map { $class->new( $case_inse, $_, @_ ) } @initializers;
  9         26  
817 1 50       8 return( wantarray ? @new_mvh : \@new_mvh );
818             }
819              
820             ######################################################################
821             # Call: $self->_reduce_hash_from_subset( $rh_hash, $ra_keys, $is_compl )
822             # This method takes a hash reference and filters keys and associated
823             # values from it. The first argument, $rh_hash, is changed in place.
824             # The second argument $ra_keys is a list to keep; however, if the third
825             # boolean argument $is_compl is true, then the complement of $ra_keys is
826             # kept instead.
827              
828             sub _reduce_hash_to_subset { # meant only for internal use
829 35     35   47 my $self = CORE::shift( @_ );
830 35         37 my $rh_hash_copy = CORE::shift( @_ );
831 35         46 my $ra_keys = CORE::shift( @_ );
832 35 100       185 $ra_keys = (ref($ra_keys) eq 'HASH') ? (CORE::keys %{$ra_keys}) :
  0 50       0  
    50          
833             UNIVERSAL::isa($ra_keys,'Data::MultiValuedHash') ? $ra_keys->keys() :
834             (ref($ra_keys) ne 'ARRAY') ? [$ra_keys] : $ra_keys;
835 35         52 my $case_inse = $self->{$KEY_CASE_INSE};
836 35 100       35 my %spec_keys = map { ( $case_inse ? lc($_) : $_ => 1 ) } @{$ra_keys};
  57         157  
  35         49  
837 35 100       75 if( CORE::shift( @_ ) ) { # want complement of keys list
838 9 100       40 %{$rh_hash_copy} = map { !$spec_keys{$_} ?
  45         89  
  9         20  
839 9         8 ($_ => $rh_hash_copy->{$_}) : () } CORE::keys %{$rh_hash_copy};
840             } else {
841 26 100       117 %{$rh_hash_copy} = map { $spec_keys{$_} ?
  133         224  
  26         66  
842 26         28 ($_ => $rh_hash_copy->{$_}) : () } CORE::keys %{$rh_hash_copy};
843             }
844             }
845              
846             ######################################################################
847              
848             1;
849             __END__