-SV *
-Perl_hv_delete(pTHX_ HV *hv, const char *key, I32 klen, I32 flags)
-{
- register XPVHV* xhv;
- register I32 i;
- register U32 hash;
- register HE *entry;
- register HE **oentry;
- SV **svp;
- SV *sv;
- bool is_utf8 = FALSE;
- const char *keysave = key;
-
- if (!hv)
- return Nullsv;
- if (klen < 0) {
- klen = -klen;
- is_utf8 = TRUE;
- }
- if (SvRMAGICAL(hv)) {
- bool needs_copy;
- bool needs_store;
- hv_magic_check (hv, &needs_copy, &needs_store);
-
- if (needs_copy && (svp = hv_fetch(hv, key, klen, TRUE))) {
- sv = *svp;
- mg_clear(sv);
- if (!needs_store) {
- if (mg_find(sv, PERL_MAGIC_tiedelem)) {
- /* No longer an element */
- sv_unmagic(sv, PERL_MAGIC_tiedelem);
- return sv;
- }
- return Nullsv; /* element cannot be deleted */
- }
-#ifdef ENV_IS_CASELESS
- else if (mg_find((SV*)hv, PERL_MAGIC_env)) {
- sv = sv_2mortal(newSVpvn(key,klen));
- key = strupr(SvPVX(sv));
- }
-#endif
- }
- }
- xhv = (XPVHV*)SvANY(hv);
- if (!xhv->xhv_array /* !HvARRAY(hv) */)
- return Nullsv;
-
- if (is_utf8) {
- STRLEN tmplen = klen;
- /* See the note in hv_fetch(). --jhi */
- key = (char*)bytes_from_utf8((U8*)key, &tmplen, &is_utf8);
- klen = tmplen;
- }
-
- PERL_HASH(hash, key, klen);
-
- /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */
- oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
- entry = *oentry;
- i = 1;
- for (; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) {
- if (HeHASH(entry) != hash) /* strings can't be equal */
- continue;
- if (HeKLEN(entry) != klen)
- continue;
- if (HeKEY(entry) != key && memNE(HeKEY(entry),key,klen)) /* is this it? */
- continue;
- if (HeKUTF8(entry) != (char)is_utf8)
- continue;
- if (key != keysave)
- Safefree(key);
- /* if placeholder is here, it's already been deleted.... */
- if (HeVAL(entry) == &PL_sv_undef)
- {
- if (SvREADONLY(hv))
- return Nullsv; /* if still SvREADONLY, leave it deleted. */
- else {
- /* okay, really delete the placeholder... */
- *oentry = HeNEXT(entry);
- if (i && !*oentry)
- xhv->xhv_fill--; /* HvFILL(hv)-- */
- if (entry == xhv->xhv_eiter /* HvEITER(hv) */)
- HvLAZYDEL_on(hv);
- else
- hv_free_ent(hv, entry);
- xhv->xhv_keys--; /* HvKEYS(hv)-- */
- xhv->xhv_placeholders--;
- return Nullsv;
- }
- }
- else if (SvREADONLY(hv) && HeVAL(entry) && SvREADONLY(HeVAL(entry))) {
- Perl_hv_notallowed(aTHX_ is_utf8, key, klen, keysave);
- }
-
- if (flags & G_DISCARD)
- sv = Nullsv;
- else {
- sv = sv_2mortal(HeVAL(entry));
- HeVAL(entry) = &PL_sv_undef;
- }
-
- /*
- * If a restricted hash, rather than really deleting the entry, put
- * a placeholder there. This marks the key as being "approved", so
- * we can still access via not-really-existing key without raising
- * an error.
- */
- if (SvREADONLY(hv)) {
- HeVAL(entry) = &PL_sv_undef;
- /* We'll be saving this slot, so the number of allocated keys
- * doesn't go down, but the number placeholders goes up */
- xhv->xhv_placeholders++; /* HvPLACEHOLDERS(hv)++ */
- } else {
- *oentry = HeNEXT(entry);
- if (i && !*oentry)
- xhv->xhv_fill--; /* HvFILL(hv)-- */
- if (entry == xhv->xhv_eiter /* HvEITER(hv) */)
- HvLAZYDEL_on(hv);
- else
- hv_free_ent(hv, entry);
- xhv->xhv_keys--; /* HvKEYS(hv)-- */
- }
- return sv;
- }
- if (SvREADONLY(hv)) {
- Perl_hv_notallowed(aTHX_ is_utf8, key, klen, keysave);
- }
-
- if (key != keysave)
- Safefree(key);
- return Nullsv;
-}
-
-/*
-=for apidoc 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
-precomputed hash value, or 0 to ask for it to be computed.
-
-=cut
-*/
-
-SV *
-Perl_hv_delete_ent(pTHX_ HV *hv, SV *keysv, I32 flags, U32 hash)
-{
- register XPVHV* xhv;
- register I32 i;
- register char *key;
- STRLEN klen;
- register HE *entry;
- register HE **oentry;
- SV *sv;
- bool is_utf8;
- char *keysave;
-
- if (!hv)
- return Nullsv;
- if (SvRMAGICAL(hv)) {
- bool needs_copy;
- bool needs_store;
- hv_magic_check (hv, &needs_copy, &needs_store);
-
- if (needs_copy && (entry = hv_fetch_ent(hv, keysv, TRUE, hash))) {
- sv = HeVAL(entry);
- mg_clear(sv);
- if (!needs_store) {
- if (mg_find(sv, PERL_MAGIC_tiedelem)) {
- /* No longer an element */
- sv_unmagic(sv, PERL_MAGIC_tiedelem);
- return sv;
- }
- return Nullsv; /* element cannot be deleted */
- }
-#ifdef ENV_IS_CASELESS
- else if (mg_find((SV*)hv, PERL_MAGIC_env)) {
- key = SvPV(keysv, klen);
- keysv = sv_2mortal(newSVpvn(key,klen));
- (void)strupr(SvPVX(keysv));
- hash = 0;
- }
-#endif
- }
- }
- xhv = (XPVHV*)SvANY(hv);
- if (!xhv->xhv_array /* !HvARRAY(hv) */)
- return Nullsv;
-
- keysave = key = SvPV(keysv, klen);
- is_utf8 = (SvUTF8(keysv) != 0);
-
- if (is_utf8)
- key = (char*)bytes_from_utf8((U8*)key, &klen, &is_utf8);
-
- if (!hash)
- PERL_HASH(hash, key, klen);
-
- /* oentry = &(HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */
- oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
- entry = *oentry;
- i = 1;
- for (; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) {
- if (HeHASH(entry) != hash) /* strings can't be equal */
- continue;
- if (HeKLEN(entry) != klen)
- continue;
- if (HeKEY(entry) != key && memNE(HeKEY(entry),key,klen)) /* is this it? */
- continue;
- if (HeKUTF8(entry) != (char)is_utf8)
- continue;
- if (key != keysave)
- Safefree(key);
-
- /* if placeholder is here, it's already been deleted.... */
- if (HeVAL(entry) == &PL_sv_undef)
- {
- if (SvREADONLY(hv))
- return Nullsv; /* if still SvREADONLY, leave it deleted. */
- else {
- // okay, really delete the placeholder.
- *oentry = HeNEXT(entry);
- if (i && !*oentry)
- xhv->xhv_fill--; /* HvFILL(hv)-- */
- if (entry == xhv->xhv_eiter /* HvEITER(hv) */)
- HvLAZYDEL_on(hv);
- else
- hv_free_ent(hv, entry);
- xhv->xhv_keys--; /* HvKEYS(hv)-- */
- xhv->xhv_placeholders--;
- return Nullsv;
- }
- }
- else if (SvREADONLY(hv) && HeVAL(entry) && SvREADONLY(HeVAL(entry))) {
- Perl_hv_notallowed(aTHX_ is_utf8, key, klen, keysave);
- }
-
- if (flags & G_DISCARD)
- sv = Nullsv;
- else {
- sv = sv_2mortal(HeVAL(entry));
- HeVAL(entry) = &PL_sv_undef;
- }
-
- /*
- * If a restricted hash, rather than really deleting the entry, put
- * a placeholder there. This marks the key as being "approved", so
- * we can still access via not-really-existing key without raising
- * an error.
- */
- if (SvREADONLY(hv)) {
- HeVAL(entry) = &PL_sv_undef;
- /* We'll be saving this slot, so the number of allocated keys
- * doesn't go down, but the number placeholders goes up */
- xhv->xhv_placeholders++; /* HvPLACEHOLDERS(hv)++ */
- } else {
- *oentry = HeNEXT(entry);
- if (i && !*oentry)
- xhv->xhv_fill--; /* HvFILL(hv)-- */
- if (entry == xhv->xhv_eiter /* HvEITER(hv) */)
- HvLAZYDEL_on(hv);
- else
- hv_free_ent(hv, entry);
- xhv->xhv_keys--; /* HvKEYS(hv)-- */
- }
- return sv;
- }
- if (SvREADONLY(hv)) {
- Perl_hv_notallowed(aTHX_ is_utf8, key, klen, keysave);
- }
-
- if (key != keysave)
- Safefree(key);
- return Nullsv;
-}
-
-/*
-=for apidoc hv_exists
-
-Returns a boolean indicating whether the specified hash key exists. The
-C<klen> is the length of the key.
-
-=cut
-*/
-
-bool
-Perl_hv_exists(pTHX_ HV *hv, const char *key, I32 klen)
-{
- register XPVHV* xhv;
- register U32 hash;
- register HE *entry;
- SV *sv;
- bool is_utf8 = FALSE;
- const char *keysave = key;
-
- if (!hv)
- return 0;
-
- if (klen < 0) {
- klen = -klen;
- is_utf8 = TRUE;
- }
-
- if (SvRMAGICAL(hv)) {
- if (mg_find((SV*)hv, PERL_MAGIC_tied) || SvGMAGICAL((SV*)hv)) {
- sv = sv_newmortal();
- mg_copy((SV*)hv, sv, key, klen);
- magic_existspack(sv, mg_find(sv, PERL_MAGIC_tiedelem));
- return SvTRUE(sv);
- }
-#ifdef ENV_IS_CASELESS
- else if (mg_find((SV*)hv, PERL_MAGIC_env)) {
- sv = sv_2mortal(newSVpvn(key,klen));
- key = strupr(SvPVX(sv));
- }
-#endif
- }
-
- xhv = (XPVHV*)SvANY(hv);
-#ifndef DYNAMIC_ENV_FETCH
- if (!xhv->xhv_array /* !HvARRAY(hv) */)
- return 0;
-#endif
-
- if (is_utf8) {
- STRLEN tmplen = klen;
- /* See the note in hv_fetch(). --jhi */
- key = (char*)bytes_from_utf8((U8*)key, &tmplen, &is_utf8);
- klen = tmplen;
- }
-
- PERL_HASH(hash, key, klen);
-
-#ifdef DYNAMIC_ENV_FETCH
- if (!xhv->xhv_array /* !HvARRAY(hv) */) entry = Null(HE*);
- else
-#endif
- /* entry = (HvARRAY(hv))[hash & (I32) HvMAX(hv)]; */
- entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
- for (; entry; entry = HeNEXT(entry)) {
- if (HeHASH(entry) != hash) /* strings can't be equal */
- continue;
- if (HeKLEN(entry) != klen)
- continue;
- if (HeKEY(entry) != key && memNE(HeKEY(entry),key,klen)) /* is this it? */
- continue;
- if (HeKUTF8(entry) != (char)is_utf8)
- continue;
- if (key != keysave)
- Safefree(key);
- /* If we find the key, but the value is a placeholder, return false. */
- if (HeVAL(entry) == &PL_sv_undef)
- return FALSE;
-
- return TRUE;
- }
-#ifdef DYNAMIC_ENV_FETCH /* is it out there? */
- if (SvRMAGICAL((SV*)hv) && mg_find((SV*)hv, PERL_MAGIC_env)) {
- unsigned long len;
- char *env = PerlEnv_ENVgetenv_len(key,&len);
- if (env) {
- sv = newSVpvn(env,len);
- SvTAINTED_on(sv);
- (void)hv_store(hv,key,klen,sv,hash);
- return TRUE;
- }