static inline VALUE mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) { rb_vm_method_t *m = rb_vm_get_method(klass, obj, id, scope); assert(m != NULL); if (m->node) { const int flag = m->node->flags & NOEX_MASK; if (scope && flag != NOEX_PUBLIC) { const char *v = ""; switch (flag) { case NOEX_PRIVATE: v = "private"; break; case NOEX_PROTECTED: v = "protected"; break; } rb_name_error(id, "method `%s' for %s `%s' is %s", rb_id2name(id), (TYPE(klass) == T_MODULE) ? "module" : "class", rb_class2name(klass), v); } } return Data_Wrap_Struct(mclass, NULL, NULL, m); }
static void remove_method(VALUE klass, ID mid) { st_data_t key, data; rb_method_entry_t *me = 0; if (klass == rb_cObject) { rb_secure(4); } if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't remove method"); } rb_check_frozen(klass); if (mid == object_id || mid == id__send__ || mid == idInitialize) { rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); } if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || !(me = (rb_method_entry_t *)data) || (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { rb_name_error(mid, "method `%s' not defined in %s", rb_id2name(mid), rb_class2name(klass)); } key = (st_data_t)mid; st_delete(RCLASS_M_TBL(klass), &key, &data); rb_vm_check_redefinition_opt_method(me, klass); rb_clear_cache_for_undef(klass, mid); rb_unlink_method_entry(me); CALL_METHOD_HOOK(klass, removed, mid); }
static VALUE step_initialize( int argc, VALUE *argv, VALUE self ) { VALUE a, b=Qnil, c=Qnil, d=Qnil, e=Qnil; rb_scan_args(argc, argv, "13", &a, &b, &c, &d); /* Selfs are immutable, so that they should be initialized only once. */ if (rb_ivar_defined(self, id_beg)) { rb_name_error(rb_intern("initialize"), "`initialize' called twice"); } if (rb_obj_is_kind_of(a,rb_cRange)) { if (argc>3) { rb_raise(rb_eArgError, "extra argument"); } d = c; c = b; e = rb_funcall(a, rb_intern("exclude_end?"), 0); //b = rb_ivar_get(a, id_end); b = rb_funcall(a, id_end, 0); //a = rb_ivar_get(a, id_beg); a = rb_funcall(a, id_beg, 0); } step_init(self, a, b, c, d, e); return Qnil; }
static VALUE rb_struct_set(VALUE obj, SEL sel, VALUE val) { VALUE members, slot; long i; // foo=: -> foo char buf[100]; const size_t s = strlcpy(buf, sel_getName(sel), sizeof buf); buf[s - 2] = '\0'; ID field = rb_intern(buf); members = rb_struct_members(obj); rb_struct_modify(obj); for (i=0; i<RARRAY_LEN(members); i++) { slot = RARRAY_AT(members, i); if (SYM2ID(slot) == field) { GC_WB(&RSTRUCT_PTR(obj)[i], val); return val; } } rb_name_error(rb_frame_this_func(), "`%s' is not a struct member", rb_id2name(field)); return Qnil; /* not reached */ }
void rb_attr(VALUE klass, ID id, int read, int write, int ex) { const char *name; int noex; if (!ex) { noex = NOEX_PUBLIC; } else { // TODO honor current scope ex noex = NOEX_PUBLIC; } if (!rb_is_local_id(id) && !rb_is_const_id(id)) { rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); } name = rb_id2name(id); if (!name) { rb_raise(rb_eArgError, "argument needs to be symbol or string"); } rb_vm_define_attr((Class)klass, name, read, write, noex); if (write) { rb_objc_define_kvo_setter(klass, id); } }
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (RCLASS_RUBY(klass)) { // Only for pure Ruby classes, as Objective-C classes // might be returned from the dynamic resolver. if (rb_class_real(RCLASS_SUPER(klass), true) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), name); } klass = rb_define_class_id(id, super); rb_set_class_path(klass, outer, name); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); return klass; }
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), name); } klass = rb_define_class_id(id, super); rb_set_class_path(klass, outer, name); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); return klass; }
VALUE rb_define_class(const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined(rb_cObject, id)) { klass = rb_const_get(rb_cObject, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } if (!super) { rb_warn("no super class for `%s', Object assumed", name); } klass = rb_define_class_id(id, super); st_add_direct(rb_class_tbl, id, klass); rb_name_class(klass, id); rb_const_set(rb_cObject, id, klass); rb_class_inherited(super, klass); return klass; }
/*! * Defines a class under the namespace of \a outer. * \param outer a class which contains the new class. * \param id name of the new class * \param super a class from which the new class will derive. * NULL means \c Object class. * \return the created class * \throw TypeError if the constant name \a name is already taken but * the constant is not a \c Class. * \throw NameError if the class is already defined but the class can not * be reopened because its superclass is not \a super. * \post top-level constant named \a name refers the returned class. * * \note if a class named \a name is already defined and its superclass is * \a super, the function just returns the defined class. */ VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super) { VALUE klass; if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id)); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", rb_id2name(id)); } return klass; } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), rb_id2name(id)); } klass = rb_define_class_id(id, super); rb_set_class_path_string(klass, outer, rb_id2str(id)); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); rb_gc_register_mark_object(klass); return klass; }
/* Foo = Numo::Struct.new { int8 :byte float64 :float, [2,2] dcomplex :compl } */ static VALUE nst_s_new(int argc, VALUE *argv, VALUE klass) { VALUE name=Qnil, rest, size; VALUE st, members; ID id; rb_scan_args(argc, argv, "0*", &rest); if (RARRAY_LEN(rest)>0) { name = RARRAY_AREF(rest,0); if (!NIL_P(name)) { VALUE tmp = rb_check_string_type(name); if (!NIL_P(tmp)) { rb_ary_shift(rest); } else { name = Qnil; } } } if (NIL_P(name)) { st = rb_define_class_id(name, klass); rb_funcall(klass, rb_intern("inherited"), 1, st); } else { char *cname = StringValuePtr(name); id = rb_intern(cname); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", cname); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", cname); rb_mod_remove_const(klass, ID2SYM(id)); } st = rb_define_class_under(klass, rb_id2name(id), klass); } rb_iv_set(st, "__members__", rb_ary_new()); rb_iv_set(st, "__offset__", INT2FIX(0)); if (rb_block_given_p()) { rb_mod_module_eval(0, 0, st); } size = rb_iv_get(st, "__offset__"); members = rb_iv_get(st, "__members__"); //printf("size=%d\n",NUM2INT(size)); rb_define_const(st, CONTIGUOUS_STRIDE, size); rb_define_const(st, ELEMENT_BYTE_SIZE, size); rb_define_const(st, ELEMENT_BIT_SIZE, rb_funcall(size,'*',1,INT2FIX(8))); OBJ_FREEZE(members); rb_define_const(st, "DEFINITIONS", members); rb_define_singleton_method(st, "new", rb_class_new_instance, -1); //rb_define_singleton_method(st, "[]", rb_class_new_instance, -1); rb_define_method(st, "allocate", nst_allocate, 0); return st; }
static VALUE rb_struct_aset_id(VALUE s, ID id, VALUE val) { VALUE members, *ptr, *ptr_members; long i, len; members = rb_struct_members(s); len = RARRAY_LEN(members); rb_struct_modify(s); if (RSTRUCT_LEN(s) != len) { rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", len, RSTRUCT_LEN(s)); } ptr = RSTRUCT_PTR(s); ptr_members = RARRAY_PTR(members); for (i=0; i<len; i++) { if (SYM2ID(ptr_members[i]) == id) { ptr[i] = val; return val; } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); UNREACHABLE; }
static void remove_method(VALUE klass, ID mid) { st_data_t key, data; rb_method_entry_t *me = 0; VALUE self = klass; klass = RCLASS_ORIGIN(klass); rb_frozen_class_p(klass); if (mid == object_id || mid == id__send__ || mid == idInitialize) { rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); } if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || !(me = (rb_method_entry_t *)data) || (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) || UNDEFINED_REFINED_METHOD_P(me->def)) { rb_name_error(mid, "method `%"PRIsVALUE"' not defined in %"PRIsVALUE, rb_id2str(mid), rb_class_path(klass)); } key = (st_data_t)mid; st_delete(RCLASS_M_TBL(klass), &key, &data); rb_vm_check_redefinition_opt_method(me, klass); rb_clear_method_cache_by_class(klass); rb_unlink_method_entry(me); if (me->def->type == VM_METHOD_TYPE_REFINED) { rb_add_refined_method_entry(klass, mid); } CALL_METHOD_HOOK(self, removed, mid); }
static void range_modify(VALUE range) { /* Ranges are immutable, so that they should be initialized only once. */ if (RANGE_EXCL(range) != Qnil) { rb_name_error(idInitialize, "`initialize' called twice"); } }
void rb_print_undef(VALUE klass, ID id, int scope) { const char *v = method_scope_name(scope); rb_name_error(id, "undefined%s method `%"PRIsVALUE"' for %s `% "PRIsVALUE"'", v, QUOTE_ID(id), (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class", rb_class_name(klass)); }
void rb_undef(VALUE klass, ID id) { // TODO #if 0 VALUE origin; NODE *body; #if 0 // TODO if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { rb_secure(4); } #endif if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); } rb_frozen_class_p(klass); if (id == object_id || id == __send__ || id == idInitialize) { rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); } /* TODO: warn if a very important method of NSObject is undefined * by default, pure objc methods are not exposed by introspections API */ body = search_method(klass, id, &origin); if (!body || !body->nd_body) { const char *s0 = " class"; VALUE c = klass; if (RCLASS_SINGLETON(c)) { VALUE obj = rb_iv_get(klass, "__attached__"); switch (TYPE(obj)) { case T_MODULE: case T_CLASS: c = obj; s0 = ""; } } else if (TYPE(c) == T_MODULE) { s0 = " module"; } rb_name_error(id, "undefined method `%s' for%s `%s'", rb_id2name(id), s0, rb_class2name(c)); } rb_add_method(klass, id, 0, NOEX_PUBLIC); if (RCLASS_SINGLETON(klass)) { rb_funcall(rb_iv_get(klass, "__attached__"), singleton_undefined, 1, ID2SYM(id)); } else { rb_funcall(klass, undefined, 1, ID2SYM(id)); } #endif }
void rb_print_inaccessible(VALUE klass, ID id, int scope) { const char *v = method_scope_name(scope); rb_name_error(id, "method `%"PRIsVALUE"' for %s `% "PRIsVALUE"' is %s", QUOTE_ID(id), (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class", rb_class_name(klass), v); }
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr; ID id; long i, len; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); #if !WITH_OBJC rb_make_metaclass(nstr, RBASIC(klass)->klass); #endif rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_under(klass, rb_id2name(id), klass); } rb_ivar_set(nstr, id_members, members); rb_objc_define_method(*(VALUE *)nstr, "alloc", struct_alloc, 0); rb_objc_define_method(*(VALUE *)nstr, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "[]", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "members", rb_struct_s_members_m, 0); len = RARRAY_LEN(members); for (i=0; i< len; i++) { ID id = SYM2ID(RARRAY_AT(members, i)); if (rb_is_local_id(id) || rb_is_const_id(id)) { long j = i; /* Needed for block data reference. */ /* Struct attribute reader */ rb_objc_define_method(nstr, rb_id2name(id), pl_imp_implementationWithBlock(^(VALUE obj) { return RSTRUCT_PTR(obj)[j]; }), 0); /* Struct attribute writer */ rb_objc_define_method(nstr, rb_id2name(rb_id_attrset(id)), pl_imp_implementationWithBlock(^(VALUE obj, VALUE val) { VALUE *ptr = RSTRUCT_PTR(obj); rb_struct_modify(obj); GC_WB(&ptr[i], val); return val; }), 1);
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr; ID id; long i, count; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); #if !WITH_OBJC rb_make_metaclass(nstr, RBASIC(klass)->klass); #endif rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_under(klass, rb_id2name(id), klass); } rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY_LEN(members))); rb_iv_set(nstr, "__members__", members); rb_objc_define_method(*(VALUE *)nstr, "alloc", struct_alloc, 0); rb_objc_define_method(*(VALUE *)nstr, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "[]", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "members", rb_struct_s_members_m, 0); for (i = 0, count = RARRAY_LEN(members); i < count; i++) { ID id = SYM2ID(RARRAY_AT(members, i)); if (rb_is_local_id(id) || rb_is_const_id(id)) { if (i < N_REF_FUNC) { rb_objc_define_method(nstr, rb_id2name(id), ref_func[i], 0); } else { rb_objc_define_method(nstr, rb_id2name(id), rb_struct_ref, 0); } rb_objc_define_method(nstr, rb_id2name(rb_id_attrset(id)), rb_struct_set, 1); } } return nstr; }
static void check_class_super(ID id, VALUE klass, VALUE super) { VALUE k = klass; do { k = RCLASS_SUPER(k); } while (k != 0 && rb_class_hidden(k)); if (rb_class_real(k, true) != super) { rb_name_error(id, "%s is already defined", rb_id2name(id)); } }
static VALUE range_initialize(VALUE range, SEL sel ,int argc, VALUE *argv) { VALUE beg, end, flags; rb_scan_args(argc, argv, "21", &beg, &end, &flags); /* Ranges are immutable, so that they should be initialized only once. */ if (RANGE_EXCL(range) != Qnil) { rb_name_error(rb_intern("initialize"), "`initialize' called twice"); } range_init(range, beg, end, RTEST(flags)); return Qnil; }
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr, *ptr_members; ID id; long i, len; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); rb_make_metaclass(nstr, RBASIC(klass)->klass); rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_id_under(klass, id, klass); } rb_ivar_set(nstr, id_members, members); rb_define_alloc_func(nstr, struct_alloc); rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i< len; i++) { ID id = SYM2ID(ptr_members[i]); if (rb_is_local_id(id) || rb_is_const_id(id)) { if (i < N_REF_FUNC) { rb_define_method_id(nstr, id, ref_func[i], 0); } else { rb_define_method_id(nstr, id, rb_struct_ref, 0); } rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1); } } return nstr; }
void rb_undef(VALUE klass, ID id) { VALUE origin; NODE *body; if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { rb_secure(4); } if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); } rb_frozen_class_p(klass); if (id == object_id || id == __send__ || id == idInitialize) { rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); } body = search_method(klass, id, &origin); if (!body || !body->nd_body) { const char *s0 = " class"; VALUE c = klass; if (FL_TEST(c, FL_SINGLETON)) { VALUE obj = rb_iv_get(klass, "__attached__"); switch (TYPE(obj)) { case T_MODULE: case T_CLASS: c = obj; s0 = ""; } } else if (TYPE(c) == T_MODULE) { s0 = " module"; } rb_name_error(id, "undefined method `%s' for%s `%s'", rb_id2name(id), s0, rb_class2name(c)); } rb_add_method(klass, id, 0, NOEX_PUBLIC); if (FL_TEST(klass, FL_SINGLETON)) { rb_funcall(rb_iv_get(klass, "__attached__"), singleton_undefined, 1, ID2SYM(id)); } else { rb_funcall(klass, undefined, 1, ID2SYM(id)); } }
static VALUE rb_struct_aref_id(VALUE s, ID id) { VALUE members = rb_struct_members(s); long i, len = RARRAY_LEN(members); for (i=0; i<len; i++) { if (SYM2ID(RARRAY_AREF(members, i)) == id) { return RSTRUCT_GET(s, i); } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); UNREACHABLE; }
void rb_attr(VALUE klass, ID id, int read, int write, int ex) { if (!rb_is_local_id(id) && !rb_is_const_id(id)) { rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); } const char *name = rb_id2name(id); if (name == NULL) { rb_raise(rb_eArgError, "argument needs to be symbol or string"); } rb_vm_define_attr((Class)klass, name, read, write); if (write) { rb_objc_define_kvo_setter(klass, id); } }
static VALUE rb_struct_aref_id(VALUE s, ID id) { VALUE members; long i, len; members = rb_struct_members(s); len = RARRAY_LEN(members); for (i=0; i<len; i++) { if (SYM2ID(RARRAY_PTR(members)[i]) == id) { return RSTRUCT_PTR(s)[i]; } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); return Qnil; /* not reached */ }
VALUE rb_struct_getmember(VALUE obj, ID id) { VALUE members, slot; long i; members = rb_struct_members(obj); slot = ID2SYM(id); for (i=0; i<RARRAY_LEN(members); i++) { if (RARRAY_PTR(members)[i] == slot) { return RSTRUCT_PTR(obj)[i]; } } rb_name_error(id, "%s is not struct member", rb_id2name(id)); return Qnil; /* not reached */ }
void rb_print_undef(VALUE klass, ID id, int scope) { const char *v; switch (scope) { default: case NOEX_PUBLIC: v = ""; break; case NOEX_PRIVATE: v = " private"; break; case NOEX_PROTECTED: v = " protected"; break; } rb_name_error(id, "undefined%s method `%"PRIsVALUE"' for %s `%"PRIsVALUE"'", v, QUOTE_ID(id), (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class", rb_class_name(klass)); }
void rb_print_undef(VALUE klass, ID id, int scope) { const char *v; switch (scope) { default: case NOEX_PUBLIC: v = ""; break; case NOEX_PRIVATE: v = " private"; break; case NOEX_PROTECTED: v = " protected"; break; } rb_name_error(id, "undefined%s method `%s' for %s `%s'", v, rb_id2name(id), (TYPE(klass) == T_MODULE) ? "module" : "class", rb_class2name(klass)); }
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr; ID id; long i; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); rb_make_metaclass(nstr, RBASIC(klass)->klass); rb_class_inherited(klass, nstr); } else { char *cname = StringValuePtr(name); id = rb_intern(cname); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", cname); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", cname); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_under(klass, rb_id2name(id), klass); } rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY(members)->len)); rb_iv_set(nstr, "__members__", members); rb_define_alloc_func(nstr, struct_alloc); rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0); for (i=0; i< RARRAY(members)->len; i++) { ID id = SYM2ID(RARRAY(members)->ptr[i]); if (rb_is_local_id(id) || rb_is_const_id(id)) { if (i<10) { rb_define_method_id(nstr, id, ref_func[i], 0); } else { rb_define_method_id(nstr, id, rb_struct_ref, 0); } rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1); } } return nstr; }
static void remove_method(VALUE klass, ID mid) { if (klass == rb_cObject) { rb_secure(4); } if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't remove method"); } if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); if (mid == object_id || mid == __send__ || mid == idInitialize) { rb_warn("removing `%s' may cause serious problem", rb_id2name(mid)); } SEL sel; Method m; sel = sel_registerName(rb_id2name(mid)); m = class_getInstanceMethod((Class)klass, sel); if (m == NULL) { char buf[100]; size_t len = strlen((char *)sel); if (((char *)sel)[len - 1] != ':') { snprintf(buf, sizeof buf, "%s:", (char *)sel); sel = sel_registerName(buf); m = class_getInstanceMethod((Class)klass, sel); } } if (m == NULL) { rb_name_error(mid, "method `%s' not defined in %s", rb_id2name(mid), rb_class2name(klass)); } if (rb_vm_get_method_node(method_getImplementation(m)) == NULL) { rb_warn("removing pure Objective-C method `%s' may cause serious " \ "problem", rb_id2name(mid)); } method_setImplementation(m, NULL); if (RCLASS_SINGLETON(klass)) { rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid)); } else { rb_funcall(klass, removed, 1, ID2SYM(mid)); } }