|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 FakeHash - Simulate the behavior of a Perl hash variable  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	use FakeHash;  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $hash = FakeHash->new;  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash->store($key, $value);     # analogous to $h{$key} = $value  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	@keys = $hash->keys;            # analogous to @keys = keys %h  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash->delete($key);		# analogous to delete $h{$key}  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$value = $hash->fetch($key);    # analogous to $value = $h{$key}  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$string = $hash->scalarval;     # analogous to $string = %h  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$string = $hash->clear;         # analogous to %h = ()  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash->iterate(...);            # Invoke callbacks for each bucket and node  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Caution: Not tested  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $hash = tie %h => FakeHash;  # $hash will mirror the changes to %h  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	use FakeHash 'hashval';  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$n = hashval($string);          # hash value for string  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	FakeHash->version(5.005);       # Use Perl 5.005 hashval function  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$version = FakeHash->version;   # Return Perl version currently in force  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C simulates the behavior of a Perl hash variable,  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 maintaining a synthetic data structure that mirrors the true data  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 structure inside of Perl.  This can be used to investigate hash  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 performance or behavior.  For example, see the C  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 class, described below, which draws a box-and-arrow diagram  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 representing the memory layout of a hash.  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The C, C, C, and C methods perform the  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 corresponding operations on the simulated hash.  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The C method iterates over the simulated structure and  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 invokes user-supplied callbacks.  The arguments to C are a  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 hash of I, and an optional I.  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The C hash may have any or all of the following keys:  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A function that is called once for each bucket in the hash, prior to  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 iterating over the nodes in the bucket.  The arguments to the  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C function are: the bucket number; a C  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 object representing the first node in the bucket (or an undefined  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 value of the bucket is empty,) and the user parameter.  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The same, except that the function is called after iterating over the  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 nodes in the bucket.  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A function that is called once for each node (key-value pair) in the  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 hash.  The node function is called for a node after the C  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 function and before the C function is called for the  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 node's bucket.  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The arguments to the C function are: The bucket number; a  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C object representing the first node in the bucket;  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the node's number within the bucket (0 for the first node in the  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 bucket); the node itself; and the user parameter.  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 If this is a number, say I, C will only iterate over the  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 first I buckets, and will skip the later buckets and their  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 contents.  If this is a function, C will call it once, with  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the user paramater as its argument, and will expect it to return a  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 number I to be used as above.  If it is omitted, C will  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 iterate over all buckets and their contents.  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 For example, the C method is implemented as a call to C, as follows:  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	sub keys {  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  my $self = shift;  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  my @r;  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  $self->iterate({node => sub { my ($i, $b, $n, $node) = @_;  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	                                push @r, $node->key;  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	                              },  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	                 });  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  @r;  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Other Methods  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 CDEBUG> will return the current setting of the C  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 flag, and will change the value of the flag if given an argument.  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 When the C flag is set to a true value, the module may emit  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 diagnostic messages to C.  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Each C object may carry auxiliary information.  Auxiliary  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 information is not used by C but may be used by subclasses.  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C<$hash-Eset_defaults(key, value, key, value,...)> sets the  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 specified auxiliariy data values for the C object.  A  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 hashref may be passed instead; its contents will be appended to the  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 values already installed.  To query the currently-set values, use  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C<$hash-Edefaults(key, key, ...)>, which will return a list of the  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 corresponding values, or, in scalar context, a reference to an array  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 of the corresponding values.  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C<$hash-Esize> retrieves the number of buckets in the  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 hash.  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The Perl hash function changed between versions 5.005 and 5.6, so the  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 behavior of Perl hashes changed at the same time.  By default,  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C will emulate the behavior of whatever version of Perl it  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 is running under.  To change this, use the C method.  Its  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 argument is the version of Perl that you would like to emulate.  It  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 returns the version number prior to setting.  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package FakeHash;  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = '0.80';  | 
| 
127
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
528
 | 
 use strict 'vars', 'refs';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99
 | 
    | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub croak;  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $DEBUG = 0;  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $VERSION = $];  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $INIT_SIZE = 8;  # Do not touch  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub import {  | 
