#include #include #include #include namespace xs { Glob Glob::create (const Stash& stash, panda::string_view name, U32 flags) { GV* gv = (GV*)newSV(0); flags |= GV_ADDMULTI; // suppress 'used only once' warning gv_init_pvn(gv, stash, name.data(), name.length(), flags); return gv; } Stash Glob::stash () const { return GvSTASH((GV*)sv); } Stash Glob::effective_stash () const { return GvESTASH((GV*)sv); } static inline void _set_slot (SV** where, SV* what) { auto old = *where; *where = what; SvREFCNT_inc_simple_void(what); SvREFCNT_dec(old); } static inline void _set_slot (GV* where, CV* what) { auto old = GvCV(where); GvCV_set(where, what); SvREFCNT_inc_simple_void(what); SvREFCNT_dec(old); } void Glob::slot (SV* val) { GV* gv = (GV*)sv; if (!val || SvTYPE(val) <= SVt_PVMG) _set_slot(&GvSV(gv), val); else switch (SvTYPE(val)) { case SVt_PVCV: _set_slot(gv, (CV*)val); break; case SVt_PVHV: _set_slot((SV**)&GvHV(gv), val); break; case SVt_PVAV: _set_slot((SV**)&GvAV(gv), val); break; case SVt_PVIO: _set_slot((SV**)&GvIOp(gv), val); break; default: throw std::invalid_argument("can set unsupported type to a typeglob"); } } void Glob::slot (AV* val) { _set_slot((SV**)&GvAV((GV*)sv), (SV*)val); } void Glob::slot (HV* val) { _set_slot((SV**)&GvHV((GV*)sv), (SV*)val); } void Glob::slot (CV* val) { _set_slot((GV*)sv, val); } void Glob::slot (IO* val) { _set_slot((SV**)&GvIOp((GV*)sv), (SV*)val); } void Glob::slot (const Scalar& val) { _set_slot(&GvSV((GV*)sv), val); } }