Commit | Line | Data |
8a2e4cdb |
1 | #include "mop.h" |
2 | |
353c6152 |
3 | #define CHECK_INSTANCE(instance) STMT_START{ \ |
4 | if(!(SvROK(instance) && SvTYPE(SvRV(instance)) == SVt_PVHV)){ \ |
5 | croak("Invalid object"); \ |
6 | } \ |
7 | if(SvTIED_mg(SvRV(instance), PERL_MAGIC_tied)){ \ |
8 | croak("MOP::Instance: tied HASH is not yet supported"); \ |
9 | } \ |
10 | } STMT_END |
11 | |
12 | static SV* |
346d43ef |
13 | mop_instance_create_instance(pTHX_ HV* const stash) { |
1124d821 |
14 | assert(stash); |
346d43ef |
15 | return sv_bless( newRV_noinc((SV*)newHV()), stash ); |
353c6152 |
16 | } |
17 | |
18 | static bool |
346d43ef |
19 | mop_instance_has_slot(pTHX_ SV* const instance, SV* const slot) { |
1124d821 |
20 | assert(instance); |
21 | assert(slot); |
353c6152 |
22 | CHECK_INSTANCE(instance); |
346d43ef |
23 | return hv_exists_ent((HV*)SvRV(instance), slot, 0U); |
353c6152 |
24 | } |
25 | |
26 | static SV* |
346d43ef |
27 | mop_instance_get_slot(pTHX_ SV* const instance, SV* const slot) { |
353c6152 |
28 | HE* he; |
1124d821 |
29 | assert(instance); |
30 | assert(slot); |
353c6152 |
31 | CHECK_INSTANCE(instance); |
346d43ef |
32 | he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); |
353c6152 |
33 | return he ? HeVAL(he) : NULL; |
34 | } |
35 | |
36 | static SV* |
346d43ef |
37 | mop_instance_set_slot(pTHX_ SV* const instance, SV* const slot, SV* const value) { |
353c6152 |
38 | HE* he; |
39 | SV* sv; |
1124d821 |
40 | assert(instance); |
41 | assert(slot); |
42 | assert(value); |
353c6152 |
43 | CHECK_INSTANCE(instance); |
346d43ef |
44 | he = hv_fetch_ent((HV*)SvRV(instance), slot, TRUE, 0U); |
353c6152 |
45 | sv = HeVAL(he); |
46 | sv_setsv_mg(sv, value); |
47 | return sv; |
48 | } |
49 | |
50 | static SV* |
346d43ef |
51 | mop_instance_delete_slot(pTHX_ SV* const instance, SV* const slot) { |
1124d821 |
52 | assert(instance); |
53 | assert(slot); |
353c6152 |
54 | CHECK_INSTANCE(instance); |
346d43ef |
55 | return hv_delete_ent((HV*)SvRV(instance), slot, 0, 0U); |
353c6152 |
56 | } |
57 | |
58 | static void |
346d43ef |
59 | mop_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot) { |
353c6152 |
60 | HE* he; |
1124d821 |
61 | assert(instance); |
62 | assert(slot); |
353c6152 |
63 | CHECK_INSTANCE(instance); |
346d43ef |
64 | he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); |
86395d9a |
65 | if(he){ |
66 | sv_rvweaken(HeVAL(he)); |
67 | } |
353c6152 |
68 | } |
69 | |
70 | static const mop_instance_vtbl mop_default_instance = { |
71 | mop_instance_create_instance, |
72 | mop_instance_has_slot, |
73 | mop_instance_get_slot, |
74 | mop_instance_set_slot, |
75 | mop_instance_delete_slot, |
76 | mop_instance_weaken_slot, |
77 | }; |
78 | |
79 | |
80 | const mop_instance_vtbl* |
81 | mop_get_default_instance_vtbl(pTHX){ |
82 | return &mop_default_instance; |
83 | } |
84 | |
85 | |
8a2e4cdb |
86 | MODULE = Class::MOP::Instance PACKAGE = Class::MOP::Instance |
87 | |
88 | PROTOTYPES: DISABLE |
89 | |
90 | BOOT: |
91 | INSTALL_SIMPLE_READER(Instance, associated_metaclass); |
353c6152 |
92 | |
93 | void* |
94 | can_xs(SV* self) |
95 | PREINIT: |
e5180c51 |
96 | CV* const default_method = get_cv("Class::MOP::Instance::get_slot_value", FALSE); |
353c6152 |
97 | SV* const can = newSVpvs_flags("can", SVs_TEMP); |
e5180c51 |
98 | SV* const method = newSVpvs_flags("get_slot_value", SVs_TEMP); |
99 | SV* code_ref; |
353c6152 |
100 | CODE: |
e5180c51 |
101 | /* $self->can("get_slot_value") == \&Class::MOP::Instance::get_slot_value */ |
102 | code_ref = mop_call1(aTHX_ self, can, method); |
103 | if(SvROK(code_ref) && SvRV(code_ref) == (SV*)default_method){ |
353c6152 |
104 | RETVAL = (void*)&mop_default_instance; |
105 | } |
106 | else{ |
107 | RETVAL = NULL; |
108 | } |
109 | OUTPUT: |
110 | RETVAL |
111 | |