X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs%2FMOP.xs;h=fd4bf1d34f817df6f74f5f15c6734de5105f68f0;hb=4baf5adc6d23648dc169dc38f0693ed48c21d052;hp=545933e319479ac9ea90ae8c42b34cb06b7844b3;hpb=d846ade3f993c0e6c140bb28284022e602b8988e;p=gitmo%2FClass-MOP.git diff --git a/xs/MOP.xs b/xs/MOP.xs index 545933e..fd4bf1d 100644 --- a/xs/MOP.xs +++ b/xs/MOP.xs @@ -4,45 +4,58 @@ static bool find_method (const char *key, STRLEN keylen, SV *val, void *ud) { bool *found_method = (bool *)ud; + PERL_UNUSED_ARG(key); + PERL_UNUSED_ARG(keylen); + PERL_UNUSED_ARG(val); *found_method = TRUE; return FALSE; } -DECLARE_KEY(name); -DECLARE_KEY(package); -DECLARE_KEY(package_name); -DECLARE_KEY(body); -DECLARE_KEY(package_cache_flag); -DECLARE_KEY(methods); -DECLARE_KEY(VERSION); -DECLARE_KEY(ISA); +static bool +check_version (SV *klass, SV *required_version) +{ + bool ret = 0; + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + EXTEND(SP, 2); + PUSHs(klass); + PUSHs(required_version); + PUTBACK; + + call_method("VERSION", G_DISCARD|G_VOID|G_EVAL); + + SPAGAIN; + + if (!SvTRUE(ERRSV)) { + ret = 1; + } + + PUTBACK; + FREETMPS; + LEAVE; + + return ret; +} -SV *method_metaclass; -SV *associated_metaclass; -SV *wrap; +EXTERN_C XS(boot_Class__MOP__Mixin__HasMethods); +EXTERN_C XS(boot_Class__MOP__Package); +EXTERN_C XS(boot_Class__MOP__Mixin__AttributeCore); +EXTERN_C XS(boot_Class__MOP__Method); MODULE = Class::MOP PACKAGE = Class::MOP PROTOTYPES: DISABLE BOOT: - PREHASH_KEY(name); - PREHASH_KEY(body); - PREHASH_KEY(package); - PREHASH_KEY(package_name); - PREHASH_KEY(methods); - PREHASH_KEY(ISA); - PREHASH_KEY(VERSION); - PREHASH_KEY_WITH_VALUE(package_cache_flag, "_package_cache_flag"); - - method_metaclass = newSVpvs("method_metaclass"); - wrap = newSVpvs("wrap"); - associated_metaclass = newSVpvs("associated_metaclass"); - - MOP_CALL_BOOT (boot_Class__MOP__Package); - MOP_CALL_BOOT (boot_Class__MOP__Class); - MOP_CALL_BOOT (boot_Class__MOP__Attribute); - MOP_CALL_BOOT (boot_Class__MOP__Method); + mop_prehash_keys(); + + MOP_CALL_BOOT (boot_Class__MOP__Mixin__HasMethods); + MOP_CALL_BOOT (boot_Class__MOP__Package); + MOP_CALL_BOOT (boot_Class__MOP__Mixin__AttributeCore); + MOP_CALL_BOOT (boot_Class__MOP__Method); # use prototype here to be compatible with get_code_info from Sub::Identify void @@ -53,23 +66,23 @@ get_code_info(coderef) char *pkg = NULL; char *name = NULL; PPCODE: - if (get_code_info(coderef, &pkg, &name)) { + SvGETMAGIC(coderef); + if (mop_get_code_info(coderef, &pkg, &name)) { EXTEND(SP, 2); - PUSHs(newSVpv(pkg, 0)); - PUSHs(newSVpv(name, 0)); + mPUSHs(newSVpv(pkg, 0)); + mPUSHs(newSVpv(name, 0)); } -# This is some pretty grotty logic. It _should_ be parallel to the -# pure Perl version in lib/Class/MOP.pm, so if you want to understand -# it we suggest you start there. void -is_class_loaded(klass=&PL_sv_undef) +is_class_loaded(klass, options=NULL) SV *klass + HV *options PREINIT: HV *stash; bool found_method = FALSE; PPCODE: - if (!SvPOK(klass) || !SvCUR(klass)) { + SvGETMAGIC(klass); + if (!(SvPOKp(klass) && SvCUR(klass))) { /* XXX: SvPOK does not work with magical scalars */ XSRETURN_NO; } @@ -78,8 +91,17 @@ is_class_loaded(klass=&PL_sv_undef) XSRETURN_NO; } - if (hv_exists_ent (stash, key_VERSION, hash_VERSION)) { - HE *version = hv_fetch_ent(stash, key_VERSION, 0, hash_VERSION); + if (options && hv_exists_ent(options, KEY_FOR(_version), HASH_FOR(_version))) { + HE *required_version = hv_fetch_ent(options, KEY_FOR(_version), 0, HASH_FOR(_version)); + if (check_version (klass, HeVAL(required_version))) { + XSRETURN_YES; + } + + XSRETURN_NO; + } + + if (hv_exists_ent (stash, KEY_FOR(VERSION), HASH_FOR(VERSION))) { + HE *version = hv_fetch_ent(stash, KEY_FOR(VERSION), 0, HASH_FOR(VERSION)); SV *version_sv; if (version && HeVAL(version) && (version_sv = GvSV(HeVAL(version)))) { if (SvROK(version_sv)) { @@ -95,14 +117,14 @@ is_class_loaded(klass=&PL_sv_undef) } } - if (hv_exists_ent (stash, key_ISA, hash_ISA)) { - HE *isa = hv_fetch_ent(stash, key_ISA, 0, hash_ISA); - if (isa && HeVAL(isa) && GvAV(HeVAL(isa))) { + if (hv_exists_ent (stash, KEY_FOR(ISA), HASH_FOR(ISA))) { + HE *isa = hv_fetch_ent(stash, KEY_FOR(ISA), 0, HASH_FOR(ISA)); + if (isa && HeVAL(isa) && GvAV(HeVAL(isa)) && av_len(GvAV(HeVAL(isa))) != -1) { XSRETURN_YES; } } - get_package_symbols(stash, TYPE_FILTER_CODE, find_method, &found_method); + mop_get_package_symbols(stash, TYPE_FILTER_CODE, find_method, &found_method); if (found_method) { XSRETURN_YES; }