summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2006-04-01 21:17:46 +0000
committerNicholas Clark <nick@ccl4.org>2006-04-01 21:17:46 +0000
commit5b9c067131ee63b4afa00d1d71c771377deb6ff9 (patch)
treef0d23e7597d8b97766a275feb1effc1c8360e3bb /hv.c
parentdef9038f0e6b68e6331316ef6cd457a2bf75dab6 (diff)
downloadperl-5b9c067131ee63b4afa00d1d71c771377deb6ff9.tar.gz
Automatically set HINT_LOCALIZE_HH whenever %^H is modified.
p4raw-id: //depot/perl@27666
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/hv.c b/hv.c
index 4565cc0d71..fe74e87849 100644
--- a/hv.c
+++ b/hv.c
@@ -1491,6 +1491,39 @@ Perl_newHVhv(pTHX_ HV *ohv)
return hv;
}
+/* A rather specialised version of newHVhv for copying %^H, ensuring all the
+ magic stays on it. */
+HV *
+Perl_hv_copy_hints_hv(pTHX_ HV *const ohv)
+{
+ HV * const hv = newHV();
+ STRLEN hv_fill;
+
+ if (ohv && (hv_fill = HvFILL(ohv))) {
+ STRLEN hv_max = HvMAX(ohv);
+ HE *entry;
+ const I32 riter = HvRITER_get(ohv);
+ HE * const eiter = HvEITER_get(ohv);
+
+ while (hv_max && hv_max + 1 >= hv_fill * 2)
+ hv_max = hv_max / 2;
+ HvMAX(hv) = hv_max;
+
+ hv_iterinit(ohv);
+ while ((entry = hv_iternext_flags(ohv, 0))) {
+ SV *const sv = newSVsv(HeVAL(entry));
+ sv_magic(sv, NULL, PERL_MAGIC_hintselem,
+ (char *)newSVhek (HeKEY_hek(entry)), HEf_SVKEY);
+ hv_store_flags(hv, HeKEY(entry), HeKLEN(entry),
+ sv, HeHASH(entry), HeKFLAGS(entry));
+ }
+ HvRITER_set(ohv, riter);
+ HvEITER_set(ohv, eiter);
+ }
+ hv_magic(hv, NULL, PERL_MAGIC_hints);
+ return hv;
+}
+
void
Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry)
{