Hash::Util#
General-utility hash subroutines — lock and unlock keys or values, inspect bucket layout, and seed the hash function.
A restricted hash is an ordinary hash that rejects new keys and,
optionally, refuses writes to its values. You build one by calling
lock_keys on a populated hash; from that point on a write to any
key not already present croaks. Locking individual values with
lock_value, or the whole hash with lock_hash, makes the existing
values immutable as well. Every lock has a matching unlock.
Alongside the locking primitives the module exposes a handful of
introspection helpers: bucket_ratio, num_buckets, used_buckets,
bucket_info, bucket_array, and the summary reports
bucket_stats and bucket_stats_formatted. They report how the
hash is laid out internally and are useful when tuning the size of
very large hashes.
hash_seed and hash_value expose the hash function itself — the
random per-process seed, and the integer hash of a given string
under that seed (or a caller-supplied seed). Both are sensitive:
handing them to untrusted code enables algorithmic-complexity
attacks against any hash in the program.
Every ref-suffixed variant (lock_ref_keys, lock_hashref,
hashref_locked, legal_ref_keys, hidden_ref_keys, etc.) does
the same work as its plain counterpart but takes an already-taken
hash reference rather than relying on the \% prototype.
Synopsis#
use Hash::Util qw(lock_keys unlock_keys lock_value hash_locked hidden_keys);
my %h = (foo => 1, bar => 2);
lock_keys(%h); # fix the keyset
$h{foo} = 10; # ok
eval { $h{baz} = 99 }; # croaks — attempt to access disallowed key
lock_value(%h, 'foo'); # make $h{foo} immutable too
print hash_locked(%h) ? "yes" : "no"; # yes
unlock_keys(%h); # lift the keyset restriction
Security#
hash_seed, hash_value, and bucket_array reveal enough about
the hash function to enable collision attacks. Do not expose their
output to code you do not trust.
Functions#
Hash locking#
lock_keys#
Restrict a hash to its current keys, or to an explicit list.
unlock_keys#
Lift the keyset restriction imposed by lock_keys.
lock_ref_keys#
Hash-reference variant of lock_keys.
unlock_ref_keys#
Hash-reference variant of unlock_keys.
Synopsis
unlock_ref_keys($href);
Lifts the keyset restriction on the referenced hash. See
unlock_keys for the full story on placeholders and values that
remain locked.
lock_ref_keys_plus#
Lock the hash to the union of its current keys and a given extra list.
lock_value#
Make the value under a given key immutable.
unlock_value#
Undo a previous lock_value, making the value at $key writable again.
Synopsis
unlock_value(%hash, $key);
Does nothing (silently) if the key is absent or was never locked. Returns a reference to the hash.
lock_ref_value#
Hash-reference variant of lock_value.
Synopsis
lock_ref_value($href, $key);
Same behaviour as lock_value but takes a hash reference.
unlock_ref_value#
Hash-reference variant of unlock_value.
Synopsis
unlock_ref_value($href, $key);
Same behaviour as unlock_value but takes a hash reference.
lock_hash#
Lock the whole hash: both its keyset and every value.
unlock_hash#
Undo a previous lock_hash, making every key and value writable again.
Synopsis
unlock_hash(%hash);
Clears the read-only flag on each existing value and lifts the keyset restriction. Returns a reference to the hash.
lock_hashref#
Hash-reference variant of lock_hash.
Synopsis
lock_hashref($href);
Same behaviour as lock_hash but takes a hash reference.
unlock_hashref#
Hash-reference variant of unlock_hash.
Synopsis
unlock_hashref($href);
Same behaviour as unlock_hash but takes a hash reference.
lock_hash_recurse#
Lock a hash and every nested hash it references, transitively.
unlock_hash_recurse#
Undo a previous lock_hash_recurse, unlocking every nested hash it touched.
Synopsis
unlock_hash_recurse(%hash);
Traverses the same subset of references as lock_hash_recurse —
hash-valued entries only. Returns a reference to the hash.
lock_hashref_recurse#
Hash-reference variant of lock_hash_recurse.
Synopsis
lock_hashref_recurse($href);
Same behaviour as lock_hash_recurse but takes a hash reference.
unlock_hashref_recurse#
Hash-reference variant of unlock_hash_recurse.
Synopsis
unlock_hashref_recurse($href);
Same behaviour as unlock_hash_recurse but takes a hash reference.
hash_locked#
Report whether the hash’s keyset is currently locked.
Synopsis
hash_locked(%hash) and print “restricted\n”;
Returns 1 when lock_keys (or an equivalent) has been applied
to the hash, 0 otherwise. Value-level locks alone do not count —
this only reports the keyset restriction.
hash_unlocked#
Report whether the hash’s keyset is not currently locked.
Synopsis
hash_unlocked(%hash) and print “open\n”;
The logical inverse of hash_locked: returns 1 on an unlocked
hash, 0 on a locked one. Handy in conditions where testing for
the open state reads more naturally than negating the locked one.
hashref_locked#
Hash-reference variant of hash_locked.
Synopsis
hashref_locked($href) and print “restricted\n”;
Same behaviour as hash_locked but takes a hash reference.
hashref_unlocked#
Hash-reference variant of hash_unlocked.
Synopsis
hashref_unlocked($href) and print “open\n”;
Same behaviour as hash_unlocked but takes a hash reference.
legal_keys#
List every key the restricted hash is allowed to carry — visible keys plus hidden placeholders.
Synopsis
my @legal = legal_keys(%hash);
On an unrestricted hash this is equivalent to keys %hash. On a
restricted hash it is the visible keys (keys %hash) merged with
whatever hidden_keys would report.
legal_ref_keys#
Hash-reference variant of legal_keys.
Synopsis
my @legal = legal_ref_keys($href);
Same behaviour as legal_keys but takes a hash reference.
all_keys#
Split a restricted hash’s keys into visible and hidden buckets, writing the results into the caller’s arrays.
hv_store#
Install an alias from $hash{$key} to an existing scalar, instead of copying its value in the usual way.
clear_placeholders#
Strip all hidden placeholder entries from a hash.
Synopsis
Hash::Util::_clear_placeholders(%hash);
Intended for internal use by Hash::Util itself when preparing a
hash for a new lock cycle. The leading underscore marks it as
unsupported for application code — its behaviour may change
without notice.
Bucket introspection#
bucket_ratio#
Return a "used/total" string describing how many of the hash’s internal buckets hold at least one key.
num_buckets#
Return the total number of buckets the hash holds (or would hold if its bucket array were allocated).
Synopsis
my $n = num_buckets(%hash);
A freshly created hash may report a non-zero bucket count even before its bucket array has been materialised — Perl allocates buckets lazily. The value is always a power of two.
used_buckets#
Return the count of buckets that currently hold at least one key.
Synopsis
my $used = used_buckets(%hash);
The value is computed from scratch on every call by walking the bucket array — there is no cache. Avoid calling it inside a hot loop on a large hash.
bucket_info#
Return a flat list summarising the hash’s bucket layout.
bucket_array#
Return a packed array-of-arrays describing which key lives in which bucket.
hash_traversal_mask#
Read or set the per-hash bucket-traversal mask used by keys, values, and each.
bucket_stats#
Return a rich statistical summary of the hash’s bucket layout.
bucket_stats_formatted#
Return a multi-line human-readable report of bucket_stats, complete with ASCII barcharts.
Hash function#
hash_seed#
Return the per-process random bytes that seed the hash function.
hash_value#
Return the integer hash value of a string under the current (or a supplied) seed.