mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
hash.c: change __except to take array argument
mrb_get_args(mrb, "*", ...) internally allocates an array when arguments are on the stack, so passing keys as direct arguments did not actually avoid allocation. Change __except to take a single array argument instead, which is simpler and GC-safe. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
+9
-8
@@ -2044,25 +2044,26 @@ mrb_hash_compact(mrb_state *mrb, mrb_value hash)
|
||||
|
||||
/*
|
||||
* Internal method for pattern matching **rest.
|
||||
* Returns a new hash excluding specified keys.
|
||||
* Returns a new hash excluding keys in the given array.
|
||||
*
|
||||
* {a: 1, b: 2, c: 3}.__except(:a, :c) #=> {b: 2}
|
||||
* {a: 1, b: 2, c: 3}.__except([:a, :c]) #=> {b: 2}
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_hash_except_keys(mrb_state *mrb, mrb_value hash)
|
||||
{
|
||||
const mrb_value *argv;
|
||||
mrb_int argc;
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
mrb_value keys;
|
||||
mrb_get_args(mrb, "A", &keys);
|
||||
|
||||
const mrb_value *ary = RARRAY_PTR(keys);
|
||||
mrb_int klen = RARRAY_LEN(keys);
|
||||
mrb_value result = mrb_hash_new(mrb);
|
||||
struct RHash *h = mrb_hash_ptr(hash);
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
H_EACH(h, entry) {
|
||||
mrb_bool found = FALSE;
|
||||
for (mrb_int i = 0; i < argc; i++) {
|
||||
if (mrb_equal(mrb, entry->key, argv[i])) {
|
||||
for (mrb_int i = 0; i < klen; i++) {
|
||||
if (mrb_equal(mrb, entry->key, ary[i])) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
@@ -2313,6 +2314,6 @@ mrb_init_hash(mrb_state *mrb)
|
||||
mrb_define_method_id(mrb, h, MRB_SYM(rassoc), mrb_hash_rassoc, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, h, MRB_SYM(__merge), mrb_hash_merge_m, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, h, MRB_SYM(__compact), mrb_hash_compact, MRB_ARGS_NONE()); /* implementation of Hash#compact! */
|
||||
mrb_define_method_id(mrb, h, MRB_SYM(__except), mrb_hash_except_keys, MRB_ARGS_ANY()); /* for pattern matching **rest */
|
||||
mrb_define_method_id(mrb, h, MRB_SYM(__except), mrb_hash_except_keys, MRB_ARGS_REQ(1)); /* for pattern matching **rest */
|
||||
}
|
||||
#undef lesser
|
||||
|
||||
Reference in New Issue
Block a user