summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-12-23 23:38:23 -0800
committerFather Chrysostomos <sprout@cpan.org>2011-12-24 16:14:31 -0800
commit3f4d1d7873e4e02f3801f2982565de93d2127bbd (patch)
tree65564dfc914364d6f7e51cd51dc6253631d5747d
parentf6f8d80714cb1a3a1417012c378a197e6d221f36 (diff)
downloadperl-3f4d1d7873e4e02f3801f2982565de93d2127bbd.tar.gz
hv.c: Make newHVhv work on tied hashes
-rw-r--r--ext/XS-APItest/APItest.xs7
-rw-r--r--ext/XS-APItest/t/hash.t8
-rw-r--r--hv.c12
3 files changed, 23 insertions, 4 deletions
diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs
index 4f84c60d3e..01b5b087f8 100644
--- a/ext/XS-APItest/APItest.xs
+++ b/ext/XS-APItest/APItest.xs
@@ -3174,6 +3174,13 @@ CODE:
HeVAL(entry) = NULL;
}
+HV *
+newHVhv(HV *hv)
+CODE:
+ RETVAL = newHVhv(hv);
+OUTPUT:
+ RETVAL
+
bool
SvIsCOW(SV *sv)
CODE:
diff --git a/ext/XS-APItest/t/hash.t b/ext/XS-APItest/t/hash.t
index de42a1df81..f66edfa1f5 100644
--- a/ext/XS-APItest/t/hash.t
+++ b/ext/XS-APItest/t/hash.t
@@ -237,6 +237,14 @@ sub test_precomputed_hashes {
'multiple stash aliases (bytes inside utf8) do not cause bad UTF8';
}
+{ # newHVhv
+ use Tie::Hash;
+ tie my %h, 'Tie::StdHash';
+ %h = 1..10;
+ is join(' ', sort %{newHVhv \%h}), '1 10 2 3 4 5 6 7 8 9',
+ 'newHVhv on tied hash';
+}
+
done_testing;
exit;
diff --git a/hv.c b/hv.c
index 1c5e6bc776..9a088a923a 100644
--- a/hv.c
+++ b/hv.c
@@ -1358,7 +1358,7 @@ Perl_newHVhv(pTHX_ HV *ohv)
HV * const hv = newHV();
STRLEN hv_max;
- if (!ohv || !HvTOTALKEYS(ohv))
+ if (!ohv || (!HvTOTALKEYS(ohv) && !SvMAGICAL((const SV *)ohv)))
return hv;
hv_max = HvMAX(ohv);
@@ -1421,9 +1421,13 @@ Perl_newHVhv(pTHX_ HV *ohv)
hv_iterinit(ohv);
while ((entry = hv_iternext_flags(ohv, 0))) {
- SV *const val = HeVAL(entry);
- (void)hv_store_flags(hv, HeKEY(entry), HeKLEN(entry),
- SvIMMORTAL(val) ? val : newSVsv(val),
+ SV *val = hv_iterval(ohv,entry);
+ SV * const keysv = HeSVKEY(entry);
+ val = SvIMMORTAL(val) ? val : newSVsv(val);
+ if (keysv)
+ (void)hv_store_ent(hv, keysv, val, 0);
+ else
+ (void)hv_store_flags(hv, HeKEY(entry), HeKLEN(entry), val,
HeHASH(entry), HeKFLAGS(entry));
}
HvRITER_set(ohv, riter);