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;
323 #ifndef STRANGE_MALLOC
327 a = (HE**)xhv->xhv_array;
329 #ifdef STRANGE_MALLOC
330 Renew(a, newsize, HE*);
332 i = newsize * sizeof(HE*);
333 #define MALLOC_OVERHEAD 16
334 tmp = MALLOC_OVERHEAD;
335 while (tmp - MALLOC_OVERHEAD < i)
337 tmp -= MALLOC_OVERHEAD;
339 assert(tmp >= newsize);
341 Copy(xhv->xhv_array, a, oldsize, HE*);
342 if (oldsize >= 64 && !nice_chunk) {
343 nice_chunk = (char*)xhv->xhv_array;
344 nice_chunk_size = oldsize * sizeof(HE*) * 2 - 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 (void)hv_iterinit(hv); /* so each() will start off right */
400 SvREFCNT_dec(hent->hent_val);
401 Safefree(hent->hent_key);
411 sv_2mortal(hent->hent_val); /* free between statements */
412 Safefree(hent->hent_key);
423 xhv = (XPVHV*)SvANY(hv);
428 (void)memzero(xhv->xhv_array, (xhv->xhv_max + 1) * sizeof(HE*));
440 register HE *ohent = Null(HE*);
456 hent = hent->hent_next;
465 (void)hv_iterinit(hv);
475 xhv = (XPVHV*)SvANY(hv);
477 Safefree(xhv->xhv_array);
479 Safefree(HvNAME(hv));
483 xhv->xhv_max = 7; /* it's a normal associative array */
495 register XPVHV* xhv = (XPVHV*)SvANY(hv);
496 HE *entry = xhv->xhv_eiter;
497 if (entry && entry->hent_klen < 0) /* was deleted earlier? */
500 xhv->xhv_eiter = Null(HE*);
501 return xhv->xhv_fill;
514 croak("Bad associative array");
515 xhv = (XPVHV*)SvANY(hv);
516 oldentry = entry = xhv->xhv_eiter;
518 if (SvRMAGICAL(hv) && (mg = mg_find((SV*)hv,'P'))) {
519 SV *key = sv_newmortal();
521 sv_usepvn(key, entry->hent_key, entry->hent_klen);
525 xhv->xhv_eiter = entry = new_he();
528 magic_nextpack((SV*) hv,mg,key);
531 entry->hent_key = SvPV_force(key, len);
532 entry->hent_klen = len;
538 SvREFCNT_dec(entry->hent_val);
540 xhv->xhv_eiter = Null(HE*);
545 Newz(506,xhv->xhv_array, sizeof(HE*) * (xhv->xhv_max + 1), char);
548 entry = entry->hent_next;
551 if (xhv->xhv_riter > xhv->xhv_max) {
555 entry = ((HE**)xhv->xhv_array)[xhv->xhv_riter];
559 if (oldentry && oldentry->hent_klen < 0) /* was deleted earlier? */
562 xhv->xhv_eiter = entry;
567 hv_iterkey(entry,retlen)
571 *retlen = entry->hent_klen;
572 return entry->hent_key;
580 if (SvRMAGICAL(hv)) {
581 if (mg_find((SV*)hv,'P')) {
582 SV* sv = sv_newmortal();
583 mg_copy((SV*)hv, sv, entry->hent_key, entry->hent_klen);
587 return entry->hent_val;
591 hv_iternextsv(hv, key, retlen)
597 if ( (he = hv_iternext(hv)) == NULL)
599 *key = hv_iterkey(he, retlen);
600 return hv_iterval(hv, he);
604 hv_magic(hv, gv, how)
609 sv_magic((SV*)hv, (SV*)gv, how, Nullch, 0);