| 
135
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
7
 | 
   my $caller = caller;  | 
| 
136
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
   my $class = shift;  | 
| 
137
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1709
 | 
   for (@_) {  | 
| 
138
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     unless ($_ eq 'hashval') {  | 
| 
139
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       croak "$_ not exported by FakeHash";  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
141
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
5
 | 
     no strict 'refs';  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1832
 | 
    | 
| 
142
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     *{"$caller\::$_"} = \&{"$class\::$_"};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # I am a constant-like subroutine *and* a class method  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub DEBUG {  | 
| 
148
 | 
37
 | 
 
 | 
 
 | 
  
37
  
 | 
  
0
  
 | 
35
 | 
   shift;                        # class name  | 
| 
149
 | 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
   my $old_debug = $DEBUG;  | 
| 
150
 | 
37
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
53
 | 
   $DEBUG = shift if @_;  | 
| 
151
 | 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
72
 | 
   $old_debug;  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub version {  | 
| 
155
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   shift;                        # class name  | 
| 
156
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $old_version = $VERSION;  | 
| 
157
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $VERSION = shift if @_;  | 
| 
158
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $old_version;  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
162
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
12
 | 
   my $self = { B => [(undef) x $INIT_SIZE],   | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                K => 0,   | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                S => $INIT_SIZE,  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                D => {},  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
              };  | 
| 
167
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   bless $self, shift();  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_defaults {  | 
| 
171
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
3
 | 
   my $self = shift;  | 
| 
172
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   my $kvps;  | 
| 
173
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   if (@_ == 1) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
174
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     $kvps = shift;  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (@_ % 2 == 0) {  | 
| 
176
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     my %kvps = @_;  | 
| 
177
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     $kvps = \%kvps;  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
179
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     croak "usage: \$fakehash->default(\$hashref) or \$fakehash->default(key, val, ...)";  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
181
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   while (my ($k => $v) = each %$kvps) {  | 
| 
182
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     $self->{D}{$k} = $v;  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub defaults {  | 
| 
187
 | 
46
 | 
 
 | 
 
 | 
  
46
  
 | 
  
0
  
 | 
67
 | 
   my ($self) = shift;  | 
| 
188
 | 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
   my @r ;  | 
| 
189
 | 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
62
 | 
   for (@_) {  | 
| 
190
 | 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
117
 | 
     push @r, $self->{D}{$_};  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
192
 | 
46
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
107
 | 
   wantarray ? @r : \@r;  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub TIEHASH {  | 
| 
196
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($pack) = @_;  | 
| 
197
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $pack->new();  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub FETCH {  | 
| 
201
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($self, $k) = @_;  | 
| 
202
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $self->fetch($k);  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub STORE {  | 
| 
206
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($self, $k, $v) = @_;  | 
| 
207
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $self->store($k, $v);  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub DELETE {  | 
| 
211
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($self, $k) = @_;  | 
| 
212
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $self->delete($k);  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub CLEAR {  | 
| 
216
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my ($self) = @_;  | 
| 
217
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $self->clear();  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub scalarval {  | 
| 
221
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my ($self) = @_;  | 
| 
222
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $n = grep defined, @{$self->{B}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
223
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $d = $self->size;  | 
| 
224
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   "$n/$d";  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub size {  | 
| 
228
 | 
30
 | 
 
 | 
 
 | 
  
30
  
 | 
  
0
  
 | 
30
 | 
   my $self = shift;  | 
| 
229
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   my $old_size = $self->{S};  | 
| 
230
 | 
30
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
51
 | 
   if (@_) {  | 
| 
231
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $self->{S} = round_up(shift());  | 
| 
232
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     $#{$self->{B}} = $self->{S} - 1;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
234
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
102
 | 
   $old_size;  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub iterate {  | 
| 
239
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
3
 | 
   my ($self, $actions, $u) = @_;  | 
| 
240
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my $s = $actions->{maxbucket};  | 
| 
241
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   if (ref $s) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
242
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $s = $s->($u);  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (! defined $s) {  | 
| 
244
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $s = $self->size;  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
246
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   for (my $i=0;  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $i < $s;  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $i++) {  | 
| 
249
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
51
 | 
     my $b = $self->_bucket($i);  | 
| 
250
 | 
32
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
67
 | 
     $actions->{prebucket}->($i, $b, $u) if exists $actions->{prebucket};  | 
| 
251
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     my $nodeno = 0;  | 
| 
252
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
63
 | 
     for (my $node = $b;  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          $node;  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          $node = $node->next) {  | 
| 
255
 | 
26
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
78
 | 
       $actions->{node}->($i, $b, $nodeno++, $node, $u) if exists $actions->{node};  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
257
 | 
32
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
96
 | 
     $actions->{postbucket}->($i, $b, $nodeno, $u) if exists $actions->{postbucket};  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub store {  | 
| 
262
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
  
0
  
 | 
93
 | 
   my ($self, $key, $value) = @_;  | 
| 
263
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   my $hash = hashval($key);  | 
| 
264
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
   my $bucket = $hash % $self->size;  | 
| 
265
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
   $self->h_insert_h($key, $value, $hash, $bucket);  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub h_insert_h {  | 
| 
269
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
  
0
  
 | 
15
 | 
   my ($self, $key, $value, $hash, $bucket) = @_;  | 
| 
270
 | 
13
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
27
 | 
   if (my $node = $self->_search_bucket($bucket, $key, $hash)) {  | 
| 
271
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $node->value($value);  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
273
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     my $head_node = $self->_bucket($bucket);  | 
| 
274
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     $self->_append_bucket($bucket, FakeHash::Node->new($key, $value, $hash));  | 
| 
275
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     ++$self->{K};  ## MOVE ME  | 
| 
276
 | 
13
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
34
 | 
     $self->double_size() if $self->is_full && ! $head_node;  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub keys {  | 
| 
281
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
8
 | 
   my $self = shift;  | 
| 
282
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
   my @r;  | 
| 
283
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
13
 | 
   $self->iterate({node => sub { my ($i, $b, $n, $node) = @_;  | 
| 
284
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
                                 push @r, $node->key;  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                               },  | 
| 
286
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
                  });  | 
| 
287
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   @r;  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_full {  | 
| 
291
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
  
0
  
 | 
9
 | 
   my $self = shift;  | 
| 
292
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
   $self->{K} >= $self->{S};  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clone {  | 
| 
297
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my $self = shift;  | 
| 
298
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $new = (ref $self)->new;  | 
| 
299
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $new->{S} = $self->{S};  | 
| 
300
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $new->{K} = $self->{K};  | 
| 
301
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $new->{B} = [@{$self->{B}}];  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
302
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   bless $new => (ref $self);  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub double_size {  | 
| 
306
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
2
 | 
   my ($self) = @_;  | 
| 
307
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   my $os = $self->size;  | 
| 
308
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
   my $ns = $os * 2;  | 
| 
309
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3
 | 
   print STDERR "Reconstructing from $os -> $ns\n" if DEBUG  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $self->size($ns);  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # copied and translated from 5.6.0 hv.c:892 ff  | 
| 
313
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   for (my $i=0; $i< $os; $i++) {  | 
| 
314
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     print STDERR "Bucket #$i:\n" if DEBUG;  | 
| 
315
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     my $prev;  | 
| 
316
 | 
8
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     for (my $entry = $self->_bucket($i);   | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          $entry;   | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          $entry = $prev ? $prev->next : $self->_bucket($i)) {  | 
| 
319
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
       print STDERR "  entry($entry->[0])\n" if DEBUG;  | 
| 
320
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
       my $hash = $entry->hash;  | 
| 
321
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
       print STDERR "  hash = $hash, ", "lowbits = ", $hash & ($ns-1), "\n"   | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if DEBUG;  | 
| 
323
 | 
11
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
       if (($hash & ($ns - 1)) != $i) { # $entry needs to move  | 
| 
324
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
         print STDERR " RELOCATING\n" if DEBUG;  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # fix pointer that was *to* $entry  | 
| 
327
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
         if ($prev) {  | 
| 
328
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
           $prev->next($entry->next);  | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
330
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
           $self->_bucket($i, $entry->next);  | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # fix pointer *from* $entry  | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # and insert $entry at beginning of bucket b  | 
| 
335
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
         $entry->next($self->_bucket($i + $os));   | 
| 
336
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
         $self->_bucket($i + $os, $entry);  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
338
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
         $prev = $entry;  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clear {  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $self = shift;  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $size = $self->size;  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   @{$self->{B}} = (undef) x $size;  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _search_bucket {  | 
| 
351
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
15
 | 
   my ($self, $b, $k, $h) = @_;  | 
| 
352
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   for (my $node = $self->_bucket($b);  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $node;  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $node = $node->next) {  | 
| 
355
 | 
9
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
19
 | 
     return $node if $h == $node->hash && $k eq $node->key;  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
357
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
   return;  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _append_bucket {  | 
| 
361
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
39
 | 
   my ($self, $b, $node) = @_;  | 
| 
362
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   $node->next($self->_bucket($b));  | 
| 
363
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
   $self->_bucket($b, $node);  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _bucket {  | 
| 
367
 | 
110
 | 
 
 | 
 
 | 
  
110
  
 | 
 
 | 
125
 | 
   my ($self, $b, $new) = @_;  | 
| 
368
 | 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
128
 | 
   my $old = $self->{B}[$b];  | 
| 
369
 | 
110
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
181
 | 
   $self->{B}[$b] = $new if @_ > 2;  | 
| 
370
 | 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
194
 | 
   $old;  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub delete {  | 
| 
374
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my ($self, $key) = @_;  | 
| 
375
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $h = hashval($key);  | 
| 
376
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $s = $self->size;  | 
| 
377
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $b = $h & ($s-1);  | 
| 
378
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my ($prev, $cur);  | 
| 
379
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   for ($cur = $self->_bucket($b);  | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $cur;  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
        $prev = $cur, $cur = $cur->next) {  | 
| 
382
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     next unless $cur->hash == $h && $cur->key eq $key;  | 
| 
383
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($prev) {  | 
| 
384
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       $prev->next($cur->next);  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
386
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       $self->_bucket($b, $cur->next);  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub fetch {  | 
| 
392
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my ($self, $key) = @_;  | 
| 
393
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $h = hashval($key);  | 
| 
394
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $s = $self->size;  | 
| 
395
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $b = $self->_bucket($h & ($s-1));  | 
| 
396
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $self->_search_bucket($b, $key, $h);  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clear {  | 
| 
400
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my $self = shift;  | 
| 
401
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   %$self = %{$self->new};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub croak {  | 
| 
405
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   require Carp;  | 
| 
406
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   Carp::croak(@_);  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # thanks to I0 from perlmonks for this  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # extremely clever solution  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub round_up {  | 
| 
412
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
0
  
 | 
3
 | 
   my $x = shift;  | 
| 
413
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   return $x unless $x & ($x-1);  | 
| 
414
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   for (1, 2, 4, 8, 16) {  | 
| 
415
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $x |= $x >> $_;  | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
417
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   ++$x;  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # sub round_up {  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   my $z = my $x = shift;  | 
| 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   return $x unless $x & ($x-1);  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   while ($x) {  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #     $z = $x;  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #     $x &= $x-1;  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   }  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   $z<<1;  | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # }  | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _B32 () { 2**32 - 1}  # constant  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # i am not a method  | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub hashval {  | 
| 
434
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
786
 | 
   use integer;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
| 
435
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
  
0
  
 | 
14
 | 
   my ($string) = @_;  | 
| 
436
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   my $h = 0;  | 
| 
437
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
   for my $c (split //, $string) {  | 
| 
438
 | 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
     $h = ($h * 33 + ord($c));  | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
440
 | 
13
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
27
 | 
   $h += $h >> 5 if $VERSION >= 5.006;  | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  print STDERR "HASH $string => $h ($VERSION)\n";  | 
| 
442
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   return $h;  | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 FakeHash::DrawHash - Draw a C diagram of the internal structure of a hash  | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
451
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $hash = FakeHash::DrawHash->new;  | 
| 
453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           | 
| 
454
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # see L for more details  | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $hash->draw($filehandle);  #  Print 'pic' commands to filehandle  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C is a subclass of C that can draw a  | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 picture of the internal structure of a Perl hash variable.  It emits  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 code suitable for the Unix C drawing program.  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
464
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C provides the following methods:  | 
| 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 draw  | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Emit C code for a box-and-arrow diagram that represents the  | 
| 
469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 current state of the simulated hash.  A filehandle argument may be  | 
| 
470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 provided to receive the output.  If omitted, output goes to C.  | 
| 
471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Additionally, a user parameter argument may be provided, which will be  | 
| 
472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 passed to the other C methods.  | 
| 
473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 draw_param  | 
| 
475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Set or retrieve various parameters dermining box size and layout.  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Takes a name and an optional value argument and returns the old value  | 
| 
478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 associated with the name.  If the value is provided, sets the new  | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 value.  Valid names are:  | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over 4  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B  | 
| 
484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Determines the size of the boxes used to represent each hash bucket.  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The value should be a reference to an array of the height and width,  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 in inches.  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Defaults to C<[1, 0.55]>, or one inch wide by 0.55 inches tall.  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B  | 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Amount of horizontal space,in inches, between the box that represents  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 a bucket and the bixes that represent the bucket contents.  If zero,  | 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the buckets will abut their contents.  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Defaults to 1/5 inch.  | 
| 
498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B  | 
| 
500
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The size of the boxes used to represent each key-value node.  The  | 
| 
502
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 value should be a reference to an array of the height and width, in  | 
| 
503
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 inches.  | 
| 
504
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Defaults to C<[1, 0.5]>, or one inch wide by half an inch tall.  | 
| 
506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back   | 
| 
508
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 draw_start  | 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Called once, each time drawing commences.  Arguments: The filehandle  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 and user parameter, if any, that were passed to C.  | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 draw_end  | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Called once, just at the end of each call to C.  Arguments: The  | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 filehandle and user parameter, if any, that were passed to C.  | 
| 
518
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 draw_bucket  | 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Called each time C needs to draw a single bucket.    | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Arguments: The filehandle that was passed to C; the bucket  | 
| 
524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 number (starting from 0) of the current bucket; a boolean value which  | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 is true if and only if the bucket is nonempty; and the user parameter  | 
| 
526
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 that was passed to C.  | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
528
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 draw_node  | 
| 
529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
530
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Called each time C needs to draw a single key-value node.    | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Arguments: The filehandle that was passed to C; the bucket  | 
| 
533
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 number (starting from 0) of the bucket in which the current node  | 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 resides; the number of the node in the current bucket (the first node  | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 is node zero); a C object representing the node  | 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 itself; and the user parameter that was passed to C.  | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 IDEA  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The theory here is that it should be easy to override these methods  | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 with corresponding methods that draw the diagram in PostScript or GD  | 
| 
542
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 or whatever.  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 If you do this, please send me the code so that I can distribute it.  | 
| 
545
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
546
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package FakeHash::DrawHash;  | 
| 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
550
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
867
 | 
 BEGIN { @FakeHash::DrawHash::ISA = 'FakeHash' }  | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %defaults = ( BUCKET => [1, 0.55],  | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                  KVP => [1, 0.5],  | 
| 
554
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                  BUCKETSPACE => 0.2,  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                );  | 
| 
556
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
558
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
273106
 | 
   my $class = shift;  | 
| 
559
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
   my $self = $class->SUPER::new(@_);  | 
| 
560
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   $self->set_defaults(\%defaults);  | 
| 
561
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
   $self;  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
563
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
564
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub draw_param {  | 
| 
565
 | 
46
 | 
 
 | 
 
 | 
  
46
  
 | 
 
 | 
90
 | 
   my ($self, $key, $value) = @_;  | 
| 
566
 | 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
77
 | 
   my ($old) = $self->defaults($key);  | 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
568
 | 
46
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
76
 | 
   if (defined $value) {  | 
| 
569
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $self->set_defaults($key, $value);  | 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }   | 
| 
571
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
572
 | 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
78
 | 
   $old;  | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
574
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
575
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub draw {  | 
| 
576
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
16
 | 
   my ($self, $fh, $u) = @_;  | 
| 
577
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
   local *FH;  | 
| 
578
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
   if (! defined $fh) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
579
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $fh = \*STDOUT;  | 
| 
580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (! defined fileno $fh) {  | 
| 
581
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     FakeHash::croak "Couldn't open file $fh" unless open FH, "< $fh";  | 
| 
582
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $fh = \*FH;  | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
584
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       | 
| 
585
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   $self->draw_start($fh, $u);  | 
| 
586
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $self->iterate({ prebucket => sub {  | 
| 
587
 | 
16
 | 
 
 | 
 
 | 
  
16
  
 | 
 
 | 
17
 | 
                      my ($b, $bucket) = @_;  | 
| 
588
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
                      $self->draw_bucket($fh, $b, defined $bucket, $u);  | 
| 
589
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                    },  | 
| 
590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                    node => sub {  | 
| 
591
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
18
 | 
                      my ($b, $bucket, $n, $node) = @_;  | 
| 
592
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
                      $self->draw_node($fh, $b, $n, $node, $u);  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                    },  | 
| 
594
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
                  });  | 
| 
595
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   $self->draw_end($fh, $u);  | 
| 
596
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub draw_bucket {  | 
| 
599
 | 
16
 | 
 
 | 
 
 | 
  
16
  
 | 
 
 | 
24
 | 
   my ($self, $fh, $bucket_no, $nonempty) = @_;  | 
| 
600
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   my ($wd, $ht) = @{$self->draw_param('BUCKET')};  | 
| 
 
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
    | 
| 
601
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
   my $bs = $self->draw_param('BUCKETSPACE');  | 
| 
602
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
69
 | 
   print $fh "boxwid:=$wd; boxht:=$ht\n";  | 
| 
603
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
   printf $fh "B%02d: box ", $bucket_no;  | 
| 
604
 | 
16
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
50
 | 
   printf $fh "with .n at B%02d.s", $bucket_no-1 if $bucket_no > 0;  | 
| 
605
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
   printf $fh "\n";  | 
| 
606
 | 
16
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
   if ($nonempty) {  | 
| 
607
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     printf $fh "circle at B%02d.c rad 0.1 filled\n", $bucket_no;  | 
| 
608
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
     printf $fh "arrow from B%02d.c right boxwid/2 + $bs\n", $bucket_no;  | 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
610
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # this method assumes that the current 'pic' position is already   | 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # correct, which might not be true if one of the other methods is  | 
| 
614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # overriden.  Fix it.  | 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub draw_node {  | 
| 
616
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
16
 | 
   my ($self, $fh, $bucket_no, $node_index, $node) = @_;  | 
| 
617
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   my ($k, $v, $h, $next) = @$node;  | 
| 
618
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   my ($wd, $ht) = @{$self->draw_param('KVP')};  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
    | 
| 
619
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
   print $fh "boxwid:=$wd; boxht:=$ht\n";  | 
| 
620
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
   printf $fh qq{N%02d%02d: box "%s" "%s" "%u(%u)"\n}, $bucket_no, $node_index, $k, $v, $h, $h&($self->size * 2  - 1);  | 
| 
621
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
622
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub draw_start {  | 
| 
624
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
2
 | 
   my ($self, $fh) = @_;  | 
| 
625
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   print $fh ".PS\n";  | 
| 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub draw_end {  | 
| 
629
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
2
 | 
   my ($self, $fh) = @_;  | 
| 
630
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   print $fh ".PE\n";  | 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
635
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
636
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 FakeHash::Node - Class used internally by C to represent key-value pairs  | 
| 
637
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
638
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
640
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $key   = $node->key;  | 
| 
641
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $value = $node->value;  | 
| 
642
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $hash  = $node->hash;  | 
| 
643
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $next  = $node->next;  | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
645
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
646
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C is used internally by C for various  | 
| 
648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 purposes.  For example, the C function invokes a  | 
| 
649
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 user-supplied callback for each key-value pair, passing it a series of  | 
| 
650
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C objects that represent the key-value pairs.  | 
| 
651
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The C and C methods retrieve the key and value of a node.  | 
| 
653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The C method retrieves the key's hash value.    | 
| 
654
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
655
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C<$node-Enext> method retrieves the node that follows C<$node> in  | 
| 
656
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 its bucket, or an undefined value if C<$node> is last in its bucket.  | 
| 
657
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
658
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 If any of these methods is passed an additional argument, it will set  | 
| 
659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the corresponding value.  It will return the old value in any case.  | 
| 
660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
661
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
662
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
663
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package FakeHash::Node;  | 
| 
664
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
666
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
23
 | 
   my ($class, @data) = @_;  | 
| 
667
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
   bless \@data => $class;  | 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
669
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
670
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _access {  | 
| 
671
 | 
104
 | 
 
 | 
 
 | 
  
104
  
 | 
 
 | 
81
 | 
   my $self = shift;  | 
| 
672
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
83
 | 
   my $index = shift;  | 
| 
673
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99
 | 
   my $oldval = $self->[$index];  | 
| 
674
 | 
104
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
155
 | 
   $self->[$index] = shift if @_;  | 
| 
675
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
230
 | 
   $oldval;  | 
| 
676
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
678
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub key {  | 
| 
679
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
 
 | 
14
 | 
   my $self = shift;  | 
| 
680
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   $self->_access(0, @_);  | 
| 
681
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
682
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
683
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub value {  | 
| 
684
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   my $self = shift;  | 
| 
685
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $self->_access(1, @_);  | 
| 
686
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
688
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub hash {  | 
| 
689
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
18
 | 
   my $self = shift;  | 
| 
690
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
   $self->_access(2, @_);  | 
| 
691
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
692
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub next {  | 
| 
694
 | 
71
 | 
 
 | 
 
 | 
  
71
  
 | 
 
 | 
63
 | 
   my $self = shift;  | 
| 
695
 | 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
112
 | 
   $self->_access(3, @_);  | 
| 
696
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
697
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
698
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
700
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 AUTHOR  | 
| 
701
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
702
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Mark-Jason Dominus (C)  | 
| 
703
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
704
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 COPYRIGHT  | 
| 
705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 C is a Perl module that simulates the behavior of a Perl hash  | 
| 
707
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 variable.  C renders a diagram of a simulated hash.  | 
| 
708
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Copyright (C) 200 Mark-Jason Dominus  | 
| 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This program is free software; you can redistribute it and/or modify it  | 
| 
712
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 under the terms of the GNU General Public License as published by the Free  | 
| 
713
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Software Foundation; either version 2 of the License, or (at your option)  | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 any later version.  | 
| 
715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This program is distributed in the hope that it will be useful, but WITHOUT  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  | 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 more details.  | 
| 
720
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 You should have received a copy of the GNU General Public License along  | 
| 
722
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 with this program; if not, write to the Free Software Foundation, Inc., 675  | 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Mass Ave, Cambridge, MA 02139, USA.  | 
| 
724
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
725
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  |