changelog
[gitmo/Package-Stash-XS.git] / XS.xs
diff --git a/XS.xs b/XS.xs
index db34488..73ca16f 100644 (file)
--- a/XS.xs
+++ b/XS.xs
 #define savesvpv(s) savepv(SvPV_nolen(s))
 #endif
 
+#ifndef GvCV_set
+#define GvCV_set(gv, cv) (GvCV(gv) = (CV*)(cv))
+#endif
+
 /* HACK: scalar slots are always populated on perl < 5.10, so treat undef
  * as nonexistent. this is consistent with the previous behavior of the pure
  * perl version of this module (since this is the behavior that perl sees
@@ -68,7 +72,7 @@
 } while (0)
 #define GvSetCV(g,v) do {               \
     SvREFCNT_dec(GvCV(g));              \
-    if ((GvCV(g) = (CV*)(v))) {         \
+    if ((GvCV_set(g, v))) {             \
         GvIMPORTED_CV_on(g);            \
         GvASSUMECV_on(g);               \
     }                                   \
@@ -193,19 +197,18 @@ void _deconstruct_variable_name(SV *variable, varspec_t *varspec)
 void _deconstruct_variable_hash(HV *variable, varspec_t *varspec)
 {
     HE *val;
-    STRLEN len;
 
     val = hv_fetch_ent(variable, name_key, 0, name_hash);
     if (!val)
         croak("The 'name' key is required in variable specs");
 
-    varspec->name = sv_2mortal(newSVhe(val));
+    varspec->name = sv_2mortal(newSVsv(HeVAL(val)));
 
     val = hv_fetch_ent(variable, type_key, 0, type_hash);
     if (!val)
         croak("The 'type' key is required in variable specs");
 
-    varspec->type = string_to_vartype(HePV(val, len));
+    varspec->type = string_to_vartype(SvPV_nolen(HeVAL(val)));
 }
 
 int _valid_for_type(SV *value, vartype_t type)
@@ -214,11 +217,11 @@ int _valid_for_type(SV *value, vartype_t type)
 
     switch (type) {
     case VAR_SCALAR:
-        return sv_type == SVt_NULL ||
-               sv_type == SVt_IV   ||
-               sv_type == SVt_NV   ||
-               sv_type == SVt_PV   ||
-               sv_type == SVt_RV;
+        /* XXX: something weird is going on here - apparently values can
+         * be SVt_NULL but also be SvROK (and also, SVt_NULL isn't SvOK) */
+        if (sv_type == SVt_NULL)
+            return 1;
+        return SvROK(value) ? SvOK(SvRV(value)) : SvOK(value);
     case VAR_ARRAY:
         return sv_type == SVt_PVAV;
     case VAR_HASH:
@@ -348,8 +351,6 @@ new(class, package_name)
     SV *package_name
   PREINIT:
     HV *instance;
-    HV *namespace;
-    SV *nsref;
   CODE:
     if (!SvPOK(package_name))
         croak("The constructor argument must be the name of a package");
@@ -361,13 +362,6 @@ new(class, package_name)
         SvREFCNT_dec(instance);
         croak("Couldn't initialize the 'name' key, hv_store failed");
     }
-    namespace = gv_stashpv(SvPV_nolen(package_name), GV_ADD);
-    nsref = newRV_inc((SV*)namespace);
-    if (!hv_store(instance, "namespace", 9, nsref, 0)) {
-        SvREFCNT_dec(nsref);
-        SvREFCNT_dec(instance);
-        croak("Couldn't initialize the 'namespace' key, hv_store failed");
-    }
 
     RETVAL = sv_bless(newRV_noinc((SV*)instance), gv_stashsv(class, 0));
   OUTPUT:
@@ -395,7 +389,24 @@ namespace(self)
     if (!sv_isobject(self))
         croak("Can't call namespace as a class method");
     slot = hv_fetch_ent((HV*)SvRV(self), namespace_key, 0, namespace_hash);
-    RETVAL = slot ? SvREFCNT_inc_simple_NN(HeVAL(slot)) : &PL_sv_undef;
+    if (slot) {
+        RETVAL = SvREFCNT_inc_simple_NN(HeVAL(slot));
+    }
+    else {
+        HV *namespace;
+        SV *nsref, *package_name;
+
+        package_name = _get_name(self);
+        namespace = gv_stashpv(SvPV_nolen(package_name), GV_ADD);
+        nsref = newRV_inc((SV*)namespace);
+        sv_rvweaken(nsref);
+        if (!hv_store((HV*)SvRV(self), "namespace", 9, nsref, 0)) {
+            SvREFCNT_dec(nsref);
+            SvREFCNT_dec(self);
+            croak("Couldn't initialize the 'namespace' key, hv_store failed");
+        }
+        RETVAL = SvREFCNT_inc_simple_NN(nsref);
+    }
   OUTPUT:
     RETVAL