Patch applied; ish.
I didn't quite like aliasing the AvARRAY with a three-SV* struct so instead I typedefed it as an SV** and made an enum for the first three indices.
--
Paul Evans
=== modified file 'lib/Sentinel.xs'
--- lib/Sentinel.xs 2012-05-30 13:18:36 +0000
+++ lib/Sentinel.xs 2019-01-14 20:37:17 +0000
@@ -11,32 +11,35 @@
#include <string.h>
#define streq(a,b) (strcmp((a),(b)) == 0)
-typedef struct {
- SV *get_cb;
- SV *set_cb;
-} sentinel_ctx;
+enum {
+ CTX_GET_CB,
+ CTX_SET_CB,
+ CTX_OBJ,
+};
+
+typedef SV *sentinel_ctx;
static int magic_get(pTHX_ SV *sv, MAGIC *mg)
{
dSP;
- sentinel_ctx *ctx = (void *)mg->mg_ptr;
+ sentinel_ctx *ctx = (sentinel_ctx*)AvARRAY(mg->mg_obj);
- if(ctx->get_cb) {
+ if(ctx[CTX_GET_CB]) {
int count;
ENTER;
SAVETMPS;
PUSHMARK(SP);
- if(mg->mg_obj)
- PUSHs(mg->mg_obj);
+ if(ctx[CTX_OBJ])
+ PUSHs(ctx[CTX_OBJ]);
PUTBACK;
- if(mg->mg_obj && SvPOK(ctx->get_cb))
+ if(ctx[CTX_OBJ] && SvPOK(ctx[CTX_GET_CB]))
// Calling method by name
- count = call_method(SvPV_nolen(ctx->get_cb), G_SCALAR);
+ count = call_method(SvPV_nolen(ctx[CTX_GET_CB]), G_SCALAR);
else
- count = call_sv(ctx->get_cb, G_SCALAR);
+ count = call_sv(ctx[CTX_GET_CB], G_SCALAR);
assert(count == 1);
SPAGAIN;
@@ -53,23 +56,23 @@
static int magic_set(pTHX_ SV *sv, MAGIC *mg)
{
dSP;
- sentinel_ctx *ctx = (void *)mg->mg_ptr;
+ sentinel_ctx *ctx = (sentinel_ctx*)AvARRAY(mg->mg_obj);
- if(ctx->set_cb) {
+ if(ctx[CTX_SET_CB]) {
ENTER;
SAVETMPS;
PUSHMARK(SP);
- if(mg->mg_obj)
- PUSHs(mg->mg_obj);
+ if(ctx[CTX_OBJ])
+ PUSHs(ctx[CTX_OBJ]);
PUSHs(sv);
PUTBACK;
- if(mg->mg_obj && SvPOK(ctx->set_cb))
+ if(ctx[CTX_OBJ] && SvPOK(ctx[CTX_SET_CB]))
// Calling method by name
- call_method(SvPV_nolen(ctx->set_cb), G_VOID);
+ call_method(SvPV_nolen(ctx[CTX_SET_CB]), G_VOID);
else
- call_sv(ctx->set_cb, G_VOID);
+ call_sv(ctx[CTX_SET_CB], G_VOID);
SPAGAIN;
@@ -80,26 +83,9 @@
return 1;
}
-static int magic_free(pTHX_ SV *sv, MAGIC *mg)
-{
- sentinel_ctx *ctx = (void *)mg->mg_ptr;
-
- if(ctx->get_cb)
- SvREFCNT_dec(ctx->get_cb);
- if(ctx->set_cb)
- SvREFCNT_dec(ctx->set_cb);
-
- Safefree(ctx);
-
- return 1;
-}
-
static MGVTBL vtbl = {
&magic_get,
&magic_set,
- NULL, /* len */
- NULL, /* clear */
- &magic_free,
};
MODULE = Sentinel PACKAGE = Sentinel
@@ -137,8 +123,7 @@
}
}
- retval = newSV(0);
- sv_2mortal(retval);
+ retval = sv_newmortal();
/**
* Perl 5.14 allows any TEMP scalar to be returned in LVALUE context provided
* it is magical. Perl versions before this only accept magic for being a tied
@@ -155,15 +140,18 @@
if(get_cb || set_cb) {
sentinel_ctx *ctx;
- Newx(ctx, 1, sentinel_ctx);
-
- ctx->get_cb = newSVsv(get_cb);
- ctx->set_cb = newSVsv(set_cb);
-
- if(obj)
- obj = sv_mortalcopy(obj);
-
- sv_magicext(retval, obj, PERL_MAGIC_ext, &vtbl, (char *)ctx, 0);
+ AV* payload = newAV();
+ av_extend(payload, 2);
+ AvFILLp(payload) = 2;
+
+ ctx = (sentinel_ctx*)AvARRAY(payload);
+
+ ctx[CTX_GET_CB] = get_cb ? newSVsv(get_cb) : NULL;
+ ctx[CTX_SET_CB] = set_cb ? newSVsv(set_cb) : NULL;
+ ctx[CTX_OBJ] = obj ? newSVsv(obj) : NULL;
+
+ sv_magicext(retval, (SV*)payload, PERL_MAGIC_ext, &vtbl, NULL, 0);
+ SvREFCNT_dec(payload);
}
PUSHs(retval);