Add assert to mi methods
[gitmo/Class-MOP.git] / xs / Instance.xs
CommitLineData
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
12static SV*
346d43ef 13mop_instance_create_instance(pTHX_ HV* const stash) {
1124d821 14 assert(stash);
346d43ef 15 return sv_bless( newRV_noinc((SV*)newHV()), stash );
353c6152 16}
17
18static bool
346d43ef 19mop_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
26static SV*
346d43ef 27mop_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
36static SV*
346d43ef 37mop_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
50static SV*
346d43ef 51mop_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
58static void
346d43ef 59mop_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
70static 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
80const mop_instance_vtbl*
81mop_get_default_instance_vtbl(pTHX){
82 return &mop_default_instance;
83}
84
85
8a2e4cdb 86MODULE = Class::MOP::Instance PACKAGE = Class::MOP::Instance
87
88PROTOTYPES: DISABLE
89
90BOOT:
91 INSTALL_SIMPLE_READER(Instance, associated_metaclass);
353c6152 92
93void*
94can_xs(SV* self)
95PREINIT:
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 100CODE:
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 }
109OUTPUT:
110 RETVAL
111