|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Tie::Hash::MultiKey;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #use diagnostics;  | 
| 
4
 | 
23
 | 
 
 | 
 
 | 
  
23
  
 | 
 
 | 
22908
 | 
 use strict;  | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
47
 | 
    | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
929
 | 
    | 
| 
5
 | 
23
 | 
 
 | 
 
 | 
  
23
  
 | 
 
 | 
129
 | 
 use Carp;  | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42
 | 
    | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1858
 | 
    | 
| 
6
 | 
23
 | 
 
 | 
 
 | 
  
23
  
 | 
 
 | 
30323
 | 
 use Tie::Hash;  | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28965
 | 
    | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
838
 | 
    | 
| 
7
 | 
23
 | 
 
 | 
 
 | 
  
23
  
 | 
 
 | 
155
 | 
 use vars qw($VERSION);  | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42
 | 
    | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
97468
 | 
    | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = do { my @r = (q$Revision: 0.08 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $indexmax = 2**48;	# a really big unique number that perl will not convert to float  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Tie::Hash::MultiKey - multiple keys per value  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Tie::Hash::MultiKey;  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $thm = tie %hash, qw(Tie::Hash::MultiKey) ,@optionalext;  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $thm = tied %hash;  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   untie %hash;  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ($href,$thm) = new Tie::Hash::MultiKey;  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $hash{'foo'}        = 'baz';  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	or  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $hash{'foo', 'bar'} = 'baz';  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	or  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $array_ref = ['foo', 'bar'];  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $hash{ $array_ref } = 'baz';  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   print $hash{foo};	# prints 'baz'  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   print $hash{bar};	# prints 'baz'  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $array_ref = ['fuz','zup'];  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $val = tied(%hash)->addkey('fuz' => 'bar');  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $val = tied(%hash)->addkey('fuz','zup' => 'bar');  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $val = tied(%hash)->addkey( $array_ref => 'bar');  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   print $hash{fuz}	# prints 'baz'  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $array_ref = ['foo', 'bar'];  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $val = tied(%hash)->remove('foo');  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $val = tied(%hash)->remove('foo', 'bar');  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $val = tied(%hash)->remove( $array_ref );  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $val = tied(%hash)->delkey(); alias for above  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   @ordered_keys = tied(%hash)->keylist('foo')  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   @allkeys_by_order = tied(%hash)->keylist();  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   @slotlist = tied(%hash)->slotlist($i);  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   @ordered_vals = tied(%hash)->vals();  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $num_vals = tied(%hash)->size;  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $num_vals = tied(%hash)->consolidate;  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ($newRef,$newThm) = tied(%hash)->clone();  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $newThm = tied(%hash)->copy(tied(%new),@optionalext);  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   All of the above methods can be accessed as:  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   i.e.	$thm->consolidate;  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Tie::Hash::MultiKey creates hashes that can have multiple ordered keys for a single value.   | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 As shown in the SYNOPSIS, multiple keys share a common value.  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Additional keys can be added that share the same value and keys can be removed without deleting other   | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 keys that share that value.  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 STORE..ing a value for one or more keys that already exist will overwrite  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the existing value and add any missing keys to the key group for that  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 value.  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B multiple key values supplied as an ARRAY to STORE and DELETE  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 operations are passed by Perl as a B string separated by Perl's $;  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 multidimensional array seperator. i.e.  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{'a','b','c'} = $something;  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   or  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	@keys = ('a','b','c');  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{@keys} = $something'  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This really means $hash{join($;, 'a','b','c')};  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Tie::Hash::MultiKey will do the right thing as long as your keys B  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 contain binary data the may include the $; separator character.  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 It is recommended that you use the ARRAY_REF construct to supply multiple  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 keys for binary data. i.e.  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{['a','b','c']} = $something;  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   or  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$keys = ['a','b','c'];  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{$keys} = $something;  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The ARRAY_REF construct is ALWAYS safe.  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # data structure  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # [  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 0 =>	{	# $kh  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	key	=> vi		# value_index for array below  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	},  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 1 =>	{	# $vh  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	vi	=> value,	# contains value  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	},  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 2 =>	{	# $sh	pointer to hash list of all shared keys  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	vi	= {key => dummy, key => dummy, ...}, values unused  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	},  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 3 =>	vi,	# numeric value of value index  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 4 =>	or,	# numeric value of key order  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 5 =>  crumbs	# STORE key value  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 6 =>	reserved  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 7 =>  {	# extensions  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   FETCH    => subref,	# required  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   STORE    => subref,	# required  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   DELETE   => subref,	# required  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   COPY     => subref,	# required  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   CLEAR    => subref,	# required  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   REORDERV => subref,	# required  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   TIE      => subref,	# optional  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   EXISTS   => subref,	# optional  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   NEXT     => subref,	# optional  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   ADDKEY   => subref,	# optional  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   DELKEY   => subref,	# optional  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   REORDERK => subref,	# optional  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   CONSOLD  => subref, # optional  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # one or more key names as required  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   DATAn     => scalar, array_ref, hash_ref  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # }  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # ]  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my @extrequired = qw(  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	FETCH  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	STORE  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	DELETE  | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	COPY  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	CLEAR  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	REORDERV  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my @extoptional = qw(  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	TIE  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	EXISTS  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	NEXT  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	ADDKEY  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	DELKEY  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	REORDERK  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	CONSOLD  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub TIEHASH {  | 
| 
160
 | 
27
 | 
 
 | 
 
 | 
  
27
  
 | 
 
 | 
8769
 | 
   my $class = shift;  | 
| 
161
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
132
 | 
   my $self = bless [{},{},{},0,0,undef], $class;  | 
| 
162
 | 
27
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
156
 | 
   if (@_) {  | 
| 
163
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     my %extensions = ref $_[0] ? @{$_[0]} : @_;  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
164
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     foreach (@extrequired) {  | 
| 
165
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
       unless (exists $extensions{$_}) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
166
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	croak "missing required extension for '$_'";  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } elsif (ref $extensions{$_} ne 'CODE') {  | 
| 
168
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	croak "'$_' extension pointer is not a subref";  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
170
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	$self->[7]->{$_} = $extensions{$_};  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
174
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     foreach(@extoptional) {  | 
| 
175
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
       unless (exists $extensions{$_}) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
176
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
 	$self->[7]->{$_} = sub {};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       elsif (ref $extensions{$_} ne 'CODE') {  | 
| 
179
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	croak "'$_' extension pointer is not a subref";  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
181
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
 	$self->[7]->{$_} = $extensions{$_};  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
185
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $self->[7]->{TIE}->($self);		# execute TIE extension to create DATA element  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
187
 | 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
110
 | 
   $self;  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # extract reference type and class from referrant or return an empty array  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # class may be empty;  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _ref_class {  | 
| 
193
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
13
 | 
   my $src = shift;  | 
| 
194
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   my $ref = ref $src or return ();  | 
| 
195
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my $class;  | 
| 
196
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
76
 | 
   if ( "$src" =~ /^\Q$ref\E\=([A-Z]+)\(0x[0-9a-fA-Z]+\)$/ ) {  | 
| 
197
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $class = $ref;  | 
| 
198
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $ref = $1;  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
200
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   return ($ref,$class);  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _isarrayref {  | 
| 
204
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
19
 | 
   my($ref,$class) = &_ref_class;   | 
| 
205
 | 
7
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
90
 | 
   return ($ref && $ref eq 'ARRAY') ? 1:0;  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _wash {  | 
| 
209
 | 
117
 | 
 
 | 
 
 | 
  
117
  
 | 
 
 | 
167
 | 
   my $keys = shift;  | 
| 
210
 | 
117
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
764
 | 
   $keys = [$keys eq ''   | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	? ('')  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	: split /$;/, $keys, -1]   | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   		unless ref $keys eq 'ARRAY';  | 
| 
214
 | 
117
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
316
 | 
   croak "empty key\n" unless @$keys;  | 
| 
215
 | 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
324
 | 
   return $keys;  | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub FETCH {  | 
| 
219
 | 
112
 | 
 
 | 
 
 | 
  
112
  
 | 
 
 | 
3688
 | 
   my($self,$key) = @_;  | 
| 
220
 | 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
108
 | 
   my $okey = $key;  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # in the case where an autoFETCH is done after a store  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # i.e.  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	$x = $hp->{[k1,k2,k3]} = item  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # or	$x = $hp->{ k1,k2,k3 } = item  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # the key set is passed by perl to the fetch instead of one of the keys  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # check if a fetch follows a store where  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 1	the key is an ARRAY and the referrant from the STORE are equal  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # 2	the key, stringified is equal to the key from the STORE  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # if either of these two condition are met, wash the keys and use  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # key[0] as the FETCH key  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
236
 | 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
150
 | 
   my $crumbs = $self->[5];  | 
| 
237
 | 
112
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
187
 | 
   if (defined $crumbs) {			# see if a recent STORE left key crumbs  | 
| 
238
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     $self->[5] = undef;				# yes, clear it  | 
| 
239
 | 
5
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
18
 | 
     if ((_isarrayref($crumbs) &&  | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 _isarrayref($key) &&			# keys are really ARRAY's  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	 $key == $crumbs ) ||			# and referrants the same  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$key . $; . 'X' eq $crumbs . $; . 'X')	# or keys as string identical  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     {  | 
| 
244
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
       $key = ${_wash($key)}[0];  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
247
 | 
112
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
209
 | 
   return undef unless exists $self->[0]->{$key};  | 
| 
248
 | 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
161
 | 
   my $vi = $self->[0]->{$key};	# get key index  | 
| 
249
 | 
112
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
206
 | 
   $self->[7]->{FETCH}->($self,$okey,$vi) if $self->[7];	# extend functionality ($vi)  | 
| 
250
 | 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
395
 | 
   return $self->[1]->{$vi};  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # take arguments of the form:  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	$array_ref, $val  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # or  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	$a0, $a1, $a2, $val  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # and returns  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	$val, @aN  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _flip {  | 
| 
261
 | 
17
 | 
 
 | 
 
 | 
  
17
  
 | 
 
 | 
1763
 | 
   my $val;  | 
| 
262
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
76
 | 
   if (ref $_[0] eq "ARRAY") {  | 
| 
263
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     return ($_[1],@{$_[0]});  | 
| 
 
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
41
 | 
    | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
265
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   return (pop(@_),@_);  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub STORE {  | 
| 
269
 | 
96
 | 
 
 | 
 
 | 
  
96
  
 | 
 
 | 
26042
 | 
   my($self,$keys,$val) = @_;  | 
| 
270
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
167
 | 
   $self->[5] = $keys;  | 
| 
271
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
114
 | 
   my @keys = @{_wash($keys)};  | 
| 
 
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
247
 | 
    | 
| 
272
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
149
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
157
 | 
    | 
| 
273
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
111
 | 
   my($vi,%found);  | 
| 
274
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
168
 | 
   foreach my $key (@keys) {  | 
| 
275
 | 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
224
 | 
     my $vi;  | 
| 
276
 | 
218
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
549
 | 
     next unless exists $kh->{$key};  | 
| 
277
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     $vi = $kh->{$key};	# get key index  | 
| 
278
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     $found{$vi} = $sh->{$vi}->{$key};	# capture shared key value  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
280
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
192
 | 
   my @vi = keys %found;  | 
| 
281
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
155
 | 
   $keys = {};  | 
| 
282
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
137
 | 
   my $ostart = $self->[4];  | 
| 
283
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
135
 | 
   my $oend = $ostart + $#keys;		# first key order entry  | 
| 
284
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
187
 | 
   $self->[4] = $oend + 1;		# last key order entry  | 
| 
285
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
163
 | 
   @{$keys}{@keys} = ($ostart..$oend);	# create key list  | 
| 
 
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
452
 | 
    | 
| 
286
 | 
96
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
220
 | 
   if (@vi) {				# if there are existing keys  | 
| 
287
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     foreach (@vi) {			# consolidate keys  | 
| 
288
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
       my @sk = keys %{$sh->{$_}};	# shared keys  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
| 
289
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
       @{$keys}{@sk} = @{$sh->{$_}}{@sk};  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
290
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
       delete $vh->{$_};		# delete existing value  | 
| 
291
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
       delete $sh->{$_};		# delete existing key list  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
294
 | 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
214
 | 
     $vi[0] = $self->[3]++;	# new key pointer  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
296
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
140
 | 
   $vi = shift @vi;  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
298
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
259
 | 
   $vh->{$vi} = $val;		# set value  | 
| 
299
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
148
 | 
   $sh->{$vi} = $keys;		# set key list  | 
| 
300
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
246
 | 
   foreach (keys %$keys) {  | 
| 
301
 | 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
443
 | 
     $kh->{$_} = $vi;		# set value index  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
303
 | 
96
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
270
 | 
   $self->_rordkeys() if $self->[3] > $indexmax;  | 
| 
304
 | 
96
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
221
 | 
   $self->_rordvals() if $self->[4] > $indexmax;  | 
| 
305
 | 
96
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
216
 | 
   $self->[7]->{STORE}->($self,\@keys,$vi) if $self->[7];	# extend functionality (value index)  | 
| 
306
 | 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
467
 | 
   $val;  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub DELETE {  | 
| 
310
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
 
 | 
16551
 | 
   my($self,$keys) = @_;  | 
| 
311
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
   $self->[5] = undef;		# clear crumbs  | 
| 
312
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
   my @keys = @{_wash($keys)};  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
    | 
| 
313
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
    | 
| 
314
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   my @vis = delete @{$kh}{@keys};	# delete all identified keys  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
315
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   my(@dkeys,@vix);  | 
| 
316
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
   foreach (@vis) {		# $vi delete key shared list entries  | 
| 
317
 | 
16
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
96
 | 
     unless (defined $_ && defined $sh->{$_}) { # already deleted?  | 
| 
318
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
       $_ = '';			# vi is never empty  | 
| 
319
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
       next;  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
321
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
     push @vix, $_;		# save unique value indices  | 
| 
322
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
     my $keys = delete $sh->{$_};  | 
| 
323
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
65
 | 
     @keys = sort { $keys->{$a} <=> $keys->{$b} } keys %$keys;	# all keys in this key set in the order added  | 
| 
 
 | 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
86
 | 
    | 
| 
324
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     push @dkeys, @keys;  | 
| 
325
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     delete @{$kh}{@keys};	# delete remaining keys in key set  | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
53
 | 
    | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
327
 | 
10
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
41
 | 
   $self->[7]->{DELETE}->($self,\@dkeys,\@vix) if $self->[7];  | 
| 
328
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
   delete @{$vh}{@vix};		# delete and return values in delete key order  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
71
 | 
    | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 } # NOTE: does not look like 'delete' does a wantarray  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub EXISTS {  | 
| 
332
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
1071
 | 
   $_[0]->[5] = undef;	# clear crumbs  | 
| 
333
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   return undef unless exists $_[0]->[0]->{$_[1]};  | 
| 
334
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   $_[0]->[7]->{EXISTS}->(@_) if $_[0]->[7];	# ($key)  | 
| 
335
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
   1;  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub FIRSTKEY {  | 
| 
339
 | 
11
 | 
 
 | 
 
 | 
  
11
  
 | 
 
 | 
23315
 | 
   keys %{$_[0]->[0]};	# reset iterator  | 
| 
 
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
    | 
| 
340
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
   &NEXTKEY;  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub NEXTKEY {  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  defined (my $key = each %{$_[0]->[0]}) or return undef;  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  return $key;  | 
| 
346
 | 
128
 | 
 
 | 
 
 | 
  
128
  
 | 
 
 | 
277
 | 
   $_[0]->[5] = undef;		# clear crumbs  | 
| 
347
 | 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
113
 | 
   my($key,$vi) = each %{$_[0]->[0]};  | 
| 
 
 | 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
231
 | 
    | 
| 
348
 | 
128
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
330
 | 
   $_[0]->[7]->{NEXT}->($_[0],$key,$vi) if $_[0]->[7] && defined $key;  | 
| 
349
 | 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
444
 | 
   $key;  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # delete all key, value sets  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _clear {  | 
| 
354
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
 
 | 
20
 | 
   my $self = shift;  | 
| 
355
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
   $self->[3] = 0;  | 
| 
356
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   $self->[4] = 0;  | 
| 
357
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
   $self->[5] = undef;  | 
| 
358
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   %{$self->[0]} = ();		# empty existing hashes  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
    | 
| 
359
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   %{$self->[1]} = ();  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
    | 
| 
360
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   %{$self->[2]} = ();  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
    | 
| 
361
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   $self;  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub CLEAR {  | 
| 
365
 | 
9
 | 
 
 | 
 
 | 
  
9
  
 | 
 
 | 
8419
 | 
   my $self = &_clear;  | 
| 
366
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
43
 | 
   $self->[7]->{CLEAR}->($self) if $self->[7];  | 
| 
367
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
420
 | 
   $self;  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub SCALAR {  | 
| 
371
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   $_[0]->[5] = undef;		# clear crumbs  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # no extension  | 
| 
373
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   scalar %{$_[0]->[0]};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over 4  | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $thm = tie %hash,'Tie::Hash::MultiKey' ,%optional_ex  | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Ties a %hash to this package for enhanced capability and returns a method  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 pointer.  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my %hash;  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $thm = tie %hash,'Tie::Hash::MultiKey';  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Extension of this module is discussed in detail below.  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $thm = tied %hash;  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Returns a method pointer for this package.  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * untie %hash;  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Breaks the binding between a variable and this package. There is no affect  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 if the variable is not tied.  | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B that if you have created a reference to the tied hash, untie  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 will not work until that binding is broken. This means that the object will  | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 not be destroyed or garbage collected and the memory will not be reclaimed.  | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 i.e	WRONG  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $thm = tie %h, 'Tie::Hash::MultiKey';  | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ... code ...  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   untie %h;  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	RIGHT  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $thm = tie %h, 'Tie::Hash::MultiKey';  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ... code ...  | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   undef $thm;  | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   untie %h;  | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * ($href,$thm) = new 'Tie::Hash::MultiKey' ,%optional_ex  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This method returns an UNBLESSED reference to an anonymous tied %hash.  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   input:	none  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns:	unblessed tied %hash reference,  | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		object handle  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 To get the object handle from \%hash use this.  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$thm = tied %{$href};  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 In SCALAR context it returns the unblessed %hash pointer. In ARRAY context it returns  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the unblessed %hash pointer and the package object/method  pointer.  | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
432
 | 
8
 | 
 
 | 
 
 | 
  
8
  
 | 
  
1
  
 | 
2724
 | 
   my($proto,@args) = @_;  | 
| 
433
 | 
8
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
66
 | 
   my $class = ref $proto || $proto || __PACKAGE__;  | 
| 
434
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   my %x;  | 
| 
435
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
51
 | 
   my $thm = tie %x, $class, @args;  | 
| 
436
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
47
 | 
   return wantarray ? (\%x,$thm) : \%x;  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $val = $thm->addkey('new_key' => 'existing_key');  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Add one or more keys to the shared key group for a particular value.  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   input:	array or array_ref,  | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		existing_key  | 
| 
445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns:	hash value  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	    or	dies with stack trace  | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Dies with stack trace if B does not exist OR if B key  | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 belongs to another key set.  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
451
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Arguments may be a single SCALAR, ARRAY, or ARRAY_REF  | 
| 
452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
454
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub addkey {  | 
| 
456
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
  
1
  
 | 
9474
 | 
   my $self = shift;  | 
| 
457
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
   $self->[5] = undef;  | 
| 
458
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
56
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
    | 
| 
459
 | 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
   my($key,@new) = &_flip;  | 
| 
460
 | 
13
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
970
 | 
   croak "key '$key' does not exist\n" unless exists $kh->{$key};  | 
| 
461
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   my $vi = $kh->{$key};  | 
| 
462
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   foreach(@new) {  | 
| 
463
 | 
14
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
59
 | 
     if (exists $kh->{$_} && $kh->{$key} != $vi) {  | 
| 
464
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       my @kset = sort { $sh->{$vi}->{$a} <=> $sh->{$vi}->{$b} } keys %{$sh->{$vi}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
465
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       croak "key belongs to key set @kset\n";  | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
467
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
     $sh->{$vi}->{$_} = $self->[4]++;  | 
| 
468
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
47
 | 
     $kh->{$_} = $vi;  | 
| 
469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
470
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
44
 | 
   $self->[7]->{ADDKEY}->($self,$key,$vi,\@new) if $self->[7];  | 
| 
471
 | 
9
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
40
 | 
   $self->_rordvals() if $self->[4] > $indexmax;  | 
| 
472
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
   return $vh->{$vi};  | 
| 
473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }      | 
| 
474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $val = ->remove('key');  | 
| 
476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $val = ->delkey('key');	alias for above  | 
| 
478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Remove one or more keys from the shared key group for a particular value   | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 If this operation removes the LAST key, then it performs a DELETE which is the same as:  | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	delete $hash{key};  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B returns a reverse list of the removed value's by key  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   i.e.	@val = remove(something);  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    or	$val = remove(something);  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Arguments may be a single SCALAR, ARRAY or ARRAY_REF  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # DELETE above does  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	array of deleted keys, array of deleted value indices  | 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $self->[7]->{DELETE}->($self,\@dkeys,\@vix) if $self->[7];  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # sub delete	DELETE a key  | 
| 
498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 *delkey = \&remove;  | 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub remove {  | 
| 
500
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
1
  
 | 
6200
 | 
   my($self,@ks) = @_;  | 
| 
501
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
    | 
| 
502
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   $self->[5] = undef;  | 
| 
503
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   my $ks = ref $ks[0] ? $ks[0] : \@ks;	# extract reference is first element was an array ref of keys  | 
| 
504
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   my @keys = @{_wash($ks)};  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
505
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my @vals;  | 
| 
506
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   foreach my $key (@keys) {  | 
| 
507
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
37
 | 
     if (exists $kh->{$key}) {  | 
| 
508
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
       my $vi = $kh->{$key};  | 
| 
509
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
       delete $kh->{$key};  | 
| 
510
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
584
 | 
       unshift @vals, $vh->{$vi};  | 
| 
511
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
       delete $sh->{$vi}->{$key};  | 
| 
512
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
       unless (keys %{$sh->{$vi}}) {	# if last element in set  | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
    | 
| 
513
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	delete $sh->{$vi};		# delete set values and keys  | 
| 
514
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	delete $vh->{$vi};  | 
| 
515
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 	$self->[7]->{DELETE}->($self,[$key],[$vi]) if $self->[7];	# delete last key extension  | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
517
 | 
10
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
38
 | 
 	$self->[7]->{DELKEY}->($self,$key,$vi) if $self->[7];	# not last key  | 
| 
518
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {	# bogus key  | 
| 
520
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       unshift @vals, undef;  | 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
523
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
55
 | 
   return wantarray ? @vals : $vals[0];  | 
| 
524
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $ks = \&delkey;			# never reached, suppress warning  | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
526
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * @ordered_keys = $thm->keylist('foo');  | 
| 
528
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * @allkeys_by_order = $thm->keylist();  | 
| 
530
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Returns all the keys in the group that includes the KEY 'foo' in the order  | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 that they were added to the %hash;  | 
| 
533
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 If no argument is specified, returns all the keys in the %hash in the order  | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 that they were added to the %hash  | 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   input:	key or EMPTY  | 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns:	@ordered_keys  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns:	() if $key is not in the %hash  | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
542
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub keylist {  | 
| 
545
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
1
  
 | 
9126
 | 
   my($self,$key) = @_;  | 
| 
546
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   $self->[5] = undef;  | 
| 
547
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
548
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   if (defined $key) {  | 
| 
549
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     return () unless exists $kh->{$key};  | 
| 
550
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     my $vi = $kh->{$key};  | 
| 
551
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     return sort { $sh->{$vi}->{$a} <=> $sh->{$vi}->{$b} } keys %{$sh->{$vi}};  | 
| 
 
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
553
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
   my %ak;			# key => order  | 
| 
554
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   foreach(keys %{$sh}) {  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
555
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     my @keys = keys %{$sh->{$_}};  | 
| 
 
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
    | 
| 
556
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     @ak{@keys} = @{$sh->{$_}}{@keys};  | 
| 
 
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
    | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
558
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   return sort { $ak{$a} <=> $ak{$b} } keys %ak;  | 
| 
 
 | 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
118
 | 
    | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
560
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
561
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * @keys = $thm->slotlist($i);  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
563
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Returns one key from each key group in position B<$i>.  | 
| 
564
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   i.e.  | 
| 
566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$thm = tie %hash, 'Tie::Hash::MultiKey';  | 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{['a','b','c']} = 'one';  | 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{['d','e','f']} = 'two';  | 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{'g'}           = 'three';  | 
| 
571
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$hash{['h','i','j']} = 'four';  | 
| 
572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	@slotkeys = $thm->slotlist(1);  | 
| 
574
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
575
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   will produce ('b','e', undef, 'i')  | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 All the keys at index '1' for the groups to which they were added, in the  | 
| 
578
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 order which the FIRST KEY in the group was added to the %hash. If there is no key in the  | 
| 
579
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 specified slot, an undef is returned for that position.  | 
| 
580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
581
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
582
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub slotlist($$) {  | 
| 
584
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
  
1
  
 | 
2514
 | 
   my($self,$i) = @_;  | 
| 
585
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   $self->[5] = undef;  | 
| 
586
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
587
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   my %kbs;			# order => key  | 
| 
588
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   foreach(keys %{$sh}) {  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
    | 
| 
589
 | 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
93
 | 
     my $slot = $sh->{$_};  | 
| 
590
 | 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
68
 | 
     my @keys = sort { $slot->{$a} <=> $slot->{$b} } keys %{$slot};  | 
| 
 
 | 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
203
 | 
    | 
| 
 
 | 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
175
 | 
    | 
| 
591
 | 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6244
 | 
     my $key = $keys[$i];  | 
| 
592
 | 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
700
 | 
     $kbs{$slot->{pop @keys}} = $key; # undef is there is no key  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
594
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
   my @order = sort { $a <=> $b } keys %kbs;  | 
| 
 
 | 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
158
 | 
    | 
| 
595
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
73
 | 
   return @kbs{@order};  | 
| 
596
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $thm->size;  | 
| 
599
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
600
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Returns the number of ITEMS in the hash (not the number of keys). Should be  | 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 faster than ... scalar @values  | 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
605
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub size {  | 
| 
606
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
1
  
 | 
3898
 | 
   $_[0]->[5] = undef;  | 
| 
607
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   return scalar values %{$_[0]->[1]};  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
94
 | 
    | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
610
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $thm->consolidate;  | 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 USE WITH CAUTION  | 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Consolidate all keys with the same values into common groups.  | 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns: number of consolidated key groups  | 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
618
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
619
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # added 3 sorts to keep key order constant across multiple platforms for testing purposes  | 
| 
621
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # while this is inefficient, this method should rarely be used by competent developers  | 
| 
622
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub consolidate {  | 
| 
624
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
5091
 | 
   my $self = shift;  | 
| 
625
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   $self->[5] = undef;  | 
| 
626
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $kbv  value => [keys]  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $ko   keys => order  | 
| 
629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # $ovm  value => [old vi order]  | 
| 
630
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   my (%kbv,%ko,%ovm);	# keys by value, key order, old vi order by value  | 
| 
631
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
45
 | 
   foreach my $vi (sort keys %$vh) {	# sort for cross platform testing	***  | 
| 
632
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
     my $v = $vh->{$vi};  | 
| 
633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  while (my($vi,$v) = each %$vh) {  | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # consolidate key sets of shared keys  | 
| 
635
 | 
34
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
63
 | 
     if (exists $ovm{$v}) {  | 
| 
636
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
       push @{$ovm{$v}}, $vi;  | 
| 
 
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
    | 
| 
637
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
638
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
       $ovm{$v} = [$vi];  | 
| 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
640
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
62
 | 
     my @keys = sort keys %{$sh->{$vi}};	# sort for cross platform testing	***  | 
| 
 
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
86
 | 
    | 
| 
641
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
     @ko{@keys} = @{$sh->{$vi}}{@keys};	# preserve key order  | 
| 
 
 | 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
76
 | 
    | 
| 
642
 | 
34
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
59
 | 
     if (exists $kbv{$v}) {		# have key group?  | 
| 
643
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
       push @{$kbv{$v}}, @keys;		# add keys  | 
| 
 
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
    | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
645
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
       $kbv{$v} = [@keys]; 	# start new key group  | 
| 
646
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
648
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my $ko = $self->[4];		# save next key order number  | 
| 
649
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   _clear($self);  | 
| 
650
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my %nvi2ovi;  | 
| 
651
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
   foreach my $v (sort keys %kbv) {	# sort for cross platform testing	***  | 
| 
652
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     my @k = @{$kbv{$v}};  | 
| 
 
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
    | 
| 
653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  while (my($v,$k) = each %kbv) {	# values by key  | 
| 
654
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
     my $indx = $self->[3]++;  | 
| 
655
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     $nvi2ovi{$indx} = $ovm{$v};		# create new => [old] map  | 
| 
656
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     $vh->{$indx} = $v;			# value  | 
| 
657
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     @{$sh->{$indx}}{@k} = @ko{@k};	# restore shared keys and order  | 
| 
 
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
    | 
| 
658
 | 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
     map { $kh->{$_} = $indx } @k;  | 
| 
 
 | 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99
 | 
    | 
| 
659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
660
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   $self->[4] = $ko;  | 
| 
661
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
533
 | 
   $self->[7]->{CONSOLD}->($self,\%kbv,\%ko,\%nvi2ovi) if $self->[7];  | 
| 
662
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   $self->_rordkeys() if $self->[3] > $indexmax;  | 
| 
663
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   $self->[3];  | 
| 
664
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
666
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item @ordered_vals = $thm->vals();  | 
| 
667
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Return a list of values in the order they were added.  | 
| 
669
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
670
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
671
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
672
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub vals {  | 
| 
673
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
2436
 | 
   $_[0]->[5] = undef;  | 
| 
674
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   map { $_[0]->[1]->{$_} } sort { $a <=> $b } keys %{$_[0]->[1]};  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
    | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
    | 
| 
675
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
676
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * ($href,$thm) = $thm->clone();  | 
| 
678
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This method returns an UNBLESSED reference to an anonymous tied %hash that  | 
| 
680
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 is a deep copy of the parent object.  | 
| 
681
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
682
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   input:	none  | 
| 
683
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns:	unblessed tied %hash reference,  | 
| 
684
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		object handle  | 
| 
685
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
686
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 To get the object handle from \%hash use this.  | 
| 
687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
688
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$thm = tied %{$href};  | 
| 
689
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
690
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 In SCALAR context it returns the unblessed %hash pointer. In ARRAY context it returns  | 
| 
691
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the unblessed %hash pointer and the package object/method  pointer.  | 
| 
692
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   i.e.  | 
| 
694
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$newRef = $thm->clone();  | 
| 
695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
696
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$newRref->{'a','b'} = 'content'  | 
| 
697
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
698
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$newThm = tied %{$newRef};  | 
| 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
700
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * $new_thm = $thm->copy(tie %new,'Tie::Hash::MultiKey');  | 
| 
701
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
702
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This method deep copies a MultiKey %hash to another B %hash. It may  | 
| 
703
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 be invoked on an existing tied object handle or a reference to a tied %hash.  | 
| 
704
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   input:	object handle OR reference to tied %hash  | 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns:	object handle / method pointer  | 
| 
707
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
708
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   i.e  | 
| 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$thm = tie %hash,'Tie::Hash::MultiKey';  | 
| 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$newThm = $thm->copy(tie %new,'Tie::Hash::MultiKey');  | 
| 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   or  | 
| 
712
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	tie %new,'Tie::Hash::MultiKey');  | 
| 
713
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$newThm = $thm->copy(\%new);  | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 NOTE: this method duplicates the data stored in the parent %hash,  | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 overwriting and destroying anything that may have been stored in the copy  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 target.  | 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
720
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
722
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub copy {  | 
| 
724
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
1718
 | 
   my($self,$copy) = @_;  | 
| 
725
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   croak "no target specified\n"  | 
| 
726
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless defined $copy;  | 
| 
727
 | 
3
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
24
 | 
   croak "argument is not a ", (ref $self) ," object\n"  | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
728
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless ref $copy eq ref $self || (ref $copy eq 'HASH' && ref ($copy = tied %$copy) eq ref $self);  | 
| 
729
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
   CLEAR($copy) unless $copy->[3] == 0;	# skip if empty hash  | 
| 
730
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   _copy($self,$copy);  | 
| 
731
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
732
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clone {  | 
| 
734
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
575
 | 
   my($href,$copy) = &new;  | 
| 
735
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   _copy($_[0],$copy);  | 
| 
736
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   return wantarray ? ($href,$copy) : $href;  | 
| 
737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
738
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
739
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _copy {  | 
| 
740
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
10
 | 
   my($self,$copy) = @_;  | 
| 
741
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   $self->[5] = undef;  | 
| 
742
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
743
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
   my @keys = keys %$kh;  | 
| 
744
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   my @vals = @{$kh}{@keys};  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
    | 
| 
745
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my($ckh,$cvh,$csh) = @{$copy};  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
746
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   @{$ckh}{@keys} = @vals;		# clone keys  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
    | 
| 
747
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   @{$cvh}{@vals} = @{$vh}{@vals};	# clone value index  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
748
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   foreach (@vals) {  | 
| 
749
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
     @keys = keys %{$sh->{$_}};  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
143
 | 
    | 
| 
750
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
     @{$csh->{$_}}{@keys} = @{$sh->{$_}}{@keys};  | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
96
 | 
    | 
| 
 
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
    | 
| 
751
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
752
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   @{$copy}[3,4,5] = @{$self}[3,4,5];  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
    | 
| 
753
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
   if ($self->[7]) {			# if extensions  | 
| 
754
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #    $copy->[7] = $self->[7];		# copy extension pointers  | 
| 
755
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     @vals = keys %{$vh};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
    | 
| 
756
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     $self->[7]->{COPY}->($self,$copy,\@vals);  | 
| 
757
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
758
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
96
 | 
   $copy;  | 
| 
759
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
760
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
761
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # belt and suspenders routines in case the indices or order index get to big  | 
| 
762
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
763
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _rordkeys {  | 
| 
764
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
3183
 | 
   my $self = shift;  | 
| 
765
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   my $nord = 0;				# new order  | 
| 
766
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   my $sh = $self->[2];  | 
| 
767
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   my $osh = {};				# a hash of all old shared keys with their order  | 
| 
768
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   foreach (keys %$sh) {  | 
| 
769
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     my @keys = keys %{$sh->{$_}};  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
    | 
| 
770
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     @{$osh}{@keys} = @{$sh->{$_}}{@keys};  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
    | 
| 
771
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
772
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
   my %rsh = reverse %$osh;		# reverse array to reorder unique numeric order numbers  | 
| 
773
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   my $nsh = {};				# new shared order hash  | 
| 
774
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   %$nsh = map { ($rsh{$_}, $nord++) } sort { $a <=> $b } keys %rsh;  | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
    | 
| 
 
 | 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
58
 | 
    | 
| 
775
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   foreach (keys %$sh) {  | 
| 
776
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     my @keys = keys %{$sh->{$_}};  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
    | 
| 
777
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     @{$sh->{$_}}{@keys} = @{$nsh}{@keys};	# replace old order with new order  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
778
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
779
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   $self->[7]->{REORDERK}->($self,$nsh) if $self->[7];  | 
| 
780
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
   $self->[4] = $nord;  | 
| 
781
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
782
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
783
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _rordvals {  | 
| 
784
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
3578
 | 
   my $self = shift;  | 
| 
785
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   my $ni = 0;				# new index  | 
| 
786
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   my($kh,$vh,$sh) = @{$self};  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
787
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   my $nvh = {};				# new value hash  | 
| 
788
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   my $nsh = {};				# new shared key hash  | 
| 
789
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   my %kmap;				# map for primary key hash and value hash  | 
| 
790
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   foreach (sort keys %$vh) {		# vh and sh share common keys  | 
| 
791
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     $nvh->{$ni} = $vh->{$_};  | 
| 
792
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     $nsh->{$ni} = $sh->{$_};  | 
| 
793
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
     $kmap{$_} = $ni++;  | 
| 
794
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
795
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   foreach(keys %$kh) {  | 
| 
796
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
101
 | 
     $kh->{$_} = $kmap{$kh->{$_}};	# replace old index pointer with new index pointer  | 
| 
797
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
798
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   @{$self}[1,2,3] = ($nvh,$nsh,$ni);  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
799
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   $self->[7]->{REORDERV}->($self,\%kmap) if $self->[7];	# if extensions  | 
| 
800
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
801
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
802
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 sub DESTROY {}  | 
| 
803
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
804
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
805
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
806
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |