Pod typos, pod2man bugs, and miscellaneous installation comments
[p5sagit/p5-mst-13.2.git] / hv.c
diff --git a/hv.c b/hv.c
index b77e44e..9547f2c 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -142,10 +142,9 @@ register U32 hash;
     if (!hv)
        return 0;
 
-    xhv = (XPVHV*)SvANY(hv);
-
     if (SvRMAGICAL(hv) && mg_find((SV*)hv,'P')) {
        sv = sv_newmortal();
+       keysv = sv_2mortal(newSVsv(keysv));
        mg_copy((SV*)hv, sv, (char*)keysv, HEf_SVKEY);
        entry = &He;
        HeVAL(entry) = sv;
@@ -154,11 +153,7 @@ register U32 hash;
        return entry;
     }
 
-    key = SvPV(keysv, klen);
-    
-    if (!hash)
-       PERL_HASH(hash, key, klen);
-
+    xhv = (XPVHV*)SvANY(hv);
     if (!xhv->xhv_array) {
        if (lval 
 #ifdef DYNAMIC_ENV_FETCH  /* if it's an %ENV lookup, we may get it on the fly */
@@ -170,6 +165,11 @@ register U32 hash;
            return 0;
     }
 
+    key = SvPV(keysv, klen);
+    
+    if (!hash)
+       PERL_HASH(hash, key, klen);
+
     entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
     for (; entry; entry = HeNEXT(entry)) {
        if (HeHASH(entry) != hash)              /* strings can't be equal */
@@ -287,6 +287,7 @@ register U32 hash;
 
     xhv = (XPVHV*)SvANY(hv);
     if (SvMAGICAL(hv)) {
+       keysv = sv_2mortal(newSVsv(keysv));
        mg_copy((SV*)hv, val, (char*)keysv, HEf_SVKEY);
 #ifndef OVERLOAD
        if (!xhv->xhv_array)
@@ -393,7 +394,7 @@ I32 flags;
        else
            sv = sv_mortalcopy(HeVAL(entry));
        if (entry == xhv->xhv_eiter)
-           HeKLEN(entry) = HEf_LAZYDEL;
+           HvLAZYDEL_on(hv);
        else
            he_free(entry, HvSHAREKEYS(hv));
        --xhv->xhv_keys;
@@ -455,7 +456,7 @@ U32 hash;
        else
            sv = sv_mortalcopy(HeVAL(entry));
        if (entry == xhv->xhv_eiter)
-           HeKLEN(entry) = HEf_LAZYDEL;
+           HvLAZYDEL_on(hv);
        else
            he_free(entry, HvSHAREKEYS(hv));
        --xhv->xhv_keys;
@@ -525,6 +526,7 @@ U32 hash;
     if (SvRMAGICAL(hv)) {
        if (mg_find((SV*)hv,'P')) {
            sv = sv_newmortal();
+           keysv = sv_2mortal(newSVsv(keysv));
            mg_copy((SV*)hv, sv, (char*)keysv, HEf_SVKEY); 
            magic_existspack(sv, mg_find(sv, 'p'));
            return SvTRUE(sv);
@@ -617,6 +619,84 @@ HV *hv;
     }
 }
 
+void
+hv_ksplit(hv, newmax)
+HV *hv;
+IV newmax;
+{
+    register XPVHV* xhv = (XPVHV*)SvANY(hv);
+    I32 oldsize = (I32) xhv->xhv_max + 1; /* sic(k) */
+    register I32 newsize;
+    register I32 i;
+    register I32 j;
+    register HE **a;
+    register HE *entry;
+    register HE **oentry;
+
+    newsize = (I32) newmax;                    /* possible truncation here */
+    if (newsize != newmax || newmax <= oldsize)
+       return;
+    while ((newsize & (1 + ~newsize)) != newsize) {
+       newsize &= ~(newsize & (1 + ~newsize)); /* get proper power of 2 */
+    }
+    if (newsize < newmax)
+       newsize *= 2;
+    if (newsize < newmax)
+       return;                                 /* overflow detection */
+
+    a = (HE**)xhv->xhv_array;
+    if (a) {
+       nomemok = TRUE;
+#ifdef STRANGE_MALLOC
+       Renew(a, newsize, HE*);
+#else
+       i = newsize * sizeof(HE*);
+       j = MALLOC_OVERHEAD;
+       while (j - MALLOC_OVERHEAD < i)
+           j += j;
+       j -= MALLOC_OVERHEAD;
+       j /= sizeof(HE*);
+       assert(j >= newsize);
+       New(2, a, j, HE*);
+       Copy(xhv->xhv_array, a, oldsize, HE*);
+       if (oldsize >= 64 && !nice_chunk) {
+           nice_chunk = (char*)xhv->xhv_array;
+           nice_chunk_size = oldsize * sizeof(HE*) * 2 - MALLOC_OVERHEAD;
+       }
+       else
+           Safefree(xhv->xhv_array);
+#endif
+       nomemok = FALSE;
+       Zero(&a[oldsize], newsize-oldsize, HE*); /* zero 2nd half*/
+    }
+    else {
+       Newz(0, a, newsize, HE*);
+    }
+    xhv->xhv_max = --newsize;
+    xhv->xhv_array = (char*)a;
+    if (!xhv->xhv_fill)                                /* skip rest if no entries */
+       return;
+
+    for (i=0; i<oldsize; i++,a++) {
+       if (!*a)                                /* non-existent */
+           continue;
+       for (oentry = a, entry = *a; entry; entry = *oentry) {
+           if ((j = (HeHASH(entry) & newsize)) != i) {
+               j -= i;
+               *oentry = HeNEXT(entry);
+               if (!(HeNEXT(entry) = a[j]))
+                   xhv->xhv_fill++;
+               a[j] = entry;
+               continue;
+           }
+           else
+               oentry = &HeNEXT(entry);
+       }
+       if (!*a)                                /* everything moved */
+           xhv->xhv_fill--;
+    }
+}
+
 HV *
 newHV()
 {
@@ -755,8 +835,13 @@ HV *hv;
 {
     register XPVHV* xhv = (XPVHV*)SvANY(hv);
     HE *entry = xhv->xhv_eiter;
-    if (entry && HeKLEN(entry) == HEf_LAZYDEL) /* was deleted earlier? */
+#ifdef DYNAMIC_ENV_FETCH  /* set up %ENV for iteration */
+    if (HvNAME(hv) && strEQ(HvNAME(hv),ENV_HV_NAME)) prime_env_iter();
+#endif
+    if (entry && HvLAZYDEL(hv)) {      /* was deleted earlier? */
+       HvLAZYDEL_off(hv);
        he_free(entry, HvSHAREKEYS(hv));
+    }
     xhv->xhv_riter = -1;
     xhv->xhv_eiter = Null(HE*);
     return xhv->xhv_fill;
@@ -813,8 +898,10 @@ HV *hv;
        entry = ((HE**)xhv->xhv_array)[xhv->xhv_riter];
     }
 
-    if (oldentry && HeKLEN(oldentry) == HEf_LAZYDEL)   /* was deleted earlier? */
+    if (oldentry && HvLAZYDEL(hv)) {           /* was deleted earlier? */
+       HvLAZYDEL_off(hv);
        he_free(oldentry, HvSHAREKEYS(hv));
+    }
 
     xhv->xhv_eiter = entry;
     return entry;