File Coverage

blib/lib/Hash/SafeKeys.pm
Criterion Covered Total %
statement 23 23 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod 3 3 100.0
total 33 33 100.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Hash::SafeKeys - get hash contents without resetting each iterator
4              
5             =head1 VERSION
6              
7             Version 0.03
8              
9             =cut
10              
11             =head1 SYNOPSIS
12              
13             use Hash::SafeKeys;
14             while (my ($k,$v) = each %hash) {
15             if (something_interesting_happens()) {
16             # get keys, values of %hash without resetting
17             # the 'each' iterator above
18             my @k = safekeys %hash;
19             my @v = safevalues %hash;
20             my %copy = safecopy %hash;
21             }
22             }
23              
24             =head1 DESCRIPTION
25              
26             Every hash variable in Perl has its own internal iterator,
27             accessed by the builtin C, C, and C
28             functions. The iterator is also implicitly used whenever
29             the hash is evaluated in list context. The iterator is
30             "reset" whenever C or C is called on a hash,
31             including the implicit calls when the hash is evaluated in
32             list context. That makes it dangerous to do certain hash
33             operations inside a C loop:
34              
35             while (my($k,$v) = each %hash) {
36             ...
37             @k = sort keys %hash; # Infinite loop!
38             @v = grep { /foo/ }, values %hash; # Ack!
39             print join ' ', %hash; # Run away!
40             }
41              
42             C provides alternate functions to access
43             the keys, values, or entire contents of a hash in a way
44             that does not reset the iterator, making them safe to use
45             in such contexts:
46              
47             while (my($k,$v) = each %hash) {
48             ...
49             @k = sort safekeys %hash; # Can do
50             @v = grep { /foo/ }, safevalues %hash; # No problem
51             print join ' ', safecopy %hash; # Right away, sir
52             }
53              
54             =head1 FUNCTIONS
55              
56             =head2 LIST = safekeys HASH
57              
58             Like the builtin L function, returns a list
59             consisting of all the keys of the named hash, in the same order
60             that the builtin function would return them in. Unlike C,
61             calling C does not reset the HASH's internal iterator
62             (see L).
63              
64             =head2 LIST = safevalues HASH
65              
66             Like the builtin L function, returns a list
67             consisting of all the values of the named hash, in the same order
68             that the builtin function would return them in. Unlike C,
69             calling C does not reset the HASH's internal iterator
70             (see L).
71              
72             =head2 LIST = safecopy HASH
73              
74             In list context, returns a shallow copy of the named HASH without
75             resetting the HASH's internal iterator. Usually, evaluating a HASH
76             in list context implicitly uses the internal iterator, resetting
77             any existing state.
78              
79             =head1 EXPORT
80              
81             L<"safekeys">, L<"safevalues">, and L<"safecopy"> are all
82             exported by default. Invoke L with the empty arg list
83              
84             use Hash::SafeKeys ();
85              
86             if you don't want these functions to be imported into the calling
87             package.
88              
89             =head1 AUTHOR
90              
91             Marty O'Brien, C<< >>
92              
93             =head1 BUGS
94              
95             Please report any bugs or feature requests to C, or through
96             the web interface at L. I will be notified, and then you'll
97             automatically be notified of progress on your bug as I make changes.
98              
99             =head1 SUPPORT
100              
101             You can find documentation for this module with the perldoc command.
102              
103             perldoc Hash::SafeKeys
104              
105              
106             You can also look for information at:
107              
108             =over 4
109              
110             =item * RT: CPAN's request tracker (report bugs here)
111              
112             L
113              
114             =item * AnnoCPAN: Annotated CPAN documentation
115              
116             L
117              
118             =item * CPAN Ratings
119              
120             L
121              
122             =item * Search CPAN
123              
124             L
125              
126             =back
127              
128              
129             =head1 ACKNOWLEDGEMENTS
130              
131             The C method in the L module demonstrated how
132             to save and restore internal hash iterator state.
133             This module is indebted to the authors of this module and to
134             L<< user C at stackoverflow.com|http://stackoverflow.com/a/10921567/168857 >>
135             for directing me to it.
136              
137             =head1 LICENSE AND COPYRIGHT
138              
139             Copyright 2012 Marty O'Brien.
140              
141             This program is free software; you can redistribute it and/or modify it
142             under the terms of either: the GNU General Public License as published
143             by the Free Software Foundation; or the Artistic License.
144              
145             See http://dev.perl.org/licenses/ for more information.
146              
147             =cut
148              
149             package Hash::SafeKeys;
150              
151 2     2   23956 use strict;
  2         5  
  2         73  
152 2     2   9 use warnings;
  2         4  
  2         63  
153 2     2   11 use base qw(Exporter);
  2         7  
  2         267  
154             our @EXPORT = qw(safekeys safevalues safecopy);
155             our $VERSION = '0.03';
156              
157             # crutch for creating the XS code ...
158             #use Inline (Config => CLEAN_AFTER_BUILD => 0, FORCE_BUILD => 1, BUILD_NOISY => 1);
159             #use Inline 'C';
160              
161             # crutches off
162 2     2   10 use base qw(DynaLoader); bootstrap Hash::SafeKeys $VERSION;
  2         3  
  2         508  
163              
164             sub safekeys (\%) {
165 28     28 1 7504 my $hash = shift;
166 28         69 my $state = save_iterator_state($hash);
167 28         162 my @keys = keys %$hash;
168 28         58 restore_iterator_state($hash,$state);
169 28         89 return @keys;
170             }
171              
172             sub safevalues (\%) {
173 10     10 1 1060 my $hash = shift;
174 10         20 return map { $hash->{$_} } safekeys(%$hash);
  48         132  
175             }
176              
177             sub safecopy (\%) {
178 8     8 1 35 my $hash = shift;
179 8         16 return map { ($_,$hash->{$_}) } safekeys(%$hash);
  40         131  
180             }
181              
182             1;
183              
184             __DATA__