Class-XSConstructor
view release on metacpan or search on metacpan
XSConstructor.xs view on Meta::CPAN
ENTER;
SAVETMPS;
/* Ensure the key SV is released */
SAVEDESTRUCTOR_X(dec_sv_refcnt, (void *)mutexkey_sv);
/* Ensure the mutex is deleted on scope exit */
struct delete_ent_ctx *ctx;
Newxz(ctx, 1, struct delete_ent_ctx);
ctx->hv = object_hv;
ctx->key = mutexkey_sv;
SAVEDESTRUCTOR_X(delete_mutex, ctx);
svp = hv_fetch(object_hv, attr_name, attr_len, 0);
value_sv = svp ? *svp : &PL_sv_undef;
SV* trigger_sv = param->trigger_sv;
if (!SvROK(trigger_sv)) {
PUSHMARK(SP);
XPUSHs((SV *)object);
XPUSHs(value_sv);
PUTBACK;
call_method(SvPV_nolen(trigger_sv), G_VOID);
}
else if (SvTYPE(SvRV(trigger_sv)) == SVt_PVCV) {
PUSHMARK(SP);
XPUSHs((SV *)object);
XPUSHs(value_sv);
PUTBACK;
call_sv(trigger_sv, G_VOID);
}
else {
croak("Unexpected trigger type");
}
FREETMPS;
LEAVE;
}
int
xscon_initialize_object(const xscon_constructor_t* sig, const char* klass, SV* const object, HV* const args, bool const is_cloning)
{
dTHX;
assert(sig);
assert(object);
assert(args);
if (sig->is_placeholder) {
croak("Called on a placeholder");
}
if(mg_find((SV*)args, PERL_MAGIC_tied)){
croak("You cannot use tied HASH reference as initializing arguments");
}
I32 i;
int used = 0;
/* we can weaken everything at the end */
AV *weakrefs = NULL;
/* copy allowed attributes */
for (i = 0; i < sig->num_params; i++) {
xscon_param_t *param = &sig->params[i];
int flags = param->flags;
char *keyname = param->name;
int keylen = strlen(param->name);
char *init_arg = param->init_arg;
int init_arg_len = -1;
if ( param->init_arg ) {
init_arg_len = strlen(param->init_arg);
}
SV** valref;
SV* val;
bool has_value = FALSE;
bool value_was_from_args = FALSE;
if ( (!( flags & XSCON_FLAG_NO_INIT_ARG )) && init_arg_len >= 0 && hv_exists(args, init_arg, init_arg_len) ) {
/* Value provided in args hash */
valref = hv_fetch(args, init_arg, init_arg_len, 0);
val = newSVsv(*valref);
has_value = TRUE;
value_was_from_args = TRUE;
used++;
}
if ( flags & XSCON_FLAG_HAS_ALIASES ) {
I32 i;
for (i = 0; i < param->num_aliases; i++) {
char *alias = param->aliases[i];
int alias_len = strlen(alias);
if ( hv_exists(args, alias, alias_len) ) {
if ( has_value ) {
croak("Superfluous alias used for attribute '%s': %s", keyname, alias);
}
else {
valref = hv_fetch(args, alias, alias_len, 0);
val = newSVsv(*valref);
has_value = TRUE;
value_was_from_args = TRUE;
used++;
}
}
}
}
if ( value_was_from_args && ( flags & XSCON_FLAG_UNDEF_TOLERANT ) && !SvOK(val) ) {
has_value = FALSE;
val = NULL;
}
if ( !has_value && flags & XSCON_FLAG_HAS_DEFAULT ) {
/* There is a default/builder
* Some very common defaults are worth hardcoding into the flags
* so we won't need to do anything expensive to fill them in.
*/
I32 has_common_default = ( flags >> XSCON_BITSHIFT_DEFAULTS ) & 255;
val = xscon_run_default( object, keyname, has_common_default, param->default_sv );
XSConstructor.xs view on Meta::CPAN
croak("ARG! Something went really wrong while installing a new XSUB!");
xscon_reader_t *sig;
Newxz(sig, 1, xscon_reader_t);
sig->slot = savepv(slot);
sig->has_default = has_default;
sig->default_flags = default_flags;
sig->default_sv = SvREFCNT_inc(default_sv);
sig->check_flags = check_flags;
if (check && IsCodeRef(check)) {
sig->has_check = TRUE;
sig->check_cv = (CV *)SvREFCNT_inc(SvRV(check));
}
else {
sig->has_check = FALSE;
sig->check_cv = NULL;
}
if (coercion && IsCodeRef(coercion)) {
sig->has_coercion = TRUE;
sig->coercion_cv = (CV *)SvREFCNT_inc(SvRV(coercion));
}
else {
sig->has_coercion = FALSE;
sig->coercion_cv = NULL;
}
SV *cloner = &PL_sv_undef;
if (items >= 9) {
cloner = ST(8);
}
if (cloner && IsCodeRef(cloner)) {
sig->should_clone = TRUE;
sig->cloner_cv = (CV *)SvREFCNT_inc(SvRV(cloner));
}
else if (cloner && SvTRUE(cloner)) {
sig->should_clone = TRUE;
sig->cloner_cv = NULL;
}
else {
sig->has_coercion = FALSE;
sig->coercion_cv = NULL;
}
CvXSUBANY(cv).any_ptr = sig;
}
void
clone(self, depth=-1)
SV *self
int depth
PREINIT:
SV *clone = &PL_sv_undef;
HV *hseen = newHV();
AV *weakrefs = newAV();
PPCODE:
TRACEME(("ref = 0x%x\n", self));
clone = sv_clone( aTHX_ self, hseen, depth, 0, weakrefs );
/* Now apply deferred weakening.
* All strong references in the clone graph are established,
* so it is safe to weaken references without destroying referents. */
HANDLE_WEAKREFS( weakrefs );
hv_clear(hseen); /* Free HV */
SvREFCNT_dec((SV *)hseen);
EXTEND(SP,1);
PUSHs(sv_2mortal(clone));
( run in 0.660 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )