Fixed crash error when #initialize is redefined for Struct; fix #3177

refactored redundant functions; removed optimized accessors for safety
this fix also close #3178
parent 97283faa
...@@ -61,10 +61,15 @@ struct_members(mrb_state *mrb, mrb_value s) ...@@ -61,10 +61,15 @@ struct_members(mrb_state *mrb, mrb_value s)
mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct");
} }
if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
if (RSTRUCT_LEN(s) == 0) { /* probably uninitialized */
mrb_ary_resize(mrb, s, RARRAY_LEN(members));
}
else {
mrb_raisef(mrb, E_TYPE_ERROR, mrb_raisef(mrb, E_TYPE_ERROR,
"struct size differs (%S required %S given)", "struct size differs (%S required %S given)",
mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
} }
}
return members; return members;
} }
...@@ -98,60 +103,14 @@ mrb_struct_members(mrb_state *mrb, mrb_value obj) ...@@ -98,60 +103,14 @@ mrb_struct_members(mrb_state *mrb, mrb_value obj)
return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj))); return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj)));
} }
static mrb_value static mrb_value struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id);
mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
{
mrb_value members, slot, *ptr;
const mrb_value *ptr_members;
mrb_int i, len;
ptr = RSTRUCT_PTR(obj);
members = struct_members(mrb, obj);
ptr_members = RARRAY_PTR(members);
slot = mrb_symbol_value(id);
len = RARRAY_LEN(members);
for (i=0; i<len; i++) {
if (mrb_obj_equal(mrb, ptr_members[i], slot)) {
return ptr[i];
}
}
mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
return mrb_nil_value(); /* not reached */
}
static mrb_value static mrb_value
mrb_struct_ref(mrb_state *mrb, mrb_value obj) mrb_struct_ref(mrb_state *mrb, mrb_value obj)
{ {
return mrb_struct_getmember(mrb, obj, mrb->c->ci->mid); return struct_aref_sym(mrb, obj, mrb->c->ci->mid);
} }
static mrb_value mrb_struct_ref0(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[0];}
static mrb_value mrb_struct_ref1(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[1];}
static mrb_value mrb_struct_ref2(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[2];}
static mrb_value mrb_struct_ref3(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[3];}
static mrb_value mrb_struct_ref4(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[4];}
static mrb_value mrb_struct_ref5(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[5];}
static mrb_value mrb_struct_ref6(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[6];}
static mrb_value mrb_struct_ref7(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[7];}
static mrb_value mrb_struct_ref8(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[8];}
static mrb_value mrb_struct_ref9(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[9];}
#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
#define N_REF_FUNC numberof(ref_func)
static const mrb_func_t ref_func[] = {
mrb_struct_ref0,
mrb_struct_ref1,
mrb_struct_ref2,
mrb_struct_ref3,
mrb_struct_ref4,
mrb_struct_ref5,
mrb_struct_ref6,
mrb_struct_ref7,
mrb_struct_ref8,
mrb_struct_ref9,
};
static mrb_sym static mrb_sym
mrb_id_attrset(mrb_state *mrb, mrb_sym id) mrb_id_attrset(mrb_state *mrb, mrb_sym id)
{ {
...@@ -171,40 +130,24 @@ mrb_id_attrset(mrb_state *mrb, mrb_sym id) ...@@ -171,40 +130,24 @@ mrb_id_attrset(mrb_state *mrb, mrb_sym id)
return mid; return mid;
} }
static mrb_value mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val);
static mrb_value static mrb_value
mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) mrb_struct_set_m(mrb_state *mrb, mrb_value obj)
{ {
mrb_value val;
const char *name; const char *name;
mrb_int i, len, slen; mrb_int slen;
mrb_sym mid; mrb_sym mid;
mrb_value members, slot, *ptr;
const mrb_value *ptr_members; mrb_get_args(mrb, "o", &val);
/* get base id */ /* get base id */
name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen); name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen);
mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */ mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */
members = struct_members(mrb, obj); return mrb_struct_aset_sym(mrb, obj, mid, val);
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);
} }
static mrb_bool static mrb_bool
...@@ -234,12 +177,7 @@ make_struct_define_accessors(mrb_state *mrb, mrb_value members, struct RClass *c ...@@ -234,12 +177,7 @@ make_struct_define_accessors(mrb_state *mrb, mrb_value members, struct RClass *c
const char *name = mrb_sym2name_len(mrb, id, NULL); const char *name = mrb_sym2name_len(mrb, id, NULL);
if (is_local_id(mrb, name) || is_const_id(mrb, name)) { if (is_local_id(mrb, name) || is_const_id(mrb, name)) {
if (i < N_REF_FUNC) {
mrb_define_method_id(mrb, c, id, ref_func[i], MRB_ARGS_NONE());
}
else {
mrb_define_method_id(mrb, c, id, mrb_struct_ref, MRB_ARGS_NONE()); 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_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, MRB_ARGS_REQ(1));
mrb_gc_arena_restore(mrb, ai); mrb_gc_arena_restore(mrb, ai);
} }
...@@ -433,22 +371,23 @@ mrb_struct_init_copy(mrb_state *mrb, mrb_value copy) ...@@ -433,22 +371,23 @@ mrb_struct_init_copy(mrb_state *mrb, mrb_value copy)
} }
static mrb_value static mrb_value
struct_aref_sym(mrb_state *mrb, mrb_value s, mrb_sym id) struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id)
{ {
mrb_value *ptr, members; mrb_value members, *ptr;
const mrb_value *ptr_members; const mrb_value *ptr_members;
mrb_int i, len; mrb_int i, len;
ptr = RSTRUCT_PTR(s); members = struct_members(mrb, obj);
members = struct_members(mrb, s);
ptr_members = RARRAY_PTR(members); ptr_members = RARRAY_PTR(members);
len = RARRAY_LEN(members); len = RARRAY_LEN(members);
ptr = RSTRUCT_PTR(obj);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
if (mrb_symbol(ptr_members[i]) == id) { mrb_value slot = ptr_members[i];
if (mrb_symbol_p(slot) && mrb_symbol(slot) == id) {
return ptr[i]; return ptr[i];
} }
} }
mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id)); mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
return mrb_nil_value(); /* not reached */ return mrb_nil_value(); /* not reached */
} }
...@@ -515,11 +454,6 @@ mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) ...@@ -515,11 +454,6 @@ mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
members = struct_members(mrb, s); members = struct_members(mrb, s);
len = RARRAY_LEN(members); len = RARRAY_LEN(members);
if (RSTRUCT_LEN(s) != len) {
mrb_raisef(mrb, E_TYPE_ERROR,
"struct size differs (%S required %S given)",
mrb_fixnum_value(len), mrb_fixnum_value(RSTRUCT_LEN(s)));
}
ptr = RSTRUCT_PTR(s); ptr = RSTRUCT_PTR(s);
ptr_members = RARRAY_PTR(members); ptr_members = RARRAY_PTR(members);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment