Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "xshelper.h"
- #define IsObject(sv) (SvROK(sv) && SvOBJECT(SvRV(sv)))
- #define IsArrayRef(sv) (SvROK(sv) && !SvOBJECT(SvRV(sv)) && SvTYPE(SvRV(sv)) == SVt_PVAV)
- #define IsHashRef(sv) (SvROK(sv) && !SvOBJECT(SvRV(sv)) && SvTYPE(SvRV(sv)) == SVt_PVHV)
- #define IsCodeRef(sv) (SvROK(sv) && !SvOBJECT(SvRV(sv)) && SvTYPE(SvRV(sv)) == SVt_PVCV)
- #define XSCON_xc_stash(a) ( (HV*)XSCON_av_at((a), XSCON_XC_STASH) )
- static HV*
- xscon_buildargs(char* const klass, I32 ax, I32 items) {
- HV* args;
- /* shift @_ */
- ax++;
- items--;
- if(items == 1){
- SV* const args_ref = ST(0);
- if(!IsHashRef(args_ref)){
- croak("Single parameters to new() must be a HASH ref");
- }
- args = newHVhv((HV*)SvRV(args_ref));
- sv_2mortal((SV*)args);
- }
- else{
- I32 i;
- if( (items % 2) != 0 ){
- croak("Odd number of parameters to new()");
- }
- args = newHV_mortal();
- for(i = 0; i < items; i += 2){
- (void)hv_store_ent(args, ST(i), newSVsv(ST(i+1)), 0U);
- }
- }
- return args;
- }
- SV*
- xscon_create_instance(char* const klass) {
- SV* instance;
- instance = sv_bless( newRV_noinc((SV*)newHV()), gv_stashpv(klass, 1) );
- return sv_2mortal(instance);
- }
- static void
- xscon_initialize_object(char* const klass, SV* const object, HV* const args, bool const is_cloning) {
- assert(object);
- assert(SvTYPE(object) == SVt_PVHV);
- assert(args);
- assert(SvTYPE(args) == SVt_PVHV);
- if(mg_find((SV*)args, PERL_MAGIC_tied)){
- croak("You cannot use tied HASH reference as initializing arguments");
- }
- HV* const stash = gv_stashpv(klass, 1);
- assert(stash != NULL);
- /* find out allowed attributes */
- SV** const HAS_globref = hv_fetch(stash, "XSCON_HAS", 9, 0);
- AV* const HAS_attrs = GvAV(*HAS_globref);
- I32 const HAS_len = av_len(HAS_attrs) + 1;
- /* copy allowed attributes */
- I32 i;
- SV* attr;
- SV** tmp;
- char* keyname;
- I32 keylen;
- for (i = 0; i < HAS_len; i++) {
- tmp = av_fetch(HAS_attrs, i, 0);
- assert(tmp);
- attr = *tmp;
- keyname = SvPV(attr, keylen);
- if (hv_exists(args, keyname, keylen)) {
- SV** val = hv_fetch(args, keyname, keylen, 0);
- SV* val2 = newSVsv(*val);
- sv_dump(val2);
- SV** val3 = hv_store(object, keyname, keylen, val2, 0);
- sv_dump(*val3);
- SvREFCNT_inc(*val3); //
- }
- }
- }
- static void
- xscon_buildall(SV* const object, SV* const args) {
- /* todo */
- }
- MODULE = Class::XSConstructor PACKAGE = Class::XSConstructor
- void
- new(SV* klass, ...)
- CODE:
- {
- char* klassname;
- SV* args;
- SV* object;
- klassname = SvROK(klass) ? sv_reftype(SvRV(klass), 1) : SvPV_nolen_const(klass);
- args = newRV_inc((SV*)xscon_buildargs(klassname, ax, items));
- sv_2mortal(args);
- object = xscon_create_instance(klassname);
- xscon_initialize_object(klassname, object, (HV*)SvRV(args), FALSE);
- xscon_buildall(object, args);
- ST(0) = object; /* because object is mortal, we should return it as is */
- XSRETURN(1);
- }
Add Comment
Please, Sign In to add comment