This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
t/op/exec.t: Add missing /i
[perl5.git] / hv.c
diff --git a/hv.c b/hv.c
index 3bd62c6..d3d02d1 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -509,7 +509,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
                /* This cast somewhat evil, but I'm merely using NULL/
                   not NULL to return the boolean exists.
                   And I know hv is not NULL.  */
-               return SvTRUE(svret) ? (void *)hv : NULL;
+               return SvTRUE_NN(svret) ? (void *)hv : NULL;
                }
 #ifdef ENV_IS_CASELESS
            else if (mg_find((const SV *)hv, PERL_MAGIC_env)) {
@@ -967,6 +967,79 @@ Perl_hv_scalar(pTHX_ HV *hv)
     return sv;
 }
 
+
+/*
+hv_pushkv(): push all the keys and/or values of a hash onto the stack.
+The rough Perl equivalents:
+    () = %hash;
+    () = keys %hash;
+    () = values %hash;
+
+Resets the hash's iterator.
+
+flags : 1   = push keys
+        2   = push values
+        1|2 = push keys and values
+        XXX use symbolic flag constants at some point?
+I might unroll the non-tied hv_iternext() in here at some point - DAPM
+*/
+
+void
+Perl_hv_pushkv(pTHX_ HV *hv, U32 flags)
+{
+    HE *entry;
+    bool tied = SvRMAGICAL(hv) && (mg_find(MUTABLE_SV(hv), PERL_MAGIC_tied)
+#ifdef DYNAMIC_ENV_FETCH  /* might not know number of keys yet */
+                                   || mg_find(MUTABLE_SV(hv), PERL_MAGIC_env)
+#endif
+                                  );
+    dSP;
+
+    PERL_ARGS_ASSERT_HV_PUSHKV;
+    assert(flags); /* must be pushing at least one of keys and values */
+
+    (void)hv_iterinit(hv);
+
+    if (tied) {
+        SSize_t ext = (flags == 3) ? 2 : 1;
+        while ((entry = hv_iternext(hv))) {
+            EXTEND(SP, ext);
+            if (flags & 1)
+                PUSHs(hv_iterkeysv(entry));
+            if (flags & 2)
+                PUSHs(hv_iterval(hv, entry));
+        }
+    }
+    else {
+        Size_t nkeys = HvUSEDKEYS(hv);
+        SSize_t ext;
+
+        if (!nkeys)
+            return;
+
+        /* 2*nkeys() should never be big enough to truncate or wrap */
+        assert(nkeys <= (SSize_t_MAX >> 1));
+        ext = nkeys * ((flags == 3) ? 2 : 1);
+
+        EXTEND_MORTAL(nkeys);
+        EXTEND(SP, ext);
+
+        while ((entry = hv_iternext(hv))) {
+            if (flags & 1) {
+                SV *keysv = newSVhek(HeKEY_hek(entry));
+                SvTEMP_on(keysv);
+                PL_tmps_stack[++PL_tmps_ix] = keysv;
+                PUSHs(keysv);
+            }
+            if (flags & 2)
+                PUSHs(HeVAL(entry));
+        }
+    }
+
+    PUTBACK;
+}
+
+
 /*
 =for apidoc hv_bucket_ratio
 
@@ -995,12 +1068,13 @@ Perl_hv_bucket_ratio(pTHX_ HV *hv)
             return magic_scalarpack(hv, mg);
     }
 
-    sv = sv_newmortal();
-    if (HvUSEDKEYS((HV *)hv))
+    if (HvUSEDKEYS((HV *)hv)) {
+        sv = sv_newmortal();
         Perl_sv_setpvf(aTHX_ sv, "%ld/%ld",
                 (long)HvFILL(hv), (long)HvMAX(hv) + 1);
+    }
     else
-        sv_setiv(sv, 0);
+        sv = &PL_sv_zero;
     
     return sv;
 }
@@ -1205,7 +1279,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
                         sv_2mortal((SV *)gv)
                        );
                }
-               else if (klen == 3 && strEQs(key, "ISA") && GvAV(gv)) {
+               else if (memEQs(key, klen, "ISA") && GvAV(gv)) {
                     AV *isa = GvAV(gv);
                     MAGIC *mg = mg_find((SV*)isa, PERL_MAGIC_isa);
 
@@ -1754,7 +1828,7 @@ Perl_hv_clear(pTHX_ HV *hv)
        }
     }
     else {
-       hfreeentries(hv);
+       hv_free_entries(hv);
        HvPLACEHOLDERS_set(hv, 0);
 
        if (SvRMAGICAL(hv))
@@ -1851,13 +1925,13 @@ S_clear_placeholders(pTHX_ HV *hv, U32 items)
 }
 
 STATIC void
-S_hfreeentries(pTHX_ HV *hv)
+S_hv_free_entries(pTHX_ HV *hv)
 {
     STRLEN index = 0;
     XPVHV * const xhv = (XPVHV*)SvANY(hv);
     SV *sv;
 
-    PERL_ARGS_ASSERT_HFREEENTRIES;
+    PERL_ARGS_ASSERT_HV_FREE_ENTRIES;
 
     while ((sv = Perl_hfree_next_entry(aTHX_ hv, &index))||xhv->xhv_keys) {
        SvREFCNT_dec(sv);
@@ -1866,7 +1940,7 @@ S_hfreeentries(pTHX_ HV *hv)
 
 
 /* hfree_next_entry()
- * For use only by S_hfreeentries() and sv_clear().
+ * For use only by S_hv_free_entries() and sv_clear().
  * Delete the next available HE from hv and return the associated SV.
  * Returns null on empty hash. Nevertheless null is not a reliable
  * indicator that the hash is empty, as the deleted entry may have a
@@ -1955,7 +2029,7 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
 {
     XPVHV* xhv;
     bool save;
-    SSize_t orig_ix;
+    SSize_t orig_ix = PL_tmps_ix; /* silence compiler warning about unitialized vars */
 
     if (!hv)
        return;
