summaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2014-04-10 00:53:32 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2014-04-10 00:53:32 +0900
commitaecdafb9ce6ea3ebdc62bd3bf5b4016ccce7bed0 (patch)
tree3c921bd73c2694e6906f902cb4636503aaa8841f /include
parent83890662727a90917c558628867bfb96c5b690a4 (diff)
downloadmruby-aecdafb9ce6ea3ebdc62bd3bf5b4016ccce7bed0.tar.gz
mruby-aecdafb9ce6ea3ebdc62bd3bf5b4016ccce7bed0.zip
kh_put in khash.h should work when direct bucket is deleted one
Diffstat (limited to 'include')
-rw-r--r--include/mruby/khash.h35
1 files changed, 24 insertions, 11 deletions
diff --git a/include/mruby/khash.h b/include/mruby/khash.h
index 9ac7ebae6..77a0e3b0f 100644
--- a/include/mruby/khash.h
+++ b/include/mruby/khash.h
@@ -168,26 +168,39 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
} \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \
{ \
- khint_t k; \
+ khint_t kk, k, seen_del = 0; \
if (h->n_occupied >= khash_upper_bound(h)) { \
kh_resize_##name(mrb, h, h->n_buckets*2); \
} \
- k = __hash_func(mrb,key) & khash_mask(h); \
- while (!__ac_iseither(h->ed_flags, k)) { \
- if (__hash_equal(mrb,h->keys[k], key)) break; \
- k = (k+khash_inc(h)) & khash_mask(h); \
+ kk = k = __hash_func(mrb,key) & khash_mask(h); \
+ while (!__ac_isempty(h->ed_flags, k)) { \
+ if (!__ac_isdel(h->ed_flags, k)) { \
+ if (__hash_equal(mrb,h->keys[k], key)) { \
+ seen_del = 0; \
+ break; \
+ } \
+ } \
+ else { \
+ seen_del = 1; \
+ } \
+ k = (k+khash_inc(h)) & khash_mask(h); \
+ } \
+ if (seen_del) { \
+ k = kk; \
+ while (!__ac_isdel(h->ed_flags, k)) { \
+ k = (k+khash_inc(h)) % h->n_buckets; \
+ } \
+ /* put at del */ \
+ h->keys[k] = key; \
+ h->ed_flags[k/4] &= ~__m_del[k%4]; \
+ h->size++; \
} \
- if (__ac_isempty(h->ed_flags, k)) { \
+ else if (__ac_isempty(h->ed_flags, k)) { \
/* put at empty */ \
h->keys[k] = key; \
h->ed_flags[k/4] &= ~__m_empty[k%4]; \
h->size++; \
h->n_occupied++; \
- } else if (__ac_isdel(h->ed_flags, k)) { \
- /* put at del */ \
- h->keys[k] = key; \
- h->ed_flags[k/4] &= ~__m_del[k%4]; \
- h->size++; \
} \
return k; \
} \