line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#line 1 |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Tie/IxHash.pm |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# Indexed hash implementation for Perl |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# See below for documentation. |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
require 5.003; |
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
1737
|
package Tie::IxHash; |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
5
|
|
13
|
|
|
|
|
|
|
use integer; |
14
|
|
|
|
|
|
|
require Tie::Hash; |
15
|
|
|
|
|
|
|
@ISA = qw(Tie::Hash); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
$VERSION = $VERSION = '1.21'; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# |
20
|
|
|
|
|
|
|
# standard tie functions |
21
|
|
|
|
|
|
|
# |
22
|
|
|
|
|
|
|
|
23
|
9
|
|
|
9
|
|
58
|
sub TIEHASH { |
24
|
9
|
|
|
|
|
15
|
my($c) = shift; |
25
|
9
|
|
|
|
|
20
|
my($s) = []; |
26
|
9
|
|
|
|
|
13
|
$s->[0] = {}; # hashkey index |
27
|
9
|
|
|
|
|
11
|
$s->[1] = []; # array of keys |
28
|
9
|
|
|
|
|
16
|
$s->[2] = []; # array of data |
29
|
|
|
|
|
|
|
$s->[3] = 0; # iter count |
30
|
9
|
|
|
|
|
14
|
|
31
|
|
|
|
|
|
|
bless $s, $c; |
32
|
9
|
50
|
|
|
|
24
|
|
33
|
|
|
|
|
|
|
$s->Push(@_) if @_; |
34
|
9
|
|
|
|
|
26
|
|
35
|
|
|
|
|
|
|
return $s; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
#sub DESTROY {} # costly if there's nothing to do |
39
|
|
|
|
|
|
|
|
40
|
13
|
|
|
13
|
|
28
|
sub FETCH { |
41
|
13
|
50
|
|
|
|
71
|
my($s, $k) = (shift, shift); |
42
|
|
|
|
|
|
|
return exists( $s->[0]{$k} ) ? $s->[2][ $s->[0]{$k} ] : undef; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
13
|
|
|
13
|
|
95
|
sub STORE { |
46
|
|
|
|
|
|
|
my($s, $k, $v) = (shift, shift, shift); |
47
|
13
|
50
|
|
|
|
28
|
|
48
|
0
|
|
|
|
|
0
|
if (exists $s->[0]{$k}) { |
49
|
0
|
|
|
|
|
0
|
my($i) = $s->[0]{$k}; |
50
|
0
|
|
|
|
|
0
|
$s->[1][$i] = $k; |
51
|
0
|
|
|
|
|
0
|
$s->[2][$i] = $v; |
52
|
|
|
|
|
|
|
$s->[0]{$k} = $i; |
53
|
|
|
|
|
|
|
} |
54
|
13
|
|
|
|
|
14
|
else { |
|
13
|
|
|
|
|
28
|
|
55
|
13
|
|
|
|
|
17
|
push(@{$s->[1]}, $k); |
|
13
|
|
|
|
|
22
|
|
56
|
13
|
|
|
|
|
17
|
push(@{$s->[2]}, $v); |
|
13
|
|
|
|
|
62
|
|
57
|
|
|
|
|
|
|
$s->[0]{$k} = $#{$s->[1]}; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
0
|
|
|
0
|
|
0
|
sub DELETE { |
62
|
|
|
|
|
|
|
my($s, $k) = (shift, shift); |
63
|
0
|
0
|
|
|
|
0
|
|
64
|
0
|
|
|
|
|
0
|
if (exists $s->[0]{$k}) { |
65
|
0
|
|
|
|
|
0
|
my($i) = $s->[0]{$k}; |
|
0
|
|
|
|
|
0
|
|
66
|
0
|
|
|
|
|
0
|
for ($i+1..$#{$s->[1]}) { # reset higher elt indexes |
67
|
|
|
|
|
|
|
$s->[0]{$s->[1][$_]}--; # timeconsuming, is there is better way? |
68
|
0
|
|
|
|
|
0
|
} |
69
|
0
|
|
|
|
|
0
|
delete $s->[0]{$k}; |
|
0
|
|
|
|
|
0
|
|
70
|
0
|
|
|
|
|
0
|
splice @{$s->[1]}, $i, 1; |
|
0
|
|
|
|
|
0
|
|
71
|
|
|
|
|
|
|
return (splice(@{$s->[2]}, $i, 1))[0]; |
72
|
0
|
|
|
|
|
0
|
} |
73
|
|
|
|
|
|
|
return undef; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
0
|
|
|
0
|
|
0
|
sub EXISTS { |
77
|
|
|
|
|
|
|
exists $_[0]->[0]{ $_[1] }; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
18
|
|
|
18
|
|
141
|
sub FIRSTKEY { |
81
|
18
|
|
|
|
|
33
|
$_[0][3] = 0; |
82
|
|
|
|
|
|
|
&NEXTKEY; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
31
|
100
|
|
31
|
|
40
|
sub NEXTKEY { |
|
31
|
|
|
|
|
124
|
|
86
|
18
|
|
|
|
|
54
|
return $_[0][1][$_[0][3]++] if ($_[0][3] <= $#{$_[0][1]}); |
87
|
|
|
|
|
|
|
return undef; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# |
93
|
|
|
|
|
|
|
# |
94
|
|
|
|
|
|
|
# class functions that provide additional capabilities |
95
|
|
|
|
|
|
|
# |
96
|
|
|
|
|
|
|
# |
97
|
0
|
|
|
0
|
0
|
|
|
98
|
|
|
|
|
|
|
sub new { TIEHASH(@_) } |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# |
101
|
|
|
|
|
|
|
# add pairs to end of indexed hash |
102
|
|
|
|
|
|
|
# note that if a supplied key exists, it will not be reordered |
103
|
|
|
|
|
|
|
# |
104
|
0
|
|
|
0
|
1
|
|
sub Push { |
105
|
0
|
|
|
|
|
|
my($s) = shift; |
106
|
0
|
|
|
|
|
|
while (@_) { |
107
|
|
|
|
|
|
|
$s->STORE(shift, shift); |
108
|
0
|
|
|
|
|
|
} |
|
0
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
return scalar(@{$s->[1]}); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
0
|
0
|
|
sub Push2 { |
113
|
0
|
|
|
|
|
|
my($s) = shift; |
|
0
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
$s->Splice($#{$s->[1]}+1, 0, @_); |
|
0
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
return scalar(@{$s->[1]}); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# |
119
|
|
|
|
|
|
|
# pop last k-v pair |
120
|
|
|
|
|
|
|
# |
121
|
0
|
|
|
0
|
1
|
|
sub Pop { |
122
|
0
|
|
|
|
|
|
my($s) = shift; |
123
|
0
|
|
|
|
|
|
my($k, $v, $i); |
|
0
|
|
|
|
|
|
|
124
|
0
|
|
|
|
|
|
$k = pop(@{$s->[1]}); |
|
0
|
|
|
|
|
|
|
125
|
0
|
0
|
|
|
|
|
$v = pop(@{$s->[2]}); |
126
|
0
|
|
|
|
|
|
if (defined $k) { |
127
|
0
|
|
|
|
|
|
delete $s->[0]{$k}; |
128
|
|
|
|
|
|
|
return ($k, $v); |
129
|
0
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
return undef; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
0
|
|
|
0
|
0
|
|
sub Pop2 { |
134
|
|
|
|
|
|
|
return $_[0]->Splice(-1); |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# |
138
|
|
|
|
|
|
|
# shift |
139
|
|
|
|
|
|
|
# |
140
|
0
|
|
|
0
|
1
|
|
sub Shift { |
141
|
0
|
|
|
|
|
|
my($s) = shift; |
142
|
0
|
|
|
|
|
|
my($k, $v, $i); |
|
0
|
|
|
|
|
|
|
143
|
0
|
|
|
|
|
|
$k = shift(@{$s->[1]}); |
|
0
|
|
|
|
|
|
|
144
|
0
|
0
|
|
|
|
|
$v = shift(@{$s->[2]}); |
145
|
0
|
|
|
|
|
|
if (defined $k) { |
146
|
0
|
|
|
|
|
|
delete $s->[0]{$k}; |
|
0
|
|
|
|
|
|
|
147
|
0
|
|
|
|
|
|
for (keys %{$s->[0]}) { |
148
|
|
|
|
|
|
|
$s->[0]{$_}--; |
149
|
0
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
return ($k, $v); |
151
|
0
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
return undef; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
0
|
|
|
0
|
0
|
|
sub Shift2 { |
156
|
|
|
|
|
|
|
return $_[0]->Splice(0, 1); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# |
160
|
|
|
|
|
|
|
# unshift |
161
|
|
|
|
|
|
|
# if a supplied key exists, it will not be reordered |
162
|
|
|
|
|
|
|
# |
163
|
0
|
|
|
0
|
1
|
|
sub Unshift { |
164
|
0
|
|
|
|
|
|
my($s) = shift; |
165
|
|
|
|
|
|
|
my($k, $v, @k, @v, $len, $i); |
166
|
0
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
|
while (@_) { |
168
|
0
|
0
|
|
|
|
|
($k, $v) = (shift, shift); |
169
|
0
|
|
|
|
|
|
if (exists $s->[0]{$k}) { |
170
|
0
|
|
|
|
|
|
$i = $s->[0]{$k}; |
171
|
0
|
|
|
|
|
|
$s->[1][$i] = $k; |
172
|
0
|
|
|
|
|
|
$s->[2][$i] = $v; |
173
|
|
|
|
|
|
|
$s->[0]{$k} = $i; |
174
|
|
|
|
|
|
|
} |
175
|
0
|
|
|
|
|
|
else { |
176
|
0
|
|
|
|
|
|
push(@k, $k); |
177
|
0
|
|
|
|
|
|
push(@v, $v); |
178
|
|
|
|
|
|
|
$len++; |
179
|
|
|
|
|
|
|
} |
180
|
0
|
0
|
|
|
|
|
} |
181
|
0
|
|
|
|
|
|
if (defined $len) { |
|
0
|
|
|
|
|
|
|
182
|
0
|
|
|
|
|
|
for (keys %{$s->[0]}) { |
183
|
|
|
|
|
|
|
$s->[0]{$_} += $len; |
184
|
0
|
|
|
|
|
|
} |
185
|
0
|
|
|
|
|
|
$i = 0; |
186
|
0
|
|
|
|
|
|
for (@k) { |
187
|
|
|
|
|
|
|
$s->[0]{$_} = $i++; |
188
|
0
|
|
|
|
|
|
} |
|
0
|
|
|
|
|
|
|
189
|
0
|
|
|
|
|
|
unshift(@{$s->[1]}, @k); |
|
0
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
return unshift(@{$s->[2]}, @v); |
191
|
0
|
|
|
|
|
|
} |
|
0
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
return scalar(@{$s->[1]}); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
0
|
|
|
0
|
0
|
|
sub Unshift2 { |
196
|
0
|
|
|
|
|
|
my($s) = shift; |
197
|
0
|
|
|
|
|
|
$s->Splice(0,0,@_); |
|
0
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
return scalar(@{$s->[1]}); |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
# |
202
|
|
|
|
|
|
|
# splice |
203
|
|
|
|
|
|
|
# |
204
|
|
|
|
|
|
|
# any existing hash key order is preserved. the value is replaced for |
205
|
|
|
|
|
|
|
# such keys, and the new keys are spliced in the regular fashion. |
206
|
|
|
|
|
|
|
# |
207
|
|
|
|
|
|
|
# supports -ve offsets but only +ve lengths |
208
|
|
|
|
|
|
|
# |
209
|
|
|
|
|
|
|
# always assumes a 0 start offset |
210
|
|
|
|
|
|
|
# |
211
|
0
|
|
|
0
|
1
|
|
sub Splice { |
212
|
0
|
|
|
|
|
|
my($s, $start, $len) = (shift, shift, shift); |
213
|
0
|
|
|
|
|
|
my($k, $v, @k, @v, @r, $i, $siz); |
214
|
|
|
|
|
|
|
my($end); # inclusive |
215
|
|
|
|
|
|
|
|
216
|
0
|
|
|
|
|
|
# XXX inline this |
217
|
|
|
|
|
|
|
($start, $end, $len) = $s->_lrange($start, $len); |
218
|
0
|
0
|
|
|
|
|
|
219
|
0
|
0
|
|
|
|
|
if (defined $start) { |
220
|
0
|
|
|
|
|
|
if ($len > 0) { |
|
0
|
|
|
|
|
|
|
221
|
0
|
|
|
|
|
|
my(@k) = splice(@{$s->[1]}, $start, $len); |
|
0
|
|
|
|
|
|
|
222
|
0
|
|
|
|
|
|
my(@v) = splice(@{$s->[2]}, $start, $len); |
223
|
0
|
|
|
|
|
|
while (@k) { |
224
|
0
|
|
|
|
|
|
$k = shift(@k); |
225
|
0
|
|
|
|
|
|
delete $s->[0]{$k}; |
226
|
|
|
|
|
|
|
push(@r, $k, shift(@v)); |
227
|
0
|
|
|
|
|
|
} |
|
0
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
|
for ($start..$#{$s->[1]}) { |
229
|
|
|
|
|
|
|
$s->[0]{$s->[1][$_]} -= $len; |
230
|
|
|
|
|
|
|
} |
231
|
0
|
|
|
|
|
|
} |
232
|
0
|
|
|
|
|
|
while (@_) { |
233
|
0
|
0
|
|
|
|
|
($k, $v) = (shift, shift); |
234
|
|
|
|
|
|
|
if (exists $s->[0]{$k}) { |
235
|
0
|
|
|
|
|
|
# $s->STORE($k, $v); |
236
|
0
|
|
|
|
|
|
$i = $s->[0]{$k}; |
237
|
0
|
|
|
|
|
|
$s->[1][$i] = $k; |
238
|
0
|
|
|
|
|
|
$s->[2][$i] = $v; |
239
|
|
|
|
|
|
|
$s->[0]{$k} = $i; |
240
|
|
|
|
|
|
|
} |
241
|
0
|
|
|
|
|
|
else { |
242
|
0
|
|
|
|
|
|
push(@k, $k); |
243
|
0
|
|
|
|
|
|
push(@v, $v); |
244
|
|
|
|
|
|
|
$siz++; |
245
|
|
|
|
|
|
|
} |
246
|
0
|
0
|
|
|
|
|
} |
247
|
0
|
|
|
|
|
|
if (defined $siz) { |
|
0
|
|
|
|
|
|
|
248
|
0
|
|
|
|
|
|
for ($start..$#{$s->[1]}) { |
249
|
|
|
|
|
|
|
$s->[0]{$s->[1][$_]} += $siz; |
250
|
0
|
|
|
|
|
|
} |
251
|
0
|
|
|
|
|
|
$i = $start; |
252
|
0
|
|
|
|
|
|
for (@k) { |
253
|
|
|
|
|
|
|
$s->[0]{$_} = $i++; |
254
|
0
|
|
|
|
|
|
} |
|
0
|
|
|
|
|
|
|
255
|
0
|
|
|
|
|
|
splice(@{$s->[1]}, $start, 0, @k); |
|
0
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
splice(@{$s->[2]}, $start, 0, @v); |
257
|
|
|
|
|
|
|
} |
258
|
0
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
return @r; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# |
263
|
|
|
|
|
|
|
# delete elements specified by key |
264
|
|
|
|
|
|
|
# other elements higher than the one deleted "slide" down |
265
|
|
|
|
|
|
|
# |
266
|
0
|
|
|
0
|
1
|
|
sub Delete { |
267
|
|
|
|
|
|
|
my($s) = shift; |
268
|
0
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
for (@_) { |
270
|
|
|
|
|
|
|
# |
271
|
|
|
|
|
|
|
# XXX potential optimization: could do $s->DELETE only if $#_ < 4. |
272
|
|
|
|
|
|
|
# otherwise, should reset all the hash indices in one loop |
273
|
0
|
|
|
|
|
|
# |
274
|
|
|
|
|
|
|
$s->DELETE($_); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# |
279
|
|
|
|
|
|
|
# replace hash element at specified index |
280
|
|
|
|
|
|
|
# |
281
|
|
|
|
|
|
|
# if the optional key is not supplied the value at index will simply be |
282
|
|
|
|
|
|
|
# replaced without affecting the order. |
283
|
|
|
|
|
|
|
# |
284
|
|
|
|
|
|
|
# if an element with the supplied key already exists, it will be deleted first. |
285
|
|
|
|
|
|
|
# |
286
|
|
|
|
|
|
|
# returns the key of replaced value if it succeeds. |
287
|
|
|
|
|
|
|
# |
288
|
0
|
|
|
0
|
1
|
|
sub Replace { |
289
|
0
|
|
|
|
|
|
my($s) = shift; |
290
|
0
|
0
|
0
|
|
|
|
my($i, $v, $k) = (shift, shift, shift); |
|
0
|
|
0
|
|
|
|
|
291
|
0
|
0
|
|
|
|
|
if (defined $i and $i <= $#{$s->[1]} and $i >= 0) { |
292
|
0
|
|
|
|
|
|
if (defined $k) { |
293
|
0
|
|
|
|
|
|
delete $s->[0]{ $s->[1][$i] }; |
294
|
0
|
|
|
|
|
|
$s->DELETE($k) ; #if exists $s->[0]{$k}; |
295
|
0
|
|
|
|
|
|
$s->[1][$i] = $k; |
296
|
0
|
|
|
|
|
|
$s->[2][$i] = $v; |
297
|
0
|
|
|
|
|
|
$s->[0]{$k} = $i; |
298
|
|
|
|
|
|
|
return $k; |
299
|
|
|
|
|
|
|
} |
300
|
0
|
|
|
|
|
|
else { |
301
|
0
|
|
|
|
|
|
$s->[2][$i] = $v; |
302
|
|
|
|
|
|
|
return $s->[1][$i]; |
303
|
|
|
|
|
|
|
} |
304
|
0
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
return undef; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# |
309
|
|
|
|
|
|
|
# Given an $start and $len, returns a legal start and end (where start <= end) |
310
|
|
|
|
|
|
|
# for the current hash. |
311
|
|
|
|
|
|
|
# Legal range is defined as 0 to $#s+1 |
312
|
|
|
|
|
|
|
# $len defaults to number of elts upto end of list |
313
|
|
|
|
|
|
|
# |
314
|
|
|
|
|
|
|
# 0 1 2 ... |
315
|
|
|
|
|
|
|
# | X | X | X ... X | X | X | |
316
|
|
|
|
|
|
|
# -2 -1 (no -0 alas) |
317
|
|
|
|
|
|
|
# X's above are the elements |
318
|
|
|
|
|
|
|
# |
319
|
0
|
|
|
0
|
|
|
sub _lrange { |
320
|
0
|
|
|
|
|
|
my($s) = shift; |
321
|
0
|
|
|
|
|
|
my($offset, $len) = @_; |
322
|
0
|
|
|
|
|
|
my($start, $end); # both inclusive |
|
0
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
my($size) = $#{$s->[1]}+1; |
324
|
0
|
0
|
|
|
|
|
|
325
|
0
|
0
|
|
|
|
|
return undef unless defined $offset; |
326
|
0
|
|
|
|
|
|
if($offset < 0) { |
327
|
0
|
0
|
|
|
|
|
$start = $offset + $size; |
328
|
|
|
|
|
|
|
$start = 0 if $start < 0; |
329
|
|
|
|
|
|
|
} |
330
|
0
|
0
|
|
|
|
|
else { |
331
|
|
|
|
|
|
|
($offset > $size) ? ($start = $size) : ($start = $offset); |
332
|
|
|
|
|
|
|
} |
333
|
0
|
0
|
|
|
|
|
|
334
|
0
|
0
|
|
|
|
|
if (defined $len) { |
335
|
0
|
0
|
|
|
|
|
$len = -$len if $len < 0; |
336
|
|
|
|
|
|
|
$len = $size - $start if $len > $size - $start; |
337
|
|
|
|
|
|
|
} |
338
|
0
|
|
|
|
|
|
else { |
339
|
|
|
|
|
|
|
$len = $size - $start; |
340
|
0
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
$end = $start + $len - 1; |
342
|
0
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
return ($start, $end, $len); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# |
347
|
|
|
|
|
|
|
# Return keys at supplied indices |
348
|
|
|
|
|
|
|
# Returns all keys if no args. |
349
|
|
|
|
|
|
|
# |
350
|
0
|
|
|
0
|
1
|
|
sub Keys { |
351
|
0
|
|
|
|
|
|
my($s) = shift; |
352
|
|
|
|
|
|
|
return ( @_ == 1 |
353
|
|
|
|
|
|
|
? $s->[1][$_[0]] |
354
|
0
|
|
|
|
|
|
: ( @_ |
355
|
0
|
0
|
|
|
|
|
? @{$s->[1]}[@_] |
|
|
0
|
|
|
|
|
|
356
|
|
|
|
|
|
|
: @{$s->[1]} ) ); |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# |
360
|
|
|
|
|
|
|
# Returns values at supplied indices |
361
|
|
|
|
|
|
|
# Returns all values if no args. |
362
|
|
|
|
|
|
|
# |
363
|
0
|
|
|
0
|
1
|
|
sub Values { |
364
|
0
|
|
|
|
|
|
my($s) = shift; |
365
|
|
|
|
|
|
|
return ( @_ == 1 |
366
|
|
|
|
|
|
|
? $s->[2][$_[0]] |
367
|
0
|
|
|
|
|
|
: ( @_ |
368
|
0
|
0
|
|
|
|
|
? @{$s->[2]}[@_] |
|
|
0
|
|
|
|
|
|
369
|
|
|
|
|
|
|
: @{$s->[2]} ) ); |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
# |
373
|
|
|
|
|
|
|
# get indices of specified hash keys |
374
|
|
|
|
|
|
|
# |
375
|
0
|
|
|
0
|
1
|
|
sub Indices { |
376
|
0
|
0
|
|
|
|
|
my($s) = shift; |
|
0
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
return ( @_ == 1 ? $s->[0]{$_[0]} : @{$s->[0]}{@_} ); |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
# |
381
|
|
|
|
|
|
|
# number of k-v pairs in the ixhash |
382
|
|
|
|
|
|
|
# note that this does not equal the highest index |
383
|
|
|
|
|
|
|
# owing to preextended arrays |
384
|
|
|
|
|
|
|
# |
385
|
0
|
|
|
0
|
1
|
|
sub Length { |
|
0
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
return scalar @{$_[0]->[1]}; |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# |
390
|
|
|
|
|
|
|
# Reorder the hash in the supplied key order |
391
|
|
|
|
|
|
|
# |
392
|
|
|
|
|
|
|
# warning: any unsupplied keys will be lost from the hash |
393
|
|
|
|
|
|
|
# any supplied keys that dont exist in the hash will be ignored |
394
|
|
|
|
|
|
|
# |
395
|
0
|
|
|
0
|
1
|
|
sub Reorder { |
396
|
0
|
|
|
|
|
|
my($s) = shift; |
397
|
0
|
0
|
|
|
|
|
my(@k, @v, %x, $i); |
398
|
|
|
|
|
|
|
return unless @_; |
399
|
0
|
|
|
|
|
|
|
400
|
0
|
|
|
|
|
|
$i = 0; |
401
|
0
|
0
|
|
|
|
|
for (@_) { |
402
|
0
|
|
|
|
|
|
if (exists $s->[0]{$_}) { |
403
|
0
|
|
|
|
|
|
push(@k, $_); |
404
|
0
|
|
|
|
|
|
push(@v, $s->[2][ $s->[0]{$_} ] ); |
405
|
|
|
|
|
|
|
$x{$_} = $i++; |
406
|
|
|
|
|
|
|
} |
407
|
0
|
|
|
|
|
|
} |
408
|
0
|
|
|
|
|
|
$s->[1] = \@k; |
409
|
0
|
|
|
|
|
|
$s->[2] = \@v; |
410
|
0
|
|
|
|
|
|
$s->[0] = \%x; |
411
|
|
|
|
|
|
|
return $s; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
|
414
|
0
|
|
|
0
|
1
|
|
sub SortByKey { |
415
|
0
|
|
|
|
|
|
my($s) = shift; |
416
|
|
|
|
|
|
|
$s->Reorder(sort $s->Keys); |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
0
|
|
|
0
|
1
|
|
sub SortByValue { |
420
|
0
|
|
|
|
|
|
my($s) = shift; |
|
0
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
$s->Reorder(sort { $s->FETCH($a) cmp $s->FETCH($b) } $s->Keys) |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
1; |
425
|
|
|
|
|
|
|
__END__ |