#include "mop.h"
void
-mop_call_xs (pTHX_ void (*subaddr) (pTHX_ CV *), CV *cv, SV **mark)
+mop_call_xs (pTHX_ XSPROTO(subaddr), CV *cv, SV **mark)
{
- dSP;
- PUSHMARK(mark);
- (*subaddr)(aTHX_ cv);
- PUTBACK;
+ dSP;
+ PUSHMARK(mark);
+ (*subaddr)(aTHX_ cv);
+ PUTBACK;
}
#if PERL_VERSION >= 10
}
int
-get_code_info (SV *coderef, char **pkg, char **name)
+mop_get_code_info (SV *coderef, char **pkg, char **name)
{
if (!SvOK(coderef) || !SvROK(coderef) || SvTYPE(SvRV(coderef)) != SVt_PVCV) {
return 0;
we hit it without the guard, we segfault. The slightly odd return
value strikes me as an improvement (mst)
*/
-#ifdef isGV_with_GP
+
if ( isGV_with_GP(CvGV(coderef)) ) {
-#endif
- *pkg = HvNAME( GvSTASH(CvGV(coderef)) );
+ GV *gv = CvGV(coderef);
+ *pkg = HvNAME( GvSTASH(gv) ? GvSTASH(gv) : CvSTASH(coderef) );
*name = GvNAME( CvGV(coderef) );
-#ifdef isGV_with_GP
} else {
*pkg = "__UNKNOWN__";
*name = "__ANON__";
}
-#endif
return 1;
}
void
-get_package_symbols (HV *stash, type_filter_t filter, get_package_symbols_cb_t cb, void *ud)
+mop_get_package_symbols (HV *stash, type_filter_t filter, get_package_symbols_cb_t cb, void *ud)
{
HE *he;
but that's the API */
key = HePV(he, keylen);
package = HvNAME(stash);
- fq = newSVpvf("%s::%s", package, key);
+ fq = sv_2mortal(newSVpvf("%s::%s", package, key));
sv = (SV *)get_cv(SvPV_nolen(fq), 0);
break;
}
}
HV *
-get_all_package_symbols (HV *stash, type_filter_t filter)
+mop_get_all_package_symbols (HV *stash, type_filter_t filter)
{
HV *ret = newHV ();
- get_package_symbols (stash, filter, collect_all_symbols, ret);
+ mop_get_package_symbols (stash, filter, collect_all_symbols, ret);
return ret;
}
+
+#define DECLARE_KEY(name) { #name, #name, NULL, 0 }
+#define DECLARE_KEY_WITH_VALUE(name, value) { #name, value, NULL, 0 }
+
+/* the order of these has to match with those in mop.h */
+static struct {
+ const char *name;
+ const char *value;
+ SV *key;
+ U32 hash;
+} prehashed_keys[key_last] = {
+ DECLARE_KEY(name),
+ DECLARE_KEY(package),
+ DECLARE_KEY(package_name),
+ DECLARE_KEY(body),
+ DECLARE_KEY_WITH_VALUE(package_cache_flag, "_package_cache_flag"),
+ DECLARE_KEY(methods),
+ DECLARE_KEY(VERSION),
+ DECLARE_KEY(ISA)
+};
+
+SV *
+mop_prehashed_key_for (mop_prehashed_key_t key)
+{
+ return prehashed_keys[key].key;
+}
+
+U32
+mop_prehashed_hash_for (mop_prehashed_key_t key)
+{
+ return prehashed_keys[key].hash;
+}
+
+void
+mop_prehash_keys ()
+{
+ int i;
+ for (i = 0; i < key_last; i++) {
+ const char *value = prehashed_keys[i].value;
+ prehashed_keys[i].key = newSVpv(value, strlen(value));
+ PERL_HASH(prehashed_keys[i].hash, value, strlen(value));
+ }
+}
+
+XS(mop_xs_simple_reader)
+{
+#ifdef dVAR
+ dVAR; dXSARGS;
+#else
+ dXSARGS;
+#endif
+ register HE *he;
+ mop_prehashed_key_t key = (mop_prehashed_key_t)CvXSUBANY(cv).any_i32;
+ SV *self;
+
+ if (items != 1) {
+ croak("expected exactly one argument");
+ }
+
+ self = ST(0);
+
+ 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))) {
+ ST(0) = HeVAL(he);
+ }
+ else {
+ ST(0) = &PL_sv_undef;
+ }
+
+ XSRETURN(1);
+}
+