mruby-hash-ext/hash.rb: implement Hash#compact! in C

Using `__compact` method defined in the core, since hash access
functions are private to `src/hash.c`.
This commit is contained in:
Yukihiro "Matz" Matsumoto
2023-02-02 22:44:04 +09:00
parent 9cda737a56
commit 1b299addaf
2 changed files with 30 additions and 16 deletions
+3 -16
View File
@@ -113,16 +113,7 @@ class Hash
#
def compact!
keys = self.keys
nk = keys.select{|k|
self[k] != nil
}
return nil if (keys.size == nk.size)
h = {}
nk.each {|k|
h[k] = self[k]
}
self.replace(h)
self.__compact
end
##
@@ -136,12 +127,8 @@ class Hash
# h #=> { a: 1, b: false, c: nil }
#
def compact
h = {}
self.keys.select{|k|
self[k] != nil
}.each {|k|
h[k] = self[k]
}
h=self.dup
h.__compact
h
end
+27
View File
@@ -1787,6 +1787,32 @@ mrb_hash_rehash(mrb_state *mrb, mrb_value self)
return self;
}
static mrb_value
mrb_hash_compact(mrb_state *mrb, mrb_value hash)
{
struct RHash *h = mrb_hash_ptr(hash);
mrb_bool ht_p = h_ht_p(h);
uint32_t size = ht_p ? ht_size(h) : ar_size(h);
uint32_t dec = 0;
mrb_check_frozen(mrb, h);
h_each(h, entry, {
if (mrb_nil_p(entry->val)) {
entry_delete(entry);
dec++;
}
});
if (dec == 0) return mrb_nil_value();
size -= dec;
if (ht_p) {
ht_set_size(h, size);
}
else {
ar_set_size(h, size);
}
return hash;
}
void
mrb_init_hash(mrb_state *mrb)
{
@@ -1821,4 +1847,5 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method(mrb, h, "values", mrb_hash_values, MRB_ARGS_NONE()); /* 15.2.13.4.28 */
mrb_define_method(mrb, h, "rehash", mrb_hash_rehash, MRB_ARGS_NONE());
mrb_define_method(mrb, h, "__merge", mrb_hash_merge_m, MRB_ARGS_REQ(1));
mrb_define_method(mrb, h, "__compact", mrb_hash_compact, MRB_ARGS_NONE()); /* implementation of Hash#compact! */
}