view release on metacpan or search on metacpan
t/1018-trim-maybe.t view on Meta::CPAN
# maybe as safe accessor pattern
my $config = { timeout => 30 };
is(maybe($config->{timeout}, $config->{timeout} * 2), 60, 'maybe for safe math');
is(maybe($config->{missing}, 100), undef, 'maybe with missing key');
# trim + maybe combo use case
my $input = " user input ";
my $cleaned = trim($input);
is($cleaned, "user input", 'trim user input');
is(maybe($cleaned, uc($cleaned)), "USER INPUT", 'maybe transform cleaned input');
done_testing;
xs/const/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/const/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/doubly/doubly.c view on Meta::CPAN
current_node_id = node->node_id;
node_data = node->data ? newSVsv(node->data) : &PL_sv_undef;
DOUBLY_UNLOCK();
{
dSP;
PUSHMARK(SP);
XPUSHs(sv_2mortal(node_data));
PUTBACK;
call_sv(cb, G_SCALAR);
SPAGAIN;
if (SvTRUE(*PL_stack_sp)) {
found = 1;
found_node_id = current_node_id;
}
POPs;
}
DOUBLY_LOCK();
xs/doubly/doubly.c view on Meta::CPAN
current_node_id = node->node_id;
node_data = node->data ? newSVsv(node->data) : &PL_sv_undef;
DOUBLY_UNLOCK();
{
dSP;
PUSHMARK(SP);
XPUSHs(sv_2mortal(node_data));
PUTBACK;
call_sv(cb, G_SCALAR);
SPAGAIN;
if (SvTRUE(*PL_stack_sp)) {
found = 1;
}
POPs;
}
DOUBLY_LOCK();
list = get_list(list_idx);
xs/doubly/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/doubly/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/file/file.c view on Meta::CPAN
} else if (entry->perl_callback) {
/* Call Perl callback */
dSP;
int count;
ENTER;
SAVETMPS;
PUSHMARK(SP);
mXPUSHs(newSVpv(path, 0));
mXPUSHs(SvREFCNT_inc(result));
PUTBACK;
count = call_sv(entry->perl_callback, G_SCALAR);
SPAGAIN;
if (count > 0) {
SV *ret = POPs;
if (SvOK(ret)) {
result = newSVsv(ret);
} else {
ctx.cancel = 1;
}
}
PUTBACK;
FREETMPS;
LEAVE;
}
if (!result || ctx.cancel) return NULL;
}
return result;
}
xs/file/file.c view on Meta::CPAN
Custom OP implementations - fastest path
============================================ */
/* pp_file_slurp: single path arg on stack */
static OP* pp_file_slurp(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
SV *result = file_slurp_internal(aTHX_ path);
PUSHs(sv_2mortal(result));
PUTBACK;
return NORMAL;
}
/* pp_file_spew: path and data on stack */
static OP* pp_file_spew(pTHX) {
dSP;
SV *data = POPs;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
if (file_spew_internal(aTHX_ path, data)) {
PUSHs(&PL_sv_yes);
} else {
PUSHs(&PL_sv_no);
}
PUTBACK;
return NORMAL;
}
/* pp_file_exists: single path arg on stack */
static OP* pp_file_exists(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_exists_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_size: single path arg on stack */
static OP* pp_file_size(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(newSViv(file_size_internal(path))));
PUTBACK;
return NORMAL;
}
/* pp_file_is_file: single path arg on stack */
static OP* pp_file_is_file(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_is_file_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_is_dir: single path arg on stack */
static OP* pp_file_is_dir(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_is_dir_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_lines: single path arg on stack */
static OP* pp_file_lines(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
SV *content = file_slurp_internal(aTHX_ path);
AV *lines;
if (content == &PL_sv_undef) {
lines = newAV();
} else {
lines = file_split_lines(aTHX_ content);
SvREFCNT_dec(content);
}
PUSHs(sv_2mortal(newRV_noinc((SV*)lines)));
PUTBACK;
return NORMAL;
}
/* pp_file_unlink: single path arg on stack */
static OP* pp_file_unlink(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_unlink_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_mkdir: single path arg on stack (mode defaults to 0755) */
static OP* pp_file_mkdir(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_mkdir_internal(path, 0755) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_rmdir: single path arg on stack */
static OP* pp_file_rmdir(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_rmdir_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_touch: single path arg on stack */
static OP* pp_file_touch(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_touch_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_basename: single path arg on stack */
static OP* pp_file_basename(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(file_basename_internal(aTHX_ path)));
PUTBACK;
return NORMAL;
}
/* pp_file_dirname: single path arg on stack */
static OP* pp_file_dirname(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(file_dirname_internal(aTHX_ path)));
PUTBACK;
return NORMAL;
}
/* pp_file_extname: single path arg on stack */
static OP* pp_file_extname(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(file_extname_internal(aTHX_ path)));
PUTBACK;
return NORMAL;
}
/* pp_file_mtime: single path arg on stack */
static OP* pp_file_mtime(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(newSViv(file_mtime_internal(path))));
PUTBACK;
return NORMAL;
}
/* pp_file_atime: single path arg on stack */
static OP* pp_file_atime(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(newSViv(file_atime_internal(path))));
PUTBACK;
return NORMAL;
}
/* pp_file_ctime: single path arg on stack */
static OP* pp_file_ctime(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(newSViv(file_ctime_internal(path))));
PUTBACK;
return NORMAL;
}
/* pp_file_mode: single path arg on stack */
static OP* pp_file_mode(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(sv_2mortal(newSViv(file_mode_internal(path))));
PUTBACK;
return NORMAL;
}
/* pp_file_is_link: single path arg on stack */
static OP* pp_file_is_link(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_is_link_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_is_readable: single path arg on stack */
static OP* pp_file_is_readable(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_is_readable_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_is_writable: single path arg on stack */
static OP* pp_file_is_writable(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_is_writable_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_is_executable: single path arg on stack */
static OP* pp_file_is_executable(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_is_executable_internal(path) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_readdir: single path arg on stack */
static OP* pp_file_readdir(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
AV *result = file_readdir_internal(aTHX_ path);
PUSHs(sv_2mortal(newRV_noinc((SV*)result)));
PUTBACK;
return NORMAL;
}
/* pp_file_slurp_raw: single path arg on stack (bypasses hooks) */
static OP* pp_file_slurp_raw(pTHX) {
dSP;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
SV *result = file_slurp_raw_internal(aTHX_ path);
PUSHs(sv_2mortal(result));
PUTBACK;
return NORMAL;
}
/* pp_file_copy: src and dst on stack */
static OP* pp_file_copy(pTHX) {
dSP;
SV *dst_sv = POPs;
SV *src_sv = POPs;
const char *src = SvPV_nolen(src_sv);
const char *dst = SvPV_nolen(dst_sv);
PUSHs(file_copy_internal(aTHX_ src, dst) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_move: src and dst on stack */
static OP* pp_file_move(pTHX) {
dSP;
SV *dst_sv = POPs;
SV *src_sv = POPs;
const char *src = SvPV_nolen(src_sv);
const char *dst = SvPV_nolen(dst_sv);
PUSHs(file_move_internal(aTHX_ src, dst) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_chmod: path and mode on stack */
static OP* pp_file_chmod(pTHX) {
dSP;
SV *mode_sv = POPs;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
int mode = SvIV(mode_sv);
PUSHs(file_chmod_internal(path, mode) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_append: path and data on stack */
static OP* pp_file_append(pTHX) {
dSP;
SV *data = POPs;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_append_internal(aTHX_ path, data) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* pp_file_atomic_spew: path and data on stack */
static OP* pp_file_atomic_spew(pTHX) {
dSP;
SV *data = POPs;
SV *path_sv = POPs;
const char *path = SvPV_nolen(path_sv);
PUSHs(file_atomic_spew_internal(aTHX_ path, data) ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
return NORMAL;
}
/* ============================================
Call checkers for compile-time optimization
============================================ */
/* 1-arg call checker (slurp, exists, size, is_file, is_dir, lines) */
static OP* file_call_checker_1arg(pTHX_ OP *entersubop, GV *namegv, SV *ckobj) {
file_ppfunc ppfunc = (file_ppfunc)SvIVX(ckobj);
xs/file/file.c view on Meta::CPAN
SV *old_defsv = DEFSV;
SAVESPTR(DEFSV); /* Automatically restore $_ on scope exit */
while ((line = file_lines_next(aTHX_ idx)) != &PL_sv_undef) {
dSP;
ENTER;
SAVETMPS;
DEFSV_set(line); /* Set $_ */
PUSHMARK(SP);
XPUSHs(line); /* Don't mortalise - line is freed by file_lines_close or DEFSV restore */
PUTBACK;
call_sv(callback, G_DISCARD);
FREETMPS;
LEAVE;
SvREFCNT_dec(line); /* Release our reference after callback completes */
}
}
file_lines_close(idx);
XSRETURN_EMPTY;
}
xs/file/file.c view on Meta::CPAN
SV *cb_sv = fcb ? fcb->perl_callback : (SV*)block_cv;
SV *old_defsv = DEFSV;
while ((line = file_lines_next(aTHX_ idx)) != &PL_sv_undef) {
dSP;
IV count;
SV *result_sv;
bool matches = FALSE;
DEFSV_set(line); /* Set $_ */
PUSHMARK(SP);
XPUSHs(line);
PUTBACK;
count = call_sv(cb_sv, G_SCALAR);
SPAGAIN;
if (count > 0) {
result_sv = POPs;
matches = SvTRUE(result_sv);
}
PUTBACK;
if (matches) {
av_push(result, line);
} else {
SvREFCNT_dec(line);
}
}
DEFSV_set(old_defsv);
}
file_lines_close(idx);
xs/file/file.c view on Meta::CPAN
SV *cb_sv = fcb ? fcb->perl_callback : (SV*)block_cv;
SV *old_defsv = DEFSV;
while ((line = file_lines_next(aTHX_ idx)) != &PL_sv_undef) {
dSP;
IV n;
SV *result_sv;
bool matches = FALSE;
DEFSV_set(line); /* Set $_ */
PUSHMARK(SP);
XPUSHs(line);
PUTBACK;
n = call_sv(cb_sv, G_SCALAR);
SPAGAIN;
if (n > 0) {
result_sv = POPs;
matches = SvTRUE(result_sv);
}
PUTBACK;
if (matches) {
count++;
}
SvREFCNT_dec(line);
}
DEFSV_set(old_defsv);
}
file_lines_close(idx);
ST(0) = sv_2mortal(newSViv(count));
xs/file/file.c view on Meta::CPAN
SV *cb_sv = fcb ? fcb->perl_callback : (SV*)block_cv;
SV *old_defsv = DEFSV;
while ((line = file_lines_next(aTHX_ idx)) != &PL_sv_undef) {
dSP;
IV n;
SV *result_sv;
bool matches = FALSE;
DEFSV_set(line); /* Set $_ */
PUSHMARK(SP);
XPUSHs(line);
PUTBACK;
n = call_sv(cb_sv, G_SCALAR);
SPAGAIN;
if (n > 0) {
result_sv = POPs;
matches = SvTRUE(result_sv);
}
PUTBACK;
if (matches) {
DEFSV_set(old_defsv);
file_lines_close(idx);
ST(0) = sv_2mortal(line);
XSRETURN(1);
}
SvREFCNT_dec(line);
}
DEFSV_set(old_defsv);
}
xs/file/file.c view on Meta::CPAN
/* Call Perl callback - set both $_ and pass as argument */
{
SV *old_defsv = DEFSV;
while ((line = file_lines_next(aTHX_ idx)) != &PL_sv_undef) {
dSP;
IV count;
SV *result_sv;
DEFSV_set(line); /* Set $_ */
PUSHMARK(SP);
XPUSHs(sv_2mortal(line));
PUTBACK;
count = call_sv(callback, G_SCALAR);
SPAGAIN;
if (count > 0) {
result_sv = POPs;
av_push(result, SvREFCNT_inc(result_sv));
}
PUTBACK;
}
DEFSV_set(old_defsv);
}
file_lines_close(idx);
ST(0) = sv_2mortal(newRV_noinc((SV*)result));
XSRETURN(1);
}
/* Register a Perl callback */
xs/file/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/file/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/heap/heap.c view on Meta::CPAN
/* Custom comparator sift operations */
static bool heap_compare_custom(pTHX_ Heap *h, SV *a, SV *b) {
dSP;
IV result;
int count;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(a);
XPUSHs(b);
PUTBACK;
count = call_sv(h->comparator, G_SCALAR);
SPAGAIN;
if (count != 1) croak("Comparator must return exactly one value");
result = POPi;
PUTBACK;
FREETMPS; LEAVE;
return h->type == HEAP_MIN ? result < 0 : result > 0;
}
static void heap_sift_up_custom(pTHX_ Heap *h, IV idx) {
while (idx > 0) {
IV parent = (idx - 1) >> 1;
if (heap_compare_custom(aTHX_ h, h->data[idx], h->data[parent])) {
SV *tmp = h->data[idx];
xs/heap/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/heap/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/lru/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/lru/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/noop/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/noop/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/nvec/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/nvec/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/object/object.c view on Meta::CPAN
/* Fall back to Perl callback (~100 cycles) */
if (spec->registered->perl_check) {
dSP;
int count;
bool result = false;
SV *result_sv;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(val);
PUTBACK;
count = call_sv(spec->registered->perl_check, G_SCALAR);
SPAGAIN;
if (count > 0) {
result_sv = POPs;
result = SvTRUE(result_sv);
}
PUTBACK;
FREETMPS;
LEAVE;
return result;
}
return true;
}
/* ============================================
Slot spec parser: "name:Type:default(val)"
xs/object/object.c view on Meta::CPAN
}
/* Create blessed reference */
obj_sv = newRV_noinc((SV*)obj_av);
sv_bless(obj_sv, meta->stash);
/* Magic for lock/freeze is added lazily when first needed */
SP = MARK;
XPUSHs(obj_sv);
PUTBACK;
return NORMAL;
}
/* ============================================
Prototype chain resolution
============================================ */
#define MAX_PROTOTYPE_DEPTH 100
/* Resolve a property through the full prototype chain.
xs/object/object.c view on Meta::CPAN
/* Readonly check */
if (spec->is_readonly) {
croak("Cannot modify readonly slot '%s'", spec->name);
}
/* Coercion (if callback exists) */
if (spec->has_coerce && spec->coerce_cb) {
dSP;
PUSHMARK(SP);
XPUSHs(val);
PUTBACK;
call_sv(spec->coerce_cb, G_SCALAR);
SPAGAIN;
val = POPs;
PUTBACK;
}
/* External XS type coercion (C function - fast path) */
if (spec->type_id == TYPE_CUSTOM && spec->registered && spec->registered->coerce) {
val = spec->registered->coerce(aTHX_ val);
}
/* Type check using helper (handles both C and Perl callbacks) */
if (spec->has_type) {
if (!check_slot_type(aTHX_ val, spec)) {
xs/object/object.c view on Meta::CPAN
}
/* Trigger callback (old, new) */
if (spec->has_trigger && spec->trigger_cb) {
SV *oldval = *av_fetch(av, idx, 0);
dSP;
PUSHMARK(SP);
XPUSHs(obj);
XPUSHs(oldval);
XPUSHs(val);
PUTBACK;
call_sv(spec->trigger_cb, G_DISCARD);
}
av_store(av, idx, newSVsv(val));
SETs(val);
RETURN;
}
/* ============================================
Call checker for accessor
xs/object/object.c view on Meta::CPAN
if (spec->has_builder && spec->builder_name) {
/* Call builder method */
dSP;
const char *builder = SvPV_nolen(spec->builder_name);
int count;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(self);
PUTBACK;
count = call_method(builder, G_SCALAR);
SPAGAIN;
if (count > 0) {
/* Copy the value BEFORE FREETMPS to avoid freed scalar issue */
built_val = newSVsv(POPs);
} else {
built_val = newSV(0); /* undef */
}
PUTBACK;
FREETMPS;
LEAVE;
} else if (spec->has_default && spec->default_sv) {
/* Use default value for lazy default */
if (SvROK(spec->default_sv)) {
/* Clone reference types (arrays, hashes) */
SV *inner = SvRV(spec->default_sv);
if (SvTYPE(inner) == SVt_PVAV) {
built_val = newRV_noinc((SV*)newAV());
} else if (SvTYPE(inner) == SVt_PVHV) {
xs/object/object.c view on Meta::CPAN
SV *self = ST(0);
PERL_UNUSED_VAR(items);
if (meta && meta->demolish_cv) {
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(self);
PUTBACK;
call_sv((SV*)meta->demolish_cv, G_DISCARD | G_EVAL);
SPAGAIN;
/* Ignore errors in DEMOLISH - don't die during destruction */
if (SvTRUE(ERRSV)) {
warn("Error in DEMOLISH: %s", SvPV_nolen(ERRSV));
}
FREETMPS;
LEAVE;
}
xs/object/object.c view on Meta::CPAN
/* Call before chain (in stack order - most recent first) */
for (m = mod->before_chain; m; m = m->next) {
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for (i = 0; i <= av_len(saved_args); i++) {
SV **svp = av_fetch(saved_args, i, 0);
XPUSHs(svp ? *svp : &PL_sv_undef);
}
PUTBACK;
call_sv(m->callback, G_DISCARD);
FREETMPS;
LEAVE;
}
/* Save results from original/around call */
saved_results = newAV();
sv_2mortal((SV*)saved_results);
/* Call around chain (or original if no around) */
xs/object/object.c view on Meta::CPAN
{
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newRV_inc((SV*)mod->original_cv)));
for (i = 0; i <= av_len(saved_args); i++) {
SV **svp = av_fetch(saved_args, i, 0);
XPUSHs(svp ? *svp : &PL_sv_undef);
}
PUTBACK;
count = call_sv(m->callback, gimme == G_ARRAY ? G_LIST : G_SCALAR);
SPAGAIN;
/* Save results before LEAVE destroys them - they're on stack in reverse */
for (i = 0; i < count; i++) {
av_push(saved_results, newSVsv(POPs));
}
FREETMPS;
LEAVE;
}
} else if (mod->original_cv) {
/* Call original method */
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for (i = 0; i <= av_len(saved_args); i++) {
SV **svp = av_fetch(saved_args, i, 0);
XPUSHs(svp ? *svp : &PL_sv_undef);
}
PUTBACK;
count = call_sv((SV*)mod->original_cv, gimme == G_ARRAY ? G_LIST : G_SCALAR);
SPAGAIN;
/* Save results before LEAVE destroys them */
for (i = 0; i < count; i++) {
av_push(saved_results, newSVsv(POPs));
}
FREETMPS;
LEAVE;
}
/* Call after chain (in order of registration) */
for (m = mod->after_chain; m; m = m->next) {
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for (i = 0; i <= av_len(saved_args); i++) {
SV **svp = av_fetch(saved_args, i, 0);
XPUSHs(svp ? *svp : &PL_sv_undef);
}
PUTBACK;
call_sv(m->callback, G_DISCARD);
FREETMPS;
LEAVE;
}
/* Put saved results back on stack (they were saved in reverse order) */
{
count = av_len(saved_results) + 1;
for (i = count - 1; i >= 0; i--) {
SV **svp = av_fetch(saved_results, i, 0);
xs/object/object.c view on Meta::CPAN
SV *obj;
GV *build_gv;
char full_build[256];
ENTER;
SAVETMPS;
/* Call ClassName->new() */
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(meta->class_name, 0)));
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
if (count != 1) {
croak("Singleton new() did not return object");
}
obj = POPs;
SvREFCNT_inc(obj); /* Keep the object alive */
PUTBACK;
/* Check for BUILD method and call it */
snprintf(full_build, sizeof(full_build), "%s::BUILD", meta->class_name);
build_gv = gv_fetchpv(full_build, 0, SVt_PVCV);
if (build_gv && GvCV(build_gv)) {
PUSHMARK(SP);
XPUSHs(obj);
PUTBACK;
call_method("BUILD", G_VOID | G_DISCARD);
}
/* Cache the instance */
meta->singleton_instance = obj;
FREETMPS;
LEAVE;
ST(0) = obj;
xs/object/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/object/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/slot/ppport.h view on Meta::CPAN
PUSH_MULTICALL_FLAGS|5.018000||Viu
PUSHn|5.006000|5.003007|
PUSHp|5.003007|5.003007|
PUSHs|5.003007|5.003007|
push_scope|5.003007|5.003007|u
PUSHSTACK|5.005000||Viu
PUSHSTACKi|5.005000||Viu
PUSHSTACK_INIT_HWM|5.027002||Viu
PUSHTARG|5.003007||Viu
PUSHu|5.004000|5.003007|p
PUTBACK|5.003007|5.003007|
putc|5.003007||Viu
put_charclass_bitmap_innards|5.021004||Viu
put_charclass_bitmap_innards_common|5.023008||Viu
put_charclass_bitmap_innards_invlist|5.023008||Viu
put_code_point|5.021004||Viu
putc_unlocked|5.003007||Viu
putenv|5.005000||Viu
put_range|5.019009||Viu
putw|5.003007||Viu
pv_display|5.006000|5.003007|p
xs/slot/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
D_PPP_CROAK_IF_ERROR(croak_on_error);
return sv;
}
#endif
#endif
#if ! defined(vload_module) && defined(start_subparse)
xs/slot/slot.c view on Meta::CPAN
AV *callbacks = (AV*)SvRV(*svp);
SSize_t i, len = av_len(callbacks);
for (i = 0; i <= len; i++) {
SV **cb = av_fetch(callbacks, i, 0);
if (cb && SvROK(*cb)) {
dSP;
ENTER; SAVETMPS;
PUSHMARK(SP);
mXPUSHs(newSVpvn(name, name_len));
XPUSHs(new_val);
PUTBACK;
call_sv(*cb, G_DISCARD);
FREETMPS; LEAVE;
}
}
}
}
/* ============================================
Slot management
============================================ */
xs/slot/slot.c view on Meta::CPAN
static XS(xs_slots) {
dXSARGS;
HE *entry;
PERL_UNUSED_VAR(items);
SP -= items;
hv_iterinit(g_slot_index);
while ((entry = hv_iternext(g_slot_index))) {
XPUSHs(hv_iterkeysv(entry));
}
PUTBACK;
return;
}
/* slot::exists - check if slot is defined */
static XS(xs_exists) {
dXSARGS;
STRLEN name_len;
const char *name;
if (items != 1) croak("Usage: slot::exists($name)");
name = SvPV(ST(0), name_len);
xs/util/ppport.h view on Meta::CPAN
PTR2ul|5.007001||p
PTRV|5.006000||p
PUSHMARK|||
PUSH_MULTICALL||5.011000|
PUSHi|||
PUSHmortal|5.009002||p
PUSHn|||
PUSHp|||
PUSHs|||
PUSHu|5.004000||p
PUTBACK|||
PerlIO_clearerr||5.007003|
PerlIO_close||5.007003|
PerlIO_context_layers||5.009004|
PerlIO_eof||5.007003|
PerlIO_error||5.007003|
PerlIO_fileno||5.007003|
PerlIO_fill||5.007003|
PerlIO_flush||5.007003|
PerlIO_get_base||5.007003|
PerlIO_get_bufsiz||5.007003|
xs/util/ppport.h view on Meta::CPAN
{
dSP;
SV* sv = newSVpv(p, 0);
PUSHMARK(sp);
eval_sv(sv, G_SCALAR);
SvREFCNT_dec(sv);
SPAGAIN;
sv = POPs;
PUTBACK;
if (croak_on_error && SvTRUE(GvSV(errgv)))
croak(SvPVx(GvSV(errgv), na));
return sv;
}
#endif
#endif
xs/util/util.c view on Meta::CPAN
/* clamp: 3 values on stack, return clamped */
static OP* pp_clamp(pTHX) {
dSP; dMARK; dORIGMARK;
SV *val_sv, *min_sv, *max_sv;
NV value, min, max, result;
/* We get 3 args on stack after the mark */
if (SP - MARK != 3) {
/* Fallback: just use direct POPs if no mark context */
SP = ORIGMARK;
PUTBACK;
/* Pop without mark - shouldn't happen in list context */
dSP;
max_sv = POPs;
min_sv = POPs;
val_sv = POPs;
} else {
val_sv = MARK[1];
min_sv = MARK[2];
max_sv = MARK[3];
SP = ORIGMARK; /* reset stack to before args */
xs/util/util.c view on Meta::CPAN
ENTER;
SAVETMPS;
PUSHMARK(SP);
IV i;
EXTEND(SP, items);
for (i = 0; i < items; i++) {
PUSHs(ST(i));
}
PUTBACK;
IV count = call_sv(mf->func, G_ARRAY);
SPAGAIN;
if (count == 1) {
SV *result = SvREFCNT_inc(POPs);
hv_store(mf->cache, key_pv, key_len, result, 0);
PUTBACK;
FREETMPS;
LEAVE;
SvREFCNT_dec_NN(key);
ST(0) = result;
XSRETURN(1);
} else if (count > 0) {
AV *av = newAV();
av_extend(av, count - 1);
for (i = count - 1; i >= 0; i--) {
av_store(av, i, SvREFCNT_inc(POPs));
}
SV *result = newRV_noinc((SV*)av);
hv_store(mf->cache, key_pv, key_len, result, 0);
PUTBACK;
FREETMPS;
LEAVE;
SvREFCNT_dec_NN(key);
for (i = 0; i < count; i++) {
SV **elem = av_fetch(av, i, 0);
ST(i) = elem ? *elem : &PL_sv_undef;
}
XSRETURN(count);
} else {
hv_store(mf->cache, key_pv, key_len, &PL_sv_undef, 0);
PUTBACK;
FREETMPS;
LEAVE;
SvREFCNT_dec_NN(key);
XSRETURN_EMPTY;
}
}
/* ============================================
Pipe/Compose implementation
============================================ */
xs/util/util.c view on Meta::CPAN
SV *func = ST(i);
if (!SvROK(func) || SvTYPE(SvRV(func)) != SVt_PVCV) {
SvREFCNT_dec(value);
croak("util::pipeline: argument %d is not a coderef", (int)i);
}
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(value);
PUTBACK;
call_sv(func, G_SCALAR);
SPAGAIN;
SV *new_value = POPs;
SvREFCNT_inc(new_value);
PUTBACK;
FREETMPS;
LEAVE;
SvREFCNT_dec(value);
value = new_value;
}
ST(0) = sv_2mortal(value);
XSRETURN(1);
}
xs/util/util.c view on Meta::CPAN
if (i == func_count - 1) {
IV j;
EXTEND(SP, items);
for (j = 0; j < items; j++) {
PUSHs(ST(j));
}
} else {
XPUSHs(value);
}
PUTBACK;
call_sv(*func_ptr, G_SCALAR);
SPAGAIN;
SV *new_value = POPs;
SvREFCNT_inc(new_value);
PUTBACK;
FREETMPS;
LEAVE;
if (value) SvREFCNT_dec(value);
value = new_value;
}
ST(0) = value ? sv_2mortal(value) : &PL_sv_undef;
XSRETURN(1);
}
xs/util/util.c view on Meta::CPAN
LazyValue *lv = &g_lazies[idx];
if (lv->forced) {
ST(0) = lv->value;
XSRETURN(1);
}
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
call_sv(lv->thunk, G_SCALAR);
SPAGAIN;
lv->value = SvREFCNT_inc(POPs);
lv->forced = TRUE;
PUTBACK;
FREETMPS;
LEAVE;
SvREFCNT_dec(lv->thunk);
lv->thunk = NULL;
ST(0) = lv->value;
XSRETURN(1);
}
xs/util/util.c view on Meta::CPAN
croak("util::tap: first argument must be a coderef");
}
ENTER;
SAVETMPS;
SAVE_DEFSV;
DEFSV_set(value);
PUSHMARK(SP);
XPUSHs(value);
PUTBACK;
call_sv(func, G_DISCARD | G_VOID);
SPAGAIN;
FREETMPS;
LEAVE;
ST(0) = value;
XSRETURN(1);
}
xs/util/util.c view on Meta::CPAN
ENTER;
SAVETMPS;
PUSHMARK(SP);
IV i;
EXTEND(SP, items);
for (i = 0; i < items; i++) {
PUSHs(ST(i));
}
PUTBACK;
call_sv(pred, G_SCALAR);
SPAGAIN;
SV *result = POPs;
bool val = SvTRUE(result);
PUTBACK;
FREETMPS;
LEAVE;
ST(0) = val ? &PL_sv_no : &PL_sv_yes;
XSRETURN(1);
}
/* once(\&f) - execute once, cache forever */
static XS(xs_once) {
dXSARGS;
xs/util/util.c view on Meta::CPAN
OnceFunc *of = &g_onces[idx];
if (of->called) {
ST(0) = of->result ? of->result : &PL_sv_undef;
XSRETURN(1);
}
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
call_sv(of->func, G_SCALAR);
SPAGAIN;
of->result = SvREFCNT_inc(POPs);
of->called = TRUE;
PUTBACK;
FREETMPS;
LEAVE;
/* Free the original function, no longer needed */
SvREFCNT_dec(of->func);
of->func = NULL;
ST(0) = of->result;
XSRETURN(1);
}
xs/util/util.c view on Meta::CPAN
IV i;
for (i = 0; i < bound_count; i++) {
SV **elem = av_fetch(pf->bound_args, i, 0);
PUSHs(elem ? *elem : &PL_sv_undef);
}
/* Push call-time args */
for (i = 0; i < items; i++) {
PUSHs(ST(i));
}
PUTBACK;
IV count = call_sv(pf->func, G_SCALAR);
SPAGAIN;
SV *result = count > 0 ? POPs : &PL_sv_undef;
SvREFCNT_inc(result);
PUTBACK;
FREETMPS;
LEAVE;
ST(0) = sv_2mortal(result);
XSRETURN(1);
}
/* ============================================
Data extraction functions
============================================ */
xs/util/util.c view on Meta::CPAN
hv_iterinit(dest);
HE *he;
while ((he = hv_iternext(dest)) != NULL) {
STRLEN klen;
const char *key = HePV(he, klen);
mPUSHp(key, klen);
mPUSHs(SvREFCNT_inc(HeVAL(he)));
}
SvREFCNT_dec((SV*)dest); /* Free the temp hash */
PUTBACK;
return;
}
/* Scalar context - return hashref */
ST(0) = sv_2mortal(newRV_noinc((SV*)dest));
XSRETURN(1);
}
/* pluck(\@hashes, $field) - extract field from each hash */
static XS(xs_pluck) {
xs/util/util.c view on Meta::CPAN
hv_iterinit(dest);
HE *he;
while ((he = hv_iternext(dest)) != NULL) {
STRLEN klen;
const char *key = HePV(he, klen);
mPUSHp(key, klen);
mPUSHs(SvREFCNT_inc(HeVAL(he)));
}
SvREFCNT_dec((SV*)dest); /* Free the temp hash */
PUTBACK;
return;
}
/* Scalar context - return hashref */
ST(0) = sv_2mortal(newRV_noinc((SV*)dest));
XSRETURN(1);
}
/* uniq(@list) - return unique elements (preserves order) */
static XS(xs_uniq) {
xs/util/util.c view on Meta::CPAN
IV i;
for (i = 1; i < items; i++) {
SV *elem = ST(i);
DEFSV_set(elem);
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(elem);
PUTBACK;
call_sv(block, G_SCALAR);
SPAGAIN;
SV *result = POPs;
bool matched = SvTRUE(result);
PUTBACK;
FREETMPS;
LEAVE;
if (matched) {
av_push(pass, SvREFCNT_inc_simple_NN(elem));
} else {
av_push(fail, SvREFCNT_inc_simple_NN(elem));
}
}
xs/util/util.c view on Meta::CPAN
hv_iterinit(dest);
HE *he;
while ((he = hv_iternext(dest)) != NULL) {
STRLEN klen;
const char *key = HePV(he, klen);
mPUSHp(key, klen);
mPUSHs(SvREFCNT_inc(HeVAL(he)));
}
SvREFCNT_dec((SV*)dest); /* Free the temp hash */
PUTBACK;
return;
}
/* Scalar context - return hashref */
ST(0) = sv_2mortal(newRV_noinc((SV*)dest));
XSRETURN(1);
}
/* ============================================
Null coalescing functions
xs/util/util.c view on Meta::CPAN
{
dSP;
int count;
SV *result;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(*svp);
PUTBACK;
count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS;
LEAVE;
}
if (matches) {
XSRETURN_YES;
}
}
}
xs/util/util.c view on Meta::CPAN
SV **svp = av_fetch(list, i, 0);
if (!svp) { XSRETURN_NO; }
bool matches = FALSE;
{
dSP;
int count;
SV *result;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(*svp);
PUTBACK;
count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS; LEAVE;
}
if (!matches) {
XSRETURN_NO;
}
}
}
XSRETURN_YES;
}
xs/util/util.c view on Meta::CPAN
SV **svp = av_fetch(list, i, 0);
if (!svp) continue;
bool matches = FALSE;
{
dSP;
int count;
SV *result;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(*svp);
PUTBACK;
count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS; LEAVE;
}
if (matches) {
XSRETURN_NO;
}
}
}
XSRETURN_YES;
}
xs/util/util.c view on Meta::CPAN
SV **svp = av_fetch(list, i, 0);
if (!svp) continue;
bool matches = FALSE;
{
dSP;
int count;
SV *result;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(*svp);
PUTBACK;
count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS; LEAVE;
}
if (matches) {
ST(0) = *svp;
XSRETURN(1);
}
}
}
XSRETURN_UNDEF;
xs/util/util.c view on Meta::CPAN
if (!svp) continue;
SV *elem = *svp;
bool matches = FALSE;
{
dSP;
int call_count;
SV *result;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(elem);
PUTBACK;
call_count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (call_count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS; LEAVE;
}
if (matches) {
av_push(results, SvREFCNT_inc(elem));
count++;
}
}
}
/* Now push all results to the stack */
SP -= items;
for (i = 0; i < count; i++) {
SV **svp = av_fetch(results, i, 0);
if (svp) {
XPUSHs(sv_2mortal(SvREFCNT_inc(*svp)));
}
}
PUTBACK;
XSRETURN(count);
}
/* count_cb(\@list, ':predicate') - count matching elements */
static XS(xs_count_cb) {
dXSARGS;
if (items != 2) croak("Usage: util::count_cb(\\@list, $callback_name)");
SV *list_sv = ST(0);
if (!SvROK(list_sv) || SvTYPE(SvRV(list_sv)) != SVt_PVAV) {
xs/util/util.c view on Meta::CPAN
SV **svp = av_fetch(list, i, 0);
if (!svp) continue;
bool matches = FALSE;
{
dSP;
int call_count;
SV *result;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(*svp);
PUTBACK;
call_count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (call_count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS; LEAVE;
}
if (matches) {
count++;
}
}
}
XSRETURN_IV(count);
}
xs/util/util.c view on Meta::CPAN
{
dSP;
int call_count;
SV *result;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(*svp);
PUTBACK;
call_count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (call_count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS;
LEAVE;
}
if (matches) {
av_push(pass, SvREFCNT_inc_simple_NN(*svp));
} else {
av_push(fail, SvREFCNT_inc_simple_NN(*svp));
}
}
xs/util/util.c view on Meta::CPAN
SV **svp = av_fetch(list, i, 0);
if (!svp) continue;
bool matches = FALSE;
{
dSP;
int count;
SV *result;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(*svp);
PUTBACK;
count = call_sv(cb->perl_callback, G_SCALAR);
SPAGAIN;
if (count > 0) {
result = POPs;
matches = SvTRUE(result);
}
PUTBACK;
FREETMPS; LEAVE;
}
if (matches) {
ST(0) = *svp;
XSRETURN(1);
}
}
}
XSRETURN_UNDEF;