static mrb_value inspect_struct(mrb_state *mrb, mrb_value s, mrb_bool recur) { const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s)); mrb_value members, str = mrb_str_new_lit(mrb, "#<struct "); mrb_value *ptr; const mrb_value *ptr_members; mrb_int i, len; if (cn) { mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, cn)); } if (recur) { return mrb_str_cat_lit(mrb, str, ":...>"); } members = mrb_struct_members(mrb, s); ptr_members = RARRAY_PTR(members); ptr = RSTRUCT_PTR(s); len = RSTRUCT_LEN(s); for (i=0; i<len; i++) { mrb_value slot; mrb_sym id; const char *name; mrb_int namelen; if (i > 0) { mrb_str_cat_lit(mrb, str, ", "); } else if (cn) { mrb_str_cat_lit(mrb, str, " "); } slot = ptr_members[i]; id = mrb_symbol(slot); name = mrb_sym2name_len(mrb, id, &namelen); if (is_local_id(mrb, name) || is_const_id(mrb, name)) { mrb_str_append(mrb, str, mrb_str_new(mrb, name, namelen)); } else { mrb_str_append(mrb, str, mrb_inspect(mrb, slot)); } mrb_str_cat_lit(mrb, str, "="); mrb_str_append(mrb, str, mrb_inspect(mrb, ptr[i])); } mrb_str_cat_lit(mrb, str, ">"); return str; }
static void make_struct_define_accessors(mrb_state *mrb, mrb_value members, struct RClass *c) { const mrb_value *ptr_members = RARRAY_PTR(members); mrb_int i; mrb_int len = RARRAY_LEN(members); int ai = mrb_gc_arena_save(mrb); for (i=0; i<len; i++) { mrb_sym id = mrb_symbol(ptr_members[i]); const char *name = mrb_sym2name_len(mrb, id, NULL); if (is_local_id(mrb, name) || is_const_id(mrb, name)) { mrb_define_method_id(mrb, c, id, mrb_struct_ref, MRB_ARGS_NONE()); mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, MRB_ARGS_REQ(1)); mrb_gc_arena_restore(mrb, ai); } } }
VALUE rb_id2str(ID id) { LOCK(); VALUE sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id); UNLOCK(); if (sym != 0) { //printf("lookup %ld -> %s\n", id, rb_sym2name(sym)); return sym; } if (is_attrset_id(id)) { // Attribute assignment. ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL; while ((sym = rb_id2str(id2)) == 0) { if (!is_local_id(id2)) { //printf("lookup %ld -> FAIL\n", id); return 0; } id2 = (id & ~ID_SCOPE_MASK) | ID_CONST; } VALUE str = rb_str_dup(RSYM(sym)->str); rb_str_cat(str, "=", 1); rb_intern_str(str); // Retry one more time. LOCK(); sym = (VALUE)CFDictionaryGetValue(id_str, (const void *)id); UNLOCK(); if (sym != 0) { //printf("lookup %ld -> %s\n", id, rb_sym2name(sym)); return sym; } } //printf("lookup %ld -> FAIL\n", id); return 0; }
/* get base id */ name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen); mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */ members = mrb_struct_members(mrb, obj); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); ptr = RSTRUCT_PTR(obj); for (i=0; i<len; i++) { slot = ptr_members[i]; if (mrb_symbol(slot) == mid) { return ptr[i] = val; } } mrb_raisef(mrb, E_INDEX_ERROR, "`%S' is not a struct member", mrb_sym2str(mrb, mid)); return mrb_nil_value(); /* not reached */ } static mrb_value mrb_struct_set_m(mrb_state *mrb, mrb_value obj) { mrb_value val; mrb_get_args(mrb, "o", &val); return mrb_struct_set(mrb, obj, val); } #define is_notop_id(id) (id) /* ((id)>tLAST_TOKEN) */ #define is_local_id(id) (is_notop_id(id)) /* &&((id)&ID_SCOPE_MASK)==ID_LOCAL) */ int mrb_is_local_id(mrb_sym id) { return is_local_id(id); }
int rb_is_local_id(ID id) { return is_local_id(id) ? Qtrue : Qfalse; }