convert the rest of the simple readers in cmop to xs
[gitmo/Class-MOP.git] / xs / HasMethods.xs
CommitLineData
9b871d79 1#include "mop.h"
2
3SV *mop_method_metaclass;
4SV *mop_associated_metaclass;
5SV *mop_wrap;
6
7static void
8mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map)
9{
9b871d79 10 char *method_name;
11 I32 method_name_len;
e4679e2c 12 SV *method;
9b871d79 13 HV *symbols;
9b871d79 14
15 symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE);
16 sv_2mortal((SV*)symbols);
9b871d79 17
e4679e2c 18 (void)hv_iterinit(map);
19 while ((method = hv_iternextsv(map, &method_name, &method_name_len))) {
20 SV *body;
21 SV *stash_slot;
22
23 if (!SvROK(method)) {
9b871d79 24 continue;
25 }
26
e4679e2c 27 if (sv_isobject(method)) {
28 /* $method_object->body() */
29 body = mop_call0(aTHX_ method, KEY_FOR(body));
30 }
31 else {
32 body = method;
9b871d79 33 }
34
e4679e2c 35 stash_slot = *hv_fetch(symbols, method_name, method_name_len, TRUE);
36 if (SvROK(stash_slot) && ((CV*)SvRV(body)) == ((CV*)SvRV(stash_slot))) {
37 continue;
9b871d79 38 }
e4679e2c 39
40 /* $map->{$method_name} = undef */
41 sv_setsv(method, &PL_sv_undef);
9b871d79 42 }
43}
44
45MODULE = Class::MOP::Mixin::HasMethods PACKAGE = Class::MOP::Mixin::HasMethods
46
47PROTOTYPES: DISABLE
48
49void
38bcde3f 50_method_map(self)
9b871d79 51 SV *self
52 PREINIT:
53 HV *const obj = (HV *)SvRV(self);
54 SV *const class_name = HeVAL( hv_fetch_ent(obj, KEY_FOR(package), 0, HASH_FOR(package)) );
55 HV *const stash = gv_stashsv(class_name, 0);
56 UV current;
57 SV *cache_flag;
58 SV *map_ref;
59 PPCODE:
60 if (!stash) {
61 mXPUSHs(newRV_noinc((SV *)newHV()));
62 return;
63 }
64
65 current = mop_check_package_cache_flag(aTHX_ stash);
66 cache_flag = HeVAL( hv_fetch_ent(obj, KEY_FOR(package_cache_flag), TRUE, HASH_FOR(package_cache_flag)));
67 map_ref = HeVAL( hv_fetch_ent(obj, KEY_FOR(methods), TRUE, HASH_FOR(methods)));
68
69 /* $self->{methods} does not yet exist (or got deleted) */
70 if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
71 SV *new_map_ref = newRV_noinc((SV *)newHV());
72 sv_2mortal(new_map_ref);
73 sv_setsv(map_ref, new_map_ref);
74 }
75
76 if ( !SvOK(cache_flag) || SvUV(cache_flag) != current ) {
77 mop_update_method_map(aTHX_ self, class_name, stash, (HV *)SvRV(map_ref));
78 sv_setuv(cache_flag, mop_check_package_cache_flag(aTHX_ stash)); /* update_cache_flag() */
79 }
80
81 XPUSHs(map_ref);
82
83BOOT:
84 mop_method_metaclass = newSVpvs("method_metaclass");
85 mop_associated_metaclass = newSVpvs("associated_metaclass");
86 mop_wrap = newSVpvs("wrap");
53362bcb 87 INSTALL_SIMPLE_READER(Mixin::HasMethods, method_metaclass);
88 INSTALL_SIMPLE_READER(Mixin::HasMethods, wrapped_method_metaclass);