diff options
Diffstat (limited to 'src/hash.c')
| -rw-r--r-- | src/hash.c | 106 |
1 files changed, 54 insertions, 52 deletions
diff --git a/src/hash.c b/src/hash.c index a06becd91..927e40e66 100644 --- a/src/hash.c +++ b/src/hash.c @@ -11,8 +11,6 @@ #include "mruby/array.h" #include "mruby/string.h" #include "mruby/variable.h" -#include <string.h> -#include <stdio.h> static inline khint_t mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) @@ -31,15 +29,8 @@ mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b) return mrb_eql(mrb, a, b); } -KHASH_INIT(ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal); - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif +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); static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); @@ -60,6 +51,7 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash) khiter_t k; khash_t(ht) *h = hash->ht; + if (!h) return; for (k = kh_begin(h); k != kh_end(h); k++) if (kh_exist(h, k)) { mrb_gc_mark_value(mrb, kh_key(h, k)); @@ -70,43 +62,48 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash) size_t mrb_gc_mark_ht_size(mrb_state *mrb, struct RHash *hash) { + if (!hash->ht) return 0; return kh_size(hash->ht)*2; } void mrb_gc_free_ht(mrb_state *mrb, struct RHash *hash) { - kh_destroy(ht, hash->ht); + if (hash->ht) kh_destroy(ht, hash->ht); } mrb_value -mrb_hash_new_capa(mrb_state *mrb, size_t capa) +mrb_hash_new_capa(mrb_state *mrb, int capa) { struct RHash *h; h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); h->ht = kh_init(ht, mrb); - kh_resize(ht, h->ht, capa); + if (capa > 0) { + kh_resize(ht, h->ht, capa); + } h->iv = 0; return mrb_obj_value(h); } mrb_value -mrb_hash_new(mrb_state *mrb, int capa) +mrb_hash_new(mrb_state *mrb) { - return mrb_hash_new_capa(mrb, capa); + return mrb_hash_new_capa(mrb, 0); } mrb_value -mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ /* mrb_hash_lookup */ +mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; - k = kh_get(ht, h, key); - if (k != kh_end(h)) - return kh_value(h, k); + if (h) { + k = kh_get(ht, h, key); + if (k != kh_end(h)) + return kh_value(h, k); + } /* not found */ if (MRB_RHASH_PROCDEFAULT_P(hash)) { @@ -116,13 +113,13 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ } mrb_value -mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def) /* mrb_hash_lookup2 */ +mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; if (h) { - k = kh_get(ht, h, vkey); + k = kh_get(ht, h, key); if (k != kh_end(h)) return kh_value(h, k); } @@ -140,6 +137,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mr mrb_hash_modify(mrb, hash); h = RHASH_TBL(hash); + if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb); k = kh_get(ht, h, key); if (k == kh_end(h)) { /* expand */ @@ -165,11 +163,11 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) khash_t(ht) *h, *ret_h; khiter_t k, ret_k; + h = RHASH_TBL(hash); ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); ret->ht = kh_init(ht, mrb); - if (!RHASH_EMPTY_P(hash)) { - h = RHASH_TBL(hash); + if (kh_size(h) > 0) { ret_h = ret->ht; for (k = kh_begin(h); k != kh_end(h); k++) { @@ -194,7 +192,7 @@ mrb_hash_tbl(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); - if (!RHASH_TBL(hash)) { + if (!h) { RHASH_TBL(hash) = kh_init(ht, mrb); } return h; @@ -331,15 +329,9 @@ mrb_hash_aget(mrb_state *mrb, mrb_value self) } mrb_value -mrb_hash_lookup2(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) -{ - return mrb_hash_getWithDef(mrb, hash, key, def); -} - -mrb_value mrb_hash_lookup(mrb_state *mrb, mrb_value hash, mrb_value key) { - return mrb_hash_lookup2(mrb, hash, key, mrb_nil_value()); + return mrb_hash_get(mrb, hash, key); } /* @@ -496,7 +488,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) return ifnone; } -mrb_value +static mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); @@ -576,7 +568,9 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) if (!kh_exist(h,k)) continue; delKey = kh_key(h,k); + mrb_gc_protect(mrb, delKey); delVal = mrb_hash_delete_key(mrb, hash, delKey); + mrb_gc_protect(mrb, delVal); return mrb_assoc_new(mrb, delKey, delVal); } @@ -700,7 +694,7 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); - kh_clear(ht, h); + if (h) kh_clear(ht, h); return hash; } @@ -817,13 +811,12 @@ static mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { khash_t(ht) *h = RHASH_TBL(self); - khiter_t k; + if (h) { - for (k = kh_begin(h); k != kh_end(h); k++) - if (kh_exist(h, k)) - return mrb_false_value(); + if (kh_size(h) == 0) + return mrb_true_value(); } - return mrb_true_value(); + return mrb_false_value(); } /* 15.2.13.4.11 */ @@ -896,9 +889,9 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; - if (recur) return mrb_str_new_cstr(mrb, "{...}"); + if (recur) return mrb_str_new(mrb, "{...}", 5); - str = mrb_str_new_cstr(mrb, "{"); + str = mrb_str_new(mrb, "{", 1); if (h && kh_size(h) > 0) { for (k = kh_begin(h); k != kh_end(h); k++) { int ai; @@ -911,14 +904,14 @@ 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_buf_cat(mrb, str, "=>", strlen("=>")); + mrb_str_buf_cat(mrb, str, "=>", 2); str2 = mrb_inspect(mrb, kh_value(h,k)); mrb_str_append(mrb, str, str2); mrb_gc_arena_restore(mrb, ai); } } - mrb_str_buf_cat(mrb, str, "}", strlen("}"));//mrb_str_buf_cat2(str, "}"); + mrb_str_buf_cat(mrb, str, "}", 1); return str; } @@ -938,8 +931,10 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) static mrb_value mrb_hash_inspect(mrb_state *mrb, mrb_value hash) { - if (RHASH_EMPTY_P(hash)) - return mrb_str_new_cstr(mrb, "{}"); + khash_t(ht) *h = RHASH_TBL(hash); + + if (!h || kh_size(h) == 0) + return mrb_str_new(mrb, "{}", 2); return inspect_hash(mrb, hash, 0); } @@ -1106,6 +1101,8 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash) static mrb_value hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) { + khash_t(ht) *h1, *h2; + if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (mrb_type(hash2) != MRB_TT_HASH) { if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) { @@ -1116,10 +1113,15 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) else return mrb_fixnum_value(mrb_equal(mrb, hash2, hash1)); } - if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2)) return mrb_false_value(); + h1 = RHASH_TBL(hash1); + h2 = RHASH_TBL(hash2); + if (!h2) { + if (!h2) return mrb_true_value(); + return mrb_false_value(); + } + if (!h2) return mrb_false_value(); + if (kh_size(h1) != kh_size(h2)) return mrb_false_value(); else { - khash_t(ht) *h1 = RHASH_TBL(hash1); - khash_t(ht) *h2 = RHASH_TBL(hash2); khiter_t k1, k2; mrb_value key; @@ -1337,9 +1339,9 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,ARGS_NONE()); /* 15.2.13.4.7 */ mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,ARGS_REQ(1)); /* 15.2.13.4.7 */ mrb_define_method(mrb, h, "__delete", mrb_hash_delete, ARGS_REQ(1)); /* core of 15.2.13.4.8 */ -//mrb_define_method(mrb, h, "each", mrb_hash_each_pair, ARGS_NONE()); /* 15.2.13.4.9 */ /* move to mrblib\hash.rb */ -//mrb_define_method(mrb, h, "each_key", mrb_hash_each_key, ARGS_NONE()); /* 15.2.13.4.10 */ /* move to mrblib\hash.rb */ -//mrb_define_method(mrb, h, "each_value", mrb_hash_each_value, ARGS_NONE()); /* 15.2.13.4.11 */ /* move to mrblib\hash.rb */ +// "each" 15.2.13.4.9 move to mrblib/hash.rb +// "each_key" 15.2.13.4.10 move to mrblib/hash.rb +// "each_value" 15.2.13.4.11 move to mrblib/hash.rb mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, ARGS_NONE()); /* 15.2.13.4.12 */ mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, ARGS_REQ(1)); /* 15.2.13.4.13 */ mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, ARGS_REQ(1)); /* 15.2.13.4.14 */ @@ -1350,7 +1352,7 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method(mrb, h, "keys", mrb_hash_keys, ARGS_NONE()); /* 15.2.13.4.19 */ mrb_define_method(mrb, h, "length", mrb_hash_size_m, ARGS_NONE()); /* 15.2.13.4.20 */ mrb_define_method(mrb, h, "member?", mrb_hash_has_key, ARGS_REQ(1)); /* 15.2.13.4.21 */ -//mrb_define_method(mrb, h, "merge", mrb_hash_merge, ARGS_REQ(1)); /* 15.2.13.4.22 */ /* move to mrblib\hash.rb */ +// "merge" 15.2.13.4.22 move to mrblib/hash.rb mrb_define_method(mrb, h, "replace", mrb_hash_replace, ARGS_REQ(1)); /* 15.2.13.4.23 */ mrb_define_method(mrb, h, "shift", mrb_hash_shift, ARGS_NONE()); /* 15.2.13.4.24 */ mrb_define_method(mrb, h, "size", mrb_hash_size_m, ARGS_NONE()); /* 15.2.13.4.25 */ |
