diff options
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 546 |
1 files changed, 99 insertions, 447 deletions
@@ -43,44 +43,39 @@ I32 lval; register I32 i; register I32 hash; register HE *entry; - register I32 maxi; SV *sv; -#ifdef SOME_DBM - datum dkey,dcontent; -#endif if (!hv) return 0; + + if (SvMAGICAL(hv)) { + if (mg_find((SV*)hv,'P')) { + sv = sv_2mortal(NEWSV(61,0)); + mg_copy((SV*)hv, sv, key, klen); + if (!lval) { + mg_get(sv); + sv_unmagic(sv,'p'); + } + Sv = sv; + return &Sv; + } + } + xhv = (XPVHV*)SvANY(hv); if (!xhv->xhv_array) { if (lval) - Newz(503,xhv->xhv_array, xhv->xhv_max + 1, HE*); + Newz(503,xhv->xhv_array, sizeof(HE*) * (xhv->xhv_max + 1), char); else return 0; } - /* The hash function we use on symbols has to be equal to the first - * character when taken modulo 128, so that sv_reset() can be implemented - * efficiently. We throw in the second character and the last character - * (times 128) so that long chains of identifiers starting with the - * same letter don't have to be strEQ'ed within hv_fetch(), since it - * compares hash values before trying strEQ(). - */ - if (!xhv->xhv_coeffsize && klen) - hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0; - else { /* use normal coefficients */ - if (klen < xhv->xhv_coeffsize) - maxi = klen; - else - maxi = xhv->xhv_coeffsize; - for (s=key, i=0, hash = 0; - i < maxi; /*SUPPRESS 8*/ - s++, i++, hash *= 5) { - hash += *s * coeff[i]; - } - } + i = klen; + hash = 0; + s = key; + while (i--) + hash = hash * 33 + *s++; - entry = xhv->xhv_array[hash & xhv->xhv_max]; + entry = ((HE**)xhv->xhv_array)[hash & xhv->xhv_max]; for (; entry; entry = entry->hent_next) { if (entry->hent_hash != hash) /* strings can't be equal */ continue; @@ -90,22 +85,6 @@ I32 lval; continue; return &entry->hent_val; } -#ifdef SOME_DBM - if (xhv->xhv_dbm) { - dkey.dptr = key; - dkey.dsize = klen; -#ifdef HAS_GDBM - dcontent = gdbm_fetch(xhv->xhv_dbm,dkey); -#else - dcontent = dbm_fetch(xhv->xhv_dbm,dkey); -#endif - if (dcontent.dptr) { /* found one */ - sv = NEWSV(60,dcontent.dsize); - sv_setpvn(sv,dcontent.dptr,dcontent.dsize); - return hv_store(hv,key,klen,sv,hash); /* cache it */ - } - } -#endif if (lval) { /* gonna assign to this, so it better be there */ sv = NEWSV(61,0); return hv_store(hv,key,klen,sv,hash); @@ -126,39 +105,30 @@ register U32 hash; register I32 i; register HE *entry; register HE **oentry; - register I32 maxi; if (!hv) return 0; xhv = (XPVHV*)SvANY(hv); - if (hash) - /*SUPPRESS 530*/ - ; - else if (!xhv->xhv_coeffsize && klen) - hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0; - else { /* use normal coefficients */ - if (klen < xhv->xhv_coeffsize) - maxi = klen; - else - maxi = xhv->xhv_coeffsize; - for (s=key, i=0, hash = 0; - i < maxi; /*SUPPRESS 8*/ - s++, i++, hash *= 5) { - hash += *s * coeff[i]; - } + if (SvMAGICAL(hv)) { + MAGIC* mg = SvMAGIC(hv); + mg_copy((SV*)hv, val, key, klen); + if (!xhv->xhv_array) + return 0; + } + if (!hash) { + i = klen; + s = key; + while (i--) + hash = hash * 33 + *s++; } if (!xhv->xhv_array) - Newz(505,xhv->xhv_array, xhv->xhv_max + 1, HE*); + Newz(505, xhv->xhv_array, sizeof(HE**) * (xhv->xhv_max + 1), char); - oentry = &(xhv->xhv_array[hash & xhv->xhv_max]); + oentry = &((HE**)xhv->xhv_array)[hash & xhv->xhv_max]; i = 1; - if (SvMAGICAL(hv)) { - MAGIC* mg = SvMAGIC(hv); - sv_magic(val, (SV*)hv, tolower(mg->mg_type), key, klen); - } for (entry = *oentry; entry; i=0, entry = entry->hent_next) { if (entry->hent_hash != hash) /* strings can't be equal */ continue; @@ -179,32 +149,12 @@ register U32 hash; entry->hent_next = *oentry; *oentry = entry; - /* hv_dbmstore not necessary here because it's called from sv_setmagic() */ - + xhv->xhv_keys++; if (i) { /* initial entry? */ - xhv->xhv_fill++; -#ifdef SOME_DBM - if (xhv->xhv_dbm && xhv->xhv_max >= DBM_CACHE_MAX) - return &entry->hent_val; -#endif - if (xhv->xhv_fill > xhv->xhv_dosplit) + ++xhv->xhv_fill; + if (xhv->xhv_keys > xhv->xhv_max) hsplit(hv); } -#ifdef SOME_DBM - else if (xhv->xhv_dbm) { /* is this just a cache for dbm file? */ - void he_delayfree(); - HE* ent; - - ent = xhv->xhv_array[hash & xhv->xhv_max]; - oentry = &ent->hent_next; - ent = *oentry; - while (ent) { /* trim chain down to 1 entry */ - *oentry = ent->hent_next; - he_delayfree(ent); /* no doubt they'll want this next, sigh... */ - ent = *oentry; - } - } -#endif return &entry->hent_val; } @@ -222,31 +172,23 @@ U32 klen; register HE *entry; register HE **oentry; SV *sv; - I32 maxi; -#ifdef SOME_DBM - datum dkey; -#endif if (!hv) return Nullsv; + if (SvMAGICAL(hv)) { + sv = *hv_fetch(hv, key, klen, TRUE); + mg_clear(sv); + } xhv = (XPVHV*)SvANY(hv); if (!xhv->xhv_array) return Nullsv; - if (!xhv->xhv_coeffsize && klen) - hash = klen ? *key + 128 * key[1] + 128 * key[klen-1] : 0; - else { /* use normal coefficients */ - if (klen < xhv->xhv_coeffsize) - maxi = klen; - else - maxi = xhv->xhv_coeffsize; - for (s=key, i=0, hash = 0; - i < maxi; /*SUPPRESS 8*/ - s++, i++, hash *= 5) { - hash += *s * coeff[i]; - } - } + i = klen; + hash = 0; + s = key; + while (i--) + hash = hash * 33 + *s++; - oentry = &(xhv->xhv_array[hash & xhv->xhv_max]); + oentry = &((HE**)xhv->xhv_array)[hash & xhv->xhv_max]; entry = *oentry; i = 1; for (; entry; i=0, oentry = &entry->hent_next, entry = *oentry) { @@ -261,26 +203,10 @@ U32 klen; xhv->xhv_fill--; sv = sv_mortalcopy(entry->hent_val); he_free(entry); -#ifdef SOME_DBM - do_dbm_delete: - if (xhv->xhv_dbm) { - dkey.dptr = key; - dkey.dsize = klen; -#ifdef HAS_GDBM - gdbm_delete(xhv->xhv_dbm,dkey); -#else - dbm_delete(xhv->xhv_dbm,dkey); -#endif - } -#endif + --xhv->xhv_keys; return sv; } -#ifdef SOME_DBM - sv = Nullsv; - goto do_dbm_delete; -#else return Nullsv; -#endif } static void @@ -296,18 +222,13 @@ HV *hv; register HE *entry; register HE **oentry; - a = xhv->xhv_array; + a = (HE**)xhv->xhv_array; nomemok = TRUE; Renew(a, newsize, HE*); nomemok = FALSE; - if (!a) { - xhv->xhv_dosplit = xhv->xhv_max + 1; /* never split again */ - return; - } Zero(&a[oldsize], oldsize, HE*); /* zero 2nd half*/ xhv->xhv_max = --newsize; - xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100; - xhv->xhv_array = a; + xhv->xhv_array = (char*)a; for (i=0; i<oldsize; i++,a++) { if (!*a) /* non-existent */ @@ -331,8 +252,7 @@ HV *hv; } HV * -newHV(lookat) -U32 lookat; +newHV() { register HV *hv; register XPVHV* xhv; @@ -343,20 +263,9 @@ U32 lookat; xhv = (XPVHV*)SvANY(hv); SvPOK_off(hv); SvNOK_off(hv); - if (lookat) { - xhv->xhv_coeffsize = lookat; - xhv->xhv_max = 7; /* it's a normal associative array */ - xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100; - } - else { - xhv->xhv_max = 127; /* it's a symbol table */ - xhv->xhv_dosplit = 128; /* so never split */ - } + xhv->xhv_max = 7; /* start with 8 buckets */ xhv->xhv_fill = 0; xhv->xhv_pmroot = 0; -#ifdef SOME_DBM - xhv->xhv_dbm = 0; -#endif (void)hv_iterinit(hv); /* so each() will start off right */ return hv; } @@ -384,81 +293,32 @@ register HE *hent; } void -hv_clear(hv,dodbm) +hv_clear(hv) HV *hv; -I32 dodbm; { register XPVHV* xhv; if (!hv) return; xhv = (XPVHV*)SvANY(hv); - hfreeentries(hv,dodbm); + hfreeentries(hv); xhv->xhv_fill = 0; -#ifndef lint if (xhv->xhv_array) - (void)memzero((char*)xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*)); -#endif + (void)memzero(xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*)); } static void -hfreeentries(hv,dodbm) +hfreeentries(hv) HV *hv; -I32 dodbm; { register XPVHV* xhv; register HE *hent; register HE *ohent = Null(HE*); -#ifdef SOME_DBM - datum dkey; - datum nextdkey; -#ifdef HAS_GDBM - GDBM_FILE old_dbm; -#else -#ifdef HAS_NDBM - DBM *old_dbm; -#else - I32 old_dbm; -#endif -#endif -#endif if (!hv) return; xhv = (XPVHV*)SvANY(hv); if (!xhv->xhv_array) return; -#ifdef SOME_DBM - if ((old_dbm = xhv->xhv_dbm) && dodbm) { -#ifdef HAS_GDBM - while (dkey = gdbm_firstkey(xhv->xhv_dbm), dkey.dptr) { -#else - while (dkey = dbm_firstkey(xhv->xhv_dbm), dkey.dptr) { -#endif - do { -#ifdef HAS_GDBM - nextdkey = gdbm_nextkey(xhv->xhv_dbm, dkey); -#else -#ifdef HAS_NDBM -#ifdef _CX_UX - nextdkey = dbm_nextkey(xhv->xhv_dbm, dkey); -#else - nextdkey = dbm_nextkey(xhv->xhv_dbm); -#endif -#else - nextdkey = nextkey(dkey); -#endif -#endif -#ifdef HAS_GDBM - gdbm_delete(xhv->xhv_dbm,dkey); -#else - dbm_delete(xhv->xhv_dbm,dkey); -#endif - dkey = nextdkey; - } while (dkey.dptr); /* one way or another, this works */ - } - } - xhv->xhv_dbm = 0; /* now clear just cache */ -#endif (void)hv_iterinit(hv); /*SUPPRESS 560*/ while (hent = hv_iternext(hv)) { /* concise but not very efficient */ @@ -466,48 +326,33 @@ I32 dodbm; ohent = hent; } he_free(ohent); -#ifdef SOME_DBM - xhv->xhv_dbm = old_dbm; -#endif if (SvMAGIC(hv)) - mg_clear(hv); + mg_clear((SV*)hv); } void -hv_undef(hv,dodbm) +hv_undef(hv) HV *hv; -I32 dodbm; { register XPVHV* xhv; if (!hv) return; xhv = (XPVHV*)SvANY(hv); - hfreeentries(hv,dodbm); + hfreeentries(hv); Safefree(xhv->xhv_array); xhv->xhv_array = 0; - if (xhv->xhv_coeffsize) { - xhv->xhv_max = 7; /* it's a normal associative array */ - xhv->xhv_dosplit = xhv->xhv_max * FILLPCT / 100; - } - else { - xhv->xhv_max = 127; /* it's a symbol table */ - xhv->xhv_dosplit = 128; /* so never split */ - } + xhv->xhv_max = 7; /* it's a normal associative array */ xhv->xhv_fill = 0; -#ifdef SOME_DBM - xhv->xhv_dbm = 0; -#endif (void)hv_iterinit(hv); /* so each() will start off right */ } void -hv_free(hv,dodbm) +hv_free(hv) register HV *hv; -I32 dodbm; { if (!hv) return; - hfreeentries(hv,dodbm); + hfreeentries(hv); Safefree(HvARRAY(hv)); Safefree(hv); } @@ -528,60 +373,39 @@ HV *hv; { register XPVHV* xhv; register HE *entry; -#ifdef SOME_DBM - datum key; -#endif + MAGIC* mg; if (!hv) - fatal("Bad associative array"); + croak("Bad associative array"); xhv = (XPVHV*)SvANY(hv); entry = xhv->xhv_eiter; -#ifdef SOME_DBM - if (xhv->xhv_dbm) { - if (entry) { -#ifdef HAS_GDBM - key.dptr = entry->hent_key; - key.dsize = entry->hent_klen; - key = gdbm_nextkey(xhv->xhv_dbm, key); -#else -#ifdef HAS_NDBM -#ifdef _CX_UX - key.dptr = entry->hent_key; - key.dsize = entry->hent_klen; - key = dbm_nextkey(xhv->xhv_dbm, key); -#else - key = dbm_nextkey(xhv->xhv_dbm); -#endif /* _CX_UX */ -#else - key.dptr = entry->hent_key; - key.dsize = entry->hent_klen; - key = nextkey(key); -#endif -#endif - } - else { - Newz(504,entry, 1, HE); - xhv->xhv_eiter = entry; -#ifdef HAS_GDBM - key = gdbm_firstkey(xhv->xhv_dbm); -#else - key = dbm_firstkey(xhv->xhv_dbm); -#endif - } - entry->hent_key = key.dptr; - entry->hent_klen = key.dsize; - if (!key.dptr) { - if (entry->hent_val) - sv_free(entry->hent_val); - Safefree(entry); - xhv->xhv_eiter = Null(HE*); - return Null(HE*); - } - return entry; + + if (SvMAGICAL(hv) && (mg = mg_find((SV*)hv,'P'))) { + SV *key = sv_2mortal(NEWSV(0,0)); + if (entry) + sv_setpvn(key, entry->hent_key, entry->hent_klen); + else { + Newz(504,entry, 1, HE); + xhv->xhv_eiter = entry; + } + magic_nextpack(hv,mg,key); + if (SvOK(key)) { + STRLEN len; + entry->hent_key = SvPV(key, len); + entry->hent_klen = len; + SvPOK_off(key); + SvPVX(key) = 0; + return entry; + } + if (entry->hent_val) + sv_free(entry->hent_val); + Safefree(entry); + xhv->xhv_eiter = Null(HE*); + return Null(HE*); } -#endif + if (!xhv->xhv_array) - Newz(506,xhv->xhv_array, xhv->xhv_max + 1, HE*); + Newz(506,xhv->xhv_array, sizeof(HE*) * (xhv->xhv_max + 1), char); do { if (entry) entry = entry->hent_next; @@ -591,7 +415,7 @@ HV *hv; xhv->xhv_riter = -1; break; } - entry = xhv->xhv_array[xhv->xhv_riter]; + entry = ((HE**)xhv->xhv_array)[xhv->xhv_riter]; } } while (!entry); @@ -613,195 +437,23 @@ hv_iterval(hv,entry) HV *hv; register HE *entry; { -#ifdef SOME_DBM - register XPVHV* xhv; - datum key, content; - - if (!hv) - fatal("Bad associative array"); - xhv = (XPVHV*)SvANY(hv); - if (xhv->xhv_dbm) { - key.dptr = entry->hent_key; - key.dsize = entry->hent_klen; -#ifdef HAS_GDBM - content = gdbm_fetch(xhv->xhv_dbm,key); -#else - content = dbm_fetch(xhv->xhv_dbm,key); -#endif - if (!entry->hent_val) - entry->hent_val = NEWSV(62,0); - sv_setpvn(entry->hent_val,content.dptr,content.dsize); + if (SvMAGICAL(hv)) { + if (mg_find((SV*)hv,'P')) { + SV* sv = sv_2mortal(NEWSV(61,0)); + mg_copy((SV*)hv, sv, entry->hent_key, entry->hent_klen); + mg_get(sv); + sv_unmagic(sv,'p'); + return sv; + } } -#endif return entry->hent_val; } -#ifdef SOME_DBM - -#ifndef OP_CREAT -# ifdef I_FCNTL -# include <fcntl.h> -# endif -# ifdef I_SYS_FILE -# include <sys/file.h> -# endif -#endif - -#ifndef OP_RDONLY -#define OP_RDONLY 0 -#endif -#ifndef OP_RDWR -#define OP_RDWR 2 -#endif -#ifndef OP_CREAT -#define OP_CREAT 01000 -#endif - -bool -hv_dbmopen(hv,fname,mode) -HV *hv; -char *fname; -I32 mode; -{ - register XPVHV* xhv; - if (!hv) - return FALSE; - xhv = (XPVHV*)SvANY(hv); -#ifdef HAS_ODBM - if (xhv->xhv_dbm) /* never really closed it */ - return TRUE; -#endif - if (xhv->xhv_dbm) { - hv_dbmclose(hv); - xhv->xhv_dbm = 0; - } - hv_clear(hv, FALSE); /* clear cache */ -#ifdef HAS_GDBM - if (mode >= 0) - xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_WRCREAT,mode, (void *) NULL); - if (!xhv->xhv_dbm) - xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_WRITER, mode, (void *) NULL); - if (!xhv->xhv_dbm) - xhv->xhv_dbm = gdbm_open(fname, 0, GDBM_READER, mode, (void *) NULL); -#else -#ifdef HAS_NDBM - if (mode >= 0) - xhv->xhv_dbm = dbm_open(fname, OP_RDWR|OP_CREAT, mode); - if (!xhv->xhv_dbm) - xhv->xhv_dbm = dbm_open(fname, OP_RDWR, mode); - if (!xhv->xhv_dbm) - xhv->xhv_dbm = dbm_open(fname, OP_RDONLY, mode); -#else - if (dbmrefcnt++) - fatal("Old dbm can only open one database"); - sprintf(buf,"%s.dir",fname); - if (stat(buf, &statbuf) < 0) { - if (mode < 0 || close(creat(buf,mode)) < 0) - return FALSE; - sprintf(buf,"%s.pag",fname); - if (close(creat(buf,mode)) < 0) - return FALSE; - } - xhv->xhv_dbm = dbminit(fname) >= 0; -#endif -#endif - if (!xhv->xhv_array && xhv->xhv_dbm != 0) - Newz(507,xhv->xhv_array, xhv->xhv_max + 1, HE*); - hv_magic(hv, 0, 'D'); - return xhv->xhv_dbm != 0; -} - -void -hv_dbmclose(hv) -HV *hv; -{ - register XPVHV* xhv; - if (!hv) - fatal("Bad associative array"); - xhv = (XPVHV*)SvANY(hv); - if (xhv->xhv_dbm) { -#ifdef HAS_GDBM - gdbm_close(xhv->xhv_dbm); - xhv->xhv_dbm = 0; -#else -#ifdef HAS_NDBM - dbm_close(xhv->xhv_dbm); - xhv->xhv_dbm = 0; -#else - /* dbmrefcnt--; */ /* doesn't work, rats */ -#endif -#endif - } - else if (dowarn) - warn("Close on unopened dbm file"); -} - -bool -hv_dbmstore(hv,key,klen,sv) -HV *hv; -char *key; -U32 klen; -register SV *sv; -{ - register XPVHV* xhv; - datum dkey, dcontent; - I32 error; - - if (!hv) - return FALSE; - xhv = (XPVHV*)SvANY(hv); - if (!xhv->xhv_dbm) - return FALSE; - dkey.dptr = key; - dkey.dsize = klen; - dcontent.dptr = SvPVn(sv); - dcontent.dsize = SvCUR(sv); -#ifdef HAS_GDBM - error = gdbm_store(xhv->xhv_dbm, dkey, dcontent, GDBM_REPLACE); -#else - error = dbm_store(xhv->xhv_dbm, dkey, dcontent, DBM_REPLACE); -#endif - if (error) { - if (errno == EPERM) - fatal("No write permission to dbm file"); - fatal("dbm store returned %d, errno %d, key \"%s\"",error,errno,key); -#ifdef HAS_NDBM - dbm_clearerr(xhv->xhv_dbm); -#endif - } - return !error; -} -#endif /* SOME_DBM */ - -#ifdef XXX - magictype = MgTYPE(magic); - switch (magictype) { - case 'E': - environ[0] = Nullch; - break; - case 'S': -#ifndef NSIG -#define NSIG 32 -#endif - for (i = 1; i < NSIG; i++) - signal(i, SIG_DFL); /* crunch, crunch, crunch */ - break; - } - - if (magic) { - sv_magic(tmpstr, (SV*)tmpgv, magic, tmps, SvCUR(sv)); - sv_magicset(tmpstr, magic); - } - - if (hv->hv_sv.sv_rare && !sv->sv_magic) - sv_magic(sv, (GV*)hv, hv->hv_sv.sv_rare, key, keylen); -#endif - void hv_magic(hv, gv, how) HV* hv; GV* gv; I32 how; { - sv_magic(hv, gv, how, 0, 0); + sv_magic((SV*)hv, (SV*)gv, how, 0, 0); } |