static VALUE find_class_path(VALUE klass) { struct fc_result arg; arg.name = 0; arg.path = 0; arg.klass = klass; arg.track = rb_cObject; arg.prev = 0; CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject); if (iv_dict != NULL) { ivar_dict_foreach(iv_dict, fc_i, (VALUE)&arg); } if (arg.path == 0) { st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); } if (arg.path) { iv_dict = rb_class_ivar_dict_or_create(klass); CFDictionarySetValue(iv_dict, (const void *)id_classpath, (const void *)arg.path); CFDictionaryRemoveValue(iv_dict, (const void *)id_tmp_classpath); return arg.path; } if (!RCLASS_RUBY(klass)) { VALUE name = rb_str_new2(class_getName((Class)klass)); iv_dict = rb_class_ivar_dict_or_create(klass); CFDictionarySetValue(iv_dict, (const void *)id_classpath, (const void *)name); CFDictionaryRemoveValue(iv_dict, (const void *)id_tmp_classpath); return name; } return Qnil; }
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; }
void rb_extend_object(VALUE obj, VALUE module) { VALUE klass; if (TYPE(obj) == T_CLASS && RCLASS_RUBY(obj)) { VALUE sklass = rb_make_singleton_class(RCLASS_SUPER(obj)); RCLASS_SET_SUPER(obj, sklass); klass = *(VALUE *)sklass; } else { klass = rb_singleton_class(obj); } rb_include_module(klass, module); VALUE m = module; do { VALUE ary = rb_attr_get(m, idIncludedModules); if (ary != Qnil) { for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) { VALUE mod = RARRAY_AT(ary, i); rb_extend_object(obj, mod); } } m = RCLASS_SUPER(m); } while (m == 0 || RCLASS_SINGLETON(m)); }
static VALUE rb_mod_append_features(VALUE module, SEL sel, VALUE include) { VALUE orig = include; switch (TYPE(include)) { case T_CLASS: case T_MODULE: break; default: Check_Type(include, T_CLASS); break; } if (RCLASS_RUBY(include)) { VALUE sinclude = rb_make_singleton_class(RCLASS_SUPER(include)); RCLASS_SET_SUPER(include, sinclude); include = sinclude; } rb_include_module2(include, orig, module, true, true); VALUE m = module; do { VALUE ary = rb_attr_get(m, idIncludedModules); if (ary != Qnil) { for (int i = 0, count = RARRAY_LEN(ary); i < count; i++) { VALUE mod = RARRAY_AT(ary, i); rb_mod_append_features(mod, sel, include); } } m = RCLASS_SUPER(m); } while (m == 0 || RCLASS_SINGLETON(m)); return module; }
VALUE rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig) { rb_obj_init_copy(clone, 0, orig); VALUE super; if (!RCLASS_RUBY(orig)) { super = orig; rb_warn("cloning class `%s' is not supported, creating a " \ "subclass instead", rb_class2name(orig)); } else { super = RCLASS_SUPER(orig); } RCLASS_SET_SUPER(clone, super); // Copy flags. unsigned long version_flag = RCLASS_IS_RUBY_CLASS; if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) { version_flag |= RCLASS_IS_OBJECT_SUBCLASS; } if (RCLASS_MODULE(orig)) { version_flag |= RCLASS_IS_MODULE; } RCLASS_SET_VERSION(clone, version_flag); if (!class_isMetaClass((Class)clone)) { // Clear type info. RCLASS_SET_VERSION(*(Class *)clone, RCLASS_VERSION(*(Class *)clone)); } // Copy methods. rb_vm_copy_methods((Class)orig, (Class)clone); if (!class_isMetaClass((Class)orig)) { rb_vm_copy_methods(*(Class *)orig, *(Class *)clone); } // Copy ivars. CFMutableDictionaryRef orig_dict = rb_class_ivar_dict(orig); CFMutableDictionaryRef clone_dict; if (orig_dict != NULL) { clone_dict = CFDictionaryCreateMutableCopy(NULL, 0, orig_dict); rb_class_ivar_set_dict(clone, clone_dict); CFMakeCollectable(clone_dict); } else { clone_dict = rb_class_ivar_dict_or_create(clone); } // Remove the classpath & classid (name) so that they are not // copied over the new module / class. CFDictionaryRemoveValue(clone_dict, (const void *)id_classpath); CFDictionaryRemoveValue(clone_dict, (const void *)id_classid); return clone; }
/* :nodoc: */ VALUE rb_mod_init_copy(VALUE clone, SEL sel, VALUE orig) { static ID classpath = 0; static ID classid = 0; rb_obj_init_copy(clone, 0, orig); { VALUE super; unsigned long version_flag; if (!RCLASS_RUBY(orig)) { super = orig; rb_warn("cloning class `%s' is not supported, creating a " \ "subclass instead", rb_class2name(orig)); } else { super = RCLASS_SUPER(orig); } RCLASS_SET_SUPER(clone, super); version_flag = RCLASS_IS_RUBY_CLASS; if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) { version_flag |= RCLASS_IS_OBJECT_SUBCLASS; } RCLASS_SET_VERSION(clone, version_flag); rb_vm_copy_methods((Class)orig, (Class)clone); CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(orig); if (ivar_dict != NULL) { CFMutableDictionaryRef cloned_ivar_dict; if (classpath == 0) { classpath = rb_intern("__classpath__"); } if (classid == 0) { classid = rb_intern("__classid__"); } cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict); // Remove the classpath & classid (name) so that they are not // copied over the new module / class CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classpath); CFDictionaryRemoveValue(cloned_ivar_dict, (const void *)classid); CFMakeCollectable(cloned_ivar_dict); rb_class_ivar_set_dict(clone, cloned_ivar_dict); } } return clone; }