summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hv.c68
1 files changed, 45 insertions, 23 deletions
diff --git a/hv.c b/hv.c
index f3ab6ccbb9..dfa0498baa 100644
--- a/hv.c
+++ b/hv.c
@@ -216,6 +216,30 @@ hv_fetch_ent(HV *hv, SV *keysv, I32 lval, register U32 hash)
return 0;
}
+static void
+hv_magic_check (hv, needs_copy, needs_store)
+HV *hv;
+bool *needs_copy;
+bool *needs_store;
+{
+ MAGIC *mg = SvMAGIC(hv);
+ *needs_copy = FALSE;
+ *needs_store = TRUE;
+ while (mg) {
+ if (isUPPER(mg->mg_type)) {
+ *needs_copy = TRUE;
+ switch (mg->mg_type) {
+ case 'P':
+ case 'I':
+ case 'S':
+ *needs_store = FALSE;
+ default:
+ }
+ }
+ mg = mg->mg_moremagic;
+ }
+}
+
SV**
hv_store(HV *hv, char *key, U32 klen, SV *val, register U32 hash)
{
@@ -229,15 +253,14 @@ hv_store(HV *hv, char *key, U32 klen, SV *val, register U32 hash)
xhv = (XPVHV*)SvANY(hv);
if (SvMAGICAL(hv)) {
- mg_copy((SV*)hv, val, key, klen);
- if (!xhv->xhv_array
- && (SvMAGIC(hv)->mg_moremagic
- || (SvMAGIC(hv)->mg_type != 'E'
-#ifdef OVERLOAD
- && SvMAGIC(hv)->mg_type != 'A'
-#endif /* OVERLOAD */
- )))
- return 0;
+ bool needs_copy;
+ bool needs_store;
+ hv_magic_check (hv, &needs_copy, &needs_store);
+ if (needs_copy) {
+ mg_copy((SV*)hv, val, key, klen);
+ if (!xhv->xhv_array && !needs_store)
+ return 0;
+ }
}
if (!hash)
PERL_HASH(hash, key, klen);
@@ -295,20 +318,19 @@ hv_store_ent(HV *hv, SV *keysv, SV *val, register U32 hash)
xhv = (XPVHV*)SvANY(hv);
if (SvMAGICAL(hv)) {
dTHR;
- bool save_taint = tainted;
- if (tainting)
- tainted = SvTAINTED(keysv);
- keysv = sv_2mortal(newSVsv(keysv));
- mg_copy((SV*)hv, val, (char*)keysv, HEf_SVKEY);
- TAINT_IF(save_taint);
- if (!xhv->xhv_array
- && (SvMAGIC(hv)->mg_moremagic
- || (SvMAGIC(hv)->mg_type != 'E'
-#ifdef OVERLOAD
- && SvMAGIC(hv)->mg_type != 'A'
-#endif /* OVERLOAD */
- )))
- return Nullhe;
+ bool needs_copy;
+ bool needs_store;
+ hv_magic_check (hv, &needs_copy, &needs_store);
+ if (needs_copy) {
+ bool save_taint = tainted;
+ if (tainting)
+ tainted = SvTAINTED(keysv);
+ keysv = sv_2mortal(newSVsv(keysv));
+ mg_copy((SV*)hv, val, (char*)keysv, HEf_SVKEY);
+ TAINT_IF(save_taint);
+ if (!xhv->xhv_array && !needs_store)
+ return Nullhe;
+ }
}
key = SvPV(keysv, klen);