+
+/*
+=for apidoc av_delete
+
+Deletes the element indexed by C<key> from the array, makes the element mortal,
+and returns it. If C<flags> equals C<G_DISCARD>, the element is freed and null
+is returned. Perl equivalent: C<my $elem = delete($myarray[$idx]);> for the
+non-C<G_DISCARD> version and a void-context C<delete($myarray[$idx]);> for the
+C<G_DISCARD> version.
+
+=cut
+*/
+SV *
+Perl_av_delete(pTHX_ AV *av, I32 key, I32 flags)
+{
+ dVAR;
+ SV *sv;
+
+ PERL_ARGS_ASSERT_AV_DELETE;
+ assert(SvTYPE(av) == SVt_PVAV);
+
+ if (SvREADONLY(av))
+ Perl_croak_no_modify(aTHX);
+
+ if (SvRMAGICAL(av)) {
+ const MAGIC * const tied_magic
+ = mg_find((const SV *)av, PERL_MAGIC_tied);
+ if ((tied_magic || mg_find((const SV *)av, PERL_MAGIC_regdata))) {
+ /* Handle negative array indices 20020222 MJD */
+ SV **svp;
+ if (key < 0) {
+ unsigned adjust_index = 1;
+ if (tied_magic) {
+ SV * const * const negative_indices_glob =
+ hv_fetch(SvSTASH(SvRV(SvTIED_obj(MUTABLE_SV(av),
+ tied_magic))),
+ NEGATIVE_INDICES_VAR, 16, 0);
+ if (negative_indices_glob
+ && SvTRUE(GvSV(*negative_indices_glob)))
+ adjust_index = 0;
+ }
+ if (adjust_index) {
+ key += AvFILL(av) + 1;
+ if (key < 0)
+ return NULL;
+ }
+ }
+ svp = av_fetch(av, key, TRUE);
+ if (svp) {
+ sv = *svp;
+ mg_clear(sv);
+ if (mg_find(sv, PERL_MAGIC_tiedelem)) {
+ sv_unmagic(sv, PERL_MAGIC_tiedelem); /* No longer an element */
+ return sv;
+ }
+ return NULL;
+ }
+ }
+ }
+
+ if (key < 0) {
+ key += AvFILL(av) + 1;
+ if (key < 0)
+ return NULL;
+ }
+
+ if (key > AvFILLp(av))
+ return NULL;
+ else {
+ if (!AvREAL(av) && AvREIFY(av))
+ av_reify(av);
+ sv = AvARRAY(av)[key];
+ if (key == AvFILLp(av)) {
+ AvARRAY(av)[key] = &PL_sv_undef;
+ do {
+ AvFILLp(av)--;
+ } while (--key >= 0 && AvARRAY(av)[key] == &PL_sv_undef);
+ }
+ else
+ AvARRAY(av)[key] = &PL_sv_undef;
+ if (SvSMAGICAL(av))
+ mg_set(MUTABLE_SV(av));
+ }
+ if (flags & G_DISCARD) {
+ SvREFCNT_dec(sv);
+ sv = NULL;
+ }
+ else if (AvREAL(av))
+ sv = sv_2mortal(sv);
+ return sv;
+}
+
+/*
+=for apidoc av_exists
+
+Returns true if the element indexed by C<key> has been initialized.
+
+This relies on the fact that uninitialized array elements are set to
+C<&PL_sv_undef>.
+
+Perl equivalent: C<exists($myarray[$key])>.
+
+=cut
+*/
+bool
+Perl_av_exists(pTHX_ AV *av, I32 key)
+{
+ dVAR;
+ PERL_ARGS_ASSERT_AV_EXISTS;
+ assert(SvTYPE(av) == SVt_PVAV);
+
+ if (SvRMAGICAL(av)) {
+ const MAGIC * const tied_magic
+ = mg_find((const SV *)av, PERL_MAGIC_tied);
+ const MAGIC * const regdata_magic
+ = mg_find((const SV *)av, PERL_MAGIC_regdata);
+ if (tied_magic || regdata_magic) {
+ SV * const sv = sv_newmortal();
+ MAGIC *mg;
+ /* Handle negative array indices 20020222 MJD */
+ if (key < 0) {
+ unsigned adjust_index = 1;
+ if (tied_magic) {
+ SV * const * const negative_indices_glob =
+ hv_fetch(SvSTASH(SvRV(SvTIED_obj(MUTABLE_SV(av),
+ tied_magic))),
+ NEGATIVE_INDICES_VAR, 16, 0);
+ if (negative_indices_glob
+ && SvTRUE(GvSV(*negative_indices_glob)))
+ adjust_index = 0;
+ }
+ if (adjust_index) {
+ key += AvFILL(av) + 1;
+ if (key < 0)
+ return FALSE;
+ else
+ return TRUE;
+ }
+ }
+
+ if(key >= 0 && regdata_magic) {
+ if (key <= AvFILL(av))
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ mg_copy(MUTABLE_SV(av), sv, 0, key);
+ mg = mg_find(sv, PERL_MAGIC_tiedelem);
+ if (mg) {
+ magic_existspack(sv, mg);
+ return cBOOL(SvTRUE(sv));
+ }
+
+ }
+ }
+
+ if (key < 0) {
+ key += AvFILL(av) + 1;
+ if (key < 0)
+ return FALSE;
+ }
+
+ if (key <= AvFILLp(av) && AvARRAY(av)[key] != &PL_sv_undef
+ && AvARRAY(av)[key])
+ {
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static MAGIC *
+S_get_aux_mg(pTHX_ AV *av) {
+ dVAR;
+ MAGIC *mg;
+
+ PERL_ARGS_ASSERT_GET_AUX_MG;
+ assert(SvTYPE(av) == SVt_PVAV);
+
+ mg = mg_find((const SV *)av, PERL_MAGIC_arylen_p);
+
+ if (!mg) {
+ mg = sv_magicext(MUTABLE_SV(av), 0, PERL_MAGIC_arylen_p,
+ &PL_vtbl_arylen_p, 0, 0);
+ assert(mg);
+ /* sv_magicext won't set this for us because we pass in a NULL obj */
+ mg->mg_flags |= MGf_REFCOUNTED;
+ }
+ return mg;
+}
+
+SV **
+Perl_av_arylen_p(pTHX_ AV *av) {
+ MAGIC *const mg = get_aux_mg(av);
+
+ PERL_ARGS_ASSERT_AV_ARYLEN_P;
+ assert(SvTYPE(av) == SVt_PVAV);
+
+ return &(mg->mg_obj);
+}
+
+IV *
+Perl_av_iter_p(pTHX_ AV *av) {
+ MAGIC *const mg = get_aux_mg(av);
+
+ PERL_ARGS_ASSERT_AV_ITER_P;
+ assert(SvTYPE(av) == SVt_PVAV);
+
+#if IVSIZE == I32SIZE
+ return (IV *)&(mg->mg_len);
+#else
+ if (!mg->mg_ptr) {
+ IV *temp;
+ mg->mg_len = IVSIZE;
+ Newxz(temp, 1, IV);
+ mg->mg_ptr = (char *) temp;
+ }
+ return (IV *)mg->mg_ptr;
+#endif
+}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 noet:
+ */