From e2982bdb57d98a4f3e1a91903c2848a3d4249d8d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Jun 2025 07:39:53 +0900 Subject: [PATCH] mruby-set: optimize join method to avoid intermediate array --- mrbgems/mruby-set/src/set.c | 40 +++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-set/src/set.c b/mrbgems/mruby-set/src/set.c index 52db7f98a..3253674fd 100644 --- a/mrbgems/mruby-set/src/set.c +++ b/mrbgems/mruby-set/src/set.c @@ -970,9 +970,45 @@ static mrb_value set_join(mrb_state *mrb, mrb_value self) { mrb_value separator = mrb_nil_value(); - mrb_get_args(mrb, "|S", &separator); - return mrb_ary_join(mrb, set_to_a(mrb, self), separator); + + khash_t(set) *kh = set_get_khash(mrb, self); + if (!kh || kh_size(kh) == 0) { + return mrb_str_new_lit(mrb, ""); + } + + /* Get separator string */ + const char *sep_ptr = ""; + mrb_int sep_len = 0; + if (!mrb_nil_p(separator)) { + sep_ptr = RSTRING_PTR(separator); + sep_len = RSTRING_LEN(separator); + } + + /* Create result string */ + mrb_value result = mrb_str_new_capa(mrb, 64); /* Initial capacity */ + mrb_bool first = TRUE; + + /* Iterate through all elements */ + int ai = mrb_gc_arena_save(mrb); + KHASH_FOREACH(mrb, kh, k) { + /* Add separator between elements */ + if (!first) { + mrb_str_cat(mrb, result, sep_ptr, sep_len); + } else { + first = FALSE; + } + + /* Convert element to string and append */ + mrb_value elem = kh_key(kh, k); + mrb_value str = mrb_obj_as_string(mrb, elem); + mrb_str_cat_str(mrb, result, str); + + /* Manage GC arena to prevent memory leaks */ + mrb_gc_arena_restore(mrb, ai); + } + + return result; } /*