X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouse.xs;h=331b5bf6d267f32ea22743a66312c2d0fc6ef714;hb=2a3e3aa63b05f2ad66d96a3e3bd559163a947a45;hp=3b1520f99b8b3651edbab5b6a41afc170d02c0e7;hpb=93fe8a5fa9c9db1d8901ad4c47a13de670673dfa;p=gitmo%2FMouse.git diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index 3b1520f..331b5bf 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -257,8 +257,8 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const } for(i = 0; i < len; i++){ - SV* const attr = AvARRAY(attrs)[i]; - AV* const xa = mouse_get_xa(aTHX_ AvARRAY(attrs)[i]); + SV* const attr = MOUSE_av_at(attrs, i); + AV* const xa = mouse_get_xa(aTHX_ attr); SV* const slot = MOUSE_xa_slot(xa); U16 const flags = (U16)MOUSE_xa_flags(xa); @@ -335,6 +335,122 @@ mouse_initialize_metaclass(pTHX_ SV* const klass) { return meta; } + +/* copied from Class-MOP/topic/symbol-manipluator */ +static GV* +mouse_get_gv(pTHX_ SV* const self, svtype const type, const char* const var_name, I32 const var_name_len, I32 const flags){ + SV* package_name; + STRLEN len; + const char* pv; + + if(!flags){ + SV* const ns = mcall0(self, mouse_namespace); + GV** gvp; + if(!(SvROK(ns) && SvTYPE(SvRV(ns)) == SVt_PVHV)){ + croak("namespace() did not return a hash reference"); + } + gvp = (GV**)hv_fetch((HV*)SvRV(ns), var_name, var_name_len, FALSE); + if(gvp && isGV_with_GP(*gvp)){ + return *gvp; + } + } + + package_name = get_slot(self, mouse_package); + + if(!(package_name && SvOK(package_name))){ + croak("No package name defined"); + } + + pv = SvPV_const(package_name, len); + + return gv_fetchpvn_flags(Perl_form(aTHX_ "%s::%s", pv, var_name), (len + var_name_len + 2), flags, type); +} + +/* copied from Class-MOP/topic/symbol-manipluator */ +static SV* +mouse_gv_elem(pTHX_ GV* const gv, svtype const type, I32 const add){ + SV* sv; + + if(!gv){ + return NULL; + } + + assert(isGV_with_GP(gv)); + + switch(type){ + case SVt_PVAV: + sv = (SV*)(add ? GvAVn(gv) : GvAV(gv)); + break; + case SVt_PVHV: + sv = (SV*)(add ? GvHVn(gv) : GvHV(gv)); + break; + case SVt_PVCV: + sv = (SV*)GvCV(gv); + break; + case SVt_PVIO: + sv = (SV*)(add ? GvIOn(gv) : GvIO(gv)); + break; + case SVt_PVGV: + sv = (SV*)gv; + break; + default: /* SCALAR */ + sv = add ? GvSVn(gv) : GvSV(gv); + break; + } + + return sv; +} + +/* copied from Class-MOP/topic/symbol-manipluator */ +static void +mouse_deconstruct_variable_name(pTHX_ SV* const variable, + const char** const var_name, STRLEN* const var_name_len, + svtype* const type, + const char** const type_name) { + + STRLEN len; + const char* pv; + + /* e.g. variable = '$foo' */ + + if(!SvOK(variable)) { + croak("You must pass a variable name"); + } + pv = SvPV_const(variable, len); + if(len < 2){ + croak("You must pass a variable name including a sigil"); + } + + *var_name = pv + 1; + *var_name_len = len - 1; + + switch(pv[0]){ + case '$': + *type = SVt_PV; /* for all the types of scalars */ + *type_name = "SCALAR"; + break; + case '@': + *type = SVt_PVAV; + *type_name = "ARRAY"; + break; + case '%': + *type = SVt_PVHV; + *type_name = "HASH"; + break; + case '&': + *type = SVt_PVCV; + *type_name = "CODE"; + break; + case '*': + *type = SVt_PVGV; + *type_name = "GLOB"; + break; + default: + croak("I do not recognize that sigil '%c'", pv[0]); + } +} + + MODULE = Mouse PACKAGE = Mouse PROTOTYPES: DISABLE @@ -403,8 +519,8 @@ CODE: SV* sv = code_ref; /* used in tryAMAGICunDEREF */ SV** sp = &sv; /* used in tryAMAGICunDEREF */ tryAMAGICunDEREF(to_cv); /* try \&{$code} */ - if(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV){ - mouse_throw_error(self, NULL, "Not a CODE reference"); + if(!(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVCV)){ + mouse_throw_error(self, NULL, "You must pass a CODE reference to add_method"); } code_ref = sv; } @@ -431,16 +547,51 @@ CODE: } } +bool +has_package_symbol(SV* self, SV* variable) +PREINIT: + svtype type; + const char* type_name; + const char* var_name; + STRLEN var_name_len; + GV* gv; +CODE: + mouse_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name); + gv = mouse_get_gv(aTHX_ self, type, var_name, var_name_len, 0); + RETVAL = mouse_gv_elem(aTHX_ gv, type, FALSE) ? TRUE : FALSE; +OUTPUT: + RETVAL + +SV* +get_package_symbol(SV* self, SV* variable) +PREINIT: + svtype type; + const char* type_name; + const char* var_name; + STRLEN var_name_len; + I32 flags = 0; + GV* gv; + SV* sv; +CODE: + mouse_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name); + gv = mouse_get_gv(aTHX_ self, type, var_name, var_name_len, flags); + sv = mouse_gv_elem(aTHX_ gv, type, FALSE); + + RETVAL = sv ? newRV_inc(sv) : &PL_sv_undef; +OUTPUT: + RETVAL + + MODULE = Mouse PACKAGE = Mouse::Meta::Class BOOT: INSTALL_SIMPLE_READER(Class, roles); INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id); - INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, method_metaclass, "Mouse::Meta::Method"); - INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, attribute_metaclass, "Mouse::Meta::Attribute"); - INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, constructor_class, "Mouse::Meta::Method::Constructor::XS"); - INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Class, destructor_class, "Mouse::Meta::Method::Destructor::XS"); + INSTALL_CLASS_HOLDER(Class, method_metaclass, "Mouse::Meta::Method"); + INSTALL_CLASS_HOLDER(Class, attribute_metaclass, "Mouse::Meta::Attribute"); + INSTALL_CLASS_HOLDER(Class, constructor_class, "Mouse::Meta::Method::Constructor::XS"); + INSTALL_CLASS_HOLDER(Class, destructor_class, "Mouse::Meta::Method::Destructor::XS"); newCONSTSUB(gv_stashpvs("Mouse::Meta::Method::Constructor::XS", TRUE), "_generate_constructor", newRV_inc((SV*)get_cvs("Mouse::Object::new", TRUE))); @@ -472,7 +623,7 @@ get_all_attributes(SV* self) PPCODE: { AV* const xc = mouse_get_xc(aTHX_ self); - AV* const all_attrs = MOUSE_xc_attrall(xc); + AV* const all_attrs = MOUSE_xc_attrall(xc); I32 const len = AvFILLp(all_attrs) + 1; I32 i; @@ -508,7 +659,7 @@ BOOT: INSTALL_SIMPLE_READER_WITH_KEY(Role, get_roles, roles); INSTALL_SIMPLE_PREDICATE_WITH_KEY(Role, is_anon_role, anon_serial_id); - INSTALL_SIMPLE_ACCESSOR_WITH_DEFAULTS(Role, method_metaclass, "Mouse::Meta::Role::Method"); + INSTALL_CLASS_HOLDER(Role, method_metaclass, "Mouse::Meta::Role::Method"); MODULE = Mouse PACKAGE = Mouse::Object