Clean up and document API for hashes
Gurusamy Sarathy [Tue, 25 Feb 1997 18:24:02 +0000 (13:24 -0500)]
On Tue, 25 Feb 1997 09:01:57 EST, Chip Salzenberg wrote:
>I've had 99.44% good reports about _90.  I'd love to go public
>immediately, but Sarathy's perl_call fix is just too valuable to pass
>up, and there's a taint test in the works.  So please don't tell
>anyone that _90 is the first public beta; that will likely be _91.

FWIW, the Beta Zvoid is alive and kicking on Linux 2.0.28.

You might want to put this in too.  (The patches to hv.h are mostly
to an unused macro that will be useful for extension writers).

p5p-msgid: <199702251824.NAA14859@aatma.engin.umich.edu>

hv.c
hv.h
perl.c
pod/perldelta.pod
pod/perlguts.pod
pp_ctl.c

diff --git a/hv.c b/hv.c
index 1ae7ad9..ab6eac7 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -177,7 +177,6 @@ register U32 hash;
            char *k;
            New(54, k, HEK_BASESIZE + sizeof(SV*), char);
            HeKEY_hek(&mh) = (HEK*)k;
-           HeKLEN(&mh) = HEf_SVKEY;    /* key will always hold an SV* */
        }
        HeSVKEY_set(&mh, keysv);
        HeVAL(&mh) = sv;
diff --git a/hv.h b/hv.h
index 7c04cc2..7c80ca3 100644 (file)
--- a/hv.h
+++ b/hv.h
@@ -95,9 +95,11 @@ struct xpvhv {
 #define HeKLEN(he)             HEK_LEN(HeKEY_hek(he))
 #define HeVAL(he)              (he)->hent_val
 #define HeHASH(he)             HEK_HASH(HeKEY_hek(he))
-#define HePV(he)               ((HeKLEN(he) == HEf_SVKEY) ?            \
-                                SvPV(HeKEY_sv(he),na) :                \
-                                HeKEY(he))
+#define HePV(he,lp)            ((HeKLEN(he) == HEf_SVKEY) ?            \
+                                SvPV(HeKEY_sv(he),lp) :                \
+                                (((lp = HeKLEN(he)) >= 0) ?            \
+                                 HeKEY(he) : Nullch))
+
 #define HeSVKEY(he)            ((HeKEY(he) &&                          \
                                  HeKLEN(he) == HEf_SVKEY) ?            \
                                 HeKEY_sv(he) : Nullsv)
@@ -108,7 +110,7 @@ struct xpvhv {
                                  sv_2mortal(newSVpv(HeKEY(he),         \
                                                     HeKLEN(he)))) :    \
                                 &sv_undef)
-#define HeSVKEY_set(he,sv)     (HeKEY_sv(he) = sv)
+#define HeSVKEY_set(he,sv)     ((HeKEY_sv(he) = sv), (HeKLEN(he) = HEf_SVKEY))
 
 #define Nullhek Null(HEK*)
 #define HEK_BASESIZE           STRUCT_OFFSET(HEK, hek_key[0])
diff --git a/perl.c b/perl.c
index 8794dd6..9f3942e 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -509,7 +509,6 @@ setuid perl scripts securely.\n");
            calllist(endav);
        return STATUS_NATIVE_EXPORT;
     case 3:
-       mustcatch = FALSE;
        PerlIO_printf(PerlIO_stderr(), "panic: top_env\n");
        return 1;
     }
@@ -801,7 +800,6 @@ PerlInterpreter *sv_interp;
 #endif
        return STATUS_NATIVE_EXPORT;
     case 3:
-       mustcatch = FALSE;
        if (!restartop) {
            PerlIO_printf(PerlIO_stderr(), "panic: restartop\n");
            FREETMPS;
@@ -1032,7 +1030,6 @@ I32 flags;                /* See G_* flags in cop.h */
            my_exit_jump();
            /* NOTREACHED */
        case 3:
-           mustcatch = FALSE;
            if (restartop) {
                op = restartop;
                restartop = 0;
@@ -1143,7 +1140,6 @@ restart:
        my_exit_jump();
        /* NOTREACHED */
     case 3:
-       mustcatch = FALSE;
        if (restartop) {
            op = restartop;
            restartop = 0;
index 23f216f..d202e70 100644 (file)
@@ -671,6 +671,18 @@ C<perl_call_sv> is Perl's producing an "Undefined subroutine called"
 error on the I<second> call to a given method (since there is no cache
 on the first call).
 
+=item Extended API for manipulating hashes
+
+Internal handling of hash keys has changed.  The old hashtable API
+is still fully supported, and will likely remain that way.  The additions
+to the API allow passing keys as C<SV*>s, so that C<tied> hashes can be
+given real scalars as keys rather than plain strings (non-tied hashes still
+can only use strings as keys).  All new extensions must use the new 
+hash access functions and macros if they wish to use C<SV*> keys.  These
+additions also make it feasible to manipulate whole C<HE*>s (hash entries),
+allowing for more efficient handling of hash data. See L<perlguts> for
+details.
+
 =back
 
 =head1 Documentation Changes
index 77acc98..5766cc0 100644 (file)
@@ -322,6 +322,48 @@ The hash algorithm is defined in the C<PERL_HASH(hash, key, klen)> macro:
     while (i--)
        hash = hash * 33 + *s++;
 
+=head2 Hash API Extensions
+
+Beginning with version 5.004, the following functions are also supported:
+
+    HE*     hv_fetch_ent  (HV* tb, SV* key, I32 lval, U32 hash);
+    HE*     hv_store_ent  (HV* tb, SV* key, SV* val, U32 hash);
+    
+    bool    hv_exists_ent (HV* tb, SV* key, U32 hash);
+    SV*     hv_delete_ent (HV* tb, SV* key, I32 flags, U32 hash);
+    
+    SV*     hv_iterkeysv  (HE* entry);
+
+Note that these functions take C<SV*> keys, which simplifies writing
+of extension code that deals with hash structures.  These functions
+also allow passing of C<SV*> keys to C<tie> functions without forcing
+you to stringify the keys (unlike the previous set of functions).
+
+They also return and accept whole hash entries (C<HE*>), making their
+use more efficient (since the hash number for a particular string
+doesn't have to be recomputed every time).  See L<API LISTING> later in
+this document for detailed descriptions.
+
+The following macros must always be used to access the contents of hash
+entries.  Note that the arguments to these macros must be simple
+variables, since they may get evaluated more than once.  See
+L<API LISTING> later in this document for detailed descriptions of these
+macros.
+
+    HePV(HE* he, STRLEN len)
+    HeVAL(HE* he)
+    HeHASH(HE* he)
+    HeSVKEY(HE* he)
+    HeSVKEY_force(HE* he)
+    HeSVKEY_set(HE* he, SV* sv)
+
+These two lower level macros are defined, but must only be used when
+dealing with keys that are not C<SV*>s:
+
+    HeKEY(HE* he)
+    HeKLEN(HE* he)
+
+
 =head2 References
 
 References are a special type of scalar that point to other data types
@@ -1392,6 +1434,12 @@ statement (or thereabouts) with C<sv_2mortal>.  See C<hv_iternext>.
 
        void    he_delayfree _((HV* hv, HE* hent));
 
+=item HEf_SVKEY
+
+This flag, used in the length slot of hash entries and magic
+structures, specifies the structure contains a C<SV*> pointer where a
+C<char*> pointer is to be expected. (For information only--not to be used).
+
 =item he_free
 
 Releases a hash entry, such as while iterating though the hash.  See
@@ -1399,6 +1447,71 @@ C<hv_iternext>.
 
        void    he_free _((HV* hv, HE* hent));
 
+=item HeHASH
+
+Returns the computed hash (type C<U32>) stored in the hash entry.
+
+       HeHASH(HE* he)
+
+=item HeKEY
+
+Returns the actual pointer stored in the key slot of the hash entry.
+The pointer may be either C<char*> or C<SV*>, depending on the value of
+C<HeKLEN()>.  Can be assigned to.  The C<HePV()> or C<HeSVKEY()> macros
+are usually preferable for finding the value of a key.
+
+       HeKEY(HE* he)
+
+=item HeKLEN
+
+If this is negative, and amounts to C<HEf_SVKEY>, it indicates the entry
+holds an C<SV*> key.  Otherwise, holds the actual length of the key.
+Can be assigned to. The C<HePV()> macro is usually preferable for finding
+key lengths.
+
+       HeKLEN(HE* he)
+
+=item HePV
+
+Returns the key slot of the hash entry as a C<char*> value, doing any
+necessary dereferencing of possibly C<SV*> keys.  The length of
+the string is placed in C<len> (this is a macro, so do I<not> use
+C<&len>).  If you do not care about what the length of the key is,
+you may use the global variable C<na>.  Remember though, that hash
+keys in perl are free to contain embedded nulls, so using C<strlen()>
+or similar is not a good way to find the length of hash keys.
+This is very similar to the C<SvPV()> macro described elsewhere in
+this document.
+
+       HePV(HE* he, STRLEN len)
+
+=item HeSVKEY
+
+Returns the key as an C<SV*>, or C<Nullsv> if the hash entry
+does not contain an C<SV*> key.
+
+       HeSVKEY(HE* he)
+
+=item HeSVKEY_force
+
+Returns the key as an C<SV*>.  Will create and return a temporary
+mortal C<SV*> if the hash entry contains only a C<char*> key.
+
+       HeSVKEY_force(HE* he)
+
+=item HeSVKEY_set
+
+Sets the key to a given C<SV*>, taking care to set the appropriate flags
+to indicate the presence of an C<SV*> key.
+
+       HeSVKEY_set(HE* he, SV* sv)
+
+=item HeVAL
+
+Returns the value slot (type C<SV*>) stored in the hash entry.
+
+       HeVAL(HE* he)
+
 =item hv_clear
 
 Clears a hash, making it empty.
@@ -1414,6 +1527,15 @@ returned.
 
        SV*     hv_delete _((HV* tb, char* key, U32 klen, I32 flags));
 
+=item hv_delete_ent
+
+Deletes a key/value pair in the hash.  The value SV is removed from the hash
+and returned to the caller.  The C<flags> value will normally be zero; if set
+to G_DISCARD then null will be returned.  C<hash> can be a valid pre-computed
+hash value, or 0 to ask for it to be computed.
+
+       SV*     hv_delete_ent _((HV* tb, SV* key, I32 flags, U32 hash));
+
 =item hv_exists
 
 Returns a boolean indicating whether the specified hash key exists.  The
@@ -1421,6 +1543,13 @@ C<klen> is the length of the key.
 
        bool    hv_exists _((HV* tb, char* key, U32 klen));
 
+=item hv_exists_ent
+
+Returns a boolean indicating whether the specified hash key exists. C<hash>
+can be a valid pre-computed hash value, or 0 to ask for it to be computed.
+
+       bool    hv_exists_ent _((HV* tb, SV* key, U32 hash));
+
 =item hv_fetch
 
 Returns the SV which corresponds to the specified key in the hash.  The
@@ -1430,6 +1559,18 @@ dereferencing it to a C<SV*>.
 
        SV**    hv_fetch _((HV* tb, char* key, U32 klen, I32 lval));
 
+=item hv_fetch_ent
+
+Returns the hash entry which corresponds to the specified key in the hash.
+C<hash> must be a valid pre-computed hash number for the given C<key>, or
+0 if you want the function to compute it.  IF C<lval> is set then the
+fetch will be part of a store.  Make sure the return value is non-null
+before accessing it.  The return value when C<tb> is a tied hash
+is a pointer to a static location, so be sure to make a copy of the
+structure if you need to store it somewhere.
+
+       HE*     hv_fetch_ent  _((HV* tb, SV* key, I32 lval, U32 hash));
+
 =item hv_iterinit
 
 Prepares a starting point to traverse a hash table.
@@ -1443,6 +1584,14 @@ C<hv_iterinit>.
 
        char*   hv_iterkey _((HE* entry, I32* retlen));
 
+=item hv_iterkeysv
+       
+Returns the key as an C<SV*> from the current position of the hash
+iterator.  The return value will always be a mortal copy of the
+key.  Also see C<hv_iterinit>.
+
+       SV*     hv_iterkeysv  _((HE* entry));
+
 =item hv_iternext
 
 Returns entries from a hash iterator.  See C<hv_iterinit>.
@@ -1485,6 +1634,17 @@ original C<SV*>.
 
        SV**    hv_store _((HV* tb, char* key, U32 klen, SV* val, U32 hash));
 
+=item hv_store_ent
+
+Stores C<val> in a hash.  The hash key is specified as C<key>.  The C<hash>
+parameter is the pre-computed hash value; if it is zero then Perl will
+compute it.  The return value is the new hash entry so created.  It will be
+null if the operation failed or if the entry was stored in a tied hash.
+Otherwise the contents of the return value can be accessed using the
+C<He???> macros described here.
+
+       HE*     hv_store_ent  _((HV* tb, SV* key, SV* val, U32 hash));
+       
 =item hv_undef
 
 Undefines the hash.
index de3c13b..6eab4da 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1946,10 +1946,10 @@ OP *o;
 {
     int ret;
     int oldrunlevel = runlevel;
-    OP *oldop = op;
     Sigjmp_buf oldtop;
 
     op = o;
+    runlevel--;                                /* pretense */
     Copy(top_env, oldtop, 1, Sigjmp_buf);
 #ifdef DEBUGGING
     assert(mustcatch == TRUE);
@@ -1960,7 +1960,6 @@ OP *o;
        Copy(oldtop, top_env, 1, Sigjmp_buf);
        runlevel = oldrunlevel;
        mustcatch = TRUE;
-       op = oldop;
        Siglongjmp(top_env, ret);
        /* NOTREACHED */
     case 3:
@@ -1968,7 +1967,6 @@ OP *o;
            PerlIO_printf(PerlIO_stderr(), "panic: restartop\n");
            break;
        }
-       mustcatch = FALSE;
        op = restartop;
        restartop = 0;
        /* FALL THROUGH */
@@ -1979,7 +1977,6 @@ OP *o;
     Copy(oldtop, top_env, 1, Sigjmp_buf);
     runlevel = oldrunlevel;
     mustcatch = TRUE;
-    op = oldop;
     return Nullop;
 }