summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorDagfinn Ilmari Mannsåker <ilmari@ilmari.org>2017-05-20 14:08:06 +0100
committerDagfinn Ilmari Mannsåker <ilmari@ilmari.org>2017-06-02 10:57:49 +0100
commitcc0776d645a326dd0aaa2dbd8cd9b014c63723f5 (patch)
tree932364ca2d8876283296be764383c282305dbd8d /pp.c
parentf92b68087fa16c181807b1e16f020d76b45c4274 (diff)
downloadperl-cc0776d645a326dd0aaa2dbd8cd9b014c63723f5.tar.gz
Add support for deleting key/value slices (RT#131328)
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/pp.c b/pp.c
index cc4cb59f7d..0c31062c3a 100644
--- a/pp.c
+++ b/pp.c
@@ -4985,20 +4985,33 @@ PP(pp_delete)
gimme = GIMME_V;
discard = (gimme == G_VOID) ? G_DISCARD : 0;
- if (PL_op->op_private & OPpSLICE) {
+ if (PL_op->op_private & (OPpSLICE|OPpKVSLICE)) {
dMARK; dORIGMARK;
HV * const hv = MUTABLE_HV(POPs);
const U32 hvtype = SvTYPE(hv);
+ int skip = 0;
+ if (PL_op->op_private & OPpKVSLICE) {
+ SSize_t items = SP - MARK;
+
+ MEXTEND(SP,items);
+ while (items > 1) {
+ *(MARK+items*2-1) = *(MARK+items);
+ items--;
+ }
+ items = SP - MARK;
+ SP += items;
+ skip = 1;
+ }
if (hvtype == SVt_PVHV) { /* hash element */
- while (++MARK <= SP) {
- SV * const sv = hv_delete_ent(hv, *MARK, discard, 0);
+ while ((MARK += (1+skip)) <= SP) {
+ SV * const sv = hv_delete_ent(hv, *(MARK-skip), discard, 0);
*MARK = sv ? sv : &PL_sv_undef;
}
}
else if (hvtype == SVt_PVAV) { /* array element */
if (PL_op->op_flags & OPf_SPECIAL) {
- while (++MARK <= SP) {
- SV * const sv = av_delete(MUTABLE_AV(hv), SvIV(*MARK), discard);
+ while ((MARK += (1+skip)) <= SP) {
+ SV * const sv = av_delete(MUTABLE_AV(hv), SvIV(*(MARK-skip)), discard);
*MARK = sv ? sv : &PL_sv_undef;
}
}