@@ -1963,7 +2037,7 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
     DEBUG_A(Perl_hv_assert(aTHX_ hv));
     xhv = (XPVHV*)SvANY(hv);
 
-    /* The name must be deleted before the call to hfreeeeentries so that
+    /* The name must be deleted before the call to hv_free_entries so that
        CVs are anonymised properly. But the effective name must be pre-
        served until after that call (and only deleted afterwards if the
        call originated from sv_clear). For stashes with one name that is
@@ -1971,7 +2045,7 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
        allocate an array for storing the effective name. We can skip that
        during global destruction, as it does not matter where the CVs point
        if they will be freed anyway. */
-    /* note that the code following prior to hfreeentries is duplicated
+    /* note that the code following prior to hv_free_entries is duplicated
      * in sv_clear(), and changes here should be done there too */
     if (PL_phase != PERL_PHASE_DESTRUCT && HvNAME(hv)) {
         if (PL_stashcache) {
@@ -1987,7 +2061,7 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
         PL_tmps_stack[++PL_tmps_ix] = SvREFCNT_inc_simple_NN(hv);
         orig_ix = PL_tmps_ix;
     }
-    hfreeentries(hv);
+    hv_free_entries(hv);
     if (SvOOK(hv)) {
       struct mro_meta *meta;
       const char *name;
@@ -2966,7 +3040,7 @@ S_unshare_hek_or_pvn(pTHX_ const HEK *hek, const char *str, I32 len, U32 hash)
  * len and hash must both be valid for str.
  */
 HEK *
-Perl_share_hek(pTHX_ const char *str, I32 len, U32 hash)
+Perl_share_hek(pTHX_ const char *str, SSize_t len, U32 hash)
 {
     bool is_utf8 = FALSE;
     int flags = 0;
@@ -2998,7 +3072,7 @@ Perl_share_hek(pTHX_ const char *str, I32 len, U32 hash)
 }
 
 STATIC HEK *
-S_share_hek_flags(pTHX_ const char *str, I32 len, U32 hash, int flags)
+S_share_hek_flags(pTHX_ const char *str, STRLEN len, U32 hash, int flags)
 {
     HE *entry;
     const int flags_masked = flags & HVhek_MASK;
@@ -3007,6 +3081,10 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, U32 hash, int flags)
 
     PERL_ARGS_ASSERT_SHARE_HEK_FLAGS;
 
+    if (UNLIKELY(len > (STRLEN) I32_MAX)) {
+        Perl_croak_nocontext("Sorry, hash keys must be smaller than 2**31 bytes");
+    }
+
     /* what follows is the moral equivalent of:
 
     if (!(Svp = hv_fetch(PL_strtab, str, len, FALSE)))
@@ -3021,7 +3099,7 @@ S_share_hek_flags(pTHX_ const char *str, I32 len, U32 hash, int flags)
     for (;entry; entry = HeNEXT(entry)) {
        if (HeHASH(entry) != hash)              /* strings can't be equal */
            continue;
-       if (HeKLEN(entry) != len)
+       if (HeKLEN(entry) != (SSize_t) len)
            continue;
        if (HeKEY(entry) != str && memNE(HeKEY(entry),str,len)) /* is this it? */
            continue;