Hash to preserve order as Ruby1.9 does

parent 00f3484f
...@@ -90,8 +90,13 @@ mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b) ...@@ -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) typedef struct {
KHASH_DEFINE (ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal) 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); 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) ...@@ -116,7 +121,7 @@ mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash)
for (k = kh_begin(h); k != kh_end(h); k++) { for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) { if (kh_exist(h, k)) {
mrb_value key = kh_key(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, key);
mrb_gc_mark_value(mrb, val); mrb_gc_mark_value(mrb, val);
...@@ -167,7 +172,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) ...@@ -167,7 +172,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
if (h) { if (h) {
k = kh_get(ht, mrb, h, key); k = kh_get(ht, mrb, h, key);
if (k != kh_end(h)) if (k != kh_end(h))
return kh_value(h, k); return kh_value(h, k).v;
} }
/* not found */ /* not found */
...@@ -186,7 +191,7 @@ mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) ...@@ -186,7 +191,7 @@ mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
if (h) { if (h) {
k = kh_get(ht, mrb, h, key); k = kh_get(ht, mrb, h, key);
if (k != kh_end(h)) if (k != kh_end(h))
return kh_value(h, k); return kh_value(h, k).v;
} }
/* not found */ /* not found */
...@@ -209,9 +214,10 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) ...@@ -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); int ai = mrb_gc_arena_save(mrb);
k = kh_put(ht, mrb, h, KEY(key)); k = kh_put(ht, mrb, h, KEY(key));
mrb_gc_arena_restore(mrb, ai); 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)); mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash));
return; return;
} }
...@@ -495,7 +501,7 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) ...@@ -495,7 +501,7 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
if (h) { if (h) {
k = kh_get(ht, mrb, h, key); k = kh_get(ht, mrb, h, key);
if (k != kh_end(h)) { if (k != kh_end(h)) {
delVal = kh_value(h, k); delVal = kh_value(h, k).v;
kh_del(ht, mrb, h, k); kh_del(ht, mrb, h, k);
return delVal; return delVal;
} }
...@@ -657,7 +663,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) ...@@ -657,7 +663,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash)
if (h2) { if (h2) {
for (k = kh_begin(h2); k != kh_end(h2); k++) { for (k = kh_begin(h2); k != kh_end(h2); k++) {
if (kh_exist(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) ...@@ -738,7 +744,7 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
str2 = mrb_inspect(mrb, kh_key(h,k)); str2 = mrb_inspect(mrb, kh_key(h,k));
mrb_str_append(mrb, str, str2); mrb_str_append(mrb, str, str2);
mrb_str_cat_lit(mrb, str, "=>"); 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_str_append(mrb, str, str2);
mrb_gc_arena_restore(mrb, ai); mrb_gc_arena_restore(mrb, ai);
...@@ -809,8 +815,10 @@ mrb_hash_keys(mrb_state *mrb, mrb_value hash) ...@@ -809,8 +815,10 @@ mrb_hash_keys(mrb_state *mrb, mrb_value hash)
ary = mrb_ary_new_capa(mrb, kh_size(h)); ary = mrb_ary_new_capa(mrb, kh_size(h));
for (k = kh_begin(h); k != kh_end(h); k++) { for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) { if (kh_exist(h, k)) {
mrb_value v = kh_key(h,k); mrb_value kv = kh_key(h,k);
mrb_ary_push(mrb, ary, v); mrb_hash_value hv = kh_value(h,k);
mrb_ary_set(mrb, ary, hv.n, kv);
} }
} }
return ary; return ary;
...@@ -840,8 +848,9 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash) ...@@ -840,8 +848,9 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash)
ary = mrb_ary_new_capa(mrb, kh_size(h)); ary = mrb_ary_new_capa(mrb, kh_size(h));
for (k = kh_begin(h); k != kh_end(h); k++) { for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)){ if (kh_exist(h, k)){
mrb_value v = kh_value(h,k); mrb_hash_value hv = kh_value(h,k);
mrb_ary_push(mrb, ary, v);
mrb_ary_set(mrb, ary, hv.n, hv.v);
} }
} }
return ary; return ary;
...@@ -898,7 +907,7 @@ mrb_hash_has_valueWithvalue(mrb_state *mrb, mrb_value hash, mrb_value value) ...@@ -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++) { for (k = kh_begin(h); k != kh_end(h); k++) {
if (!kh_exist(h, k)) continue; 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(); return mrb_true_value();
} }
} }
...@@ -969,9 +978,9 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) ...@@ -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); k2 = kh_get(ht, mrb, h2, key);
if (k2 != kh_end(h2)) { if (k2 != kh_end(h2)) {
if (eql) 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 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) { if (eq) {
continue; /* next key */ continue; /* next key */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment