From: Florian Ragwitz Date: Wed, 11 Mar 2009 04:20:04 +0000 (+0100) Subject: Make it easier to simple xs hashref readers using prehashed keys. X-Git-Tag: 0.78_01~65 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7ec7b950c0cc43c8ba1f2c53a8ebffcfc23ef858;p=gitmo%2FClass-MOP.git Make it easier to simple xs hashref readers using prehashed keys. --- diff --git a/mop.c b/mop.c index 08e5349..25358f8 100644 --- a/mop.c +++ b/mop.c @@ -242,3 +242,41 @@ mop_prehash_keys () PERL_HASH(prehashed_keys[i].hash, value, strlen(value)); } } + +SV * +mop_simple_reader (SV *self, mop_prehashed_key_t key) +{ + register HE *he; + + if (!SvROK(self)) { + croak("can't call %s as a class method", prehashed_keys[key].name); + } + + if (SvTYPE(SvRV(self)) != SVt_PVHV) { + croak("object is not a hashref"); + } + + if (!(he = hv_fetch_ent((HV *)SvRV(self), prehashed_keys[key].key, 0, prehashed_keys[key].hash))) { + return &PL_sv_undef; + } + + return SvREFCNT_inc(HeVAL(he)); +} + +XS(mop_xs_simple_reader) +{ +#ifdef dVAR + dVAR; dXSARGS; +#else + dXSARGS; +#endif + + if (items != 1) { + croak("expected exactly one argument"); + } + + ST(0) = mop_simple_reader (ST(0), CvXSUBANY(cv).any_i32); + sv_2mortal(ST(0)); + XSRETURN(1); +} + diff --git a/mop.h b/mop.h index 444f8ac..afa9358 100644 --- a/mop.h +++ b/mop.h @@ -40,6 +40,21 @@ void mop_prehash_keys (void); inline SV *mop_prehashed_key_for (mop_prehashed_key_t key); inline U32 mop_prehashed_hash_for (mop_prehashed_key_t key); +#define INSTALL_SIMPLE_READER(klass, name) \ + { \ + CV *cv = newXS("Class::MOP::" #klass "::" #name, mop_xs_simple_reader, __FILE__); \ + CvXSUBANY(cv).any_i32 = KEY_ ##name; \ + } + +#define INSTALL_SIMPLE_READER_WITH_KEY(klass, name, key) \ + { \ + CV *cv = newXS("Class::MOP::" #klass "::" #name, mop_xs_simple_reader, __FILE__); \ + CvXSUBANY(cv).any_i32 = KEY_ ##key; \ + } + +SV *mop_simple_reader (SV *self, mop_prehashed_key_t key); +XS(mop_xs_simple_reader); + extern SV *mop_method_metaclass; extern SV *mop_associated_metaclass; extern SV *mop_wrap; diff --git a/xs/Attribute.xs b/xs/Attribute.xs index 150fd05..0375cb4 100644 --- a/xs/Attribute.xs +++ b/xs/Attribute.xs @@ -4,17 +4,5 @@ MODULE = Class::MOP::Attribute PACKAGE = Class::MOP::Attribute PROTOTYPES: DISABLE -void -name(self) - SV *self - PREINIT: - register HE *he; - PPCODE: - if ( ! SvROK(self) ) { - die("Cannot call name as a class method"); - } - - if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(name), 0, HASH_FOR(name))) ) - XPUSHs(HeVAL(he)); - else - ST(0) = &PL_sv_undef; +BOOT: + INSTALL_SIMPLE_READER(Attribute, name); diff --git a/xs/MOP.xs b/xs/MOP.xs index f3a6384..60c006c 100644 --- a/xs/MOP.xs +++ b/xs/MOP.xs @@ -1,5 +1,9 @@ #include "mop.h" +SV *mop_method_metaclass; +SV *mop_associated_metaclass; +SV *mop_wrap; + static bool find_method (const char *key, STRLEN keylen, SV *val, void *ud) { @@ -8,10 +12,6 @@ find_method (const char *key, STRLEN keylen, SV *val, void *ud) return FALSE; } -SV *mop_method_metaclass; -SV *mop_associated_metaclass; -SV *mop_wrap; - MODULE = Class::MOP PACKAGE = Class::MOP PROTOTYPES: DISABLE diff --git a/xs/Method.xs b/xs/Method.xs index ba2c850..590cd06 100644 --- a/xs/Method.xs +++ b/xs/Method.xs @@ -4,47 +4,7 @@ MODULE = Class::MOP::Method PACKAGE = Class::MOP::Method PROTOTYPES: DISABLE -void -name(self) - SV *self - PREINIT: - register HE *he; - PPCODE: - if ( ! SvROK(self) ) { - die("Cannot call name as a class method"); - } - - if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(name), 0, HASH_FOR(name))) ) - XPUSHs(HeVAL(he)); - else - ST(0) = &PL_sv_undef; - -void -package_name(self) - SV *self - PREINIT: - register HE *he; - PPCODE: - if ( ! SvROK(self) ) { - die("Cannot call package_name as a class method"); - } - - if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(package_name), 0, HASH_FOR(package_name))) ) - XPUSHs(HeVAL(he)); - else - ST(0) = &PL_sv_undef; - -void -body(self) - SV *self - PREINIT: - register HE *he; - PPCODE: - if ( ! SvROK(self) ) { - die("Cannot call body as a class method"); - } - - if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(body), 0, HASH_FOR(body))) ) - XPUSHs(HeVAL(he)); - else - ST(0) = &PL_sv_undef; +BOOT: + INSTALL_SIMPLE_READER(Method, name); + INSTALL_SIMPLE_READER(Method, package_name); + INSTALL_SIMPLE_READER(Method, body); diff --git a/xs/Package.xs b/xs/Package.xs index eaac489..ce8d390 100644 --- a/xs/Package.xs +++ b/xs/Package.xs @@ -35,17 +35,5 @@ get_all_package_symbols(self, filter=TYPE_FILTER_NONE) symbols = mop_get_all_package_symbols(stash, filter); PUSHs(sv_2mortal(newRV_noinc((SV *)symbols))); -void -name(self) - SV *self - PREINIT: - register HE *he; - PPCODE: - if ( ! SvROK(self) ) { - die("Cannot call name as a class method"); - } - - if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(package), 0, HASH_FOR(package))) ) - XPUSHs(HeVAL(he)); - else - ST(0) = &PL_sv_undef; +BOOT: + INSTALL_SIMPLE_READER_WITH_KEY(Package, name, package);