diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2014-04-01 14:18:21 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2014-04-01 14:18:21 +0900 |
| commit | f05069fd1a80c0fd46f92a7763ba0dbcab0feebc (patch) | |
| tree | e8438e57c67c2dde00ca21c27962cb49421a065f /src/hash.c | |
| parent | 00f3484ff7edcfd9e6f790fbc8e84595b160d3e8 (diff) | |
| download | mruby-f05069fd1a80c0fd46f92a7763ba0dbcab0feebc.tar.gz mruby-f05069fd1a80c0fd46f92a7763ba0dbcab0feebc.zip | |
Hash to preserve order as Ruby1.9 does
Diffstat (limited to 'src/hash.c')
| -rw-r--r-- | src/hash.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/src/hash.c b/src/hash.c index 26f732700..3b4b2a003 100644 --- a/src/hash.c +++ b/src/hash.c @@ -90,8 +90,13 @@ mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b) } } -KHASH_DECLARE(ht, mrb_value, mrb_value, 1) -KHASH_DEFINE (ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal) +typedef struct { + mrb_value v; + mrb_int n; +} mrb_hash_value; + +KHASH_DECLARE(ht, mrb_value, mrb_hash_value, 1) +KHASH_DEFINE (ht, mrb_value, mrb_hash_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal) static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); @@ -116,7 +121,7 @@ mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash) for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)) { mrb_value key = kh_key(h, k); - mrb_value val = kh_value(h, k); + mrb_value val = kh_value(h, k).v; mrb_gc_mark_value(mrb, key); mrb_gc_mark_value(mrb, val); @@ -167,7 +172,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) if (h) { k = kh_get(ht, mrb, h, key); if (k != kh_end(h)) - return kh_value(h, k); + return kh_value(h, k).v; } /* not found */ @@ -186,7 +191,7 @@ mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) if (h) { k = kh_get(ht, mrb, h, key); if (k != kh_end(h)) - return kh_value(h, k); + return kh_value(h, k).v; } /* not found */ @@ -209,9 +214,10 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) int ai = mrb_gc_arena_save(mrb); k = kh_put(ht, mrb, h, KEY(key)); mrb_gc_arena_restore(mrb, ai); + kh_value(h, k).n = kh_size(h)-1; } - kh_value(h, k) = val; + kh_value(h, k).v = val; mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash)); return; } @@ -495,7 +501,7 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) if (h) { k = kh_get(ht, mrb, h, key); if (k != kh_end(h)) { - delVal = kh_value(h, k); + delVal = kh_value(h, k).v; kh_del(ht, mrb, h, k); return delVal; } @@ -657,7 +663,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) if (h2) { for (k = kh_begin(h2); k != kh_end(h2); k++) { if (kh_exist(h2, k)) - mrb_hash_set(mrb, hash, kh_key(h2, k), kh_value(h2, k)); + mrb_hash_set(mrb, hash, kh_key(h2, k), kh_value(h2, k).v); } } @@ -738,7 +744,7 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) str2 = mrb_inspect(mrb, kh_key(h,k)); mrb_str_append(mrb, str, str2); mrb_str_cat_lit(mrb, str, "=>"); - str2 = mrb_inspect(mrb, kh_value(h,k)); + str2 = mrb_inspect(mrb, kh_value(h,k).v); mrb_str_append(mrb, str, str2); mrb_gc_arena_restore(mrb, ai); @@ -809,8 +815,10 @@ mrb_hash_keys(mrb_state *mrb, mrb_value hash) ary = mrb_ary_new_capa(mrb, kh_size(h)); for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)) { - mrb_value v = kh_key(h,k); - mrb_ary_push(mrb, ary, v); + mrb_value kv = kh_key(h,k); + mrb_hash_value hv = kh_value(h,k); + + mrb_ary_set(mrb, ary, hv.n, kv); } } return ary; @@ -840,8 +848,9 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash) ary = mrb_ary_new_capa(mrb, kh_size(h)); for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)){ - mrb_value v = kh_value(h,k); - mrb_ary_push(mrb, ary, v); + mrb_hash_value hv = kh_value(h,k); + + mrb_ary_set(mrb, ary, hv.n, hv.v); } } return ary; @@ -898,7 +907,7 @@ mrb_hash_has_valueWithvalue(mrb_state *mrb, mrb_value hash, mrb_value value) for (k = kh_begin(h); k != kh_end(h); k++) { if (!kh_exist(h, k)) continue; - if (mrb_equal(mrb, kh_value(h,k), value)) { + if (mrb_equal(mrb, kh_value(h,k).v, value)) { return mrb_true_value(); } } @@ -969,9 +978,9 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) k2 = kh_get(ht, mrb, h2, key); if (k2 != kh_end(h2)) { if (eql) - eq = mrb_eql(mrb, kh_value(h1,k1), kh_value(h2,k2)); + eq = mrb_eql(mrb, kh_value(h1,k1).v, kh_value(h2,k2).v); else - eq = mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2)); + eq = mrb_equal(mrb, kh_value(h1,k1).v, kh_value(h2,k2).v); if (eq) { continue; /* next key */ } |
