3 * Copyright (c) 1991-1994, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
11 * "I sit beside the fire and think of all that I have seen." --Bilbo
17 static void hsplit _((HV *hv));
18 static void hfreeentries _((HV *hv));
28 he_root = (HE*)he->hent_next;
38 p->hent_next = (HE*)he_root;
47 he_root = (HE*)safemalloc(1008);
49 heend = &he[1008 / sizeof(HE) - 1];
51 he->hent_next = (HE*)(he + 1);
59 hv_fetch(hv,key,klen,lval)
76 if (mg_find((SV*)hv,'P')) {
78 mg_copy((SV*)hv, sv, key, klen);
84 xhv = (XPVHV*)SvANY(hv);
85 if (!xhv->xhv_array) {
87 #ifdef DYNAMIC_ENV_FETCH /* if it's an %ENV lookup, we may get it on the fly */
88 || (HvNAME(hv) && strEQ(HvNAME(hv),ENV_HV_NAME))
91 Newz(503,xhv->xhv_array, sizeof(HE*) * (xhv->xhv_max + 1), char);
100 hash = hash * 33 + *s++;
102 entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
103 for (; entry; entry = entry->hent_next) {
104 if (entry->hent_hash != hash) /* strings can't be equal */
106 if (entry->hent_klen != klen)
108 if (bcmp(entry->hent_key,key,klen)) /* is this it? */
110 return &entry->hent_val;
112 #ifdef DYNAMIC_ENV_FETCH /* %ENV lookup? If so, try to fetch the value now */
113 if (HvNAME(hv) && strEQ(HvNAME(hv),ENV_HV_NAME)) {
116 gotenv = my_getenv(key);
117 if (gotenv != NULL) {
118 sv = newSVpv(gotenv,strlen(gotenv));
119 return hv_store(hv,key,klen,sv,hash);
123 if (lval) { /* gonna assign to this, so it better be there */
125 return hv_store(hv,key,klen,sv,hash);
131 hv_store(hv,key,klen,val,hash)
142 register HE **oentry;
147 xhv = (XPVHV*)SvANY(hv);
149 mg_copy((SV*)hv, val, key, klen);
154 if (!xhv->xhv_array && (SvMAGIC(hv)->mg_type != 'A'
155 || SvMAGIC(hv)->mg_moremagic))
157 #endif /* OVERLOAD */
163 hash = hash * 33 + *s++;
167 Newz(505, xhv->xhv_array, sizeof(HE**) * (xhv->xhv_max + 1), char);
169 oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
172 for (entry = *oentry; entry; i=0, entry = entry->hent_next) {
173 if (entry->hent_hash != hash) /* strings can't be equal */
175 if (entry->hent_klen != klen)
177 if (bcmp(entry->hent_key,key,klen)) /* is this it? */
179 SvREFCNT_dec(entry->hent_val);
180 entry->hent_val = val;
181 return &entry->hent_val;
185 entry->hent_klen = klen;
186 entry->hent_key = savepvn(key,klen);
187 entry->hent_val = val;
188 entry->hent_hash = hash;
189 entry->hent_next = *oentry;
193 if (i) { /* initial entry? */
195 if (xhv->xhv_keys > xhv->xhv_max)
199 return &entry->hent_val;
203 hv_delete(hv,key,klen,flags)
214 register HE **oentry;
219 if (SvRMAGICAL(hv)) {
220 sv = *hv_fetch(hv, key, klen, TRUE);
222 if (mg_find(sv, 'p')) {
223 sv_unmagic(sv, 'p'); /* No longer an element */
227 xhv = (XPVHV*)SvANY(hv);
234 hash = hash * 33 + *s++;
236 oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
239 for (; entry; i=0, oentry = &entry->hent_next, entry = *oentry) {
240 if (entry->hent_hash != hash) /* strings can't be equal */
242 if (entry->hent_klen != klen)
244 if (bcmp(entry->hent_key,key,klen)) /* is this it? */
246 *oentry = entry->hent_next;
249 if (flags & G_DISCARD)
252 sv = sv_mortalcopy(entry->hent_val);
253 if (entry == xhv->xhv_eiter)
254 entry->hent_klen = -1;
264 hv_exists(hv,key,klen)
279 if (SvRMAGICAL(hv)) {
280 if (mg_find((SV*)hv,'P')) {
282 mg_copy((SV*)hv, sv, key, klen);
283 magic_existspack(sv, mg_find(sv, 'p'));
288 xhv = (XPVHV*)SvANY(hv);
296 hash = hash * 33 + *s++;
298 entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
299 for (; entry; entry = entry->hent_next) {
300 if (entry->hent_hash != hash) /* strings can't be equal */
302 if (entry->hent_klen != klen)
304 if (bcmp(entry->hent_key,key,klen)) /* is this it? */
315 register XPVHV* xhv = (XPVHV*)SvANY(hv);
316 I32 oldsize = (I32) xhv->xhv_max + 1; /* sic(k) */
317 register I32 newsize = oldsize * 2;
322 register HE **oentry;
325 a = (HE**)xhv->xhv_array;
327 #ifdef STRANGE_MALLOC
328 Renew(a, newsize, HE*);
330 i = newsize * sizeof(HE*);
331 #define MALLOC_OVERHEAD 16
332 tmp = MALLOC_OVERHEAD;
333 while (tmp - MALLOC_OVERHEAD < i)
335 tmp -= MALLOC_OVERHEAD;
337 assert(tmp >= newsize);
339 Copy(xhv->xhv_array, a, oldsize, HE*);
340 if (oldsize >= 64 && *(char*)&xhv->xnv_nv == 0) {
341 sv_add_arena((char*)xhv->xhv_array, oldsize * sizeof(HE*), 0);
342 sv_add_arena(((char*)a) + newsize * sizeof(HE*),
343 newsize * sizeof(HE*) - MALLOC_OVERHEAD,
347 Safefree(xhv->xhv_array);
351 Zero(&a[oldsize], oldsize, HE*); /* zero 2nd half*/
352 xhv->xhv_max = --newsize;
353 xhv->xhv_array = (char*)a;
355 for (i=0; i<oldsize; i++,a++) {
356 if (!*a) /* non-existent */
359 for (oentry = a, entry = *a; entry; entry = *oentry) {
360 if ((entry->hent_hash & newsize) != i) {
361 *oentry = entry->hent_next;
362 entry->hent_next = *b;
369 oentry = &entry->hent_next;
371 if (!*a) /* everything moved */
382 hv = (HV*)NEWSV(502,0);
383 sv_upgrade((SV *)hv, SVt_PVHV);
384 xhv = (XPVHV*)SvANY(hv);
387 xhv->xhv_max = 7; /* start with 8 buckets */
390 *(char*)&xhv->xnv_nv = 0;
391 (void)hv_iterinit(hv); /* so each() will start off right */
401 SvREFCNT_dec(hent->hent_val);
402 Safefree(hent->hent_key);
412 sv_2mortal(hent->hent_val); /* free between statements */
413 Safefree(hent->hent_key);
424 xhv = (XPVHV*)SvANY(hv);
429 (void)memzero(xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*));
441 register HE *ohent = Null(HE*);
457 hent = hent->hent_next;
466 (void)hv_iterinit(hv);
476 xhv = (XPVHV*)SvANY(hv);
478 #ifdef STRANGE_MALLOC
479 Safefree(xhv->xhv_array);
481 if (xhv->xhv_max < 127 || *(char*)&xhv->xnv_nv)
482 Safefree(xhv->xhv_array);
483 else /* We used last half, so use first half for SV arena too. */
484 sv_add_arena((char*)xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*),0);
487 Safefree(HvNAME(hv));
491 xhv->xhv_max = 7; /* it's a normal associative array */
494 *(char*)&xhv->xnv_nv = 1;
504 register XPVHV* xhv = (XPVHV*)SvANY(hv);
505 HE *entry = xhv->xhv_eiter;
506 if (entry && entry->hent_klen < 0) /* was deleted earlier? */
509 xhv->xhv_eiter = Null(HE*);
510 return xhv->xhv_fill;
523 croak("Bad associative array");
524 xhv = (XPVHV*)SvANY(hv);
525 oldentry = entry = xhv->xhv_eiter;
527 if (SvRMAGICAL(hv) && (mg = mg_find((SV*)hv,'P'))) {
528 SV *key = sv_newmortal();
530 sv_usepvn(key, entry->hent_key, entry->hent_klen);
534 xhv->xhv_eiter = entry = new_he();
537 magic_nextpack((SV*) hv,mg,key);
540 entry->hent_key = SvPV_force(key, len);
541 entry->hent_klen = len;
547 SvREFCNT_dec(entry->hent_val);
549 xhv->xhv_eiter = Null(HE*);
554 Newz(506,xhv->xhv_array, sizeof(HE*) * (xhv->xhv_max + 1), char);
557 entry = entry->hent_next;
560 if (xhv->xhv_riter > xhv->xhv_max) {
564 entry = ((HE**)xhv->xhv_array)[xhv->xhv_riter];
568 if (oldentry && oldentry->hent_klen < 0) /* was deleted earlier? */
571 xhv->xhv_eiter = entry;
576 hv_iterkey(entry,retlen)
580 *retlen = entry->hent_klen;
581 return entry->hent_key;
589 if (SvRMAGICAL(hv)) {
590 if (mg_find((SV*)hv,'P')) {
591 SV* sv = sv_newmortal();
592 mg_copy((SV*)hv, sv, entry->hent_key, entry->hent_klen);
596 return entry->hent_val;
600 hv_iternextsv(hv, key, retlen)
606 if ( (he = hv_iternext(hv)) == NULL)
608 *key = hv_iterkey(he, retlen);
609 return hv_iterval(hv, he);
613 hv_magic(hv, gv, how)
618 sv_magic((SV*)hv, (SV*)gv, how, Nullch, 0);