X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=MOP.xs;h=4fbf38f2f1a09d1e5f4dc9675fa91236614f5d8b;hb=69b950261dbccf60b607713bc7a4c60a1245b04a;hp=1a5cba54a9cea0552916479944df15a910d3ab2c;hpb=d508fabd5ee73bb632d8bb24f5dd275dfe7c57df;p=gitmo%2FClass-MOP.git diff --git a/MOP.xs b/MOP.xs index 1a5cba5..4fbf38f 100644 --- a/MOP.xs +++ b/MOP.xs @@ -14,29 +14,32 @@ This shuts up warnings from gcc -Wall #define NEED_sv_2pv_nolen #include "ppport.h" -SV *key_name; -U32 hash_name; - -SV *key_package; -U32 hash_package; - -SV *key_package_name; -U32 hash_package_name; - -SV *key_body; -U32 hash_body; - -SV *key_package_cache_flag; -U32 hash_package_cache_flag; - -SV *key_methods; -U32 hash_methods; - -SV *key_VERSION; -U32 hash_VERSION; - -SV *key_ISA; -U32 hash_ISA; +#define DECLARE_KEY(name) SV *key_##name; U32 hash_##name; + +#define PREHASH_KEY_WITH_VALUE(name, value) do { \ + key_##name = newSVpvs(value); \ + PERL_HASH(hash_##name, value, sizeof(value) - 1); \ +} while (0) + +/* this is basically the same as the above macro, except that the value will be + * the stringified name. However, we can't just implement this in terms of + * PREHASH_KEY_WITH_VALUE as that'd cause macro expansion on the value of + * 'name' when it's being passed to the other macro. suggestions on how to make + * this more elegant would be much appreciated */ + +#define PREHASH_KEY(name) do { \ + key_##name = newSVpvs(#name); \ + PERL_HASH(hash_##name, #name, sizeof(#name) - 1); \ +} while (0) + +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); SV *method_metaclass; SV *associated_metaclass; @@ -310,35 +313,27 @@ get_code_info: MODULE = Class::MOP PACKAGE = Class::MOP BOOT: - key_name = newSVpvs("name"); - key_body = newSVpvs("body"); - key_package = newSVpvs("package"); - key_package_name = newSVpvs("package_name"); - key_package_cache_flag = newSVpvs("_package_cache_flag"); - key_methods = newSVpvs("methods"); - key_VERSION = newSVpvs("VERSION"); - key_ISA = newSVpvs("ISA"); - - PERL_HASH(hash_name, "name", 4); - PERL_HASH(hash_body, "body", 4); - PERL_HASH(hash_package, "package", 7); - PERL_HASH(hash_package_name, "package_name", 12); - PERL_HASH(hash_package_cache_flag, "_package_cache_flag", 19); - PERL_HASH(hash_methods, "methods", 7); - PERL_HASH(hash_VERSION, "VERSION", 7); - PERL_HASH(hash_ISA, "ISA", 3); + 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"); -PROTOTYPES: ENABLE - +PROTOTYPES: DISABLE +# use prototype here to be compatible with get_code_info from Sub::Identify void get_code_info(coderef) SV *coderef + PROTOTYPE: $ PREINIT: char *pkg = NULL; char *name = NULL; @@ -349,8 +344,9 @@ get_code_info(coderef) PUSHs(newSVpv(name, 0)); } -PROTOTYPES: DISABLE - +# 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) SV *klass @@ -358,7 +354,7 @@ is_class_loaded(klass=&PL_sv_undef) HV *stash; char *key; I32 keylen; - GV *gv; + SV *gv; PPCODE: if (!SvPOK(klass) || !SvCUR(klass)) { XSRETURN_NO; @@ -371,8 +367,18 @@ is_class_loaded(klass=&PL_sv_undef) if (hv_exists_ent (stash, key_VERSION, hash_VERSION)) { HE *version = hv_fetch_ent(stash, key_VERSION, 0, hash_VERSION); - if (version && HeVAL(version) && GvSV(HeVAL(version))) { - XSRETURN_YES; + SV *version_sv; + if (version && HeVAL(version) && (version_sv = GvSV(HeVAL(version)))) { + if (SvROK(version_sv)) { + SV *version_sv_ref = SvRV(version_sv); + + if (SvOK(version_sv_ref)) { + XSRETURN_YES; + } + } + else if (SvOK(version_sv)) { + XSRETURN_YES; + } } } @@ -384,7 +390,7 @@ is_class_loaded(klass=&PL_sv_undef) } (void)hv_iterinit(stash); - while (gv = (GV *)hv_iternextsv(stash, &key, &keylen)) { + while ((gv = hv_iternextsv(stash, &key, &keylen))) { if (keylen <= 0) { continue; } @@ -393,7 +399,7 @@ is_class_loaded(klass=&PL_sv_undef) continue; } - if (!isGV(gv) || GvCV(gv) || GvSV(gv) || GvAV(gv) || GvHV(gv) || GvIO(gv) || GvFORM(gv)) { + if (!isGV(gv) || GvCV(gv)) { XSRETURN_YES; } } @@ -402,13 +408,10 @@ is_class_loaded(klass=&PL_sv_undef) MODULE = Class::MOP PACKAGE = Class::MOP::Package -PROTOTYPES: ENABLE - void get_all_package_symbols(self, filter=TYPE_FILTER_NONE) SV *self type_filter_t filter - PROTOTYPE: $;$ PREINIT: HV *stash = NULL; HV *symbols = NULL; @@ -422,7 +425,6 @@ get_all_package_symbols(self, filter=TYPE_FILTER_NONE) XSRETURN_EMPTY; } - PUTBACK; if ( (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package)) ) { @@ -431,34 +433,11 @@ get_all_package_symbols(self, filter=TYPE_FILTER_NONE) if (!stash) { - switch (GIMME_V) { - case G_SCALAR: XSRETURN_UNDEF; break; - case G_ARRAY: XSRETURN_EMPTY; break; - } + XSRETURN_UNDEF; } symbols = get_all_package_symbols(stash, filter); - - switch (GIMME_V) { - case G_SCALAR: - PUSHs(sv_2mortal(newRV_inc((SV *)symbols))); - break; - case G_ARRAY: - warn("Class::MOP::Package::get_all_package_symbols in list context is deprecated. use scalar context instead."); - - EXTEND(SP, HvKEYS(symbols) * 2); - - while ((he = hv_iternext(symbols))) { - PUSHs(hv_iterkeysv(he)); - PUSHs(sv_2mortal(SvREFCNT_inc(HeVAL(he)))); - } - - break; - default: - break; - } - - SvREFCNT_dec((SV *)symbols); + PUSHs(sv_2mortal(newRV_noinc((SV *)symbols))); void name(self)