diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2018-04-28 11:24:26 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2018-04-28 11:26:23 +0900 |
| commit | 50a9c5d7c704e84c6bdec9affa270824fed02034 (patch) | |
| tree | 59b7fb5558399a37d0de50dbf208cccec39a8f6c /src/enum.c | |
| parent | 4b29abc565b5791d6d39b28358e2c82c17d3c500 (diff) | |
| download | mruby-50a9c5d7c704e84c6bdec9affa270824fed02034.tar.gz mruby-50a9c5d7c704e84c6bdec9affa270824fed02034.zip | |
Update the patch to not use `funcall` in C; ref #4013
Diffstat (limited to 'src/enum.c')
| -rw-r--r-- | src/enum.c | 64 |
1 files changed, 18 insertions, 46 deletions
diff --git a/src/enum.c b/src/enum.c index ed3ebdd9f..94103e35e 100644 --- a/src/enum.c +++ b/src/enum.c @@ -7,55 +7,28 @@ #include <mruby.h> #include <mruby/proc.h> -typedef struct enumerable_hash_context { - mrb_int hash; - mrb_int index; -} enumerable_hash_context; - +/* internal method `__update_hash(oldhash, index, itemhash)` */ static mrb_value -enumerable_hash_each(mrb_state *mrb, mrb_value self) +enum_update_hash(mrb_state *mrb, mrb_value self) { - mrb_value item; - mrb_value closure; - - mrb_get_args(mrb, "o", &item); - closure = mrb_proc_cfunc_env_get(mrb, 0); - - if (mrb_cptr_p(closure)) { - mrb_value item_hash; - enumerable_hash_context *context = (enumerable_hash_context *)mrb_cptr(closure); + mrb_int hash; + mrb_int index; + mrb_int hv; + mrb_value item_hash; - item_hash = mrb_funcall(mrb, item, "hash", 0); - if (mrb_fixnum_p(item_hash)) { - context->hash ^= (mrb_fixnum(item_hash) << (context->index % 16)); - ++context->index; - return mrb_nil_value(); - } + mrb_get_args(mrb, "iio", &hash, &index, &item_hash); + if (mrb_fixnum_p(item_hash)) { + hv = mrb_fixnum(item_hash); } + else if (mrb_float_p(item_hash)) { + hv = (mrb_int)mrb_float(item_hash); + } + else { + mrb_raise(mrb, E_TYPE_ERROR, "can't calculate hash"); + } + hash ^= (hv << (index % 16)); - mrb_raise(mrb, E_TYPE_ERROR, "can't calculate hash"); -} - -static mrb_value -enumerable_hash(mrb_state *mrb, mrb_value self) -{ - /* redefine #hash 15.3.1.3.15 */ - struct RProc *proc; - enumerable_hash_context context; - mrb_value closure; - mrb_value blk; - int ai = mrb_gc_arena_save(mrb); - - context.hash = 12347; - context.index = 0; - closure = mrb_cptr_value(mrb, &context); - - proc = mrb_proc_new_cfunc_with_env(mrb, enumerable_hash_each, 1, &closure); - blk = mrb_obj_value(proc); - mrb_funcall_with_block(mrb, self, mrb_intern_cstr(mrb, "each"), 0, NULL, blk); - - mrb_gc_arena_restore(mrb, ai); - return mrb_fixnum_value(context.hash); + return mrb_fixnum_value(hash); } void @@ -63,6 +36,5 @@ mrb_init_enumerable(mrb_state *mrb) { struct RClass *enumerable; enumerable = mrb_define_module(mrb, "Enumerable"); /* 15.3.2 */ - mrb_define_module_function(mrb, enumerable, "hash", enumerable_hash, MRB_ARGS_NONE()); + mrb_define_module_function(mrb, enumerable, "__update_hash", enum_update_hash, MRB_ARGS_REQ(1)); } - |
