From 3f4d1d7873e4e02f3801f2982565de93d2127bbd Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Fri, 23 Dec 2011 23:38:23 -0800 Subject: hv.c: Make newHVhv work on tied hashes --- ext/XS-APItest/APItest.xs | 7 +++++++ ext/XS-APItest/t/hash.t | 8 ++++++++ hv.c | 12 ++++++++---- 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); -- cgit v1.2.1