1 /*
2 ** hash.c - Hash class
3 **
4 ** See Copyright Notice in mruby.h
5 */
6 
7 #include <mruby.h>
8 #include <mruby/array.h>
9 #include <mruby/class.h>
10 #include <mruby/hash.h>
11 #include <mruby/string.h>
12 #include <mruby/variable.h>
13 
14 #ifndef MRB_WITHOUT_FLOAT
15 /* a function to get hash value of a float number */
16 mrb_int mrb_float_id(mrb_float f);
17 #endif
18 
19 #ifndef MRB_HT_INIT_SIZE
20 #define MRB_HT_INIT_SIZE 4
21 #endif
22 #define HT_SEG_INCREASE_RATIO 6 / 5
23 
24 struct segkv {
25   mrb_value key;
26   mrb_value val;
27 };
28 
29 typedef struct segment {
30   uint16_t size;
31   struct segment *next;
32   struct segkv e[];
33 } segment;
34 
35 typedef struct segindex {
36   size_t size;
37   size_t capa;
38   struct segkv *table[];
39 } segindex;
40 
41 /* hash table structure */
42 typedef struct htable {
43   segment *rootseg;
44   segment *lastseg;
45   mrb_int size;
46   uint16_t last_len;
47   segindex *index;
48 } htable;
49 
50 static /* inline */ size_t
ht_hash_func(mrb_state * mrb,htable * t,mrb_value key)51 ht_hash_func(mrb_state *mrb, htable *t, mrb_value key)
52 {
53   enum mrb_vtype tt = mrb_type(key);
54   mrb_value hv;
55   size_t h;
56   segindex *index = t->index;
57   size_t capa = index ? index->capa : 0;
58 
59   switch (tt) {
60   case MRB_TT_STRING:
61     h = mrb_str_hash(mrb, key);
62     break;
63 
64   case MRB_TT_TRUE:
65   case MRB_TT_FALSE:
66   case MRB_TT_SYMBOL:
67   case MRB_TT_FIXNUM:
68 #ifndef MRB_WITHOUT_FLOAT
69   case MRB_TT_FLOAT:
70 #endif
71     h = (size_t)mrb_obj_id(key);
72     break;
73 
74   default:
75     hv = mrb_funcall(mrb, key, "hash", 0);
76     h = (size_t)tt ^ (size_t)mrb_fixnum(hv);
77     break;
78   }
79   if (index && (index != t->index || capa != index->capa)) {
80     mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified");
81   }
82   return ((h)^((h)<<2)^((h)>>2));
83 }
84 
85 static inline mrb_bool
ht_hash_equal(mrb_state * mrb,htable * t,mrb_value a,mrb_value b)86 ht_hash_equal(mrb_state *mrb, htable *t, mrb_value a, mrb_value b)
87 {
88   enum mrb_vtype tt = mrb_type(a);
89 
90   switch (tt) {
91   case MRB_TT_STRING:
92     return mrb_str_equal(mrb, a, b);
93 
94   case MRB_TT_SYMBOL:
95     if (!mrb_symbol_p(b)) return FALSE;
96     return mrb_symbol(a) == mrb_symbol(b);
97 
98   case MRB_TT_FIXNUM:
99     switch (mrb_type(b)) {
100     case MRB_TT_FIXNUM:
101       return mrb_fixnum(a) == mrb_fixnum(b);
102 #ifndef MRB_WITHOUT_FLOAT
103     case MRB_TT_FLOAT:
104       return (mrb_float)mrb_fixnum(a) == mrb_float(b);
105 #endif
106     default:
107       return FALSE;
108     }
109 
110 #ifndef MRB_WITHOUT_FLOAT
111   case MRB_TT_FLOAT:
112     switch (mrb_type(b)) {
113     case MRB_TT_FIXNUM:
114       return mrb_float(a) == (mrb_float)mrb_fixnum(b);
115     case MRB_TT_FLOAT:
116       return mrb_float(a) == mrb_float(b);
117     default:
118       return FALSE;
119     }
120 #endif
121 
122   default:
123     {
124       segindex *index = t->index;
125       size_t capa = index ? index->capa : 0;
126       mrb_bool eql = mrb_eql(mrb, a, b);
127       if (index && (index != t->index || capa != index->capa)) {
128         mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified");
129       }
130       return eql;
131     }
132   }
133 }
134 
135 /* Creates the hash table. */
136 static htable*
ht_new(mrb_state * mrb)137 ht_new(mrb_state *mrb)
138 {
139   htable *t;
140 
141   t = (htable*)mrb_malloc(mrb, sizeof(htable));
142   t->size = 0;
143   t->rootseg =  NULL;
144   t->lastseg =  NULL;
145   t->last_len = 0;
146   t->index = NULL;
147 
148   return t;
149 }
150 
151 #define power2(v) do { \
152   v--;\
153   v |= v >> 1;\
154   v |= v >> 2;\
155   v |= v >> 4;\
156   v |= v >> 8;\
157   v |= v >> 16;\
158   v++;\
159 } while (0)
160 
161 #ifndef UPPER_BOUND
162 #define UPPER_BOUND(x) ((x)>>2|(x)>>1)
163 #endif
164 
165 #define HT_MASK(index) ((index->capa)-1)
166 
167 /* Build index for the hash table */
168 static void
ht_index(mrb_state * mrb,htable * t)169 ht_index(mrb_state *mrb, htable *t)
170 {
171   size_t size = (size_t)t->size;
172   size_t mask;
173   segindex *index = t->index;
174   segment *seg;
175   size_t i;
176 
177   /* allocate index table */
178   if (index && index->size >= UPPER_BOUND(index->capa)) {
179     size = index->capa+1;
180   }
181   power2(size);
182   if (!index || index->capa < size) {
183     index = (segindex*)mrb_realloc_simple(mrb, index, sizeof(segindex)+sizeof(struct segkv*)*size);
184     if (index == NULL) {
185       mrb_free(mrb, t->index);
186       t->index = NULL;
187       return;
188     }
189     t->index = index;
190   }
191   index->size = t->size;
192   index->capa = size;
193   for (i=0; i<size; i++) {
194     index->table[i] = NULL;
195   }
196 
197   /* rebuld index */
198   mask = HT_MASK(index);
199   seg = t->rootseg;
200   while (seg) {
201     for (i=0; i<seg->size; i++) {
202       mrb_value key;
203       size_t k, step = 0;
204 
205       if (!seg->next && i >= (size_t)t->last_len) {
206         return;
207       }
208       key = seg->e[i].key;
209       if (mrb_undef_p(key)) continue;
210       k = ht_hash_func(mrb, t, key) & mask;
211       while (index->table[k]) {
212         k = (k+(++step)) & mask;
213       }
214       index->table[k] = &seg->e[i];
215     }
216     seg = seg->next;
217   }
218 }
219 
220 /* Compacts the hash table removing deleted entries. */
221 static void
ht_compact(mrb_state * mrb,htable * t)222 ht_compact(mrb_state *mrb, htable *t)
223 {
224   segment *seg;
225   uint16_t i, i2;
226   segment *seg2 = NULL;
227   mrb_int size = 0;
228 
229   if (t == NULL) return;
230   seg = t->rootseg;
231   if (t->index && (size_t)t->size == t->index->size) {
232     ht_index(mrb, t);
233     return;
234   }
235   while (seg) {
236     for (i=0; i<seg->size; i++) {
237       mrb_value k = seg->e[i].key;
238 
239       if (!seg->next && i >= t->last_len) {
240         goto exit;
241       }
242       if (mrb_undef_p(k)) {     /* found deleted key */
243         if (seg2 == NULL) {
244           seg2 = seg;
245           i2 = i;
246         }
247       }
248       else {
249         size++;
250         if (seg2 != NULL) {
251           seg2->e[i2++] = seg->e[i];
252           if (i2 >= seg2->size) {
253             seg2 = seg2->next;
254             i2 = 0;
255           }
256         }
257       }
258     }
259     seg = seg->next;
260   }
261  exit:
262   /* reached at end */
263   t->size = size;
264   if (seg2) {
265     seg = seg2->next;
266     seg2->next = NULL;
267     t->last_len = i2;
268     t->lastseg = seg2;
269     while (seg) {
270       seg2 = seg->next;
271       mrb_free(mrb, seg);
272       seg = seg2;
273     }
274   }
275   if (t->index) {
276     ht_index(mrb, t);
277   }
278 }
279 
280 static segment*
segment_alloc(mrb_state * mrb,segment * seg)281 segment_alloc(mrb_state *mrb, segment *seg)
282 {
283   uint32_t size;
284 
285   if (!seg) size = MRB_HT_INIT_SIZE;
286   else {
287     size = seg->size*HT_SEG_INCREASE_RATIO + 1;
288     if (size > UINT16_MAX) size = UINT16_MAX;
289   }
290 
291   seg = (segment*)mrb_malloc(mrb, sizeof(segment)+sizeof(struct segkv)*size);
292   seg->size = size;
293   seg->next = NULL;
294 
295   return seg;
296 }
297 
298 /* Set the value for the key in the indexed table. */
299 static void
ht_index_put(mrb_state * mrb,htable * t,mrb_value key,mrb_value val)300 ht_index_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
301 {
302   segindex *index = t->index;
303   size_t k, sp, step = 0, mask;
304   segment *seg;
305 
306   if (index->size >= UPPER_BOUND(index->capa)) {
307     /* need to expand table */
308     ht_compact(mrb, t);
309     index = t->index;
310   }
311   mask = HT_MASK(index);
312   sp = index->capa;
313   k = ht_hash_func(mrb, t, key) & mask;
314   while (index->table[k]) {
315     mrb_value key2 = index->table[k]->key;
316     if (mrb_undef_p(key2)) {
317       if (sp == index->capa) sp = k;
318     }
319     else if (ht_hash_equal(mrb, t, key, key2)) {
320       index->table[k]->val = val;
321       return;
322     }
323     k = (k+(++step)) & mask;
324   }
325   if (sp < index->capa) {
326     k = sp;
327   }
328 
329   /* put the value at the last */
330   seg = t->lastseg;
331   if (t->last_len < seg->size) {
332     index->table[k] = &seg->e[t->last_len++];
333   }
334   else {                        /* append a new segment */
335     seg->next = segment_alloc(mrb, seg);
336     seg = seg->next;
337     seg->next = NULL;
338     t->lastseg = seg;
339     t->last_len = 1;
340     index->table[k] = &seg->e[0];
341   }
342   index->table[k]->key = key;
343   index->table[k]->val = val;
344   index->size++;
345   t->size++;
346 }
347 
348 /* Set the value for the key in the hash table. */
349 static void
ht_put(mrb_state * mrb,htable * t,mrb_value key,mrb_value val)350 ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
351 {
352   segment *seg;
353   mrb_int i, deleted = 0;
354 
355   if (t == NULL) return;
356   if (t->index) {
357     ht_index_put(mrb, t, key, val);
358     return;
359   }
360   seg = t->rootseg;
361   while (seg) {
362     for (i=0; i<seg->size; i++) {
363       mrb_value k = seg->e[i].key;
364       /* Found room in last segment after last_len */
365       if (!seg->next && i >= t->last_len) {
366         seg->e[i].key = key;
367         seg->e[i].val = val;
368         t->last_len = (uint16_t)i+1;
369         t->size++;
370         return;
371       }
372       if (mrb_undef_p(k)) {
373         deleted++;
374         continue;
375       }
376       if (ht_hash_equal(mrb, t, key, k)) {
377         seg->e[i].val = val;
378         return;
379       }
380     }
381     seg = seg->next;
382   }
383   /* Not found */
384 
385   /* Compact if last segment has room */
386   if (deleted > 0 && deleted > MRB_HT_INIT_SIZE) {
387     ht_compact(mrb, t);
388   }
389   t->size++;
390 
391   /* check if thre's room after compaction */
392   if (t->lastseg && t->last_len < t->lastseg->size) {
393     seg = t->lastseg;
394     i = t->last_len;
395   }
396   else {
397     /* append new segment */
398     seg = segment_alloc(mrb, t->lastseg);
399     i = 0;
400     if (t->rootseg == NULL) {
401       t->rootseg = seg;
402     }
403     else {
404       t->lastseg->next = seg;
405     }
406     t->lastseg = seg;
407   }
408   seg->e[i].key = key;
409   seg->e[i].val = val;
410   t->last_len = (uint16_t)i+1;
411   if (t->index == NULL && t->size > MRB_HT_INIT_SIZE*4) {
412     ht_index(mrb, t);
413   }
414 }
415 
416 /* Get a value for a key from the indexed table. */
417 static mrb_bool
ht_index_get(mrb_state * mrb,htable * t,mrb_value key,mrb_value * vp)418 ht_index_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
419 {
420   segindex *index = t->index;
421   size_t mask = HT_MASK(index);
422   size_t k = ht_hash_func(mrb, t, key) & mask;
423   size_t step = 0;
424 
425   while (index->table[k]) {
426     mrb_value key2 = index->table[k]->key;
427     if (!mrb_undef_p(key2) && ht_hash_equal(mrb, t, key, key2)) {
428       if (vp) *vp = index->table[k]->val;
429       return TRUE;
430     }
431     k = (k+(++step)) & mask;
432   }
433   return FALSE;
434 }
435 
436 /* Get a value for a key from the hash table. */
437 static mrb_bool
ht_get(mrb_state * mrb,htable * t,mrb_value key,mrb_value * vp)438 ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
439 {
440   segment *seg;
441   mrb_int i;
442 
443   if (t == NULL) return FALSE;
444   if (t->index) {
445     return ht_index_get(mrb, t, key, vp);
446   }
447 
448   seg = t->rootseg;
449   while (seg) {
450     for (i=0; i<seg->size; i++) {
451       mrb_value k = seg->e[i].key;
452 
453       if (!seg->next && i >= t->last_len) {
454         return FALSE;
455       }
456       if (mrb_undef_p(k)) continue;
457       if (ht_hash_equal(mrb, t, key, k)) {
458         if (vp) *vp = seg->e[i].val;
459         return TRUE;
460       }
461     }
462     seg = seg->next;
463   }
464   return FALSE;
465 }
466 
467 /* Deletes the value for the symbol from the hash table. */
468 /* Deletion is done by overwriting keys by `undef`. */
469 static mrb_bool
ht_del(mrb_state * mrb,htable * t,mrb_value key,mrb_value * vp)470 ht_del(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
471 {
472   segment *seg;
473   mrb_int i;
474 
475   if (t == NULL) return FALSE;
476   seg = t->rootseg;
477   while (seg) {
478     for (i=0; i<seg->size; i++) {
479       mrb_value key2;
480 
481       if (!seg->next && i >= t->last_len) {
482         /* not found */
483         return FALSE;
484       }
485       key2 = seg->e[i].key;
486       if (!mrb_undef_p(key2) && ht_hash_equal(mrb, t, key, key2)) {
487         if (vp) *vp = seg->e[i].val;
488         seg->e[i].key = mrb_undef_value();
489         t->size--;
490         return TRUE;
491       }
492     }
493     seg = seg->next;
494   }
495   return FALSE;
496 }
497 
498 /* Iterates over the hash table. */
499 static void
ht_foreach(mrb_state * mrb,htable * t,mrb_hash_foreach_func * func,void * p)500 ht_foreach(mrb_state *mrb, htable *t, mrb_hash_foreach_func *func, void *p)
501 {
502   segment *seg;
503   mrb_int i;
504 
505   if (t == NULL) return;
506   seg = t->rootseg;
507   while (seg) {
508     for (i=0; i<seg->size; i++) {
509       /* no value in last segment after last_len */
510       if (!seg->next && i >= t->last_len) {
511         return;
512       }
513       if (mrb_undef_p(seg->e[i].key)) continue;
514       if ((*func)(mrb, seg->e[i].key, seg->e[i].val, p) != 0)
515         return;
516     }
517     seg = seg->next;
518   }
519 }
520 
521 /* Iterates over the hash table. */
522 MRB_API void
mrb_hash_foreach(mrb_state * mrb,struct RHash * hash,mrb_hash_foreach_func * func,void * p)523 mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p)
524 {
525   ht_foreach(mrb, hash->ht, func, p);
526 }
527 
528 /* Copy the hash table. */
529 static htable*
ht_copy(mrb_state * mrb,htable * t)530 ht_copy(mrb_state *mrb, htable *t)
531 {
532   segment *seg;
533   htable *t2;
534   mrb_int i;
535 
536   seg = t->rootseg;
537   t2 = ht_new(mrb);
538   if (t->size == 0) return t2;
539 
540   while (seg) {
541     for (i=0; i<seg->size; i++) {
542       mrb_value key = seg->e[i].key;
543       mrb_value val = seg->e[i].val;
544 
545       if ((seg->next == NULL) && (i >= t->last_len)) {
546         return t2;
547       }
548       if (mrb_undef_p(key)) continue; /* skip deleted key */
549       ht_put(mrb, t2, key, val);
550     }
551     seg = seg->next;
552   }
553   return t2;
554 }
555 
556 /* Free memory of the hash table. */
557 static void
ht_free(mrb_state * mrb,htable * t)558 ht_free(mrb_state *mrb, htable *t)
559 {
560   segment *seg;
561 
562   if (!t) return;
563   seg = t->rootseg;
564   while (seg) {
565     segment *p = seg;
566     seg = seg->next;
567     mrb_free(mrb, p);
568   }
569   if (t->index) mrb_free(mrb, t->index);
570   mrb_free(mrb, t);
571 }
572 
573 static void mrb_hash_modify(mrb_state *mrb, mrb_value hash);
574 
575 static inline mrb_value
ht_key(mrb_state * mrb,mrb_value key)576 ht_key(mrb_state *mrb, mrb_value key)
577 {
578   if (mrb_string_p(key) && !mrb_frozen_p(mrb_str_ptr(key))) {
579     key = mrb_str_dup(mrb, key);
580     MRB_SET_FROZEN_FLAG(mrb_str_ptr(key));
581   }
582   return key;
583 }
584 
585 #define KEY(key) ht_key(mrb, key)
586 
587 static int
hash_mark_i(mrb_state * mrb,mrb_value key,mrb_value val,void * p)588 hash_mark_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
589 {
590   mrb_gc_mark_value(mrb, key);
591   mrb_gc_mark_value(mrb, val);
592   return 0;
593 }
594 
595 void
mrb_gc_mark_hash(mrb_state * mrb,struct RHash * hash)596 mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash)
597 {
598   ht_foreach(mrb, hash->ht, hash_mark_i, NULL);
599 }
600 
601 size_t
mrb_gc_mark_hash_size(mrb_state * mrb,struct RHash * hash)602 mrb_gc_mark_hash_size(mrb_state *mrb, struct RHash *hash)
603 {
604   if (!hash->ht) return 0;
605   return hash->ht->size*2;
606 }
607 
608 void
mrb_gc_free_hash(mrb_state * mrb,struct RHash * hash)609 mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash)
610 {
611   ht_free(mrb, hash->ht);
612 }
613 
614 MRB_API mrb_value
mrb_hash_new(mrb_state * mrb)615 mrb_hash_new(mrb_state *mrb)
616 {
617   struct RHash *h;
618 
619   h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
620   h->ht = 0;
621   h->iv = 0;
622   return mrb_obj_value(h);
623 }
624 
625 MRB_API mrb_value
mrb_hash_new_capa(mrb_state * mrb,mrb_int capa)626 mrb_hash_new_capa(mrb_state *mrb, mrb_int capa)
627 {
628   struct RHash *h;
629 
630   h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
631   /* preallocate hash table */
632   h->ht = ht_new(mrb);
633   /* capacity ignored */
634   h->iv = 0;
635   return mrb_obj_value(h);
636 }
637 
638 static mrb_value mrb_hash_default(mrb_state *mrb, mrb_value hash);
639 static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key);
640 
641 static mrb_value
mrb_hash_init_copy(mrb_state * mrb,mrb_value self)642 mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
643 {
644   mrb_value orig = mrb_get_arg1(mrb);
645   struct RHash* copy;
646   htable *orig_h;
647   mrb_value ifnone, vret;
648 
649   if (mrb_obj_equal(mrb, self, orig)) return self;
650   if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
651       mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
652   }
653 
654   orig_h = RHASH_TBL(self);
655   copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
656   copy->ht = ht_copy(mrb, orig_h);
657 
658   if (MRB_RHASH_DEFAULT_P(self)) {
659     copy->flags |= MRB_HASH_DEFAULT;
660   }
661   if (MRB_RHASH_PROCDEFAULT_P(self)) {
662     copy->flags |= MRB_HASH_PROC_DEFAULT;
663   }
664   vret = mrb_obj_value(copy);
665   ifnone = RHASH_IFNONE(self);
666   if (!mrb_nil_p(ifnone)) {
667       mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone);
668   }
669   return vret;
670 }
671 
672 static int
check_kdict_i(mrb_state * mrb,mrb_value key,mrb_value val,void * data)673 check_kdict_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data)
674 {
675   if (!mrb_symbol_p(key)) {
676     mrb_raise(mrb, E_ARGUMENT_ERROR, "keyword argument hash with non symbol keys");
677   }
678   return 0;
679 }
680 
681 void
mrb_hash_check_kdict(mrb_state * mrb,mrb_value self)682 mrb_hash_check_kdict(mrb_state *mrb, mrb_value self)
683 {
684   htable *t;
685 
686   t = RHASH_TBL(self);
687   if (!t || t->size == 0) return;
688   ht_foreach(mrb, t, check_kdict_i, NULL);
689 }
690 
691 MRB_API mrb_value
mrb_hash_dup(mrb_state * mrb,mrb_value self)692 mrb_hash_dup(mrb_state *mrb, mrb_value self)
693 {
694   struct RHash* copy;
695   htable *orig_h;
696 
697   orig_h = RHASH_TBL(self);
698   copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
699   copy->ht = orig_h ? ht_copy(mrb, orig_h) : NULL;
700   return mrb_obj_value(copy);
701 }
702 
703 MRB_API mrb_value
mrb_hash_get(mrb_state * mrb,mrb_value hash,mrb_value key)704 mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
705 {
706   mrb_value val;
707   mrb_sym mid;
708 
709   if (ht_get(mrb, RHASH_TBL(hash), key, &val)) {
710     return val;
711   }
712 
713   mid = mrb_intern_lit(mrb, "default");
714   if (mrb_func_basic_p(mrb, hash, mid, mrb_hash_default)) {
715     return hash_default(mrb, hash, key);
716   }
717   /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */
718   return mrb_funcall_argv(mrb, hash, mid, 1, &key);
719 }
720 
721 MRB_API mrb_value
mrb_hash_fetch(mrb_state * mrb,mrb_value hash,mrb_value key,mrb_value def)722 mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
723 {
724   mrb_value val;
725 
726   if (ht_get(mrb, RHASH_TBL(hash), key, &val)) {
727     return val;
728   }
729   /* not found */
730   return def;
731 }
732 
733 MRB_API void
mrb_hash_set(mrb_state * mrb,mrb_value hash,mrb_value key,mrb_value val)734 mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
735 {
736   mrb_hash_modify(mrb, hash);
737 
738   key = KEY(key);
739   ht_put(mrb, RHASH_TBL(hash), key, val);
740   mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key);
741   mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val);
742   return;
743 }
744 
745 static void
mrb_hash_modify(mrb_state * mrb,mrb_value hash)746 mrb_hash_modify(mrb_state *mrb, mrb_value hash)
747 {
748   mrb_check_frozen(mrb, mrb_hash_ptr(hash));
749   if (!RHASH_TBL(hash)) {
750     RHASH_TBL(hash) = ht_new(mrb);
751   }
752 }
753 
754 /* 15.2.13.4.16 */
755 /*
756  *  call-seq:
757  *     Hash.new                          -> new_hash
758  *     Hash.new(obj)                     -> new_hash
759  *     Hash.new {|hash, key| block }     -> new_hash
760  *
761  *  Returns a new, empty hash. If this hash is subsequently accessed by
762  *  a key that doesn't correspond to a hash entry, the value returned
763  *  depends on the style of <code>new</code> used to create the hash. In
764  *  the first form, the access returns <code>nil</code>. If
765  *  <i>obj</i> is specified, this single object will be used for
766  *  all <em>default values</em>. If a block is specified, it will be
767  *  called with the hash object and the key, and should return the
768  *  default value. It is the block's responsibility to store the value
769  *  in the hash if required.
770  *
771  *      h = Hash.new("Go Fish")
772  *      h["a"] = 100
773  *      h["b"] = 200
774  *      h["a"]           #=> 100
775  *      h["c"]           #=> "Go Fish"
776  *      # The following alters the single default object
777  *      h["c"].upcase!   #=> "GO FISH"
778  *      h["d"]           #=> "GO FISH"
779  *      h.keys           #=> ["a", "b"]
780  *
781  *      # While this creates a new default object each time
782  *      h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
783  *      h["c"]           #=> "Go Fish: c"
784  *      h["c"].upcase!   #=> "GO FISH: C"
785  *      h["d"]           #=> "Go Fish: d"
786  *      h.keys           #=> ["c", "d"]
787  *
788  */
789 
790 static mrb_value
mrb_hash_init(mrb_state * mrb,mrb_value hash)791 mrb_hash_init(mrb_state *mrb, mrb_value hash)
792 {
793   mrb_value block, ifnone;
794   mrb_bool ifnone_p;
795 
796   ifnone = mrb_nil_value();
797   mrb_get_args(mrb, "&|o?", &block, &ifnone, &ifnone_p);
798   mrb_hash_modify(mrb, hash);
799   if (!mrb_nil_p(block)) {
800     if (ifnone_p) {
801       mrb_argnum_error(mrb, 1, 0, 0);
802     }
803     RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
804     ifnone = block;
805   }
806   if (!mrb_nil_p(ifnone)) {
807     RHASH(hash)->flags |= MRB_HASH_DEFAULT;
808     mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
809   }
810   return hash;
811 }
812 
813 /* 15.2.13.4.2  */
814 /*
815  *  call-seq:
816  *     hsh[key]    ->  value
817  *
818  *  Element Reference---Retrieves the <i>value</i> object corresponding
819  *  to the <i>key</i> object. If not found, returns the default value (see
820  *  <code>Hash::new</code> for details).
821  *
822  *     h = { "a" => 100, "b" => 200 }
823  *     h["a"]   #=> 100
824  *     h["c"]   #=> nil
825  *
826  */
827 static mrb_value
mrb_hash_aget(mrb_state * mrb,mrb_value self)828 mrb_hash_aget(mrb_state *mrb, mrb_value self)
829 {
830   mrb_value key = mrb_get_arg1(mrb);
831 
832   return mrb_hash_get(mrb, self, key);
833 }
834 
835 static mrb_value
hash_default(mrb_state * mrb,mrb_value hash,mrb_value key)836 hash_default(mrb_state *mrb, mrb_value hash, mrb_value key)
837 {
838   if (MRB_RHASH_DEFAULT_P(hash)) {
839     if (MRB_RHASH_PROCDEFAULT_P(hash)) {
840       return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key);
841     }
842     else {
843       return RHASH_IFNONE(hash);
844     }
845   }
846   return mrb_nil_value();
847 }
848 
849 /* 15.2.13.4.5  */
850 /*
851  *  call-seq:
852  *     hsh.default(key=nil)   -> obj
853  *
854  *  Returns the default value, the value that would be returned by
855  *  <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
856  *  See also <code>Hash::new</code> and <code>Hash#default=</code>.
857  *
858  *     h = Hash.new                            #=> {}
859  *     h.default                               #=> nil
860  *     h.default(2)                            #=> nil
861  *
862  *     h = Hash.new("cat")                     #=> {}
863  *     h.default                               #=> "cat"
864  *     h.default(2)                            #=> "cat"
865  *
866  *     h = Hash.new {|h,k| h[k] = k.to_i*10}   #=> {}
867  *     h.default                               #=> nil
868  *     h.default(2)                            #=> 20
869  */
870 
871 static mrb_value
mrb_hash_default(mrb_state * mrb,mrb_value hash)872 mrb_hash_default(mrb_state *mrb, mrb_value hash)
873 {
874   mrb_value key;
875   mrb_bool given;
876 
877   mrb_get_args(mrb, "|o?", &key, &given);
878   if (MRB_RHASH_DEFAULT_P(hash)) {
879     if (MRB_RHASH_PROCDEFAULT_P(hash)) {
880       if (!given) return mrb_nil_value();
881       return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key);
882     }
883     else {
884       return RHASH_IFNONE(hash);
885     }
886   }
887   return mrb_nil_value();
888 }
889 
890 /* 15.2.13.4.6  */
891 /*
892  *  call-seq:
893  *     hsh.default = obj     -> obj
894  *
895  *  Sets the default value, the value returned for a key that does not
896  *  exist in the hash. It is not possible to set the default to a
897  *  <code>Proc</code> that will be executed on each key lookup.
898  *
899  *     h = { "a" => 100, "b" => 200 }
900  *     h.default = "Go fish"
901  *     h["a"]     #=> 100
902  *     h["z"]     #=> "Go fish"
903  *     # This doesn't do what you might hope...
904  *     h.default = proc do |hash, key|
905  *       hash[key] = key + key
906  *     end
907  *     h[2]       #=> #<Proc:0x401b3948@-:6>
908  *     h["cat"]   #=> #<Proc:0x401b3948@-:6>
909  */
910 
911 static mrb_value
mrb_hash_set_default(mrb_state * mrb,mrb_value hash)912 mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
913 {
914   mrb_value ifnone = mrb_get_arg1(mrb);
915 
916   mrb_hash_modify(mrb, hash);
917   mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
918   RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT;
919   if (!mrb_nil_p(ifnone)) {
920     RHASH(hash)->flags |= MRB_HASH_DEFAULT;
921   }
922   else {
923     RHASH(hash)->flags &= ~MRB_HASH_DEFAULT;
924   }
925   return ifnone;
926 }
927 
928 /* 15.2.13.4.7  */
929 /*
930  *  call-seq:
931  *     hsh.default_proc -> anObject
932  *
933  *  If <code>Hash::new</code> was invoked with a block, return that
934  *  block, otherwise return <code>nil</code>.
935  *
936  *     h = Hash.new {|h,k| h[k] = k*k }   #=> {}
937  *     p = h.default_proc                 #=> #<Proc:0x401b3d08@-:1>
938  *     a = []                             #=> []
939  *     p.call(a, 2)
940  *     a                                  #=> [nil, nil, 4]
941  */
942 
943 
944 static mrb_value
mrb_hash_default_proc(mrb_state * mrb,mrb_value hash)945 mrb_hash_default_proc(mrb_state *mrb, mrb_value hash)
946 {
947   if (MRB_RHASH_PROCDEFAULT_P(hash)) {
948     return RHASH_PROCDEFAULT(hash);
949   }
950   return mrb_nil_value();
951 }
952 
953 /*
954  *  call-seq:
955  *     hsh.default_proc = proc_obj     -> proc_obj
956  *
957  *  Sets the default proc to be executed on each key lookup.
958  *
959  *     h.default_proc = proc do |hash, key|
960  *       hash[key] = key + key
961  *     end
962  *     h[2]       #=> 4
963  *     h["cat"]   #=> "catcat"
964  */
965 
966 static mrb_value
mrb_hash_set_default_proc(mrb_state * mrb,mrb_value hash)967 mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
968 {
969   mrb_value ifnone = mrb_get_arg1(mrb);
970 
971   mrb_hash_modify(mrb, hash);
972   mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
973   if (!mrb_nil_p(ifnone)) {
974     RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
975     RHASH(hash)->flags |= MRB_HASH_DEFAULT;
976   }
977   else {
978     RHASH(hash)->flags &= ~MRB_HASH_DEFAULT;
979     RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT;
980   }
981 
982   return ifnone;
983 }
984 
985 MRB_API mrb_value
mrb_hash_delete_key(mrb_state * mrb,mrb_value hash,mrb_value key)986 mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
987 {
988   htable *t = RHASH_TBL(hash);
989   mrb_value del_val;
990 
991   if (ht_del(mrb, t, key, &del_val)) {
992     return del_val;
993   }
994 
995   /* not found */
996   return mrb_nil_value();
997 }
998 
999 static mrb_value
mrb_hash_delete(mrb_state * mrb,mrb_value self)1000 mrb_hash_delete(mrb_state *mrb, mrb_value self)
1001 {
1002   mrb_value key = mrb_get_arg1(mrb);
1003 
1004   mrb_hash_modify(mrb, self);
1005   return mrb_hash_delete_key(mrb, self, key);
1006 }
1007 
1008 /* find first element in the hash table, and remove it. */
1009 static void
ht_shift(mrb_state * mrb,htable * t,mrb_value * kp,mrb_value * vp)1010 ht_shift(mrb_state *mrb, htable *t, mrb_value *kp, mrb_value *vp)
1011 {
1012   segment *seg = t->rootseg;
1013   mrb_int i;
1014 
1015   while (seg) {
1016     for (i=0; i<seg->size; i++) {
1017       mrb_value key;
1018 
1019       if (!seg->next && i >= t->last_len) {
1020         return;
1021       }
1022       key = seg->e[i].key;
1023       if (mrb_undef_p(key)) continue;
1024       *kp = key;
1025       *vp = seg->e[i].val;
1026       /* delete element */
1027       seg->e[i].key = mrb_undef_value();
1028       t->size--;
1029       return;
1030     }
1031     seg = seg->next;
1032   }
1033 }
1034 
1035 /* 15.2.13.4.24 */
1036 /*
1037  *  call-seq:
1038  *     hsh.shift -> anArray or obj
1039  *
1040  *  Removes a key-value pair from <i>hsh</i> and returns it as the
1041  *  two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
1042  *  the hash's default value if the hash is empty.
1043  *
1044  *      h = { 1 => "a", 2 => "b", 3 => "c" }
1045  *      h.shift   #=> [1, "a"]
1046  *      h         #=> {2=>"b", 3=>"c"}
1047  */
1048 
1049 static mrb_value
mrb_hash_shift(mrb_state * mrb,mrb_value hash)1050 mrb_hash_shift(mrb_state *mrb, mrb_value hash)
1051 {
1052   htable *t = RHASH_TBL(hash);
1053 
1054   mrb_hash_modify(mrb, hash);
1055   if (t && t->size > 0) {
1056     mrb_value del_key, del_val;
1057 
1058     ht_shift(mrb, t, &del_key, &del_val);
1059     mrb_gc_protect(mrb, del_key);
1060     mrb_gc_protect(mrb, del_val);
1061     return mrb_assoc_new(mrb, del_key, del_val);
1062   }
1063 
1064   if (MRB_RHASH_DEFAULT_P(hash)) {
1065     if (MRB_RHASH_PROCDEFAULT_P(hash)) {
1066       return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, mrb_nil_value());
1067     }
1068     else {
1069       return RHASH_IFNONE(hash);
1070     }
1071   }
1072   return mrb_nil_value();
1073 }
1074 
1075 /* 15.2.13.4.4  */
1076 /*
1077  *  call-seq:
1078  *     hsh.clear -> hsh
1079  *
1080  *  Removes all key-value pairs from `hsh`.
1081  *
1082  *      h = { "a" => 100, "b" => 200 }   #=> {"a"=>100, "b"=>200}
1083  *      h.clear                          #=> {}
1084  *
1085  */
1086 
1087 MRB_API mrb_value
mrb_hash_clear(mrb_state * mrb,mrb_value hash)1088 mrb_hash_clear(mrb_state *mrb, mrb_value hash)
1089 {
1090   htable *t = RHASH_TBL(hash);
1091 
1092   mrb_hash_modify(mrb, hash);
1093   if (t) {
1094     ht_free(mrb, t);
1095     RHASH_TBL(hash) = NULL;
1096   }
1097   return hash;
1098 }
1099 
1100 /* 15.2.13.4.3  */
1101 /* 15.2.13.4.26 */
1102 /*
1103  *  call-seq:
1104  *     hsh[key] = value        -> value
1105  *     hsh.store(key, value)   -> value
1106  *
1107  *  Element Assignment---Associates the value given by
1108  *  <i>value</i> with the key given by <i>key</i>.
1109  *  <i>key</i> should not have its value changed while it is in
1110  *  use as a key (a <code>String</code> passed as a key will be
1111  *  duplicated and frozen).
1112  *
1113  *      h = { "a" => 100, "b" => 200 }
1114  *      h["a"] = 9
1115  *      h["c"] = 4
1116  *      h   #=> {"a"=>9, "b"=>200, "c"=>4}
1117  *
1118  */
1119 static mrb_value
mrb_hash_aset(mrb_state * mrb,mrb_value self)1120 mrb_hash_aset(mrb_state *mrb, mrb_value self)
1121 {
1122   mrb_value key, val;
1123 
1124   mrb_get_args(mrb, "oo", &key, &val);
1125   mrb_hash_set(mrb, self, key, val);
1126   return val;
1127 }
1128 
1129 MRB_API mrb_int
mrb_hash_size(mrb_state * mrb,mrb_value hash)1130 mrb_hash_size(mrb_state *mrb, mrb_value hash)
1131 {
1132   htable *t = RHASH_TBL(hash);
1133 
1134   if (!t) return 0;
1135   return t->size;
1136 }
1137 
1138 /* 15.2.13.4.20 */
1139 /* 15.2.13.4.25 */
1140 /*
1141  *  call-seq:
1142  *     hsh.length    ->  fixnum
1143  *     hsh.size      ->  fixnum
1144  *
1145  *  Returns the number of key-value pairs in the hash.
1146  *
1147  *     h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
1148  *     h.length        #=> 4
1149  *     h.delete("a")   #=> 200
1150  *     h.length        #=> 3
1151  */
1152 static mrb_value
mrb_hash_size_m(mrb_state * mrb,mrb_value self)1153 mrb_hash_size_m(mrb_state *mrb, mrb_value self)
1154 {
1155   mrb_int size = mrb_hash_size(mrb, self);
1156   return mrb_fixnum_value(size);
1157 }
1158 
1159 MRB_API mrb_bool
mrb_hash_empty_p(mrb_state * mrb,mrb_value self)1160 mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
1161 {
1162   htable *t = RHASH_TBL(self);
1163 
1164   if (!t) return TRUE;
1165   return t->size == 0;
1166 }
1167 
1168 /* 15.2.13.4.12 */
1169 /*
1170  *  call-seq:
1171  *     hsh.empty?    -> true or false
1172  *
1173  *  Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
1174  *
1175  *     {}.empty?   #=> true
1176  *
1177  */
1178 static mrb_value
mrb_hash_empty_m(mrb_state * mrb,mrb_value self)1179 mrb_hash_empty_m(mrb_state *mrb, mrb_value self)
1180 {
1181   return mrb_bool_value(mrb_hash_empty_p(mrb, self));
1182 }
1183 
1184 static int
hash_keys_i(mrb_state * mrb,mrb_value key,mrb_value val,void * p)1185 hash_keys_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
1186 {
1187   mrb_ary_push(mrb, *(mrb_value*)p, key);
1188   return 0;
1189 }
1190 
1191 /* 15.2.13.4.19 */
1192 /*
1193  *  call-seq:
1194  *     hsh.keys    -> array
1195  *
1196  *  Returns a new array populated with the keys from this hash. See also
1197  *  <code>Hash#values</code>.
1198  *
1199  *     h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
1200  *     h.keys   #=> ["a", "b", "c", "d"]
1201  *
1202  */
1203 
1204 MRB_API mrb_value
mrb_hash_keys(mrb_state * mrb,mrb_value hash)1205 mrb_hash_keys(mrb_state *mrb, mrb_value hash)
1206 {
1207   htable *t = RHASH_TBL(hash);
1208   mrb_int size;
1209   mrb_value ary;
1210 
1211   if (!t || (size = t->size) == 0)
1212     return mrb_ary_new(mrb);
1213   ary = mrb_ary_new_capa(mrb, size);
1214   ht_foreach(mrb, t, hash_keys_i, (void*)&ary);
1215   return ary;
1216 }
1217 
1218 static int
hash_vals_i(mrb_state * mrb,mrb_value key,mrb_value val,void * p)1219 hash_vals_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
1220 {
1221   mrb_ary_push(mrb, *(mrb_value*)p, val);
1222   return 0;
1223 }
1224 
1225 /* 15.2.13.4.28 */
1226 /*
1227  *  call-seq:
1228  *     hsh.values    -> array
1229  *
1230  *  Returns a new array populated with the values from <i>hsh</i>. See
1231  *  also <code>Hash#keys</code>.
1232  *
1233  *     h = { "a" => 100, "b" => 200, "c" => 300 }
1234  *     h.values   #=> [100, 200, 300]
1235  *
1236  */
1237 
1238 MRB_API mrb_value
mrb_hash_values(mrb_state * mrb,mrb_value hash)1239 mrb_hash_values(mrb_state *mrb, mrb_value hash)
1240 {
1241   htable *t = RHASH_TBL(hash);
1242   mrb_int size;
1243   mrb_value ary;
1244 
1245   if (!t || (size = t->size) == 0)
1246     return mrb_ary_new(mrb);
1247   ary = mrb_ary_new_capa(mrb, size);
1248   ht_foreach(mrb, t, hash_vals_i, (void*)&ary);
1249   return ary;
1250 }
1251 
1252 /* 15.2.13.4.13 */
1253 /* 15.2.13.4.15 */
1254 /* 15.2.13.4.18 */
1255 /* 15.2.13.4.21 */
1256 /*
1257  *  call-seq:
1258  *     hsh.has_key?(key)    -> true or false
1259  *     hsh.include?(key)    -> true or false
1260  *     hsh.key?(key)        -> true or false
1261  *     hsh.member?(key)     -> true or false
1262  *
1263  *  Returns <code>true</code> if the given key is present in <i>hsh</i>.
1264  *
1265  *     h = { "a" => 100, "b" => 200 }
1266  *     h.has_key?("a")   #=> true
1267  *     h.has_key?("z")   #=> false
1268  *
1269  */
1270 
1271 MRB_API mrb_bool
mrb_hash_key_p(mrb_state * mrb,mrb_value hash,mrb_value key)1272 mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key)
1273 {
1274   htable *t;
1275 
1276   t = RHASH_TBL(hash);
1277   if (ht_get(mrb, t, key, NULL)) {
1278     return TRUE;
1279   }
1280   return FALSE;
1281 }
1282 
1283 static mrb_value
mrb_hash_has_key(mrb_state * mrb,mrb_value hash)1284 mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
1285 {
1286   mrb_value key = mrb_get_arg1(mrb);
1287   mrb_bool key_p;
1288 
1289   key_p = mrb_hash_key_p(mrb, hash, key);
1290   return mrb_bool_value(key_p);
1291 }
1292 
1293 struct has_v_arg {
1294   mrb_bool found;
1295   mrb_value val;
1296 };
1297 
1298 static int
hash_has_value_i(mrb_state * mrb,mrb_value key,mrb_value val,void * p)1299 hash_has_value_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
1300 {
1301   struct has_v_arg *arg = (struct has_v_arg*)p;
1302 
1303   if (mrb_equal(mrb, arg->val, val)) {
1304     arg->found = TRUE;
1305     return 1;
1306   }
1307   return 0;
1308 }
1309 
1310 /* 15.2.13.4.14 */
1311 /* 15.2.13.4.27 */
1312 /*
1313  *  call-seq:
1314  *     hsh.has_value?(value)    -> true or false
1315  *     hsh.value?(value)        -> true or false
1316  *
1317  *  Returns <code>true</code> if the given value is present for some key
1318  *  in <i>hsh</i>.
1319  *
1320  *     h = { "a" => 100, "b" => 200 }
1321  *     h.has_value?(100)   #=> true
1322  *     h.has_value?(999)   #=> false
1323  */
1324 
1325 static mrb_value
mrb_hash_has_value(mrb_state * mrb,mrb_value hash)1326 mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
1327 {
1328   mrb_value val = mrb_get_arg1(mrb);
1329   struct has_v_arg arg;
1330 
1331   arg.found = FALSE;
1332   arg.val = val;
1333   ht_foreach(mrb, RHASH_TBL(hash), hash_has_value_i, &arg);
1334   return mrb_bool_value(arg.found);
1335 }
1336 
1337 static int
merge_i(mrb_state * mrb,mrb_value key,mrb_value val,void * data)1338 merge_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data)
1339 {
1340   htable *h1 = (htable*)data;
1341 
1342   ht_put(mrb, h1, key, val);
1343   return 0;
1344 }
1345 
1346 MRB_API void
mrb_hash_merge(mrb_state * mrb,mrb_value hash1,mrb_value hash2)1347 mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2)
1348 {
1349   htable *h1, *h2;
1350 
1351   mrb_hash_modify(mrb, hash1);
1352   hash2 = mrb_ensure_hash_type(mrb, hash2);
1353   h1 = RHASH_TBL(hash1);
1354   h2 = RHASH_TBL(hash2);
1355 
1356   if (!h2) return;
1357   if (!h1) {
1358     RHASH_TBL(hash1) = ht_copy(mrb, h2);
1359     return;
1360   }
1361   ht_foreach(mrb, h2, merge_i, h1);
1362   mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash1));
1363   return;
1364 }
1365 
1366 /*
1367  *  call-seq:
1368  *    hsh.rehash -> hsh
1369  *
1370  *  Rebuilds the hash based on the current hash values for each key. If
1371  *  values of key objects have changed since they were inserted, this
1372  *  method will reindex <i>hsh</i>.
1373  *
1374  *     keys = (1..17).map{|n| [n]}
1375  *     k = keys[0]
1376  *     h = {}
1377  *     keys.each{|key| h[key] = key[0]}
1378  *     h     #=> { [1]=> 1, [2]=> 2, [3]=> 3, [4]=> 4, [5]=> 5, [6]=> 6, [7]=> 7,
1379  *                 [8]=> 8, [9]=> 9,[10]=>10,[11]=>11,[12]=>12,[13]=>13,[14]=>14,
1380  *                [15]=>15,[16]=>16,[17]=>17}
1381  *     h[k]  #=> 1
1382  *     k[0] = keys.size + 1
1383  *     h     #=> {[18]=> 1, [2]=> 2, [3]=> 3, [4]=> 4, [5]=> 5, [6]=> 6, [7]=> 7,
1384  *                 [8]=> 8, [9]=> 9,[10]=>10,[11]=>11,[12]=>12,[13]=>13,[14]=>14,
1385  *                [15]=>15,[16]=>16,[17]=>17}
1386  *     h[k]  #=> nil
1387  *     h.rehash
1388  *     h[k]  #=> 1
1389  */
1390 static mrb_value
mrb_hash_rehash(mrb_state * mrb,mrb_value self)1391 mrb_hash_rehash(mrb_state *mrb, mrb_value self)
1392 {
1393   ht_compact(mrb, RHASH_TBL(self));
1394   return self;
1395 }
1396 
1397 void
mrb_init_hash(mrb_state * mrb)1398 mrb_init_hash(mrb_state *mrb)
1399 {
1400   struct RClass *h;
1401 
1402   mrb->hash_class = h = mrb_define_class(mrb, "Hash", mrb->object_class);              /* 15.2.13 */
1403   MRB_SET_INSTANCE_TT(h, MRB_TT_HASH);
1404 
1405   mrb_define_method(mrb, h, "initialize_copy", mrb_hash_init_copy,   MRB_ARGS_REQ(1));
1406   mrb_define_method(mrb, h, "[]",              mrb_hash_aget,        MRB_ARGS_REQ(1)); /* 15.2.13.4.2  */
1407   mrb_define_method(mrb, h, "[]=",             mrb_hash_aset,        MRB_ARGS_REQ(2)); /* 15.2.13.4.3  */
1408   mrb_define_method(mrb, h, "clear",           mrb_hash_clear,       MRB_ARGS_NONE()); /* 15.2.13.4.4  */
1409   mrb_define_method(mrb, h, "default",         mrb_hash_default,     MRB_ARGS_OPT(1));  /* 15.2.13.4.5  */
1410   mrb_define_method(mrb, h, "default=",        mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6  */
1411   mrb_define_method(mrb, h, "default_proc",    mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7  */
1412   mrb_define_method(mrb, h, "default_proc=",   mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7  */
1413   mrb_define_method(mrb, h, "__delete",        mrb_hash_delete,      MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8  */
1414   mrb_define_method(mrb, h, "empty?",          mrb_hash_empty_m,     MRB_ARGS_NONE()); /* 15.2.13.4.12 */
1415   mrb_define_method(mrb, h, "has_key?",        mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */
1416   mrb_define_method(mrb, h, "has_value?",      mrb_hash_has_value,   MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */
1417   mrb_define_method(mrb, h, "include?",        mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */
1418   mrb_define_method(mrb, h, "initialize",      mrb_hash_init,        MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.2.13.4.16 */
1419   mrb_define_method(mrb, h, "key?",            mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */
1420   mrb_define_method(mrb, h, "keys",            mrb_hash_keys,        MRB_ARGS_NONE()); /* 15.2.13.4.19 */
1421   mrb_define_method(mrb, h, "length",          mrb_hash_size_m,      MRB_ARGS_NONE()); /* 15.2.13.4.20 */
1422   mrb_define_method(mrb, h, "member?",         mrb_hash_has_key,     MRB_ARGS_REQ(1)); /* 15.2.13.4.21 */
1423   mrb_define_method(mrb, h, "shift",           mrb_hash_shift,       MRB_ARGS_NONE()); /* 15.2.13.4.24 */
1424   mrb_define_method(mrb, h, "size",            mrb_hash_size_m,      MRB_ARGS_NONE()); /* 15.2.13.4.25 */
1425   mrb_define_method(mrb, h, "store",           mrb_hash_aset,        MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */
1426   mrb_define_method(mrb, h, "value?",          mrb_hash_has_value,   MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */
1427   mrb_define_method(mrb, h, "values",          mrb_hash_values,      MRB_ARGS_NONE()); /* 15.2.13.4.28 */
1428   mrb_define_method(mrb, h, "rehash",          mrb_hash_rehash,      MRB_ARGS_NONE());
1429 }
1430