From 3cd2201b700a973b006dd5f1c1d96a84a24e2570 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 1 Aug 2025 14:11:43 +0900 Subject: [PATCH] khash: add kh_init_data and kh_destroy_data functions Add core data initialization functions that handle only the internal data allocation/deallocation without managing the khash struct itself. Changes: - Add kh_init_data_##name() for initializing khash internal data - Add kh_destroy_data_##name() for cleaning up khash internal data - Refactor kh_init_##name##_size() to use kh_init_data internally - Refactor kh_destroy_##name() to use kh_destroy_data internally - Add corresponding kh_init_data() and kh_destroy_data() macros Benefits: - Eliminates code duplication between init/destroy and embed functions - Provides clear separation: data functions handle internals, regular functions handle struct lifecycle - Enables embedding khash in other structures (e.g., mruby-set's RSet) - Centralizes complex initialization logic in single implementation Architecture: - kh_init_data/kh_destroy_data: core implementation with small table optimization - kh_init_size/kh_destroy: convenience wrappers that add struct allocation - Same functionality preserved, all tests pass This prepares khash for mruby-set integration while improving code organization and maintainability. Co-authored-by: Claude --- include/mruby/khash.h | 53 +++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/include/mruby/khash.h b/include/mruby/khash.h index ef3b23211..a31e58e81 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -99,7 +99,9 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \ void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \ void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \ - kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h); + kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h); \ + void kh_init_data_##name(mrb_state *mrb, kh_##name##_t *h, khint_t size); \ + void kh_destroy_data_##name(mrb_state *mrb, kh_##name##_t *h); /* define kh_xxx_funcs @@ -187,24 +189,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; } \ kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \ kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \ - if (size <= KHASH_SMALL_THRESHOLD) { \ - /* Start as small table */ \ - h->n_buckets = 0; /* Small table marker */ \ - if (kh_alloc_small_##name(mrb, h)) { \ - mrb_free(mrb, h); \ - mrb_raise_nomemory(mrb); \ - } \ - } else { \ - /* Start as regular hash table */ \ - if (size < KHASH_MIN_SIZE) \ - size = KHASH_MIN_SIZE; \ - khash_power2(size); \ - h->n_buckets = size; \ - if (kh_alloc_simple_##name(mrb, h)) { \ - mrb_free(mrb, h); \ - mrb_raise_nomemory(mrb); \ - } \ - } \ + kh_init_data_##name(mrb, h, size); \ return h; \ } \ kh_##name##_t *kh_init_##name(mrb_state *mrb) { \ @@ -213,7 +198,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h) \ { \ if (h) { \ - mrb_free(mrb, h->data); /* Free single data allocation */ \ + kh_destroy_data_##name(mrb, h); \ mrb_free(mrb, h); \ } \ } \ @@ -345,6 +330,32 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; } \ } \ return h2; \ + } \ + void kh_init_data_##name(mrb_state *mrb, kh_##name##_t *h, khint_t size) { \ + if (size <= KHASH_SMALL_THRESHOLD) { \ + /* Start as small table */ \ + h->n_buckets = 0; /* Small table marker */ \ + if (kh_alloc_small_##name(mrb, h)) { \ + mrb_raise_nomemory(mrb); \ + } \ + } \ + else { \ + /* Start as regular hash table */ \ + if (size < KHASH_MIN_SIZE) \ + size = KHASH_MIN_SIZE; \ + khash_power2(size); \ + h->n_buckets = size; \ + if (kh_alloc_simple_##name(mrb, h)) { \ + mrb_raise_nomemory(mrb); \ + } \ + } \ + } \ + void kh_destroy_data_##name(mrb_state *mrb, kh_##name##_t *h) \ + { \ + if (h && h->data) { \ + mrb_free(mrb, h->data); /* Free only the data allocation */ \ + h->data = NULL; \ + } \ } @@ -360,6 +371,8 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; #define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k) #define kh_del(name, mrb, h, k) kh_del_##name(mrb, h, k) #define kh_copy(name, mrb, h) kh_copy_##name(mrb, h) +#define kh_init_data(name, mrb, h, size) kh_init_data_##name(mrb, h, size) +#define kh_destroy_data(name, mrb, h) kh_destroy_data_##name(mrb, h) /* BREAKING CHANGE: Field access macros now require type name as first parameter * The macros keep their familiar names but now need the hash type name.