summaryrefslogtreecommitdiff
path: root/doop.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2017-07-21 14:32:57 +0100
committerDavid Mitchell <davem@iabyn.com>2017-07-27 11:30:24 +0100
commit8dc9003ff3914e78971f561eaece965e9ceeb49e (patch)
tree9ddb6c6946453365682c422f311a985fce2725ef /doop.c
parenta16ac36c3b97d0d80762b2900667f3759f354d9f (diff)
downloadperl-8dc9003ff3914e78971f561eaece965e9ceeb49e.tar.gz
hv_pushkv(): handle keys() and values() too
The newish function hv_pushkv() currently just pushes all key/value pairs on the stack. i.e. it does the equivalent of the perl code '() = %h'. Extend it so that it can handle 'keys %h' and values %h' too. This is basically moving the remaining list-context functionality out of do_kv() and into hv_pushkv(). The rationale for this is that hv_pushkv() is a pure HV-related function, while do_kv() is a pp function for several ops including OP_KEYS/VALUES, and expects PL_op->op_flags/op_private to be valid.
Diffstat (limited to 'doop.c')
-rw-r--r--doop.c21
1 files changed, 3 insertions, 18 deletions
diff --git a/doop.c b/doop.c
index 88f8439c39..5234e26a65 100644
--- a/doop.c
+++ b/doop.c
@@ -1255,8 +1255,6 @@ Perl_do_kv(pTHX)
{
dSP;
HV * const keys = MUTABLE_HV(POPs);
- HE *entry;
- SSize_t extend_size;
const U8 gimme = GIMME_V;
const I32 dokeys = (PL_op->op_type == OP_KEYS)
@@ -1317,22 +1315,9 @@ Perl_do_kv(pTHX)
Perl_croak(aTHX_ "Can't modify keys in list assignment");
}
- /* 2*HvUSEDKEYS() should never be big enough to truncate or wrap */
- assert(HvUSEDKEYS(keys) <= (SSize_t_MAX >> 1));
- extend_size = (SSize_t)HvUSEDKEYS(keys) * (dokeys + dovalues);
- EXTEND(SP, extend_size);
-
- while ((entry = hv_iternext(keys))) {
- if (dokeys) {
- SV* const sv = hv_iterkeysv(entry);
- XPUSHs(sv);
- }
- if (dovalues) {
- SV *const sv = hv_iterval(keys,entry);
- XPUSHs(sv);
- }
- }
- RETURN;
+ PUTBACK;
+ hv_pushkv(keys, (dokeys | (dovalues << 1)));
+ return NORMAL;
}
/*