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