Data-Buffer-Shared
view release on metacpan or search on metacpan
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "buf_i8.h"
#include "buf_u8.h"
#include "buf_i16.h"
#include "buf_u16.h"
#include "buf_i32.h"
#include "buf_u32.h"
#include "buf_i64.h"
#include "buf_u64.h"
#include "buf_f32.h"
#include "buf_f64.h"
#include "buf_str.h"
#include "XSParseKeyword.h"
/* ---- as_scalar magic: prevent use-after-free by preventing buffer DESTROY
* while the returned scalar ref is alive. We attach magic to the inner SV
* that holds a reference to the buffer object. When the inner SV is freed,
* the magic destructor releases the reference. ---- */
static int buf_scalar_magic_free(pTHX_ SV *sv, MAGIC *mg) {
PERL_UNUSED_ARG(sv);
if (mg->mg_obj) SvREFCNT_dec(mg->mg_obj);
return 0;
}
static const MGVTBL buf_scalar_magic_vtbl = {
NULL, NULL, NULL, NULL, buf_scalar_magic_free, NULL, NULL, NULL
};
/* ---- Helper macros ---- */
#define EXTRACT_BUF(classname, sv) \
if (!sv_isobject(sv) || !sv_derived_from(sv, classname)) \
croak("Expected a %s object", classname); \
BufHandle* h = INT2PTR(BufHandle*, SvIV(SvRV(sv))); \
if (!h) croak("Attempted to use a destroyed %s object", classname)
/* ---- Generic keyword build functions ---- */
static int build_kw_1arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
(void)nargs;
const char *func = (const char *)hookdata;
OP *map_op = args[0]->op;
OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
OP *arglist = op_append_elem(OP_LIST, map_op, cvref);
*out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
return KEYWORD_PLUGIN_EXPR;
}
static int build_kw_2arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
(void)nargs;
const char *func = (const char *)hookdata;
OP *map_op = args[0]->op;
OP *key_op = args[1]->op;
OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
OP *arglist = op_append_elem(OP_LIST, map_op, key_op);
arglist = op_append_elem(OP_LIST, arglist, cvref);
*out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
return KEYWORD_PLUGIN_EXPR;
}
static int build_kw_3arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
(void)nargs;
const char *func = (const char *)hookdata;
OP *map_op = args[0]->op;
OP *key_op = args[1]->op;
OP *val_op = args[2]->op;
OP *cvref = newCVREF(0, newGVOP(OP_GV, 0, gv_fetchpv(func, GV_ADD, SVt_PVCV)));
OP *arglist = op_append_elem(OP_LIST, map_op, key_op);
arglist = op_append_elem(OP_LIST, arglist, val_op);
arglist = op_append_elem(OP_LIST, arglist, cvref);
*out = op_convert_list(OP_ENTERSUB, OPf_STACKED, arglist);
return KEYWORD_PLUGIN_EXPR;
}
static int build_kw_4arg(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata) {
( run in 3.235 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )