summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2016-07-25 10:32:10 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2016-07-25 10:32:10 +0900
commit417092360dced241f9cc04884887a55c2407e81a (patch)
tree215b1045bc74d65b31436d4b3a3038a14e445e1b
parent97283faa16d2e69a27de891e5a6695bf370cb4c3 (diff)
downloadmruby-417092360dced241f9cc04884887a55c2407e81a.tar.gz
mruby-417092360dced241f9cc04884887a55c2407e81a.zip
Fixed crash error when #initialize is redefined for Struct; fix #3177
refactored redundant functions; removed optimized accessors for safety this fix also close #3178
-rw-r--r--mrbgems/mruby-struct/src/struct.c120
1 files changed, 27 insertions, 93 deletions
diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c
index f084e4031..51256c6af 100644
--- a/mrbgems/mruby-struct/src/struct.c
+++ b/mrbgems/mruby-struct/src/struct.c
@@ -61,9 +61,14 @@ struct_members(mrb_state *mrb, mrb_value s)
mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct");
}
if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
- mrb_raisef(mrb, E_TYPE_ERROR,
- "struct size differs (%S required %S given)",
- mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
+ if (RSTRUCT_LEN(s) == 0) { /* probably uninitialized */
+ mrb_ary_resize(mrb, s, RARRAY_LEN(members));
+ }
+ else {
+ mrb_raisef(mrb, E_TYPE_ERROR,
+ "struct size differs (%S required %S given)",
+ mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
+ }
}
return members;
}
@@ -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)));
}
-static mrb_value
-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 struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id);
static mrb_value
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
mrb_id_attrset(mrb_state *mrb, mrb_sym id)
{
@@ -171,40 +130,24 @@ mrb_id_attrset(mrb_state *mrb, mrb_sym id)
return mid;
}
+static mrb_value mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val);
+
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;
- mrb_int i, len, slen;
+ mrb_int slen;
mrb_sym mid;
- mrb_value members, slot, *ptr;
- const mrb_value *ptr_members;
+
+ mrb_get_args(mrb, "o", &val);
/* get base id */
name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen);
mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */
- members = 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);
+ return mrb_struct_aset_sym(mrb, obj, mid, val);
}
static mrb_bool
@@ -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);
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_gc_arena_restore(mrb, ai);
}
@@ -433,22 +371,23 @@ mrb_struct_init_copy(mrb_state *mrb, mrb_value copy)
}
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;
mrb_int i, len;
- ptr = RSTRUCT_PTR(s);
- members = struct_members(mrb, s);
+ members = struct_members(mrb, obj);
ptr_members = RARRAY_PTR(members);
len = RARRAY_LEN(members);
+ ptr = RSTRUCT_PTR(obj);
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];
}
}
- 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 */
}
@@ -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);
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_members = RARRAY_PTR(members);
for (i=0; i<len; i++) {