summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hash.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/src/hash.c b/src/hash.c
index 6d176e80c..4a85fcec3 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -60,6 +60,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,13 +71,14 @@ 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);
}
@@ -106,9 +108,11 @@ 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)) {
@@ -142,6 +146,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 */
@@ -167,11 +172,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++) {
@@ -196,7 +201,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;
@@ -696,7 +701,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;
}
@@ -813,13 +818,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 */
@@ -934,8 +938,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_cstr(mrb, "{}");
return inspect_hash(mrb, hash, 0);
}
@@ -1102,6 +1108,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"))) {
@@ -1112,10 +1120,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;