if (key <= AvFILLp(av) && AvARRAY(av)[key])
{
+ if (SvSMAGICAL(AvARRAY(av)[key])
+ && mg_find(AvARRAY(av)[key], PERL_MAGIC_nonelem))
+ return FALSE;
return TRUE;
}
else
}
}
+SV *
+Perl_av_nonelem(pTHX_ AV *av, SSize_t ix) {
+ SV * const sv = newSV(0);
+ PERL_ARGS_ASSERT_AV_NONELEM;
+ if (!av_store(av,ix,sv))
+ return sv_2mortal(sv); /* has tie magic */
+ sv_magic(sv, NULL, PERL_MAGIC_nonelem, NULL, 0);
+ return sv;
+}
+
/*
* ex: set ts=8 sts=4 sw=4 et:
*/
Apd |void |av_fill |NN AV *av|SSize_t fill
ApdR |SSize_t|av_len |NN AV *av
ApdR |AV* |av_make |SSize_t size|NN SV **strp
+p |SV* |av_nonelem |NN AV *av|SSize_t ix
Apd |SV* |av_pop |NN AV *av
ApdoxM |void |av_create_and_push|NN AV **const avp|NN SV *const val
Apd |void |av_push |NN AV *av|NN SV *val
p |int |magic_setdbline|NN SV* sv|NN MAGIC* mg
p |int |magic_setdebugvar|NN SV* sv|NN MAGIC* mg
p |int |magic_setdefelem|NN SV* sv|NN MAGIC* mg
+p |int |magic_setnonelem|NN SV* sv|NN MAGIC* mg
p |int |magic_setenv |NN SV* sv|NN MAGIC* mg
dp |int |magic_sethint |NN SV* sv|NN MAGIC* mg
p |int |magic_setisa |NN SV* sv|NN MAGIC* mg
#define amagic_is_enabled(a) Perl_amagic_is_enabled(aTHX_ a)
#define apply(a,b,c) Perl_apply(aTHX_ a,b,c)
#define av_extend_guts(a,b,c,d,e) Perl_av_extend_guts(aTHX_ a,b,c,d,e)
+#define av_nonelem(a,b) Perl_av_nonelem(aTHX_ a,b)
#define bind_match(a,b,c) Perl_bind_match(aTHX_ a,b,c)
#define boot_core_PerlIO() Perl_boot_core_PerlIO(aTHX)
#define boot_core_UNIVERSAL() Perl_boot_core_UNIVERSAL(aTHX)
#define magic_setlvref(a,b) Perl_magic_setlvref(aTHX_ a,b)
#define magic_setmglob(a,b) Perl_magic_setmglob(aTHX_ a,b)
#define magic_setnkeys(a,b) Perl_magic_setnkeys(aTHX_ a,b)
+#define magic_setnonelem(a,b) Perl_magic_setnonelem(aTHX_ a,b)
#define magic_setpack(a,b) Perl_magic_setpack(aTHX_ a,b)
#define magic_setpos(a,b) Perl_magic_setpos(aTHX_ a,b)
#define magic_setregexp(a,b) Perl_magic_setregexp(aTHX_ a,b)
}
int
+Perl_magic_setnonelem(pTHX_ SV *sv, MAGIC *mg)
+{
+ PERL_ARGS_ASSERT_MAGIC_SETNONELEM;
+ PERL_UNUSED_ARG(mg);
+ sv_unmagic(sv, PERL_MAGIC_nonelem);
+ return 0;
+}
+
+int
Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
{
PERL_ARGS_ASSERT_MAGIC_KILLBACKREFS;
{ PERL_MAGIC_vec, "vec(v)" },
{ PERL_MAGIC_utf8, "utf8(w)" },
{ PERL_MAGIC_substr, "substr(x)" },
+ { PERL_MAGIC_nonelem, "nonelem(Y)" },
{ PERL_MAGIC_defelem, "defelem(y)" },
{ PERL_MAGIC_lvref, "lvref(\\)" },
{ PERL_MAGIC_checkcall, "checkcall(])" },
"/* utf8 'w' Cached UTF-8 information */" },
{ 'x', "want_vtbl_substr | PERL_MAGIC_VALUE_MAGIC",
"/* substr 'x' substr() lvalue */" },
+ { 'Y', "want_vtbl_nonelem | PERL_MAGIC_VALUE_MAGIC",
+ "/* nonelem 'Y' Array element that does not exist */" },
{ 'y', "want_vtbl_defelem | PERL_MAGIC_VALUE_MAGIC",
"/* defelem 'y' Shadow \"foreach\" iterator variable / smart parameter vivification */" },
{ '\\', "want_vtbl_lvref",
#define PERL_MAGIC_vec 'v' /* vec() lvalue */
#define PERL_MAGIC_utf8 'w' /* Cached UTF-8 information */
#define PERL_MAGIC_substr 'x' /* substr() lvalue */
+#define PERL_MAGIC_nonelem 'Y' /* Array element that does not exist */
#define PERL_MAGIC_defelem 'y' /* Shadow "foreach" iterator variable /
smart parameter vivification */
#define PERL_MAGIC_lvref '\\' /* Lvalue reference constructor */
want_vtbl_lvref,
want_vtbl_mglob,
want_vtbl_nkeys,
+ want_vtbl_nonelem,
want_vtbl_ovrld,
want_vtbl_pack,
want_vtbl_packelem,
"lvref",
"mglob",
"nkeys",
+ "nonelem",
"ovrld",
"pack",
"packelem",
{ 0, Perl_magic_setlvref, 0, 0, 0, 0, 0, 0 },
{ 0, Perl_magic_setmglob, 0, 0, 0, 0, 0, 0 },
{ Perl_magic_getnkeys, Perl_magic_setnkeys, 0, 0, 0, 0, 0, 0 },
+ { 0, Perl_magic_setnonelem, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, Perl_magic_freeovrld, 0, 0, 0 },
{ 0, 0, Perl_magic_sizepack, Perl_magic_wipepack, 0, 0, 0, 0 },
{ Perl_magic_getpack, Perl_magic_setpack, 0, Perl_magic_clearpack, 0, 0, 0, 0 },
#define PL_vtbl_lvref PL_magic_vtables[want_vtbl_lvref]
#define PL_vtbl_mglob PL_magic_vtables[want_vtbl_mglob]
#define PL_vtbl_nkeys PL_magic_vtables[want_vtbl_nkeys]
+#define PL_vtbl_nonelem PL_magic_vtables[want_vtbl_nonelem]
#define PL_vtbl_ovrld PL_magic_vtables[want_vtbl_ovrld]
#define PL_vtbl_pack PL_magic_vtables[want_vtbl_pack]
#define PL_vtbl_packelem PL_magic_vtables[want_vtbl_packelem]
v PERL_MAGIC_vec vtbl_vec vec() lvalue
w PERL_MAGIC_utf8 vtbl_utf8 Cached UTF-8 information
x PERL_MAGIC_substr vtbl_substr substr() lvalue
+ Y PERL_MAGIC_nonelem vtbl_nonelem Array element that does not
+ exist
y PERL_MAGIC_defelem vtbl_defelem Shadow "foreach" iterator
variable / smart parameter
vivification
else if (SvPADTMP(sv)) {
sv = newSVsv(sv);
}
+ else if (UNLIKELY(SvSMAGICAL(sv) && mg_find(sv, PERL_MAGIC_nonelem)))
+ sv_unmagic(SvREFCNT_inc_simple_NN(sv), PERL_MAGIC_nonelem);
else {
SvTEMP_off(sv);
SvREFCNT_inc_void_NN(sv);
SP[i+1] = LIKELY(svp)
? *svp
: UNLIKELY(PL_op->op_flags & OPf_MOD)
- ? newSVavdefelem(av,i,1)
+ ? av_nonelem(av,i)
: &PL_sv_undef;
}
}
SP[i+1] = LIKELY(sv)
? sv
: UNLIKELY(PL_op->op_flags & OPf_MOD)
- ? newSVavdefelem(av,i,1)
+ ? av_nonelem(av,i)
: &PL_sv_undef;
}
}
#define PERL_ARGS_ASSERT_AV_MAKE \
assert(strp)
+PERL_CALLCONV SV* Perl_av_nonelem(pTHX_ AV *av, SSize_t ix);
+#define PERL_ARGS_ASSERT_AV_NONELEM \
+ assert(av)
PERL_CALLCONV SV* Perl_av_pop(pTHX_ AV *av);
#define PERL_ARGS_ASSERT_AV_POP \
assert(av)
PERL_CALLCONV int Perl_magic_setnkeys(pTHX_ SV* sv, MAGIC* mg);
#define PERL_ARGS_ASSERT_MAGIC_SETNKEYS \
assert(sv); assert(mg)
+PERL_CALLCONV int Perl_magic_setnonelem(pTHX_ SV* sv, MAGIC* mg);
+#define PERL_ARGS_ASSERT_MAGIC_SETNONELEM \
+ assert(sv); assert(mg)
PERL_CALLCONV int Perl_magic_setpack(pTHX_ SV* sv, MAGIC* mg);
#define PERL_ARGS_ASSERT_MAGIC_SETPACK \
assert(sv); assert(mg)
desc => 'substr() lvalue' },
defelem => { char => 'y', vtable => 'defelem', value_magic => 1,
desc => "Shadow \"foreach\" iterator variable /\nsmart parameter vivification" },
+ nonelem => { char => 'Y', vtable => 'nonelem', value_magic => 1,
+ desc => "Array element that does not exist" },
arylen => { char => '#', vtable => 'arylen', value_magic => 1,
desc => 'Array length ($#ary)' },
pos => { char => '.', vtable => 'pos', value_magic => 1,
'pos' => {get => 'getpos', set => 'setpos'},
'uvar' => {get => 'getuvar', set => 'setuvar'},
'defelem' => {get => 'getdefelem', set => 'setdefelem'},
+ 'nonelem' => {set => 'setnonelem'},
'regexp' => {set => 'setregexp', alias => [qw(bm fm)]},
'regdata' => {len => 'regdata_cnt'},
'regdatum' => {get => 'regdatum_get', set => 'regdatum_set'},