simplify has_method check
[gitmo/Class-MOP.git] / MOP.xs
diff --git a/MOP.xs b/MOP.xs
index b7dfd03..e4bdb81 100644 (file)
--- a/MOP.xs
+++ b/MOP.xs
@@ -3,9 +3,19 @@
 #include "perl.h"
 #include "XSUB.h"
 
+#define NEED_sv_2pv_flags
 #define NEED_sv_2pv_nolen
 #include "ppport.h"
 
+SV *key_name;
+U32 hash_name;
+
+SV *key_package;
+U32 hash_package;
+
+SV *key_body;
+U32 hash_body;
+
 /*
 get_code_info:
   Pass in a coderef, returns:
@@ -15,8 +25,19 @@ get_code_info:
 
 MODULE = Class::MOP   PACKAGE = Class::MOP
 
+BOOT:
+    key_name = newSVpvs("name");
+    key_body = newSVpvs("body");
+    key_package = newSVpvs("package");
+
+    PERL_HASH(hash_name, "name", 4);
+    PERL_HASH(hash_body, "body", 4);
+    PERL_HASH(hash_package, "package", 7);
+
+
 PROTOTYPES: ENABLE
 
+
 void
 get_code_info(coderef)
   SV* coderef
@@ -51,12 +72,13 @@ get_code_info(coderef)
 MODULE = Class::MOP   PACKAGE = Class::MOP::Package
 
 void
-get_all_package_symbols(package, ...)
-    SV *package
+get_all_package_symbols(self, ...)
+    SV *self
     PROTOTYPE: $;$
     PREINIT:
-        HV *stash;
+        HV *stash = NULL;
         SV *type_filter = NULL;
+        register HE *he;
     PPCODE:
 
         switch ( GIMME_V ) {
@@ -68,21 +90,10 @@ get_all_package_symbols(package, ...)
 
         PUTBACK;
 
-        ENTER;
-        SAVETMPS;
-        PUSHMARK(SP);
-        XPUSHs(package);
-        PUTBACK;
-        call_method("name", 0);
-        SPAGAIN;
-        stash = gv_stashsv(POPs, 0);
-        FREETMPS;
-        LEAVE;
-
-        PUTBACK;
+        if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package)))
+            stash = gv_stashsv(HeVAL(he),0);
 
         if ( stash ) {
-            register HE *entry;
 
             (void)hv_iterinit(stash);
 
@@ -90,17 +101,16 @@ get_all_package_symbols(package, ...)
                 const char *const type = SvPV_nolen(type_filter);
 
 
-                while ((entry = hv_iternext(stash))) {
-                    SV *const gv = hv_iterval(stash, entry);
-                    SV *const key = hv_iterkeysv(entry);
+                while ((he = hv_iternext(stash))) {
+                    SV *const gv = HeVAL(he);
                     SV *sv;
                     char *package = HvNAME(stash);
                     STRLEN pkglen = strlen(package);
+                    char *key;
+                    STRLEN keylen;
                     char *fq;
                     STRLEN fqlen;
 
-                    SPAGAIN;
-
                     switch( SvTYPE(gv) ) {
                         case SVt_PVGV:
                             switch (*type) {
@@ -115,35 +125,34 @@ get_all_package_symbols(package, ...)
                             break;
                         case SVt_RV:
                             /* BAH! constants are horrible */
-                            fqlen = pkglen + SvCUR(key) + 3;
+                            key = HePV(he, keylen);
+                            fqlen = pkglen + keylen + 3;
                             fq = (char *)alloca(fqlen);
-                            snprintf(fq, fqlen, "%s::%s", package, SvPV_nolen(key));
-                            sv = get_cv(fq, 0);
+                            snprintf(fq, fqlen, "%s::%s", package, key);
+                            sv = (SV*)get_cv(fq, 0);
+                            sv_2mortal(sv);
                             break;
                         default:
                             continue;
                     }
 
                     if ( sv ) {
+                        SV *key = hv_iterkeysv(he);
                         SPAGAIN;
                         EXTEND(SP, 2);
                         PUSHs(key);
-                        PUSHs(newRV_noinc(sv));
+                        PUSHs(sv_2mortal(newRV_inc(sv)));
                         PUTBACK;
                     }
                 }
             } else {
                 EXTEND(SP, HvKEYS(stash) * 2);
 
-                while ((entry = hv_iternext(stash))) {
-                    SV *sv;
-                    SPAGAIN;
-                    sv = hv_iterkeysv(entry);
-                    SPAGAIN;
-                    PUSHs(sv);
-                    PUTBACK;
-                    sv = hv_iterval(stash, entry);
+                while ((he = hv_iternext(stash))) {
+                    SV *key = hv_iterkeysv(he);
+                    SV *sv = HeVAL(he);
                     SPAGAIN;
+                    PUSHs(key);
                     PUSHs(sv);
                     PUTBACK;
                 }
@@ -151,3 +160,50 @@ get_all_package_symbols(package, ...)
 
         }
 
+SV *
+name(self)
+    SV *self
+    PREINIT:
+        register HE *he;
+    PPCODE:
+        if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package)))
+            XPUSHs(HeVAL(he));
+        else
+            ST(0) = &PL_sv_undef;
+
+MODULE = Class::MOP   PACKAGE = Class::Attribute
+
+SV *
+name(self)
+    SV *self
+    PREINIT:
+        register HE *he;
+    PPCODE:
+        if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name)))
+            XPUSHs(HeVAL(he));
+        else
+            ST(0) = &PL_sv_undef;
+
+MODULE = Class::MOP   PACKAGE = Class::Method
+
+SV *
+name(self)
+    SV *self
+    PREINIT:
+        register HE *he;
+    PPCODE:
+        if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name)))
+            XPUSHs(HeVAL(he));
+        else
+            ST(0) = &PL_sv_undef;
+
+SV *
+body(self)
+    SV *self
+    PREINIT:
+        register HE *he;
+    PPCODE:
+        if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_body, 0, hash_body)))
+            XPUSHs(HeVAL(he));
+        else
+            ST(0) = &PL_sv_undef;