%PDF- %PDF-
Direktori : /home/opti/optisoftcom/.cpanm/work/1544535406.20768/Class-XSAccessor-1.19/XS/ |
Current File : /home/opti/optisoftcom/.cpanm/work/1544535406.20768/Class-XSAccessor-1.19/XS/Hash.xs |
#include "ppport.h" ## we want hv_fetch but with the U32 hash argument of hv_fetch_ent, so do it ourselves... #ifdef hv_common_key_len # define CXSA_HASH_FETCH(hv, key, len, hash) \ hv_common_key_len((hv), (key), (len), HV_FETCH_JUST_SV, NULL, (hash)) # define CXSA_HASH_FETCH_LVALUE(hv, key, len, hash) \ hv_common_key_len((hv), (key), (len), (HV_FETCH_JUST_SV|HV_FETCH_LVALUE), NULL, (hash)) # define CXSA_HASH_EXISTS(hv, key, len, hash) \ hv_common_key_len((hv), (key), (len), HV_FETCH_ISEXISTS, NULL, (hash)) #else # define CXSA_HASH_FETCH(hv, key, len, hash) hv_fetch((hv), (key), (len), 0) # define CXSA_HASH_FETCH_LVALUE(hv, key, len, hash) hv_fetch((hv), (key), (len), 1) # define CXSA_HASH_EXISTS(hv, key, len, hash) hv_exists((hv), (key), (len)) #endif #ifndef croak_xs_usage #define croak_xs_usage(cv,msg) croak(aTHX_ "Usage: %s(%s)", GvNAME(CvGV(cv)), msg) #endif MODULE = Class::XSAccessor PACKAGE = Class::XSAccessor PROTOTYPES: DISABLE void getter(self) SV* self; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; SV** svp; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(getter); if ((svp = CXSA_HASH_FETCH((HV *)SvRV(self), readfrom->key, readfrom->len, readfrom->hash))) PUSHs(*svp); else XSRETURN_UNDEF; void lvalue_accessor(self) SV* self; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; SV** svp; SV* sv; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(lvalue_accessor); if ((svp = CXSA_HASH_FETCH_LVALUE((HV *)SvRV(self), readfrom->key, readfrom->len, readfrom->hash))) { sv = *svp; sv_upgrade(sv, SVt_PVLV); sv_magic(sv, 0, PERL_MAGIC_ext, Nullch, 0); SvSMAGICAL_on(sv); LvTYPE(sv) = '~'; SvREFCNT_inc(sv); LvTARG(sv) = SvREFCNT_inc(sv); SvMAGIC(sv)->mg_virtual = &cxsa_lvalue_acc_magic_vtable; ST(0) = sv; XSRETURN(1); } else XSRETURN_UNDEF; void setter(self, newvalue) SV* self; SV* newvalue; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(setter); if (NULL == hv_store((HV*)SvRV(self), readfrom->key, readfrom->len, newSVsv(newvalue), readfrom->hash)) croak("Failed to write new value to hash."); PUSHs(newvalue); void chained_setter(self, newvalue) SV* self; SV* newvalue; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(chained_setter); if (NULL == hv_store((HV*)SvRV(self), readfrom->key, readfrom->len, newSVsv(newvalue), readfrom->hash)) croak("Failed to write new value to hash."); PUSHs(self); void accessor(self, ...) SV* self; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; SV** svp; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(accessor); if (items > 1) { SV* newvalue = ST(1); if (NULL == hv_store((HV*)SvRV(self), readfrom->key, readfrom->len, newSVsv(newvalue), readfrom->hash)) croak("Failed to write new value to hash."); PUSHs(newvalue); } else { if ((svp = CXSA_HASH_FETCH((HV *)SvRV(self), readfrom->key, readfrom->len, readfrom->hash))) PUSHs(*svp); else XSRETURN_UNDEF; } void chained_accessor(self, ...) SV* self; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; SV** svp; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(chained_accessor); if (items > 1) { SV* newvalue = ST(1); if (NULL == hv_store((HV*)SvRV(self), readfrom->key, readfrom->len, newSVsv(newvalue), readfrom->hash)) croak("Failed to write new value to hash."); PUSHs(self); } else { if ((svp = CXSA_HASH_FETCH((HV *)SvRV(self), readfrom->key, readfrom->len, readfrom->hash))) PUSHs(*svp); else XSRETURN_UNDEF; } void exists_predicate(self) SV* self; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(exists_predicate); if ( CXSA_HASH_EXISTS((HV *)SvRV(self), readfrom->key, readfrom->len, readfrom->hash) != NULL ) XSRETURN_YES; else XSRETURN_NO; void defined_predicate(self) SV* self; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; SV** svp; PPCODE: CXA_CHECK_HASH(self); CXAH_OPTIMIZE_ENTERSUB(defined_predicate); if ( ((svp = CXSA_HASH_FETCH((HV *)SvRV(self), readfrom->key, readfrom->len, readfrom->hash))) && SvOK(*svp) ) XSRETURN_YES; else XSRETURN_NO; void constructor(class, ...) SV* class; PREINIT: int iStack; HV* hash; SV* obj; const char* classname; PPCODE: CXAH_OPTIMIZE_ENTERSUB(constructor); classname = SvROK(class) ? sv_reftype(SvRV(class), 1) : SvPV_nolen_const(class); hash = newHV(); obj = sv_bless(newRV_noinc((SV *)hash), gv_stashpv(classname, 1)); if (items > 1) { /* if @_ - 1 (for $class) is even: most compilers probably convert items % 2 into this, but just in case */ if (items & 1) { for (iStack = 1; iStack < items; iStack += 2) { /* we could check for the hv_store_ent return value, but perl doesn't in this situation (see pp_anonhash) */ (void)hv_store_ent(hash, ST(iStack), newSVsv(ST(iStack+1)), 0); } } else { croak("Uneven number of arguments to constructor."); } } PUSHs(sv_2mortal(obj)); void constant_false(self) SV *self; PPCODE: PERL_UNUSED_VAR(self); CXAH_OPTIMIZE_ENTERSUB(constant_false); { XSRETURN_NO; } void constant_true(self) SV* self; PPCODE: PERL_UNUSED_VAR(self); CXAH_OPTIMIZE_ENTERSUB(constant_true); { XSRETURN_YES; } void test(self, ...) SV* self; INIT: /* Get the const hash key struct from the global storage */ const autoxs_hashkey * readfrom = CXAH_GET_HASHKEY; SV** svp; PPCODE: CXA_CHECK_HASH(self); warn("cxah: accessor: inside test"); CXAH_OPTIMIZE_ENTERSUB_TEST(test); if (items > 1) { SV* newvalue = ST(1); if (NULL == hv_store((HV*)SvRV(self), readfrom->key, readfrom->len, newSVsv(newvalue), readfrom->hash)) croak("Failed to write new value to hash."); PUSHs(newvalue); } else { if ((svp = CXSA_HASH_FETCH((HV *)SvRV(self), readfrom->key, readfrom->len, readfrom->hash))) PUSHs(*svp); else XSRETURN_UNDEF; } void newxs_getter(namesv, keysv) SV *namesv; SV *keysv; ALIAS: Class::XSAccessor::newxs_lvalue_accessor = 1 Class::XSAccessor::newxs_predicate = 2 Class::XSAccessor::newxs_defined_predicate = 3 Class::XSAccessor::newxs_exists_predicate = 4 PREINIT: char *name; char *key; STRLEN namelen, keylen; PPCODE: name = SvPV(namesv, namelen); key = SvPV(keysv, keylen); switch (ix) { case 0: /* newxs_getter */ INSTALL_NEW_CV_HASH_OBJ(name, CXAH(getter), key, keylen); break; case 1: { /* newxs_lvalue_accessor */ CV* cv; INSTALL_NEW_CV_HASH_OBJ(name, CXAH(lvalue_accessor), key, keylen); /* Make the CV lvalue-able. "cv" was set by the previous macro */ CvLVALUE_on(cv); } break; case 2: case 3: INSTALL_NEW_CV_HASH_OBJ(name, CXAH(defined_predicate), key, keylen); break; case 4: INSTALL_NEW_CV_HASH_OBJ(name, CXAH(exists_predicate), key, keylen); break; default: croak("Invalid alias of newxs_getter called"); break; } void newxs_setter(namesv, keysv, chained) SV *namesv; SV *keysv; bool chained; ALIAS: Class::XSAccessor::newxs_accessor = 1 PREINIT: char *name; char *key; STRLEN namelen, keylen; PPCODE: name = SvPV(namesv, namelen); key = SvPV(keysv, keylen); if (ix == 0) { /* newxs_setter */ if (chained) INSTALL_NEW_CV_HASH_OBJ(name, CXAH(chained_setter), key, keylen); else INSTALL_NEW_CV_HASH_OBJ(name, CXAH(setter), key, keylen); } else { /* newxs_accessor */ if (chained) INSTALL_NEW_CV_HASH_OBJ(name, CXAH(chained_accessor), key, keylen); else INSTALL_NEW_CV_HASH_OBJ(name, CXAH(accessor), key, keylen); } void newxs_constructor(namesv) SV *namesv; PREINIT: char *name; STRLEN namelen; PPCODE: name = SvPV(namesv, namelen); INSTALL_NEW_CV(name, CXAH(constructor)); void newxs_boolean(namesv, truth) SV *namesv; bool truth; PREINIT: char *name; STRLEN namelen; PPCODE: name = SvPV(namesv, namelen); if (truth) INSTALL_NEW_CV(name, CXAH(constant_true)); else INSTALL_NEW_CV(name, CXAH(constant_false)); void newxs_test(namesv, keysv) SV *namesv; SV *keysv; PREINIT: char *name; char *key; STRLEN namelen, keylen; PPCODE: name = SvPV(namesv, namelen); key = SvPV(keysv, keylen); INSTALL_NEW_CV_HASH_OBJ(name, CXAH(test), key, keylen);