Code tidy. No functionality changed
[gitmo/Class-MOP.git] / xs / MethodConstructor.xs
CommitLineData
87cfe982 1#include "mop.h"
2
3
87cfe982 4static MGVTBL mop_constructor_vtbl;
5
6static HV*
7mop_build_args(pTHX_ CV* const cv, I32 const ax, I32 const items){
8 HV* args;
9 if(items == 1){
10 SV* const sv = ST(0);
11 SvGETMAGIC(sv);
12 if(!(SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV)){
13 croak("Single arguments to %s() must be a HASH ref", GvNAME(CvGV(cv)));
14 }
15 args = (HV*)SvRV(sv);
16 }
17 else{
18 I32 i;
19
20 if( items % 2 ){
21 croak("Odd number of arguments for %s()", GvNAME(CvGV(cv)));
22 }
23
24 args = newHV();
25 sv_2mortal((SV*)args);
26
27 for(i = 0; i < items; i += 2){
28 SV* const key = ST(i);
29 SV* const value = ST(i+1);
30 (void)hv_store_ent(args, key, value, 0U);
31 SvREFCNT_inc_simple_void_NN(value);
32 }
33 }
34 return args;
35}
36
87cfe982 37
38XS(mop_xs_constructor);
39XS(mop_xs_constructor)
40{
41 dVAR; dXSARGS;
42 dMOP_mg(cv);
43 AV* const attrs = (AV*)MOP_mg_obj(mg);
44 SV* klass;
45 HV* stash;
46 SV* instance;
47 I32 i;
48 I32 len;
49 HV* args;
50
51 assert(SvTYPE(attrs) == SVt_PVAV);
52
53 if(items < 0){
54 croak("Not enough arguments for %s()", GvNAME(CvGV(cv)));
55 }
56
57 klass = ST(0);
58
59 if(SvROK(klass)){
60 croak("The constructor must be called as a class method");
61 }
62
87cfe982 63 args = mop_build_args(aTHX_ cv, ax+1, items-1);
64
5bd0f967 65 stash = gv_stashsv(klass, TRUE);
87cfe982 66 if( stash != GvSTASH(CvGV(cv)) ){
67 SV* const metaclass = mop_class_of(aTHX_ klass);
68 dSP;
69
70 PUSHMARK(SP);
71 EXTEND(SP, 2);
72 PUSHs(metaclass);
73 mPUSHs(newRV_inc((SV*)args));
74 PUTBACK;
75
76 call_method("new_object", GIMME_V);
77 return;
78 }
79
80 instance = sv_2mortal( MOP_mg_create_instance(mg, stash) );
81 if(!IsObject(instance)){
82 croak("create_instance() did not return an object instance");
83 }
84
85 len = AvFILLp(attrs) + 1;
86 for(i = 0; i < len; i++){
87 mop_attr_initialize_instance_slot(aTHX_ AvARRAY(attrs)[i], MOP_mg_vtbl(mg), instance, args);
88 }
89
90 ST(0) = instance;
91 XSRETURN(1);
92}
93
94
95static CV*
96mop_generate_constructor_method_xs(pTHX_ SV* const constructor, mop_instance_vtbl* const vtbl){
97 SV* const metaclass = mop_call0(aTHX_ constructor, mop_associated_metaclass);
98
99 CV* const xsub = newXS(NULL, mop_xs_constructor, __FILE__);
100 MAGIC* mg;
101 AV* attrs;
102
103 sv_2mortal((SV*)xsub);
104
105 attrs = mop_class_get_all_attributes(aTHX_ metaclass);
106 mg = sv_magicext((SV*)xsub, (SV*)attrs, PERL_MAGIC_ext, &mop_constructor_vtbl, (char*)vtbl, 0);
107 SvREFCNT_dec(attrs);
108 CvXSUBANY(xsub).any_ptr = (void*)mg;
109
110 return xsub;
111}
112
113
114MODULE = Class::MOP::Method::Constructor PACKAGE = Class::MOP::Method::Constructor
115
116PROTOTYPES: DISABLE
117
b66ddbab 118VERSIONCHECK: DISABLE
119
87cfe982 120BOOT:
121 INSTALL_SIMPLE_READER(Method::Constructor, options);
122 INSTALL_SIMPLE_READER(Method::Constructor, associated_metaclass);
123
124CV*
125_generate_constructor_method_xs(SV* self, void* instance_vtbl)
126CODE:
127 RETVAL = mop_generate_constructor_method_xs(aTHX_ self, instance_vtbl);
128OUTPUT:
129 RETVAL
130