Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

hash.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 hash.c -
4
5 $Author$
6 created at: Mon Nov 22 18:51:18 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12 **********************************************************************/
13
14 #include "ruby/encoding.h"
15 #include "ruby/st.h"
16 #include "ruby/util.h"
17 #include "internal.h"
18 #include <errno.h>
19 #include "probes.h"
20 #include "id.h"
21 #include "symbol.h"
22 #include "debug_counter.h"
23 #include "transient_heap.h"
24 #include "ruby_assert.h"
25 #ifdef __APPLE__
26 # ifdef HAVE_CRT_EXTERNS_H
27 # include <crt_externs.h>
28 # else
29 # include "missing/crt_externs.h"
30 # endif
31 #endif
32
33 #ifndef HASH_DEBUG
34 #define HASH_DEBUG 0
35 #endif
36
37 #if HASH_DEBUG
38 #include "gc.h"
39 #endif
40
41 #define HAS_EXTRA_STATES(hash, klass) ( \
42 ((klass = has_extra_methods(rb_obj_class(hash))) != 0) || \
43 FL_TEST((hash), FL_EXIVAR|RHASH_PROC_DEFAULT) || \
44 !NIL_P(RHASH_IFNONE(hash)))
45
46 #define SET_DEFAULT(hash, ifnone) ( \
47 FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \
48 RHASH_SET_IFNONE(hash, ifnone))
49
50 #define SET_PROC_DEFAULT(hash, proc) set_proc_default(hash, proc)
51
52 #define COPY_DEFAULT(hash, hash2) copy_default(RHASH(hash), RHASH(hash2))
53
54 static inline void
55 copy_default(struct RHash *hash, const struct RHash *hash2)
56 {
57 hash->basic.flags &= ~RHASH_PROC_DEFAULT;
58 hash->basic.flags |= hash2->basic.flags & RHASH_PROC_DEFAULT;
59 RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
60 }
61
62 static VALUE
63 has_extra_methods(VALUE klass)
64 {
65 const VALUE base = rb_cHash;
66 VALUE c = klass;
67 while (c != base) {
68 if (rb_class_has_methods(c)) return klass;
69 c = RCLASS_SUPER(c);
70 }
71 return 0;
72 }
73
74 static VALUE rb_hash_s_try_convert(VALUE, VALUE);
75
76 /*
77 * Hash WB strategy:
78 * 1. Check mutate st_* functions
79 * * st_insert()
80 * * st_insert2()
81 * * st_update()
82 * * st_add_direct()
83 * 2. Insert WBs
84 */
85
86 VALUE
87 rb_hash_freeze(VALUE hash)
88 {
89 return rb_obj_freeze(hash);
90 }
91
92 VALUE rb_cHash;
93
94 static VALUE envtbl;
95 static ID id_hash, id_yield, id_default, id_flatten_bang;
96 static ID id_hash_iter_lev;
97
98 VALUE
99 rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
100 {
101 RB_OBJ_WRITE(hash, (&RHASH(hash)->ifnone), ifnone);
102 return hash;
103 }
104
105 static int
106 rb_any_cmp(VALUE a, VALUE b)
107 {
108 if (a == b) return 0;
109 if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString &&
110 RB_TYPE_P(b, T_STRING) && RBASIC(b)->klass == rb_cString) {
111 return rb_str_hash_cmp(a, b);
112 }
113 if (a == Qundef || b == Qundef) return -1;
114 if (SYMBOL_P(a) && SYMBOL_P(b)) {
115 return a != b;
116 }
117
118 return !rb_eql(a, b);
119 }
120
121 static VALUE
122 hash_recursive(VALUE obj, VALUE arg, int recurse)
123 {
124 if (recurse) return INT2FIX(0);
125 return rb_funcallv(obj, id_hash, 0, 0);
126 }
127
128 VALUE
129 rb_hash(VALUE obj)
130 {
131 VALUE hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
132
133 while (!FIXNUM_P(hval)) {
134 if (RB_TYPE_P(hval, T_BIGNUM)) {
135 int sign;
136 unsigned long ul;
137 sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0,
138 INTEGER_PACK_NATIVE_BYTE_ORDER);
139 ul &= (1UL << (sizeof(long)*CHAR_BIT-1)) - 1;
140 if (sign < 0)
141 return LONG2FIX(-(long)ul);
142 return LONG2FIX((long)ul);
143 }
144 hval = rb_to_int(hval);
145 }
146 return hval;
147 }
148
149 static long rb_objid_hash(st_index_t index);
150
151 static st_index_t
152 dbl_to_index(double d)
153 {
154 union {double d; st_index_t i;} u;
155 u.d = d;
156 return u.i;
157 }
158
159 long
160 rb_dbl_long_hash(double d)
161 {
162 /* normalize -0.0 to 0.0 */
163 if (d == 0.0) d = 0.0;
164 #if SIZEOF_INT == SIZEOF_VOIDP
165 return rb_memhash(&d, sizeof(d));
166 #else
167 return rb_objid_hash(dbl_to_index(d));
168 #endif
169 }
170
171 static inline long
172 any_hash(VALUE a, st_index_t (*other_func)(VALUE))
173 {
174 VALUE hval;
175 st_index_t hnum;
176
177 if (SPECIAL_CONST_P(a)) {
178 if (STATIC_SYM_P(a)) {
179 hnum = a >> (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT);
180 hnum = rb_hash_start(hnum);
181 goto out;
182 }
183 else if (FLONUM_P(a)) {
184 /* prevent pathological behavior: [Bug #10761] */
185 goto flt;
186 }
187 hnum = rb_objid_hash((st_index_t)a);
188 }
189 else if (BUILTIN_TYPE(a) == T_STRING) {
190 hnum = rb_str_hash(a);
191 }
192 else if (BUILTIN_TYPE(a) == T_SYMBOL) {
193 hnum = RSYMBOL(a)->hashval;
194 }
195 else if (BUILTIN_TYPE(a) == T_BIGNUM) {
196 hval = rb_big_hash(a);
197 hnum = FIX2LONG(hval);
198 }
199 else if (BUILTIN_TYPE(a) == T_FLOAT) {
200 flt:
201 hnum = rb_dbl_long_hash(rb_float_value(a));
202 }
203 else {
204 hnum = other_func(a);
205 }
206 out:
207 #if SIZEOF_LONG < SIZEOF_ST_INDEX_T
208 if (hnum > 0)
209 hnum &= (unsigned long)-1 >> 2;
210 else
211 hnum |= ~((unsigned long)-1 >> 2);
212 #else
213 hnum <<= 1;
214 hnum = RSHIFT(hnum, 1);
215 #endif
216 return (long)hnum;
217 }
218
219 static st_index_t
220 obj_any_hash(VALUE obj)
221 {
222 obj = rb_hash(obj);
223 return FIX2LONG(obj);
224 }
225
226 static st_index_t
227 rb_any_hash(VALUE a)
228 {
229 return any_hash(a, obj_any_hash);
230 }
231
232 /* Here is a hash function for 64-bit key. It is about 5 times faster
233 (2 times faster when uint128 type is absent) on Haswell than
234 tailored Spooky or City hash function can be. */
235
236 /* Here we two primes with random bit generation. */
237 static const uint64_t prime1 = ((uint64_t)0x2e0bb864 << 32) | 0xe9ea7df5;
238 static const uint32_t prime2 = 0x830fcab9;
239
240
241 static inline uint64_t
242 mult_and_mix(uint64_t m1, uint64_t m2)
243 {
244 #if defined HAVE_UINT128_T
245 uint128_t r = (uint128_t) m1 * (uint128_t) m2;
246 return (uint64_t) (r >> 64) ^ (uint64_t) r;
247 #else
248 uint64_t hm1 = m1 >> 32, hm2 = m2 >> 32;
249 uint64_t lm1 = m1, lm2 = m2;
250 uint64_t v64_128 = hm1 * hm2;
251 uint64_t v32_96 = hm1 * lm2 + lm1 * hm2;
252 uint64_t v1_32 = lm1 * lm2;
253
254 return (v64_128 + (v32_96 >> 32)) ^ ((v32_96 << 32) + v1_32);
255 #endif
256 }
257
258 static inline uint64_t
259 key64_hash(uint64_t key, uint32_t seed)
260 {
261 return mult_and_mix(key + seed, prime1);
262 }
263
264 /* Should cast down the result for each purpose */
265 #define st_index_hash(index) key64_hash(rb_hash_start(index), prime2)
266
267 static long
268 rb_objid_hash(st_index_t index)
269 {
270 return (long)st_index_hash(index);
271 }
272
273 static st_index_t
274 objid_hash(VALUE obj)
275 {
276 VALUE object_id = rb_obj_id(obj);
277 if (!FIXNUM_P(object_id))
278 object_id = rb_big_hash(object_id);
279
280 #if SIZEOF_LONG == SIZEOF_VOIDP
281 return (st_index_t)st_index_hash((st_index_t)NUM2LONG(object_id));
282 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
283 return (st_index_t)st_index_hash((st_index_t)NUM2LL(object_id));
284 #endif
285 }
286
290 VALUE
291 rb_obj_hash(VALUE obj)
292 {
293 long hnum = any_hash(obj, objid_hash);
294 return ST2FIX(hnum);
295 }
296
297 static const struct st_hash_type objhash = {
298 rb_any_cmp,
299 rb_any_hash,
300 };
301
302 #define rb_ident_cmp st_numcmp
303
304 static st_index_t
305 rb_ident_hash(st_data_t n)
306 {
307 #ifdef USE_FLONUM /* RUBY */
308 /*
309 * - flonum (on 64-bit) is pathologically bad, mix the actual
310 * float value in, but do not use the float value as-is since
311 * many integers get interpreted as 2.0 or -2.0 [Bug #10761]
312 */
313 if (FLONUM_P(n)) {
314 n ^= dbl_to_index(rb_float_value(n));
315 }
316 #endif
317
318 return (st_index_t)st_index_hash((st_index_t)n);
319 }
320
321 #define identhash rb_hashtype_ident
322 const struct st_hash_type rb_hashtype_ident = {
323 rb_ident_cmp,
324 rb_ident_hash,
325 };
326
327 typedef st_index_t st_hash_t;
328
329 /*
330 * RHASH_AR_TABLE_P(h):
331 * * as.ar == NULL or
332 * as.ar points ar_table.
333 * * as.ar is allocated by transient heap or xmalloc.
334 *
335 * !RHASH_AR_TABLE_P(h):
336 * * as.st points st_table.
337 */
338
339 #define RHASH_AR_TABLE_MAX_BOUND RHASH_AR_TABLE_MAX_SIZE
340
341 #define RHASH_AR_TABLE_REF(hash, n) (&RHASH_AR_TABLE(hash)->pairs[n])
342 #define RHASH_AR_CLEARED_HINT 0xff
343
344 typedef struct ar_table_pair_struct {
345 VALUE key;
346 VALUE val;
347 } ar_table_pair;
348
349 typedef struct ar_table_struct {
350 /* 64bit CPU: 8B * 2 * 8 = 128B */
351 ar_table_pair pairs[RHASH_AR_TABLE_MAX_SIZE];
352 } ar_table;
353
354 size_t
355 rb_hash_ar_table_size(void)
356 {
357 return sizeof(ar_table);
358 }
359
360 static inline st_hash_t
361 ar_do_hash(st_data_t key)
362 {
363 return (st_hash_t)rb_any_hash(key);
364 }
365
366 static inline ar_hint_t
367 ar_do_hash_hint(st_hash_t hash_value)
368 {
369 return (ar_hint_t)hash_value;
370 }
371
372 static inline ar_hint_t
373 ar_hint(VALUE hash, unsigned int index)
374 {
375 return RHASH(hash)->ar_hint.ary[index];
376 }
377
378 static inline void
379 ar_hint_set_hint(VALUE hash, unsigned int index, ar_hint_t hint)
380 {
381 RHASH(hash)->ar_hint.ary[index] = hint;
382 }
383
384 static inline void
385 ar_hint_set(VALUE hash, unsigned int index, st_hash_t hash_value)
386 {
387 ar_hint_set_hint(hash, index, ar_do_hash_hint(hash_value));
388 }
389
390 static inline void
391 ar_clear_entry(VALUE hash, unsigned int index)
392 {
393 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
394 pair->key = Qundef;
395 ar_hint_set_hint(hash, index, RHASH_AR_CLEARED_HINT);
396 }
397
398 static inline int
399 ar_cleared_entry(VALUE hash, unsigned int index)
400 {
401 if (ar_hint(hash, index) == RHASH_AR_CLEARED_HINT) {
402 /* RHASH_AR_CLEARED_HINT is only a hint, not mean cleared entry,
403 * so you need to check key == Qundef
404 */
405 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
406 return pair->key == Qundef;
407 }
408 else {
409 return FALSE;
410 }
411 }
412
413 static inline void
414 ar_set_entry(VALUE hash, unsigned int index, st_data_t key, st_data_t val, st_hash_t hash_value)
415 {
416 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
417 pair->key = key;
418 pair->val = val;
419 ar_hint_set(hash, index, hash_value);
420 }
421
422 #define RHASH_AR_TABLE_SIZE(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
423 RHASH_AR_TABLE_SIZE_RAW(h))
424
425 #define RHASH_AR_TABLE_BOUND_RAW(h) \
426 ((unsigned int)((RBASIC(h)->flags >> RHASH_AR_TABLE_BOUND_SHIFT) & \
427 (RHASH_AR_TABLE_BOUND_MASK >> RHASH_AR_TABLE_BOUND_SHIFT)))
428
429 #define RHASH_AR_TABLE_BOUND(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
430 RHASH_AR_TABLE_BOUND_RAW(h))
431
432 #define RHASH_ST_TABLE_SET(h, s) rb_hash_st_table_set(h, s)
433 #define RHASH_TYPE(hash) (RHASH_AR_TABLE_P(hash) ? &objhash : RHASH_ST_TABLE(hash)->type)
434
435 #define HASH_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(HASH_DEBUG, expr, #expr)
436
437 #if HASH_DEBUG
438 #define hash_verify(hash) hash_verify_(hash, __FILE__, __LINE__)
439
440 void
441 rb_hash_dump(VALUE hash)
442 {
443 rb_obj_info_dump(hash);
444
445 if (RHASH_AR_TABLE_P(hash)) {
446 unsigned i, n = 0, bound = RHASH_AR_TABLE_BOUND(hash);
447
448 fprintf(stderr, " size:%u bound:%u\n",
449 RHASH_AR_TABLE_SIZE(hash), RHASH_AR_TABLE_BOUND(hash));
450
451 for (i=0; i<bound; i++) {
452 st_data_t k, v;
453
454 if (!ar_cleared_entry(hash, i)) {
455 char b1[0x100], b2[0x100];
456 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
457 k = pair->key;
458 v = pair->val;
459 fprintf(stderr, " %d key:%s val:%s hint:%02x\n", i,
460 rb_raw_obj_info(b1, 0x100, k),
461 rb_raw_obj_info(b2, 0x100, v),
462 ar_hint(hash, i));
463 n++;
464 }
465 else {
466 fprintf(stderr, " %d empty\n", i);
467 }
468 }
469 }
470 }
471
472 static VALUE
473 hash_verify_(VALUE hash, const char *file, int line)
474 {
475 HASH_ASSERT(RB_TYPE_P(hash, T_HASH));
476
477 if (RHASH_AR_TABLE_P(hash)) {
478 unsigned i, n = 0, bound = RHASH_AR_TABLE_BOUND(hash);
479
480 for (i=0; i<bound; i++) {
481 st_data_t k, v;
482 if (!ar_cleared_entry(hash, i)) {
483 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
484 k = pair->key;
485 v = pair->val;
486 HASH_ASSERT(k != Qundef);
487 HASH_ASSERT(v != Qundef);
488 n++;
489 }
490 }
491 if (n != RHASH_AR_TABLE_SIZE(hash)) {
492 rb_bug("n:%u, RHASH_AR_TABLE_SIZE:%u", n, RHASH_AR_TABLE_SIZE(hash));
493 }
494 }
495 else {
496 HASH_ASSERT(RHASH_ST_TABLE(hash) != NULL);
497 HASH_ASSERT(RHASH_AR_TABLE_SIZE_RAW(hash) == 0);
498 HASH_ASSERT(RHASH_AR_TABLE_BOUND_RAW(hash) == 0);
499 }
500
501 if (RHASH_TRANSIENT_P(hash)) {
502 volatile st_data_t MAYBE_UNUSED(key) = RHASH_AR_TABLE_REF(hash, 0)->key; /* read */
503 HASH_ASSERT(RHASH_AR_TABLE(hash) != NULL);
504 HASH_ASSERT(rb_transient_heap_managed_ptr_p(RHASH_AR_TABLE(hash)));
505 }
506 return hash;
507 }
508
509 #else
510 #define hash_verify(h) ((void)0)
511 #endif
512
513 static inline int
514 RHASH_TABLE_NULL_P(VALUE hash)
515 {
516 if (RHASH(hash)->as.ar == NULL) {
517 HASH_ASSERT(RHASH_AR_TABLE_P(hash));
518 return TRUE;
519 }
520 else {
521 return FALSE;
522 }
523 }
524
525 static inline int
526 RHASH_TABLE_EMPTY_P(VALUE hash)
527 {
528 return RHASH_SIZE(hash) == 0;
529 }
530
531 int
532 rb_hash_ar_table_p(VALUE hash)
533 {
534 if (FL_TEST_RAW((hash), RHASH_ST_TABLE_FLAG)) {
535 HASH_ASSERT(RHASH(hash)->as.st != NULL);
536 return FALSE;
537 }
538 else {
539 return TRUE;
540 }
541 }
542
543 ar_table *
544 rb_hash_ar_table(VALUE hash)
545 {
546 HASH_ASSERT(RHASH_AR_TABLE_P(hash));
547 return RHASH(hash)->as.ar;
548 }
549
550 st_table *
551 rb_hash_st_table(VALUE hash)
552 {
553 HASH_ASSERT(!RHASH_AR_TABLE_P(hash));
554 return RHASH(hash)->as.st;
555 }
556
557 void
558 rb_hash_st_table_set(VALUE hash, st_table *st)
559 {
560 HASH_ASSERT(st != NULL);
561 FL_SET_RAW((hash), RHASH_ST_TABLE_FLAG);
562 RHASH(hash)->as.st = st;
563 }
564
565 static void
566 hash_ar_table_set(VALUE hash, ar_table *ar)
567 {
568 HASH_ASSERT(RHASH_AR_TABLE_P(hash));
569 HASH_ASSERT((RHASH_TRANSIENT_P(hash) && ar == NULL) ? FALSE : TRUE);
570 RHASH(hash)->as.ar = ar;
571 hash_verify(hash);
572 }
573
574 #define RHASH_SET_ST_FLAG(h) FL_SET_RAW(h, RHASH_ST_TABLE_FLAG)
575 #define RHASH_UNSET_ST_FLAG(h) FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG)
576
577 static inline void
578 RHASH_AR_TABLE_BOUND_SET(VALUE h, st_index_t n)
579 {
580 HASH_ASSERT(RHASH_AR_TABLE_P(h));
581 HASH_ASSERT(n <= RHASH_AR_TABLE_MAX_BOUND);
582
583 RBASIC(h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
584 RBASIC(h)->flags |= n << RHASH_AR_TABLE_BOUND_SHIFT;
585 }
586
587 static inline void
588 RHASH_AR_TABLE_SIZE_SET(VALUE h, st_index_t n)
589 {
590 HASH_ASSERT(RHASH_AR_TABLE_P(h));
591 HASH_ASSERT(n <= RHASH_AR_TABLE_MAX_SIZE);
592
593 RBASIC(h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
594 RBASIC(h)->flags |= n << RHASH_AR_TABLE_SIZE_SHIFT;
595 }
596
597 static inline void
598 HASH_AR_TABLE_SIZE_ADD(VALUE h, st_index_t n)
599 {
600 HASH_ASSERT(RHASH_AR_TABLE_P(h));
601
602 RHASH_AR_TABLE_SIZE_SET(h, RHASH_AR_TABLE_SIZE(h) + n);
603
604 hash_verify(h);
605 }
606
607 #define RHASH_AR_TABLE_SIZE_INC(h) HASH_AR_TABLE_SIZE_ADD(h, 1)
608
609 static inline void
610 RHASH_AR_TABLE_SIZE_DEC(VALUE h)
611 {
612 HASH_ASSERT(RHASH_AR_TABLE_P(h));
613 int new_size = RHASH_AR_TABLE_SIZE(h) - 1;
614
615 if (new_size != 0) {
616 RHASH_AR_TABLE_SIZE_SET(h, new_size);
617 }
618 else {
619 RHASH_AR_TABLE_SIZE_SET(h, 0);
620 RHASH_AR_TABLE_BOUND_SET(h, 0);
621 }
622 hash_verify(h);
623 }
624
625 static inline void
626 RHASH_AR_TABLE_CLEAR(VALUE h)
627 {
628 RBASIC(h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
629 RBASIC(h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
630
631 hash_ar_table_set(h, NULL);
632 }
633
634 static ar_table*
635 ar_alloc_table(VALUE hash)
636 {
637 ar_table *tab = (ar_table*)rb_transient_heap_alloc(hash, sizeof(ar_table));
638
639 if (tab != NULL) {
640 RHASH_SET_TRANSIENT_FLAG(hash);
641 }
642 else {
643 RHASH_UNSET_TRANSIENT_FLAG(hash);
644 tab = (ar_table*)ruby_xmalloc(sizeof(ar_table));
645 }
646
647 RHASH_AR_TABLE_SIZE_SET(hash, 0);
648 RHASH_AR_TABLE_BOUND_SET(hash, 0);
649 hash_ar_table_set(hash, tab);
650
651 return tab;
652 }
653
654 NOINLINE(static int ar_equal(VALUE x, VALUE y));
655
656 static int
657 ar_equal(VALUE x, VALUE y)
658 {
659 return rb_any_cmp(x, y) == 0;
660 }
661
662 static unsigned
663 ar_find_entry_hint(VALUE hash, ar_hint_t hint, st_data_t key)
664 {
665 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
666 const ar_hint_t *hints = RHASH(hash)->ar_hint.ary;
667
668 /* if table is NULL, then bound also should be 0 */
669
670 for (i = 0; i < bound; i++) {
671 if (hints[i] == hint) {
672 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
673 if (ar_equal(key, pair->key)) {
674 RB_DEBUG_COUNTER_INC(artable_hint_hit);
675 return i;
676 }
677 else {
678 #if 0
679 static int pid;
680 static char fname[256];
681 static FILE *fp;
682
683 if (pid != getpid()) {
684 snprintf(fname, sizeof(fname), "/tmp/ruby-armiss.%d", pid = getpid());
685 if ((fp = fopen(fname, "w")) == NULL) rb_bug("fopen");
686 }
687
688 st_hash_t h1 = ar_do_hash(key);
689 st_hash_t h2 = ar_do_hash(pair->key);
690
691 fprintf(fp, "miss: hash_eq:%d hints[%d]:%02x hint:%02x\n"
692 " key :%016lx %s\n"
693 " pair->key:%016lx %s\n",
694 h1 == h2, i, hints[i], hint,
695 h1, rb_obj_info(key), h2, rb_obj_info(pair->key));
696 #endif
697 RB_DEBUG_COUNTER_INC(artable_hint_miss);
698 }
699 }
700 }
701 RB_DEBUG_COUNTER_INC(artable_hint_notfound);
702 return RHASH_AR_TABLE_MAX_BOUND;
703 }
704
705 static unsigned
706 ar_find_entry(VALUE hash, st_hash_t hash_value, st_data_t key)
707 {
708 ar_hint_t hint = ar_do_hash_hint(hash_value);
709 return ar_find_entry_hint(hash, hint, key);
710 }
711
712 static inline void
713 ar_free_and_clear_table(VALUE hash)
714 {
715 ar_table *tab = RHASH_AR_TABLE(hash);
716
717 if (tab) {
718 if (RHASH_TRANSIENT_P(hash)) {
719 RHASH_UNSET_TRANSIENT_FLAG(hash);
720 }
721 else {
722 ruby_xfree(RHASH_AR_TABLE(hash));
723 }
724 RHASH_AR_TABLE_CLEAR(hash);
725 }
726 HASH_ASSERT(RHASH_AR_TABLE_SIZE(hash) == 0);
727 HASH_ASSERT(RHASH_AR_TABLE_BOUND(hash) == 0);
728 HASH_ASSERT(RHASH_TRANSIENT_P(hash) == 0);
729 }
730
731 static void
732 ar_try_convert_table(VALUE hash)
733 {
734 st_table *new_tab;
735 const unsigned size = RHASH_AR_TABLE_SIZE(hash);
736 st_index_t i;
737
738 if (!RHASH_AR_TABLE_P(hash) || size < RHASH_AR_TABLE_MAX_SIZE) {
739 return;
740 }
741
742 new_tab = st_init_table_with_size(&objhash, size * 2);
743
744 for (i = 0; i < RHASH_AR_TABLE_MAX_BOUND; i++) {
745 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
746 st_add_direct(new_tab, pair->key, pair->val);
747 }
748 ar_free_and_clear_table(hash);
749 RHASH_ST_TABLE_SET(hash, new_tab);
750 return;
751 }
752
753 static st_table *
754 ar_force_convert_table(VALUE hash, const char *file, int line)
755 {
756 st_table *new_tab;
757
758 if (RHASH_ST_TABLE_P(hash)) {
759 return RHASH_ST_TABLE(hash);
760 }
761
762 if (RHASH_AR_TABLE(hash)) {
763 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
764
765 #if RHASH_CONVERT_TABLE_DEBUG
766 rb_obj_info_dump(hash);
767 fprintf(stderr, "force_convert: %s:%d\n", file, line);
768 RB_DEBUG_COUNTER_INC(obj_hash_force_convert);
769 #endif
770
771 new_tab = st_init_table_with_size(&objhash, RHASH_AR_TABLE_SIZE(hash));
772
773 for (i = 0; i < bound; i++) {
774 if (ar_cleared_entry(hash, i)) continue;
775
776 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
777 st_add_direct(new_tab, pair->key, pair->val);
778 }
779 ar_free_and_clear_table(hash);
780 }
781 else {
782 new_tab = st_init_table(&objhash);
783 }
784 RHASH_ST_TABLE_SET(hash, new_tab);
785
786 return new_tab;
787 }
788
789 static ar_table *
790 hash_ar_table(VALUE hash)
791 {
792 if (RHASH_TABLE_NULL_P(hash)) {
793 ar_alloc_table(hash);
794 }
795 return RHASH_AR_TABLE(hash);
796 }
797
798 static int
799 ar_compact_table(VALUE hash)
800 {
801 const unsigned bound = RHASH_AR_TABLE_BOUND(hash);
802 const unsigned size = RHASH_AR_TABLE_SIZE(hash);
803
804 if (size == bound) {
805 return size;
806 }
807 else {
808 unsigned i, j=0;
809 ar_table_pair *pairs = RHASH_AR_TABLE(hash)->pairs;
810
811 for (i=0; i<bound; i++) {
812 if (ar_cleared_entry(hash, i)) {
813 if (j <= i) j = i+1;
814 for (; j<bound; j++) {
815 if (!ar_cleared_entry(hash, j)) {
816 pairs[i] = pairs[j];
817 ar_hint_set_hint(hash, i, (st_hash_t)ar_hint(hash, j));
818 ar_clear_entry(hash, j);
819 j++;
820 goto found;
821 }
822 }
823 /* non-empty is not found */
824 goto done;
825 found:;
826 }
827 }
828 done:
829 HASH_ASSERT(i<=bound);
830
831 RHASH_AR_TABLE_BOUND_SET(hash, size);
832 hash_verify(hash);
833 return size;
834 }
835 }
836
837 static int
838 ar_add_direct_with_hash(VALUE hash, st_data_t key, st_data_t val, st_hash_t hash_value)
839 {
840 unsigned bin = RHASH_AR_TABLE_BOUND(hash);
841
842 if (RHASH_AR_TABLE_SIZE(hash) >= RHASH_AR_TABLE_MAX_SIZE) {
843 return 1;
844 }
845 else {
846 if (UNLIKELY(bin >= RHASH_AR_TABLE_MAX_BOUND)) {
847 bin = ar_compact_table(hash);
848 hash_ar_table(hash);
849 }
850 HASH_ASSERT(bin < RHASH_AR_TABLE_MAX_BOUND);
851
852 ar_set_entry(hash, bin, key, val, hash_value);
853 RHASH_AR_TABLE_BOUND_SET(hash, bin+1);
854 RHASH_AR_TABLE_SIZE_INC(hash);
855 return 0;
856 }
857 }
858
859 static int
860 ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
861 {
862 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
863 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
864
865 for (i = 0; i < bound; i++) {
866 if (ar_cleared_entry(hash, i)) continue;
867
868 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
869 enum st_retval retval = (*func)(pair->key, pair->val, arg, 0);
870 /* pair may be not valid here because of theap */
871
872 switch (retval) {
873 case ST_CONTINUE:
874 break;
875 case ST_CHECK:
876 case ST_STOP:
877 return 0;
878 case ST_REPLACE:
879 if (replace) {
880 VALUE key = pair->key;
881 VALUE val = pair->val;
882 retval = (*replace)(&key, &val, arg, TRUE);
883
884 // TODO: pair should be same as pair before.
885 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
886 pair->key = key;
887 pair->val = val;
888 }
889 break;
890 case ST_DELETE:
891 ar_clear_entry(hash, i);
892 RHASH_AR_TABLE_SIZE_DEC(hash);
893 break;
894 }
895 }
896 }
897 return 0;
898 }
899
900 static int
901 ar_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
902 {
903 return ar_general_foreach(hash, func, replace, arg);
904 }
905
906 struct functor {
907 st_foreach_callback_func *func;
908 st_data_t arg;
909 };
910
911 static int
912 apply_functor(st_data_t k, st_data_t v, st_data_t d, int _)
913 {
914 const struct functor *f = (void *)d;
915 return f->func(k, v, f->arg);
916 }
917
918 static int
919 ar_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
920 {
921 const struct functor f = { func, arg };
922 return ar_general_foreach(hash, apply_functor, NULL, (st_data_t)&f);
923 }
924
925 static int
926 ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg,
927 st_data_t never)
928 {
929 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
930 unsigned i, ret = 0, bound = RHASH_AR_TABLE_BOUND(hash);
931 enum st_retval retval;
932 st_data_t key;
933 ar_table_pair *pair;
934 ar_hint_t hint;
935
936 for (i = 0; i < bound; i++) {
937 if (ar_cleared_entry(hash, i)) continue;
938
939 pair = RHASH_AR_TABLE_REF(hash, i);
940 key = pair->key;
941 hint = ar_hint(hash, i);
942
943 retval = (*func)(key, pair->val, arg, 0);
944 hash_verify(hash);
945
946 switch (retval) {
947 case ST_CHECK: {
948 if (pair->key == never) break;
949 ret = ar_find_entry_hint(hash, hint, key);
950 if (ret == RHASH_AR_TABLE_MAX_BOUND) {
951 retval = (*func)(0, 0, arg, 1);
952 return 2;
953 }
954 }
955 case ST_CONTINUE:
956 break;
957 case ST_STOP:
958 case ST_REPLACE:
959 return 0;
960 case ST_DELETE: {
961 if (!ar_cleared_entry(hash, i)) {
962 ar_clear_entry(hash, i);
963 RHASH_AR_TABLE_SIZE_DEC(hash);
964 }
965 break;
966 }
967 }
968 }
969 }
970 return 0;
971 }
972
973 static int
974 ar_update(VALUE hash, st_data_t key,
975 st_update_callback_func *func, st_data_t arg)
976 {
977 int retval, existing;
978 unsigned bin = RHASH_AR_TABLE_MAX_BOUND;
979 st_data_t value = 0, old_key;
980 st_hash_t hash_value = ar_do_hash(key);
981
982 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
983 bin = ar_find_entry(hash, hash_value, key);
984 existing = (bin != RHASH_AR_TABLE_MAX_BOUND) ? TRUE : FALSE;
985 }
986 else {
987 hash_ar_table(hash); /* allocate ltbl if needed */
988 existing = FALSE;
989 }
990
991 if (existing) {
992 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, bin);
993 key = pair->key;
994 value = pair->val;
995 }
996 old_key = key;
997 retval = (*func)(&key, &value, arg, existing);
998 /* pair can be invalid here because of theap */
999
1000 switch (retval) {
1001 case ST_CONTINUE:
1002 if (!existing) {
1003 if (ar_add_direct_with_hash(hash, key, value, hash_value)) {
1004 return -1;
1005 }
1006 }
1007 else {
1008 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, bin);
1009 if (old_key != key) {
1010 pair->key = key;
1011 }
1012 pair->val = value;
1013 }
1014 break;
1015 case ST_DELETE:
1016 if (existing) {
1017 ar_clear_entry(hash, bin);
1018 RHASH_AR_TABLE_SIZE_DEC(hash);
1019 }
1020 break;
1021 }
1022 return existing;
1023 }
1024
1025 static int
1026 ar_insert(VALUE hash, st_data_t key, st_data_t value)
1027 {
1028 unsigned bin = RHASH_AR_TABLE_BOUND(hash);
1029 st_hash_t hash_value = ar_do_hash(key);
1030
1031 hash_ar_table(hash); /* prepare ltbl */
1032
1033 bin = ar_find_entry(hash, hash_value, key);
1034 if (bin == RHASH_AR_TABLE_MAX_BOUND) {
1035 if (RHASH_AR_TABLE_SIZE(hash) >= RHASH_AR_TABLE_MAX_SIZE) {
1036 return -1;
1037 }
1038 else if (bin >= RHASH_AR_TABLE_MAX_BOUND) {
1039 bin = ar_compact_table(hash);
1040 hash_ar_table(hash);
1041 }
1042 HASH_ASSERT(bin < RHASH_AR_TABLE_MAX_BOUND);
1043
1044 ar_set_entry(hash, bin, key, value, hash_value);
1045 RHASH_AR_TABLE_BOUND_SET(hash, bin+1);
1046 RHASH_AR_TABLE_SIZE_INC(hash);
1047 return 0;
1048 }
1049 else {
1050 RHASH_AR_TABLE_REF(hash, bin)->val = value;
1051 return 1;
1052 }
1053 }
1054
1055 static int
1056 ar_lookup(VALUE hash, st_data_t key, st_data_t *value)
1057 {
1058 if (RHASH_AR_TABLE_SIZE(hash) == 0) {
1059 return 0;
1060 }
1061 else {
1062 st_hash_t hash_value = ar_do_hash(key);
1063 unsigned bin = ar_find_entry(hash, hash_value, key);
1064
1065 if (bin == RHASH_AR_TABLE_MAX_BOUND) {
1066 return 0;
1067 }
1068 else {
1069 HASH_ASSERT(bin < RHASH_AR_TABLE_MAX_BOUND);
1070 if (value != NULL) {
1071 *value = RHASH_AR_TABLE_REF(hash, bin)->val;
1072 }
1073 return 1;
1074 }
1075 }
1076 }
1077
1078 static int
1079 ar_delete(VALUE hash, st_data_t *key, st_data_t *value)
1080 {
1081 unsigned bin;
1082 st_hash_t hash_value = ar_do_hash(*key);
1083
1084
1085 bin = ar_find_entry(hash, hash_value, *key);
1086
1087 if (bin == RHASH_AR_TABLE_MAX_BOUND) {
1088 if (value != 0) *value = 0;
1089 return 0;
1090 }
1091 else {
1092 if (value != 0) {
1093 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, bin);
1094 *value = pair->val;
1095 }
1096 ar_clear_entry(hash, bin);
1097 RHASH_AR_TABLE_SIZE_DEC(hash);
1098 return 1;
1099 }
1100 }
1101
1102 static int
1103 ar_shift(VALUE hash, st_data_t *key, st_data_t *value)
1104 {
1105 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
1106 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
1107
1108 for (i = 0; i < bound; i++) {
1109 if (!ar_cleared_entry(hash, i)) {
1110 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
1111 if (value != 0) *value = pair->val;
1112 *key = pair->key;
1113 ar_clear_entry(hash, i);
1114 RHASH_AR_TABLE_SIZE_DEC(hash);
1115 return 1;
1116 }
1117 }
1118 }
1119 if (value != NULL) *value = 0;
1120 return 0;
1121 }
1122
1123 static long
1124 ar_keys(VALUE hash, st_data_t *keys, st_index_t size)
1125 {
1126 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
1127 st_data_t *keys_start = keys, *keys_end = keys + size;
1128
1129 for (i = 0; i < bound; i++) {
1130 if (keys == keys_end) {
1131 break;
1132 }
1133 else {
1134 if (!ar_cleared_entry(hash, i)) {
1135 *keys++ = RHASH_AR_TABLE_REF(hash, i)->key;
1136 }
1137 }
1138 }
1139
1140 return keys - keys_start;
1141 }
1142
1143 static long
1144 ar_values(VALUE hash, st_data_t *values, st_index_t size)
1145 {
1146 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
1147 st_data_t *values_start = values, *values_end = values + size;
1148
1149 for (i = 0; i < bound; i++) {
1150 if (values == values_end) {
1151 break;
1152 }
1153 else {
1154 if (!ar_cleared_entry(hash, i)) {
1155 *values++ = RHASH_AR_TABLE_REF(hash, i)->val;
1156 }
1157 }
1158 }
1159
1160 return values - values_start;
1161 }
1162
1163 static ar_table*
1164 ar_copy(VALUE hash1, VALUE hash2)
1165 {
1166 ar_table *old_tab = RHASH_AR_TABLE(hash2);
1167
1168 if (old_tab != NULL) {
1169 ar_table *new_tab = RHASH_AR_TABLE(hash1);
1170 if (new_tab == NULL) {
1171 new_tab = (ar_table*) rb_transient_heap_alloc(hash1, sizeof(ar_table));
1172 if (new_tab != NULL) {
1173 RHASH_SET_TRANSIENT_FLAG(hash1);
1174 }
1175 else {
1176 RHASH_UNSET_TRANSIENT_FLAG(hash1);
1177 new_tab = (ar_table*)ruby_xmalloc(sizeof(ar_table));
1178 }
1179 }
1180 *new_tab = *old_tab;
1181 RHASH(hash1)->ar_hint.word = RHASH(hash2)->ar_hint.word;
1182 RHASH_AR_TABLE_BOUND_SET(hash1, RHASH_AR_TABLE_BOUND(hash2));
1183 RHASH_AR_TABLE_SIZE_SET(hash1, RHASH_AR_TABLE_SIZE(hash2));
1184 hash_ar_table_set(hash1, new_tab);
1185
1186 rb_gc_writebarrier_remember(hash1);
1187 return new_tab;
1188 }
1189 else {
1190 RHASH_AR_TABLE_BOUND_SET(hash1, RHASH_AR_TABLE_BOUND(hash2));
1191 RHASH_AR_TABLE_SIZE_SET(hash1, RHASH_AR_TABLE_SIZE(hash2));
1192
1193 if (RHASH_TRANSIENT_P(hash1)) {
1194 RHASH_UNSET_TRANSIENT_FLAG(hash1);
1195 }
1196 else if (RHASH_AR_TABLE(hash1)) {
1197 ruby_xfree(RHASH_AR_TABLE(hash1));
1198 }
1199
1200 hash_ar_table_set(hash1, NULL);
1201
1202 rb_gc_writebarrier_remember(hash1);
1203 return old_tab;
1204 }
1205 }
1206
1207 static void
1208 ar_clear(VALUE hash)
1209 {
1210 if (RHASH_AR_TABLE(hash) != NULL) {
1211 RHASH_AR_TABLE_SIZE_SET(hash, 0);
1212 RHASH_AR_TABLE_BOUND_SET(hash, 0);
1213 }
1214 else {
1215 HASH_ASSERT(RHASH_AR_TABLE_SIZE(hash) == 0);
1216 HASH_ASSERT(RHASH_AR_TABLE_BOUND(hash) == 0);
1217 }
1218 }
1219
1220 #if USE_TRANSIENT_HEAP
1221 void
1222 rb_hash_transient_heap_evacuate(VALUE hash, int promote)
1223 {
1224 if (RHASH_TRANSIENT_P(hash)) {
1225 ar_table *new_tab;
1226 ar_table *old_tab = RHASH_AR_TABLE(hash);
1227
1228 if (UNLIKELY(old_tab == NULL)) {
1229 rb_gc_force_recycle(hash);
1230 return;
1231 }
1232 HASH_ASSERT(old_tab != NULL);
1233 if (promote) {
1234 promote:
1235 new_tab = ruby_xmalloc(sizeof(ar_table));
1236 RHASH_UNSET_TRANSIENT_FLAG(hash);
1237 }
1238 else {
1239 new_tab = rb_transient_heap_alloc(hash, sizeof(ar_table));
1240 if (new_tab == NULL) goto promote;
1241 }
1242 *new_tab = *old_tab;
1243 hash_ar_table_set(hash, new_tab);
1244 }
1245 hash_verify(hash);
1246 }
1247 #endif
1248
1249 typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
1250
1251 struct foreach_safe_arg {
1252 st_table *tbl;
1253 st_foreach_func *func;
1254 st_data_t arg;
1255 };
1256
1257 static int
1258 foreach_safe_i(st_data_t key, st_data_t value, st_data_t args, int error)
1259 {
1260 int status;
1261 struct foreach_safe_arg *arg = (void *)args;
1262
1263 if (error) return ST_STOP;
1264 status = (*arg->func)(key, value, arg->arg);
1265 if (status == ST_CONTINUE) {
1266 return ST_CHECK;
1267 }
1268 return status;
1269 }
1270
1271 void
1272 st_foreach_safe(st_table *table, st_foreach_func *func, st_data_t a)
1273 {
1274 struct foreach_safe_arg arg;
1275
1276 arg.tbl = table;
1277 arg.func = (st_foreach_func *)func;
1278 arg.arg = a;
1279 if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) {
1280 rb_raise(rb_eRuntimeError, "hash modified during iteration");
1281 }
1282 }
1283
1284 typedef int rb_foreach_func(VALUE, VALUE, VALUE);
1285
1286 struct hash_foreach_arg {
1287 VALUE hash;
1288 rb_foreach_func *func;
1289 VALUE arg;
1290 };
1291
1292 static int
1293 hash_ar_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
1294 {
1295 struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
1296 int status;
1297
1298 if (error) return ST_STOP;
1299 status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
1300 /* TODO: rehash check? rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); */
1301
1302 switch (status) {
1303 case ST_DELETE:
1304 return ST_DELETE;
1305 case ST_CONTINUE:
1306 break;
1307 case ST_STOP:
1308 return ST_STOP;
1309 }
1310 return ST_CHECK;
1311 }
1312
1313 static int
1314 hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
1315 {
1316 struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
1317 int status;
1318 st_table *tbl;
1319
1320 if (error) return ST_STOP;
1321 tbl = RHASH_ST_TABLE(arg->hash);
1322 status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
1323 if (RHASH_ST_TABLE(arg->hash) != tbl) {
1324 rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
1325 }
1326 switch (status) {
1327 case ST_DELETE:
1328 return ST_DELETE;
1329 case ST_CONTINUE:
1330 break;
1331 case ST_STOP:
1332 return ST_STOP;
1333 }
1334 return ST_CHECK;
1335 }
1336
1337 static int
1338 iter_lev_in_ivar(VALUE hash)
1339 {
1340 VALUE levval = rb_ivar_get(hash, id_hash_iter_lev);
1341 HASH_ASSERT(FIXNUM_P(levval));
1342 return FIX2INT(levval);
1343 }
1344
1345 void rb_ivar_set_internal(VALUE obj, ID id, VALUE val);
1346
1347 static void
1348 iter_lev_in_ivar_set(VALUE hash, int lev)
1349 {
1350 rb_ivar_set_internal(hash, id_hash_iter_lev, INT2FIX(lev));
1351 }
1352
1353 static int
1354 iter_lev_in_flags(VALUE hash)
1355 {
1356 unsigned int u = (unsigned int)((RBASIC(hash)->flags >> RHASH_LEV_SHIFT) & RHASH_LEV_MAX);
1357 return (int)u;
1358 }
1359
1360 static int
1361 RHASH_ITER_LEV(VALUE hash)
1362 {
1363 int lev = iter_lev_in_flags(hash);
1364
1365 if (lev == RHASH_LEV_MAX) {
1366 return iter_lev_in_ivar(hash);
1367 }
1368 else {
1369 return lev;
1370 }
1371 }
1372
1373 static void
1374 hash_iter_lev_inc(VALUE hash)
1375 {
1376 int lev = iter_lev_in_flags(hash);
1377 if (lev == RHASH_LEV_MAX) {
1378 lev = iter_lev_in_ivar(hash);
1379 iter_lev_in_ivar_set(hash, lev+1);
1380 }
1381 else {
1382 lev += 1;
1383 RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | (lev << RHASH_LEV_SHIFT));
1384 if (lev == RHASH_LEV_MAX) {
1385 iter_lev_in_ivar_set(hash, lev);
1386 }
1387 }
1388 }
1389
1390 static void
1391 hash_iter_lev_dec(VALUE hash)
1392 {
1393 int lev = iter_lev_in_flags(hash);
1394 if (lev == RHASH_LEV_MAX) {
1395 lev = iter_lev_in_ivar(hash);
1396 HASH_ASSERT(lev > 0);
1397 iter_lev_in_ivar_set(hash, lev-1);
1398 }
1399 else {
1400 HASH_ASSERT(lev > 0);
1401 RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((lev-1) << RHASH_LEV_SHIFT));
1402 }
1403 }
1404
1405 static VALUE
1406 hash_foreach_ensure_rollback(VALUE hash)
1407 {
1408 hash_iter_lev_inc(hash);
1409 return 0;
1410 }
1411
1412 static VALUE
1413 hash_foreach_ensure(VALUE hash)
1414 {
1415 hash_iter_lev_dec(hash);
1416 return 0;
1417 }
1418
1419 int
1420 rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
1421 {
1422 if (RHASH_AR_TABLE_P(hash)) {
1423 return ar_foreach(hash, func, arg);
1424 }
1425 else {
1426 return st_foreach(RHASH_ST_TABLE(hash), func, arg);
1427 }
1428 }
1429
1430 int
1431 rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
1432 {
1433 if (RHASH_AR_TABLE_P(hash)) {
1434 return ar_foreach_with_replace(hash, func, replace, arg);
1435 }
1436 else {
1437 return st_foreach_with_replace(RHASH_ST_TABLE(hash), func, replace, arg);
1438 }
1439 }
1440
1441 static VALUE
1442 hash_foreach_call(VALUE arg)
1443 {
1444 VALUE hash = ((struct hash_foreach_arg *)arg)->hash;
1445 int ret = 0;
1446 if (RHASH_AR_TABLE_P(hash)) {
1447 ret = ar_foreach_check(hash, hash_ar_foreach_iter,
1448 (st_data_t)arg, (st_data_t)Qundef);
1449 }
1450 else if (RHASH_ST_TABLE_P(hash)) {
1451 ret = st_foreach_check(RHASH_ST_TABLE(hash), hash_foreach_iter,
1452 (st_data_t)arg, (st_data_t)Qundef);
1453 }
1454 if (ret) {
1455 rb_raise(rb_eRuntimeError, "ret: %d, hash modified during iteration", ret);
1456 }
1457 return Qnil;
1458 }
1459
1460 void
1461 rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
1462 {
1463 struct hash_foreach_arg arg;
1464
1465 if (RHASH_TABLE_EMPTY_P(hash))
1466 return;
1467 hash_iter_lev_inc(hash);
1468 arg.hash = hash;
1469 arg.func = (rb_foreach_func *)func;
1470 arg.arg = farg;
1471 rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
1472 hash_verify(hash);
1473 }
1474
1475 static VALUE
1476 hash_alloc_flags(VALUE klass, VALUE flags, VALUE ifnone)
1477 {
1478 const VALUE wb = (RGENGC_WB_PROTECTED_HASH ? FL_WB_PROTECTED : 0);
1479 NEWOBJ_OF(hash, struct RHash, klass, T_HASH | wb | flags);
1480
1481 RHASH_SET_IFNONE((VALUE)hash, ifnone);
1482
1483 return (VALUE)hash;
1484 }
1485
1486 static VALUE
1487 hash_alloc(VALUE klass)
1488 {
1489 return hash_alloc_flags(klass, 0, Qnil);
1490 }
1491
1492 static VALUE
1493 empty_hash_alloc(VALUE klass)
1494 {
1495 RUBY_DTRACE_CREATE_HOOK(HASH, 0);
1496
1497 return hash_alloc(klass);
1498 }
1499
1500 VALUE
1501 rb_hash_new(void)
1502 {
1503 return hash_alloc(rb_cHash);
1504 }
1505
1506 MJIT_FUNC_EXPORTED VALUE
1507 rb_hash_new_with_size(st_index_t size)
1508 {
1509 VALUE ret = rb_hash_new();
1510 if (size == 0) {
1511 /* do nothing */
1512 }
1513 else if (size <= RHASH_AR_TABLE_MAX_SIZE) {
1514 ar_alloc_table(ret);
1515 }
1516 else {
1517 RHASH_ST_TABLE_SET(ret, st_init_table_with_size(&objhash, size));
1518 }
1519 return ret;
1520 }
1521
1522 static VALUE
1523 hash_dup(VALUE hash, VALUE klass, VALUE flags)
1524 {
1525 VALUE ret = hash_alloc_flags(klass, flags,
1526 RHASH_IFNONE(hash));
1527 if (!RHASH_EMPTY_P(hash)) {
1528 if (RHASH_AR_TABLE_P(hash))
1529 ar_copy(ret, hash);
1530 else if (RHASH_ST_TABLE_P(hash))
1531 RHASH_ST_TABLE_SET(ret, st_copy(RHASH_ST_TABLE(hash)));
1532 }
1533 return ret;
1534 }
1535
1536 VALUE
1537 rb_hash_dup(VALUE hash)
1538 {
1539 const VALUE flags = RBASIC(hash)->flags;
1540 VALUE ret = hash_dup(hash, rb_obj_class(hash),
1541 flags & (FL_EXIVAR|RHASH_PROC_DEFAULT));
1542 if (flags & FL_EXIVAR)
1543 rb_copy_generic_ivar(ret, hash);
1544 return ret;
1545 }
1546
1547 MJIT_FUNC_EXPORTED VALUE
1548 rb_hash_resurrect(VALUE hash)
1549 {
1550 VALUE ret = hash_dup(hash, rb_cHash, 0);
1551 return ret;
1552 }
1553
1554 static void
1555 rb_hash_modify_check(VALUE hash)
1556 {
1557 rb_check_frozen(hash);
1558 }
1559
1560 MJIT_FUNC_EXPORTED struct st_table *
1561 #if RHASH_CONVERT_TABLE_DEBUG
1562 rb_hash_tbl_raw(VALUE hash, const char *file, int line)
1563 {
1564 return ar_force_convert_table(hash, file, line);
1565 }
1566 #else
1567 rb_hash_tbl_raw(VALUE hash)
1568 {
1569 return ar_force_convert_table(hash, NULL, 0);
1570 }
1571 #endif
1572
1573 struct st_table *
1574 rb_hash_tbl(VALUE hash, const char *file, int line)
1575 {
1576 OBJ_WB_UNPROTECT(hash);
1577 return RHASH_TBL_RAW(hash);
1578 }
1579
1580 static void
1581 rb_hash_modify(VALUE hash)
1582 {
1583 rb_hash_modify_check(hash);
1584 }
1585
1586 NORETURN(static void no_new_key(void));
1587 static void
1588 no_new_key(void)
1589 {
1590 rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
1591 }
1592
1593 struct update_callback_arg {
1594 VALUE hash;
1595 st_data_t arg;
1596 };
1597
1598 #define NOINSERT_UPDATE_CALLBACK(func) \
1599 static int \
1600 func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1601 { \
1602 if (!existing) no_new_key(); \
1603 return func(key, val, (struct update_arg *)arg, existing); \
1604 } \
1605 \
1606 static int \
1607 func##_insert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1608 { \
1609 return func(key, val, (struct update_arg *)arg, existing); \
1610 }
1611
1612 struct update_arg {
1613 st_data_t arg;
1614 VALUE hash;
1615 VALUE new_key;
1616 VALUE old_key;
1617 VALUE new_value;
1618 VALUE old_value;
1619 };
1620
1621 typedef int (*tbl_update_func)(st_data_t *, st_data_t *, st_data_t, int);
1622
1623 int
1624 rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg)
1625 {
1626 if (RHASH_AR_TABLE_P(hash)) {
1627 int result = ar_update(hash, (st_data_t)key, func, arg);
1628 if (result == -1) {
1629 ar_try_convert_table(hash);
1630 }
1631 else {
1632 return result;
1633 }
1634 }
1635
1636 return st_update(RHASH_ST_TABLE(hash), (st_data_t)key, func, arg);
1637 }
1638
1639 static int
1640 tbl_update(VALUE hash, VALUE key, tbl_update_func func, st_data_t optional_arg)
1641 {
1642 struct update_arg arg;
1643 int result;
1644
1645 arg.arg = optional_arg;
1646 arg.hash = hash;
1647 arg.new_key = 0;
1648 arg.old_key = Qundef;
1649 arg.new_value = 0;
1650 arg.old_value = Qundef;
1651
1652 result = rb_hash_stlike_update(hash, key, func, (st_data_t)&arg);
1653
1654 /* write barrier */
1655 if (arg.new_key) RB_OBJ_WRITTEN(hash, arg.old_key, arg.new_key);
1656 if (arg.new_value) RB_OBJ_WRITTEN(hash, arg.old_value, arg.new_value);
1657
1658 return result;
1659 }
1660
1661 #define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func##_insert)
1662
1663 #define RHASH_UPDATE_ITER(h, iter_lev, key, func, a) do { \
1664 tbl_update((h), (key), UPDATE_CALLBACK((iter_lev), func), (st_data_t)(a)); \
1665 } while (0)
1666
1667 #define RHASH_UPDATE(hash, key, func, arg) \
1668 RHASH_UPDATE_ITER(hash, RHASH_ITER_LEV(hash), key, func, arg)
1669
1670 static void
1671 set_proc_default(VALUE hash, VALUE proc)
1672 {
1673 if (rb_proc_lambda_p(proc)) {
1674 int n = rb_proc_arity(proc);
1675
1676 if (n != 2 && (n >= 0 || n < -3)) {
1677 if (n < 0) n = -n-1;
1678 rb_raise(rb_eTypeError, "default_proc takes two arguments (2 for %d)", n);
1679 }
1680 }
1681
1682 FL_SET_RAW(hash, RHASH_PROC_DEFAULT);
1683 RHASH_SET_IFNONE(hash, proc);
1684 }
1685
1686 /*
1687 * call-seq:
1688 * Hash.new -> new_hash
1689 * Hash.new(obj) -> new_hash
1690 * Hash.new {|hash, key| block } -> new_hash
1691 *
1692 * Returns a new, empty hash. If this hash is subsequently accessed by
1693 * a key that doesn't correspond to a hash entry, the value returned
1694 * depends on the style of <code>new</code> used to create the hash. In
1695 * the first form, the access returns <code>nil</code>. If
1696 * <i>obj</i> is specified, this single object will be used for
1697 * all <em>default values</em>. If a block is specified, it will be
1698 * called with the hash object and the key, and should return the
1699 * default value. It is the block's responsibility to store the value
1700 * in the hash if required.
1701 *
1702 * h = Hash.new("Go Fish")
1703 * h["a"] = 100
1704 * h["b"] = 200
1705 * h["a"] #=> 100
1706 * h["c"] #=> "Go Fish"
1707 * # The following alters the single default object
1708 * h["c"].upcase! #=> "GO FISH"
1709 * h["d"] #=> "GO FISH"
1710 * h.keys #=> ["a", "b"]
1711 *
1712 * # While this creates a new default object each time
1713 * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
1714 * h["c"] #=> "Go Fish: c"
1715 * h["c"].upcase! #=> "GO FISH: C"
1716 * h["d"] #=> "Go Fish: d"
1717 * h.keys #=> ["c", "d"]
1718 *
1719 */
1720
1721 static VALUE
1722 rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
1723 {
1724 VALUE ifnone;
1725
1726 rb_hash_modify(hash);
1727 if (rb_block_given_p()) {
1728 rb_check_arity(argc, 0, 0);
1729 ifnone = rb_block_proc();
1730 SET_PROC_DEFAULT(hash, ifnone);
1731 }
1732 else {
1733 rb_check_arity(argc, 0, 1);
1734 ifnone = argc == 0 ? Qnil : argv[0];
1735 RHASH_SET_IFNONE(hash, ifnone);
1736 }
1737
1738 return hash;
1739 }
1740
1741 /*
1742 * call-seq:
1743 * Hash[ key, value, ... ] -> new_hash
1744 * Hash[ [ [key, value], ... ] ] -> new_hash
1745 * Hash[ object ] -> new_hash
1746 *
1747 * Creates a new hash populated with the given objects.
1748 *
1749 * Similar to the literal <code>{ _key_ => _value_, ... }</code>. In the first
1750 * form, keys and values occur in pairs, so there must be an even number of
1751 * arguments.
1752 *
1753 * The second and third form take a single argument which is either an array
1754 * of key-value pairs or an object convertible to a hash.
1755 *
1756 * Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
1757 * Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
1758 * Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
1759 */
1760
1761 static VALUE
1762 rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
1763 {
1764 VALUE hash, tmp;
1765
1766 if (argc == 1) {
1767 tmp = rb_hash_s_try_convert(Qnil, argv[0]);
1768 if (!NIL_P(tmp)) {
1769 hash = hash_alloc(klass);
1770 if (RHASH_AR_TABLE_P(tmp)) {
1771 ar_copy(hash, tmp);
1772 }
1773 else {
1774 RHASH_ST_TABLE_SET(hash, st_copy(RHASH_ST_TABLE(tmp)));
1775 }
1776 return hash;
1777 }
1778
1779 tmp = rb_check_array_type(argv[0]);
1780 if (!NIL_P(tmp)) {
1781 long i;
1782
1783 hash = hash_alloc(klass);
1784 for (i = 0; i < RARRAY_LEN(tmp); ++i) {
1785 VALUE e = RARRAY_AREF(tmp, i);
1786 VALUE v = rb_check_array_type(e);
1787 VALUE key, val = Qnil;
1788
1789 if (NIL_P(v)) {
1790 rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
1791 rb_builtin_class_name(e), i);
1792 }
1793 switch (RARRAY_LEN(v)) {
1794 default:
1795 rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
1796 RARRAY_LEN(v));
1797 case 2:
1798 val = RARRAY_AREF(v, 1);
1799 case 1:
1800 key = RARRAY_AREF(v, 0);
1801 rb_hash_aset(hash, key, val);
1802 }
1803 }
1804 return hash;
1805 }
1806 }
1807 if (argc % 2 != 0) {
1808 rb_raise(rb_eArgError, "odd number of arguments for Hash");
1809 }
1810
1811 hash = hash_alloc(klass);
1812 rb_hash_bulk_insert(argc, argv, hash);
1813 hash_verify(hash);
1814 return hash;
1815 }
1816
1817 VALUE
1818 rb_to_hash_type(VALUE hash)
1819 {
1820 return rb_convert_type_with_id(hash, T_HASH, "Hash", idTo_hash);
1821 }
1822 #define to_hash rb_to_hash_type
1823
1824 VALUE
1825 rb_check_hash_type(VALUE hash)
1826 {
1827 return rb_check_convert_type_with_id(hash, T_HASH, "Hash", idTo_hash);
1828 }
1829
1830 /*
1831 * call-seq:
1832 * Hash.try_convert(obj) -> hash or nil
1833 *
1834 * Try to convert <i>obj</i> into a hash, using to_hash method.
1835 * Returns converted hash or nil if <i>obj</i> cannot be converted
1836 * for any reason.
1837 *
1838 * Hash.try_convert({1=>2}) # => {1=>2}
1839 * Hash.try_convert("1=>2") # => nil
1840 */
1841 static VALUE
1842 rb_hash_s_try_convert(VALUE dummy, VALUE hash)
1843 {
1844 return rb_check_hash_type(hash);
1845 }
1846
1847 struct rehash_arg {
1848 VALUE hash;
1849 st_table *tbl;
1850 };
1851
1852 static int
1853 rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
1854 {
1855 if (RHASH_AR_TABLE_P(arg)) {
1856 ar_insert(arg, (st_data_t)key, (st_data_t)value);
1857 }
1858 else {
1859 st_insert(RHASH_ST_TABLE(arg), (st_data_t)key, (st_data_t)value);
1860 }
1861 return ST_CONTINUE;
1862 }
1863
1864 /*
1865 * call-seq:
1866 * hsh.rehash -> hsh
1867 *
1868 * Rebuilds the hash based on the current hash values for each key. If
1869 * values of key objects have changed since they were inserted, this
1870 * method will reindex <i>hsh</i>. If Hash#rehash is
1871 * called while an iterator is traversing the hash, a
1872 * RuntimeError will be raised in the iterator.
1873 *
1874 * a = [ "a", "b" ]
1875 * c = [ "c", "d" ]
1876 * h = { a => 100, c => 300 }
1877 * h[a] #=> 100
1878 * a[0] = "z"
1879 * h[a] #=> nil
1880 * h.rehash #=> {["z", "b"]=>100, ["c", "d"]=>300}
1881 * h[a] #=> 100
1882 */
1883
1884 VALUE
1885 rb_hash_rehash(VALUE hash)
1886 {
1887 VALUE tmp;
1888 st_table *tbl;
1889
1890 if (RHASH_ITER_LEV(hash) > 0) {
1891 rb_raise(rb_eRuntimeError, "rehash during iteration");
1892 }
1893 rb_hash_modify_check(hash);
1894 if (RHASH_AR_TABLE_P(hash)) {
1895 tmp = hash_alloc(0);
1896 ar_alloc_table(tmp);
1897 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
1898 ar_free_and_clear_table(hash);
1899 ar_copy(hash, tmp);
1900 ar_free_and_clear_table(tmp);
1901 }
1902 else if (RHASH_ST_TABLE_P(hash)) {
1903 st_table *old_tab = RHASH_ST_TABLE(hash);
1904 tmp = hash_alloc(0);
1905 tbl = st_init_table_with_size(old_tab->type, old_tab->num_entries);
1906 RHASH_ST_TABLE_SET(tmp, tbl);
1907 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
1908 st_free_table(old_tab);
1909 RHASH_ST_TABLE_SET(hash, tbl);
1910 RHASH_ST_CLEAR(tmp);
1911 }
1912 hash_verify(hash);
1913 return hash;
1914 }
1915
1916 VALUE
1917 rb_hash_default_value(VALUE hash, VALUE key)
1918 {
1919 if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) {
1920 VALUE ifnone = RHASH_IFNONE(hash);
1921 if (!FL_TEST(hash, RHASH_PROC_DEFAULT)) return ifnone;
1922 if (key == Qundef) return Qnil;
1923 return rb_funcall(ifnone, id_yield, 2, hash, key);
1924 }
1925 else {
1926 return rb_funcall(hash, id_default, 1, key);
1927 }
1928 }
1929
1930 static inline int
1931 hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
1932 {
1933 hash_verify(hash);
1934
1935 if (RHASH_AR_TABLE_P(hash)) {
1936 return ar_lookup(hash, key, pval);
1937 }
1938 else {
1939 return st_lookup(RHASH_ST_TABLE(hash), key, pval);
1940 }
1941 }
1942
1943 MJIT_FUNC_EXPORTED int
1944 rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
1945 {
1946 return hash_stlike_lookup(hash, key, pval);
1947 }
1948
1949 /*
1950 * call-seq:
1951 * hsh[key] -> value
1952 *
1953 * Element Reference---Retrieves the <i>value</i> object corresponding
1954 * to the <i>key</i> object. If not found, returns the default value (see
1955 * Hash::new for details).
1956 *
1957 * h = { "a" => 100, "b" => 200 }
1958 * h["a"] #=> 100
1959 * h["c"] #=> nil
1960 *
1961 */
1962
1963 VALUE
1964 rb_hash_aref(VALUE hash, VALUE key)
1965 {
1966 st_data_t val;
1967
1968 if (hash_stlike_lookup(hash, key, &val)) {
1969 return (VALUE)val;
1970 }
1971 else {
1972 return rb_hash_default_value(hash, key);
1973 }
1974 }
1975
1976 VALUE
1977 rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
1978 {
1979 st_data_t val;
1980
1981 if (hash_stlike_lookup(hash, key, &val)) {
1982 return (VALUE)val;
1983 }
1984 else {
1985 return def; /* without Hash#default */
1986 }
1987 }
1988
1989 VALUE
1990 rb_hash_lookup(VALUE hash, VALUE key)
1991 {
1992 return rb_hash_lookup2(hash, key, Qnil);
1993 }
1994
1995 /*
1996 * call-seq:
1997 * hsh.fetch(key [, default] ) -> obj
1998 * hsh.fetch(key) {| key | block } -> obj
1999 *
2000 * Returns a value from the hash for the given key. If the key can't be
2001 * found, there are several options: With no other arguments, it will
2002 * raise a KeyError exception; if <i>default</i> is given,
2003 * then that will be returned; if the optional code block is specified,
2004 * then that will be run and its result returned.
2005 *
2006 * h = { "a" => 100, "b" => 200 }
2007 * h.fetch("a") #=> 100
2008 * h.fetch("z", "go fish") #=> "go fish"
2009 * h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
2010 *
2011 * The following example shows that an exception is raised if the key
2012 * is not found and a default value is not supplied.
2013 *
2014 * h = { "a" => 100, "b" => 200 }
2015 * h.fetch("z")
2016 *
2017 * <em>produces:</em>
2018 *
2019 * prog.rb:2:in `fetch': key not found (KeyError)
2020 * from prog.rb:2
2021 *
2022 */
2023
2024 static VALUE
2025 rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
2026 {
2027 VALUE key;
2028 st_data_t val;
2029 long block_given;
2030
2031 rb_check_arity(argc, 1, 2);
2032 key = argv[0];
2033
2034 block_given = rb_block_given_p();
2035 if (block_given && argc == 2) {
2036 rb_warn("block supersedes default value argument");
2037 }
2038
2039 if (hash_stlike_lookup(hash, key, &val)) {
2040 return (VALUE)val;
2041 }
2042 else {
2043 if (block_given) {
2044 return rb_yield(key);
2045 }
2046 else if (argc == 1) {
2047 VALUE desc = rb_protect(rb_inspect, key, 0);
2048 if (NIL_P(desc)) {
2049 desc = rb_any_to_s(key);
2050 }
2051 desc = rb_str_ellipsize(desc, 65);
2052 rb_key_err_raise(rb_sprintf("key not found: %"PRIsVALUE, desc), hash, key);
2053 }
2054 else {
2055 return argv[1];
2056 }
2057 }
2058 }
2059
2060 VALUE
2061 rb_hash_fetch(VALUE hash, VALUE key)
2062 {
2063 return rb_hash_fetch_m(1, &key, hash);
2064 }
2065
2066 /*
2067 * call-seq:
2068 * hsh.default(key=nil) -> obj
2069 *
2070 * Returns the default value, the value that would be returned by
2071 * <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
2072 * See also Hash::new and Hash#default=.
2073 *
2074 * h = Hash.new #=> {}
2075 * h.default #=> nil
2076 * h.default(2) #=> nil
2077 *
2078 * h = Hash.new("cat") #=> {}
2079 * h.default #=> "cat"
2080 * h.default(2) #=> "cat"
2081 *
2082 * h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {}
2083 * h.default #=> nil
2084 * h.default(2) #=> 20
2085 */
2086
2087 static VALUE
2088 rb_hash_default(int argc, VALUE *argv, VALUE hash)
2089 {
2090 VALUE args[2], ifnone;
2091
2092 rb_check_arity(argc, 0, 1);
2093 ifnone = RHASH_IFNONE(hash);
2094 if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
2095 if (argc == 0) return Qnil;
2096 args[0] = hash;
2097 args[1] = argv[0];
2098 return rb_funcallv(ifnone, id_yield, 2, args);
2099 }
2100 return ifnone;
2101 }
2102
2103 /*
2104 * call-seq:
2105 * hsh.default = obj -> obj
2106 *
2107 * Sets the default value, the value returned for a key that does not
2108 * exist in the hash. It is not possible to set the default to a
2109 * Proc that will be executed on each key lookup.
2110 *
2111 * h = { "a" => 100, "b" => 200 }
2112 * h.default = "Go fish"
2113 * h["a"] #=> 100
2114 * h["z"] #=> "Go fish"
2115 * # This doesn't do what you might hope...
2116 * h.default = proc do |hash, key|
2117 * hash[key] = key + key
2118 * end
2119 * h[2] #=> #<Proc:0x401b3948@-:6>
2120 * h["cat"] #=> #<Proc:0x401b3948@-:6>
2121 */
2122
2123 static VALUE
2124 rb_hash_set_default(VALUE hash, VALUE ifnone)
2125 {
2126 rb_hash_modify_check(hash);
2127 SET_DEFAULT(hash, ifnone);
2128 return ifnone;
2129 }
2130
2131 /*
2132 * call-seq:
2133 * hsh.default_proc -> anObject
2134 *
2135 * If Hash::new was invoked with a block, return that
2136 * block, otherwise return <code>nil</code>.
2137 *
2138 * h = Hash.new {|h,k| h[k] = k*k } #=> {}
2139 * p = h.default_proc #=> #<Proc:0x401b3d08@-:1>
2140 * a = [] #=> []
2141 * p.call(a, 2)
2142 * a #=> [nil, nil, 4]
2143 */
2144
2145
2146 static VALUE
2147 rb_hash_default_proc(VALUE hash)
2148 {
2149 if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
2150 return RHASH_IFNONE(hash);
2151 }
2152 return Qnil;
2153 }
2154
2155 /*
2156 * call-seq:
2157 * hsh.default_proc = proc_obj or nil
2158 *
2159 * Sets the default proc to be executed on each failed key lookup.
2160 *
2161 * h.default_proc = proc do |hash, key|
2162 * hash[key] = key + key
2163 * end
2164 * h[2] #=> 4
2165 * h["cat"] #=> "catcat"
2166 */
2167
2168 VALUE
2169 rb_hash_set_default_proc(VALUE hash, VALUE proc)
2170 {
2171 VALUE b;
2172
2173 rb_hash_modify_check(hash);
2174 if (NIL_P(proc)) {
2175 SET_DEFAULT(hash, proc);
2176 return proc;
2177 }
2178 b = rb_check_convert_type_with_id(proc, T_DATA, "Proc", idTo_proc);
2179 if (NIL_P(b) || !rb_obj_is_proc(b)) {
2180 rb_raise(rb_eTypeError,
2181 "wrong default_proc type %s (expected Proc)",
2182 rb_obj_classname(proc));
2183 }
2184 proc = b;
2185 SET_PROC_DEFAULT(hash, proc);
2186 return proc;
2187 }
2188
2189 static int
2190 key_i(VALUE key, VALUE value, VALUE arg)
2191 {
2192 VALUE *args = (VALUE *)arg;
2193
2194 if (rb_equal(value, args[0])) {
2195 args[1] = key;
2196 return ST_STOP;
2197 }
2198 return ST_CONTINUE;
2199 }
2200
2201 /*
2202 * call-seq:
2203 * hsh.key(value) -> key
2204 *
2205 * Returns the key of an occurrence of a given value. If the value is
2206 * not found, returns <code>nil</code>.
2207 *
2208 * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
2209 * h.key(200) #=> "b"
2210 * h.key(300) #=> "c"
2211 * h.key(999) #=> nil
2212 *
2213 */
2214
2215 static VALUE
2216 rb_hash_key(VALUE hash, VALUE value)
2217 {
2218 VALUE args[2];
2219
2220 args[0] = value;
2221 args[1] = Qnil;
2222
2223 rb_hash_foreach(hash, key_i, (VALUE)args);
2224
2225 return args[1];
2226 }
2227
2228 /* :nodoc: */
2229 static VALUE
2230 rb_hash_index(VALUE hash, VALUE value)
2231 {
2232 rb_warn_deprecated("Hash#index", "Hash#key");
2233 return rb_hash_key(hash, value);
2234 }
2235
2236 int
2237 rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval)
2238 {
2239 if (RHASH_AR_TABLE_P(hash)) {
2240 return ar_delete(hash, pkey, pval);
2241 }
2242 else {
2243 return st_delete(RHASH_ST_TABLE(hash), pkey, pval);
2244 }
2245 }
2246
2247 /*
2248 * delete a specified entry a given key.
2249 * if there is the corresponding entry, return a value of the entry.
2250 * if there is no corresponding entry, return Qundef.
2251 */
2252 VALUE
2253 rb_hash_delete_entry(VALUE hash, VALUE key)
2254 {
2255 st_data_t ktmp = (st_data_t)key, val;
2256
2257 if (rb_hash_stlike_delete(hash, &ktmp, &val)) {
2258 return (VALUE)val;
2259 }
2260 else {
2261 return Qundef;
2262 }
2263 }
2264
2265 /*
2266 * delete a specified entry by a given key.
2267 * if there is the corresponding entry, return a value of the entry.
2268 * if there is no corresponding entry, return Qnil.
2269 */
2270 VALUE
2271 rb_hash_delete(VALUE hash, VALUE key)
2272 {
2273 VALUE deleted_value = rb_hash_delete_entry(hash, key);
2274
2275 if (deleted_value != Qundef) { /* likely pass */
2276 return deleted_value;
2277 }
2278 else {
2279 return Qnil;
2280 }
2281 }
2282
2283 /*
2284 * call-seq:
2285 * hsh.delete(key) -> value
2286 * hsh.delete(key) {| key | block } -> value
2287 *
2288 * Deletes the key-value pair and returns the value from <i>hsh</i> whose
2289 * key is equal to <i>key</i>. If the key is not found, it returns
2290 * <em>nil</em>. If the optional code block is given and the
2291 * key is not found, pass in the key and return the result of
2292 * <i>block</i>.
2293 *
2294 * h = { "a" => 100, "b" => 200 }
2295 * h.delete("a") #=> 100
2296 * h.delete("z") #=> nil
2297 * h.delete("z") { |el| "#{el} not found" } #=> "z not found"
2298 *
2299 */
2300
2301 static VALUE
2302 rb_hash_delete_m(VALUE hash, VALUE key)
2303 {
2304 VALUE val;
2305
2306 rb_hash_modify_check(hash);
2307 val = rb_hash_delete_entry(hash, key);
2308
2309 if (val != Qundef) {
2310 return val;
2311 }
2312 else {
2313 if (rb_block_given_p()) {
2314 return rb_yield(key);
2315 }
2316 else {
2317 return Qnil;
2318 }
2319 }
2320 }
2321
2322 struct shift_var {
2323 VALUE key;
2324 VALUE val;
2325 };
2326
2327 static int
2328 shift_i_safe(VALUE key, VALUE value, VALUE arg)
2329 {
2330 struct shift_var *var = (struct shift_var *)arg;
2331
2332 var->key = key;
2333 var->val = value;
2334 return ST_STOP;
2335 }
2336
2337 /*
2338 * call-seq:
2339 * hsh.shift -> anArray or obj
2340 *
2341 * Removes a key-value pair from <i>hsh</i> and returns it as the
2342 * two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
2343 * the hash's default value if the hash is empty.
2344 *
2345 * h = { 1 => "a", 2 => "b", 3 => "c" }
2346 * h.shift #=> [1, "a"]
2347 * h #=> {2=>"b", 3=>"c"}
2348 */
2349
2350 static VALUE
2351 rb_hash_shift(VALUE hash)
2352 {
2353 struct shift_var var;
2354
2355 rb_hash_modify_check(hash);
2356 if (RHASH_AR_TABLE_P(hash)) {
2357 var.key = Qundef;
2358 if (RHASH_ITER_LEV(hash) == 0) {
2359 if (ar_shift(hash, &var.key, &var.val)) {
2360 return rb_assoc_new(var.key, var.val);
2361 }
2362 }
2363 else {
2364 rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
2365 if (var.key != Qundef) {
2366 rb_hash_delete_entry(hash, var.key);
2367 return rb_assoc_new(var.key, var.val);
2368 }
2369 }
2370 }
2371 if (RHASH_ST_TABLE_P(hash)) {
2372 var.key = Qundef;
2373 if (RHASH_ITER_LEV(hash) == 0) {
2374 if (st_shift(RHASH_ST_TABLE(hash), &var.key, &var.val)) {
2375 return rb_assoc_new(var.key, var.val);
2376 }
2377 }
2378 else {
2379 rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
2380 if (var.key != Qundef) {
2381 rb_hash_delete_entry(hash, var.key);
2382 return rb_assoc_new(var.key, var.val);
2383 }
2384 }
2385 }
2386 return rb_hash_default_value(hash, Qnil);
2387 }
2388
2389 static int
2390 delete_if_i(VALUE key, VALUE value, VALUE hash)
2391 {
2392 if (RTEST(rb_yield_values(2, key, value))) {
2393 return ST_DELETE;
2394 }
2395 return ST_CONTINUE;
2396 }
2397
2398 static VALUE
2399 hash_enum_size(VALUE hash, VALUE args, VALUE eobj)
2400 {
2401 return rb_hash_size(hash);
2402 }
2403
2404 /*
2405 * call-seq:
2406 * hsh.delete_if {| key, value | block } -> hsh
2407 * hsh.delete_if -> an_enumerator
2408 *
2409 * Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
2410 * evaluates to <code>true</code>.
2411 *
2412 * If no block is given, an enumerator is returned instead.
2413 *
2414 * h = { "a" => 100, "b" => 200, "c" => 300 }
2415 * h.delete_if {|key, value| key >= "b" } #=> {"a"=>100}
2416 *
2417 */
2418
2419 VALUE
2420 rb_hash_delete_if(VALUE hash)
2421 {
2422 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2423 rb_hash_modify_check(hash);
2424 if (!RHASH_TABLE_EMPTY_P(hash)) {
2425 rb_hash_foreach(hash, delete_if_i, hash);
2426 }
2427 return hash;
2428 }
2429
2430 /*
2431 * call-seq:
2432 * hsh.reject! {| key, value | block } -> hsh or nil
2433 * hsh.reject! -> an_enumerator
2434 *
2435 * Equivalent to Hash#delete_if, but returns
2436 * <code>nil</code> if no changes were made.
2437 */
2438
2439 VALUE
2440 rb_hash_reject_bang(VALUE hash)
2441 {
2442 st_index_t n;
2443
2444 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2445 rb_hash_modify(hash);
2446 n = RHASH_SIZE(hash);
2447 if (!n) return Qnil;
2448 rb_hash_foreach(hash, delete_if_i, hash);
2449 if (n == RHASH_SIZE(hash)) return Qnil;
2450 return hash;
2451 }
2452
2453 static int
2454 reject_i(VALUE key, VALUE value, VALUE result)
2455 {
2456 if (!RTEST(rb_yield_values(2, key, value))) {
2457 rb_hash_aset(result, key, value);
2458 }
2459 return ST_CONTINUE;
2460 }
2461
2462 /*
2463 * call-seq:
2464 * hsh.reject {|key, value| block} -> a_hash
2465 * hsh.reject -> an_enumerator
2466 *
2467 * Returns a new hash consisting of entries for which the block returns false.
2468 *
2469 * If no block is given, an enumerator is returned instead.
2470 *
2471 * h = { "a" => 100, "b" => 200, "c" => 300 }
2472 * h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300}
2473 * h.reject {|k,v| v > 100} #=> {"a" => 100}
2474 */
2475
2476 VALUE
2477 rb_hash_reject(VALUE hash)
2478 {
2479 VALUE result;
2480
2481 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2482 if (RTEST(ruby_verbose)) {
2483 VALUE klass;
2484 if (HAS_EXTRA_STATES(hash, klass)) {
2485 rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash);
2486 }
2487 }
2488 result = rb_hash_new();
2489 if (!RHASH_EMPTY_P(hash)) {
2490 rb_hash_foreach(hash, reject_i, result);
2491 }
2492 return result;
2493 }
2494
2495 /*
2496 * call-seq:
2497 * hsh.slice(*keys) -> a_hash
2498 *
2499 * Returns a hash containing only the given keys and their values.
2500 *
2501 * h = { a: 100, b: 200, c: 300 }
2502 * h.slice(:a) #=> {:a=>100}
2503 * h.slice(:b, :c, :d) #=> {:b=>200, :c=>300}
2504 */
2505
2506 static VALUE
2507 rb_hash_slice(int argc, VALUE *argv, VALUE hash)
2508 {
2509 int i;
2510 VALUE key, value, result;
2511
2512 if (argc == 0 || RHASH_EMPTY_P(hash)) {
2513 return rb_hash_new();
2514 }
2515 result = rb_hash_new_with_size(argc);
2516
2517 for (i = 0; i < argc; i++) {
2518 key = argv[i];
2519 value = rb_hash_lookup2(hash, key, Qundef);
2520 if (value != Qundef)
2521 rb_hash_aset(result, key, value);
2522 }
2523
2524 return result;
2525 }
2526
2527 /*
2528 * call-seq:
2529 * hsh.values_at(key, ...) -> array
2530 *
2531 * Return an array containing the values associated with the given keys.
2532 * Also see Hash.select.
2533 *
2534 * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
2535 * h.values_at("cow", "cat") #=> ["bovine", "feline"]
2536 */
2537
2538 VALUE
2539 rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
2540 {
2541 VALUE result = rb_ary_new2(argc);
2542 long i;
2543
2544 for (i=0; i<argc; i++) {
2545 rb_ary_push(result, rb_hash_aref(hash, argv[i]));
2546 }
2547 return result;
2548 }
2549
2550 /*
2551 * call-seq:
2552 * hsh.fetch_values(key, ...) -> array
2553 * hsh.fetch_values(key, ...) { |key| block } -> array
2554 *
2555 * Returns an array containing the values associated with the given keys
2556 * but also raises KeyError when one of keys can't be found.
2557 * Also see Hash#values_at and Hash#fetch.
2558 *
2559 * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
2560 *
2561 * h.fetch_values("cow", "cat") #=> ["bovine", "feline"]
2562 * h.fetch_values("cow", "bird") # raises KeyError
2563 * h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
2564 */
2565
2566 VALUE
2567 rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
2568 {
2569 VALUE result = rb_ary_new2(argc);
2570 long i;
2571
2572 for (i=0; i<argc; i++) {
2573 rb_ary_push(result, rb_hash_fetch(hash, argv[i]));
2574 }
2575 return result;
2576 }
2577
2578 static int
2579 select_i(VALUE key, VALUE value, VALUE result)
2580 {
2581 if (RTEST(rb_yield_values(2, key, value))) {
2582 rb_hash_aset(result, key, value);
2583 }
2584 return ST_CONTINUE;
2585 }
2586
2587 /*
2588 * call-seq:
2589 * hsh.select {|key, value| block} -> a_hash
2590 * hsh.select -> an_enumerator
2591 * hsh.filter {|key, value| block} -> a_hash
2592 * hsh.filter -> an_enumerator
2593 *
2594 * Returns a new hash consisting of entries for which the block returns true.
2595 *
2596 * If no block is given, an enumerator is returned instead.
2597 *
2598 * h = { "a" => 100, "b" => 200, "c" => 300 }
2599 * h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300}
2600 * h.select {|k,v| v < 200} #=> {"a" => 100}
2601 *
2602 * Hash#filter is an alias for Hash#select.
2603 */
2604
2605 VALUE
2606 rb_hash_select(VALUE hash)
2607 {
2608 VALUE result;
2609
2610 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2611 result = rb_hash_new();
2612 if (!RHASH_EMPTY_P(hash)) {
2613 rb_hash_foreach(hash, select_i, result);
2614 }
2615 return result;
2616 }
2617
2618 static int
2619 keep_if_i(VALUE key, VALUE value, VALUE hash)
2620 {
2621 if (!RTEST(rb_yield_values(2, key, value))) {
2622 return ST_DELETE;
2623 }
2624 return ST_CONTINUE;
2625 }
2626
2627 /*
2628 * call-seq:
2629 * hsh.select! {| key, value | block } -> hsh or nil
2630 * hsh.select! -> an_enumerator
2631 * hsh.filter! {| key, value | block } -> hsh or nil
2632 * hsh.filter! -> an_enumerator
2633 *
2634 * Equivalent to Hash#keep_if, but returns
2635 * +nil+ if no changes were made.
2636 *
2637 * Hash#filter! is an alias for Hash#select!.
2638 */
2639
2640 VALUE
2641 rb_hash_select_bang(VALUE hash)
2642 {
2643 st_index_t n;
2644
2645 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2646 rb_hash_modify_check(hash);
2647 n = RHASH_SIZE(hash);
2648 if (!n) return Qnil;
2649 rb_hash_foreach(hash, keep_if_i, hash);
2650 if (n == RHASH_SIZE(hash)) return Qnil;
2651 return hash;
2652 }
2653
2654 /*
2655 * call-seq:
2656 * hsh.keep_if {| key, value | block } -> hsh
2657 * hsh.keep_if -> an_enumerator
2658 *
2659 * Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
2660 * evaluates to +false+.
2661 *
2662 * If no block is given, an enumerator is returned instead.
2663 *
2664 * See also Hash#select!.
2665 */
2666
2667 VALUE
2668 rb_hash_keep_if(VALUE hash)
2669 {
2670 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2671 rb_hash_modify_check(hash);
2672 if (!RHASH_TABLE_EMPTY_P(hash)) {
2673 rb_hash_foreach(hash, keep_if_i, hash);
2674 }
2675 return hash;
2676 }
2677
2678 static int
2679 clear_i(VALUE key, VALUE value, VALUE dummy)
2680 {
2681 return ST_DELETE;
2682 }
2683
2684 /*
2685 * call-seq:
2686 * hsh.clear -> hsh
2687 *
2688 * Removes all key-value pairs from <i>hsh</i>.
2689 *
2690 * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
2691 * h.clear #=> {}
2692 *
2693 */
2694
2695 VALUE
2696 rb_hash_clear(VALUE hash)
2697 {
2698 rb_hash_modify_check(hash);
2699
2700 if (RHASH_ITER_LEV(hash) > 0) {
2701 rb_hash_foreach(hash, clear_i, 0);
2702 }
2703 else if (RHASH_AR_TABLE_P(hash)) {
2704 ar_clear(hash);
2705 }
2706 else {
2707 st_clear(RHASH_ST_TABLE(hash));
2708 }
2709
2710 return hash;
2711 }
2712
2713 static int
2714 hash_aset(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
2715 {
2716 if (existing) {
2717 arg->new_value = arg->arg;
2718 arg->old_value = *val;
2719 }
2720 else {
2721 arg->new_key = *key;
2722 arg->new_value = arg->arg;
2723 }
2724 *val = arg->arg;
2725 return ST_CONTINUE;
2726 }
2727
2728 VALUE
2729 rb_hash_key_str(VALUE key)
2730 {
2731 if (!RB_FL_ANY_RAW(key, FL_EXIVAR) && RBASIC_CLASS(key) == rb_cString) {
2732 return rb_fstring(key);
2733 }
2734 else {
2735 return rb_str_new_frozen(key);
2736 }
2737 }
2738
2739 static int
2740 hash_aset_str(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
2741 {
2742 if (!existing && !RB_OBJ_FROZEN(*key)) {
2743 *key = rb_hash_key_str(*key);
2744 }
2745 return hash_aset(key, val, arg, existing);
2746 }
2747
2748 NOINSERT_UPDATE_CALLBACK(hash_aset)
2749 NOINSERT_UPDATE_CALLBACK(hash_aset_str)
2750
2751 /*
2752 * call-seq:
2753 * hsh[key] = value -> value
2754 * hsh.store(key, value) -> value
2755 *
2756 * == Element Assignment
2757 *
2758 * Associates the value given by +value+ with the key given by +key+.
2759 *
2760 * h = { "a" => 100, "b" => 200 }
2761 * h["a"] = 9
2762 * h["c"] = 4
2763 * h #=> {"a"=>9, "b"=>200, "c"=>4}
2764 * h.store("d", 42) #=> 42
2765 * h #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42}
2766 *
2767 * +key+ should not have its value changed while it is in use as a key (an
2768 * <tt>unfrozen String</tt> passed as a key will be duplicated and frozen).
2769 *
2770 * a = "a"
2771 * b = "b".freeze
2772 * h = { a => 100, b => 200 }
2773 * h.key(100).equal? a #=> false
2774 * h.key(200).equal? b #=> true
2775 *
2776 */
2777
2778 VALUE
2779 rb_hash_aset(VALUE hash, VALUE key, VALUE val)
2780 {
2781 int iter_lev = RHASH_ITER_LEV(hash);
2782
2783 rb_hash_modify(hash);
2784
2785 if (RHASH_TABLE_NULL_P(hash)) {
2786 if (iter_lev > 0) no_new_key();
2787 ar_alloc_table(hash);
2788 }
2789
2790 if (RHASH_TYPE(hash) == &identhash || rb_obj_class(key) != rb_cString) {
2791 RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
2792 }
2793 else {
2794 RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
2795 }
2796 return val;
2797 }
2798
2799 /*
2800 * call-seq:
2801 * hsh.replace(other_hash) -> hsh
2802 *
2803 * Replaces the contents of <i>hsh</i> with the contents of
2804 * <i>other_hash</i>.
2805 *
2806 * h = { "a" => 100, "b" => 200 }
2807 * h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}
2808 *
2809 */
2810
2811 static VALUE
2812 rb_hash_replace(VALUE hash, VALUE hash2)
2813 {
2814 rb_hash_modify_check(hash);
2815 if (hash == hash2) return hash;
2816 if (RHASH_ITER_LEV(hash) > 0) {
2817 rb_raise(rb_eRuntimeError, "can't replace hash during iteration");
2818 }
2819 hash2 = to_hash(hash2);
2820
2821 COPY_DEFAULT(hash, hash2);
2822
2823 if (RHASH_AR_TABLE_P(hash)) {
2824 if (RHASH_AR_TABLE_P(hash2)) {
2825 ar_clear(hash);
2826 }
2827 else {
2828 ar_free_and_clear_table(hash);
2829 RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), RHASH_SIZE(hash2)));
2830 }
2831 }
2832 else {
2833 if (RHASH_AR_TABLE_P(hash2)) {
2834 st_free_table(RHASH_ST_TABLE(hash));
2835 RHASH_ST_CLEAR(hash);
2836 }
2837 else {
2838 st_clear(RHASH_ST_TABLE(hash));
2839 RHASH_TBL_RAW(hash)->type = RHASH_ST_TABLE(hash2)->type;
2840 }
2841 }
2842 rb_hash_foreach(hash2, rb_hash_rehash_i, (VALUE)hash);
2843
2844 rb_gc_writebarrier_remember(hash);
2845
2846 return hash;
2847 }
2848
2849 /*
2850 * call-seq:
2851 * hsh.length -> integer
2852 * hsh.size -> integer
2853 *
2854 * Returns the number of key-value pairs in the hash.
2855 *
2856 * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
2857 * h.size #=> 4
2858 * h.delete("a") #=> 200
2859 * h.size #=> 3
2860 * h.length #=> 3
2861 *
2862 * Hash#length is an alias for Hash#size.
2863 */
2864
2865 VALUE
2866 rb_hash_size(VALUE hash)
2867 {
2868 return INT2FIX(RHASH_SIZE(hash));
2869 }
2870
2871 size_t
2872 rb_hash_size_num(VALUE hash)
2873 {
2874 return (long)RHASH_SIZE(hash);
2875 }
2876
2877 /*
2878 * call-seq:
2879 * hsh.empty? -> true or false
2880 *
2881 * Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
2882 *
2883 * {}.empty? #=> true
2884 *
2885 */
2886
2887 static VALUE
2888 rb_hash_empty_p(VALUE hash)
2889 {
2890 return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
2891 }
2892
2893 static int
2894 each_value_i(VALUE key, VALUE value, VALUE _)
2895 {
2896 rb_yield(value);
2897 return ST_CONTINUE;
2898 }
2899
2900 /*
2901 * call-seq:
2902 * hsh.each_value {| value | block } -> hsh
2903 * hsh.each_value -> an_enumerator
2904 *
2905 * Calls <i>block</i> once for each key in <i>hsh</i>, passing the
2906 * value as a parameter.
2907 *
2908 * If no block is given, an enumerator is returned instead.
2909 *
2910 * h = { "a" => 100, "b" => 200 }
2911 * h.each_value {|value| puts value }
2912 *
2913 * <em>produces:</em>
2914 *
2915 * 100
2916 * 200
2917 */
2918
2919 static VALUE
2920 rb_hash_each_value(VALUE hash)
2921 {
2922 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2923 rb_hash_foreach(hash, each_value_i, 0);
2924 return hash;
2925 }
2926
2927 static int
2928 each_key_i(VALUE key, VALUE value, VALUE _)
2929 {
2930 rb_yield(key);
2931 return ST_CONTINUE;
2932 }
2933
2934 /*
2935 * call-seq:
2936 * hsh.each_key {| key | block } -> hsh
2937 * hsh.each_key -> an_enumerator
2938 *
2939 * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key
2940 * as a parameter.
2941 *
2942 * If no block is given, an enumerator is returned instead.
2943 *
2944 * h = { "a" => 100, "b" => 200 }
2945 * h.each_key {|key| puts key }
2946 *
2947 * <em>produces:</em>
2948 *
2949 * a
2950 * b
2951 */
2952 static VALUE
2953 rb_hash_each_key(VALUE hash)
2954 {
2955 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2956 rb_hash_foreach(hash, each_key_i, 0);
2957 return hash;
2958 }
2959
2960 static int
2961 each_pair_i(VALUE key, VALUE value, VALUE _)
2962 {
2963 rb_yield(rb_assoc_new(key, value));
2964 return ST_CONTINUE;
2965 }
2966
2967 static int
2968 each_pair_i_fast(VALUE key, VALUE value, VALUE _)
2969 {
2970 VALUE argv[2];
2971 argv[0] = key;
2972 argv[1] = value;
2973 rb_yield_values2(2, argv);
2974 return ST_CONTINUE;
2975 }
2976
2977 /*
2978 * call-seq:
2979 * hsh.each {| key, value | block } -> hsh
2980 * hsh.each_pair {| key, value | block } -> hsh
2981 * hsh.each -> an_enumerator
2982 * hsh.each_pair -> an_enumerator
2983 *
2984 * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key-value
2985 * pair as parameters.
2986 *
2987 * If no block is given, an enumerator is returned instead.
2988 *
2989 * h = { "a" => 100, "b" => 200 }
2990 * h.each {|key, value| puts "#{key} is #{value}" }
2991 *
2992 * <em>produces:</em>
2993 *
2994 * a is 100
2995 * b is 200
2996 *
2997 */
2998
2999 static VALUE
3000 rb_hash_each_pair(VALUE hash)
3001 {
3002 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3003 if (rb_block_arity() > 1)
3004 rb_hash_foreach(hash, each_pair_i_fast, 0);
3005 else
3006 rb_hash_foreach(hash, each_pair_i, 0);
3007 return hash;
3008 }
3009
3010 static int
3011 transform_keys_i(VALUE key, VALUE value, VALUE result)
3012 {
3013 VALUE new_key = rb_yield(key);
3014 rb_hash_aset(result, new_key, value);
3015 return ST_CONTINUE;
3016 }
3017
3018 /*
3019 * call-seq:
3020 * hsh.transform_keys {|key| block } -> new_hash
3021 * hsh.transform_keys -> an_enumerator
3022 *
3023 * Returns a new hash with the results of running the block once for
3024 * every key.
3025 * This method does not change the values.
3026 *
3027 * h = { a: 1, b: 2, c: 3 }
3028 * h.transform_keys {|k| k.to_s } #=> { "a" => 1, "b" => 2, "c" => 3 }
3029 * h.transform_keys(&:to_s) #=> { "a" => 1, "b" => 2, "c" => 3 }
3030 * h.transform_keys.with_index {|k, i| "#{k}.#{i}" }
3031 * #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 }
3032 *
3033 * If no block is given, an enumerator is returned instead.
3034 */
3035 static VALUE
3036 rb_hash_transform_keys(VALUE hash)
3037 {
3038 VALUE result;
3039
3040 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3041 result = rb_hash_new();
3042 if (!RHASH_EMPTY_P(hash)) {
3043 rb_hash_foreach(hash, transform_keys_i, result);
3044 }
3045
3046 return result;
3047 }
3048
3049 static VALUE rb_hash_flatten(int argc, VALUE *argv, VALUE hash);
3050
3051 /*
3052 * call-seq:
3053 * hsh.transform_keys! {|key| block } -> hsh
3054 * hsh.transform_keys! -> an_enumerator
3055 *
3056 * Invokes the given block once for each key in <i>hsh</i>, replacing it
3057 * with the new key returned by the block, and then returns <i>hsh</i>.
3058 * This method does not change the values.
3059 *
3060 * h = { a: 1, b: 2, c: 3 }
3061 * h.transform_keys! {|k| k.to_s } #=> { "a" => 1, "b" => 2, "c" => 3 }
3062 * h.transform_keys!(&:to_sym) #=> { a: 1, b: 2, c: 3 }
3063 * h.transform_keys!.with_index {|k, i| "#{k}.#{i}" }
3064 * #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 }
3065 *
3066 * If no block is given, an enumerator is returned instead.
3067 */
3068 static VALUE
3069 rb_hash_transform_keys_bang(VALUE hash)
3070 {
3071 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3072 rb_hash_modify_check(hash);
3073 if (!RHASH_TABLE_EMPTY_P(hash)) {
3074 long i;
3075 VALUE pairs = rb_hash_flatten(0, NULL, hash);
3076 rb_hash_clear(hash);
3077 for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
3078 VALUE key = RARRAY_AREF(pairs, i), new_key = rb_yield(key),
3079 val = RARRAY_AREF(pairs, i+1);
3080 rb_hash_aset(hash, new_key, val);
3081 }
3082 }
3083 return hash;
3084 }
3085
3086 static int
3087 transform_values_foreach_func(st_data_t key, st_data_t value, st_data_t argp, int error)
3088 {
3089 return ST_REPLACE;
3090 }
3091
3092 static int
3093 transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
3094 {
3095 VALUE new_value = rb_yield((VALUE)*value);
3096 *value = new_value;
3097 return ST_CONTINUE;
3098 }
3099
3100 /*
3101 * call-seq:
3102 * hsh.transform_values {|value| block } -> new_hash
3103 * hsh.transform_values -> an_enumerator
3104 *
3105 * Returns a new hash with the results of running the block once for
3106 * every value.
3107 * This method does not change the keys.
3108 *
3109 * h = { a: 1, b: 2, c: 3 }
3110 * h.transform_values {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 }
3111 * h.transform_values(&:to_s) #=> { a: "1", b: "2", c: "3" }
3112 * h.transform_values.with_index {|v, i| "#{v}.#{i}" }
3113 * #=> { a: "1.0", b: "2.1", c: "3.2" }
3114 *
3115 * If no block is given, an enumerator is returned instead.
3116 */
3117 static VALUE
3118 rb_hash_transform_values(VALUE hash)
3119 {
3120 VALUE result;
3121
3122 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3123 result = hash_dup(hash, rb_cHash, 0);
3124
3125 if (!RHASH_EMPTY_P(hash)) {
3126 rb_hash_stlike_foreach_with_replace(result, transform_values_foreach_func, transform_values_foreach_replace, 0);
3127 }
3128
3129 return result;
3130 }
3131
3132 /*
3133 * call-seq:
3134 * hsh.transform_values! {|value| block } -> hsh
3135 * hsh.transform_values! -> an_enumerator
3136 *
3137 * Invokes the given block once for each value in <i>hsh</i>, replacing it
3138 * with the new value returned by the block, and then returns <i>hsh</i>.
3139 * This method does not change the keys.
3140 *
3141 * h = { a: 1, b: 2, c: 3 }
3142 * h.transform_values! {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 }
3143 * h.transform_values!(&:to_s) #=> { a: "2", b: "5", c: "10" }
3144 * h.transform_values!.with_index {|v, i| "#{v}.#{i}" }
3145 * #=> { a: "2.0", b: "5.1", c: "10.2" }
3146 *
3147 * If no block is given, an enumerator is returned instead.
3148 */
3149 static VALUE
3150 rb_hash_transform_values_bang(VALUE hash)
3151 {
3152 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3153 rb_hash_modify_check(hash);
3154
3155 if (!RHASH_TABLE_EMPTY_P(hash)) {
3156 rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, 0);
3157 }
3158
3159 return hash;
3160 }
3161
3162 static int
3163 to_a_i(VALUE key, VALUE value, VALUE ary)
3164 {
3165 rb_ary_push(ary, rb_assoc_new(key, value));
3166 return ST_CONTINUE;
3167 }
3168
3169 /*
3170 * call-seq:
3171 * hsh.to_a -> array
3172 *
3173 * Converts <i>hsh</i> to a nested array of <code>[</code> <i>key,
3174 * value</i> <code>]</code> arrays.
3175 *
3176 * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
3177 * h.to_a #=> [["c", 300], ["a", 100], ["d", 400]]
3178 */
3179
3180 static VALUE
3181 rb_hash_to_a(VALUE hash)
3182 {
3183 VALUE ary;
3184
3185 ary = rb_ary_new_capa(RHASH_SIZE(hash));
3186 rb_hash_foreach(hash, to_a_i, ary);
3187
3188 return ary;
3189 }
3190
3191 static int
3192 inspect_i(VALUE key, VALUE value, VALUE str)
3193 {
3194 VALUE str2;
3195
3196 str2 = rb_inspect(key);
3197 if (RSTRING_LEN(str) > 1) {
3198 rb_str_buf_cat_ascii(str, ", ");
3199 }
3200 else {
3201 rb_enc_copy(str, str2);
3202 }
3203 rb_str_buf_append(str, str2);
3204 rb_str_buf_cat_ascii(str, "=>");
3205 str2 = rb_inspect(value);
3206 rb_str_buf_append(str, str2);
3207
3208 return ST_CONTINUE;
3209 }
3210
3211 static VALUE
3212 inspect_hash(VALUE hash, VALUE dummy, int recur)
3213 {
3214 VALUE str;
3215
3216 if (recur) return rb_usascii_str_new2("{...}");
3217 str = rb_str_buf_new2("{");
3218 rb_hash_foreach(hash, inspect_i, str);
3219 rb_str_buf_cat2(str, "}");
3220
3221 return str;
3222 }
3223
3224 /*
3225 * call-seq:
3226 * hsh.to_s -> string
3227 * hsh.inspect -> string
3228 *
3229 * Return the contents of this hash as a string.
3230 *
3231 * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
3232 * h.to_s #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}"
3233 */
3234
3235 static VALUE
3236 rb_hash_inspect(VALUE hash)
3237 {
3238 if (RHASH_EMPTY_P(hash))
3239 return rb_usascii_str_new2("{}");
3240 return rb_exec_recursive(inspect_hash, hash, 0);
3241 }
3242
3243 /*
3244 * call-seq:
3245 * hsh.to_hash => hsh
3246 *
3247 * Returns +self+.
3248 */
3249
3250 static VALUE
3251 rb_hash_to_hash(VALUE hash)
3252 {
3253 return hash;
3254 }
3255
3256 VALUE
3257 rb_hash_set_pair(VALUE hash, VALUE arg)
3258 {
3259 VALUE pair;
3260
3261 pair = rb_check_array_type(arg);
3262 if (NIL_P(pair)) {
3263 rb_raise(rb_eTypeError, "wrong element type %s (expected array)",
3264 rb_builtin_class_name(arg));
3265 }
3266 if (RARRAY_LEN(pair) != 2) {
3267 rb_raise(rb_eArgError, "element has wrong array length (expected 2, was %ld)",
3268 RARRAY_LEN(pair));
3269 }
3270 rb_hash_aset(hash, RARRAY_AREF(pair, 0), RARRAY_AREF(pair, 1));
3271 return hash;
3272 }
3273
3274 static int
3275 to_h_i(VALUE key, VALUE value, VALUE hash)
3276 {
3277 rb_hash_set_pair(hash, rb_yield_values(2, key, value));
3278 return ST_CONTINUE;
3279 }
3280
3281 static VALUE
3282 rb_hash_to_h_block(VALUE hash)
3283 {
3284 VALUE h = rb_hash_new_with_size(RHASH_SIZE(hash));
3285 rb_hash_foreach(hash, to_h_i, h);
3286 return h;
3287 }
3288
3289 /*
3290 * call-seq:
3291 * hsh.to_h -> hsh or new_hash
3292 * hsh.to_h {|key, value| block } -> new_hash
3293 *
3294 * Returns +self+. If called on a subclass of Hash, converts
3295 * the receiver to a Hash object.
3296 *
3297 * If a block is given, the results of the block on each pair of
3298 * the receiver will be used as pairs.
3299 */
3300
3301 static VALUE
3302 rb_hash_to_h(VALUE hash)
3303 {
3304 if (rb_block_given_p()) {
3305 return rb_hash_to_h_block(hash);
3306 }
3307 if (rb_obj_class(hash) != rb_cHash) {
3308 const VALUE flags = RBASIC(hash)->flags;
3309 hash = hash_dup(hash, rb_cHash, flags & RHASH_PROC_DEFAULT);
3310 }
3311 return hash;
3312 }
3313
3314 static int
3315 keys_i(VALUE key, VALUE value, VALUE ary)
3316 {
3317 rb_ary_push(ary, key);
3318 return ST_CONTINUE;
3319 }
3320
3321 /*
3322 * call-seq:
3323 * hsh.keys -> array
3324 *
3325 * Returns a new array populated with the keys from this hash. See also
3326 * Hash#values.
3327 *
3328 * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
3329 * h.keys #=> ["a", "b", "c", "d"]
3330 *
3331 */
3332
3333 MJIT_FUNC_EXPORTED VALUE
3334 rb_hash_keys(VALUE hash)
3335 {
3336 st_index_t size = RHASH_SIZE(hash);
3337 VALUE keys = rb_ary_new_capa(size);
3338
3339 if (size == 0) return keys;
3340
3341 if (ST_DATA_COMPATIBLE_P(VALUE)) {
3342 RARRAY_PTR_USE_TRANSIENT(keys, ptr, {
3343 if (RHASH_AR_TABLE_P(hash)) {
3344 size = ar_keys(hash, ptr, size);
3345 }
3346 else {
3347 st_table *table = RHASH_ST_TABLE(hash);
3348 size = st_keys(table, ptr, size);
3349 }
3350 });
3351 rb_gc_writebarrier_remember(keys);
3352 rb_ary_set_len(keys, size);
3353 }
3354 else {
3355 rb_hash_foreach(hash, keys_i, keys);
3356 }
3357
3358 return keys;
3359 }
3360
3361 static int
3362 values_i(VALUE key, VALUE value, VALUE ary)
3363 {
3364 rb_ary_push(ary, value);
3365 return ST_CONTINUE;
3366 }
3367
3368 /*
3369 * call-seq:
3370 * hsh.values -> array
3371 *
3372 * Returns a new array populated with the values from <i>hsh</i>. See
3373 * also Hash#keys.
3374 *
3375 * h = { "a" => 100, "b" => 200, "c" => 300 }
3376 * h.values #=> [100, 200, 300]
3377 *
3378 */
3379
3380 VALUE
3381 rb_hash_values(VALUE hash)
3382 {
3383 VALUE values;
3384 st_index_t size = RHASH_SIZE(hash);
3385
3386 values = rb_ary_new_capa(size);
3387 if (size == 0) return values;
3388
3389 if (ST_DATA_COMPATIBLE_P(VALUE)) {
3390 if (RHASH_AR_TABLE_P(hash)) {
3391 rb_gc_writebarrier_remember(values);
3392 RARRAY_PTR_USE_TRANSIENT(values, ptr, {
3393 size = ar_values(hash, ptr, size);
3394 });
3395 }
3396 else if (RHASH_ST_TABLE_P(hash)) {
3397 st_table *table = RHASH_ST_TABLE(hash);
3398 rb_gc_writebarrier_remember(values);
3399 RARRAY_PTR_USE_TRANSIENT(values, ptr, {
3400 size = st_values(table, ptr, size);
3401 });
3402 }
3403 rb_ary_set_len(values, size);
3404 }
3405 else {
3406 rb_hash_foreach(hash, values_i, values);
3407 }
3408
3409 return values;
3410 }
3411
3412 /*
3413 * call-seq:
3414 * hsh.has_key?(key) -> true or false
3415 * hsh.include?(key) -> true or false
3416 * hsh.key?(key) -> true or false
3417 * hsh.member?(key) -> true or false
3418 *
3419 * Returns <code>true</code> if the given key is present in <i>hsh</i>.
3420 *
3421 * h = { "a" => 100, "b" => 200 }
3422 * h.has_key?("a") #=> true
3423 * h.has_key?("z") #=> false
3424 *
3425 * Note that #include? and #member? do not test member
3426 * equality using <code>==</code> as do other Enumerables.
3427 *
3428 * See also Enumerable#include?
3429 */
3430
3431 MJIT_FUNC_EXPORTED VALUE
3432 rb_hash_has_key(VALUE hash, VALUE key)
3433 {
3434 if (hash_stlike_lookup(hash, key, NULL)) {
3435 return Qtrue;
3436 }
3437 else {
3438 return Qfalse;
3439 }
3440 }
3441
3442 static int
3443 rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
3444 {
3445 VALUE *data = (VALUE *)arg;
3446
3447 if (rb_equal(value, data[1])) {
3448 data[0] = Qtrue;
3449 return ST_STOP;
3450 }
3451 return ST_CONTINUE;
3452 }
3453
3454 /*
3455 * call-seq:
3456 * hsh.has_value?(value) -> true or false
3457 * hsh.value?(value) -> true or false
3458 *
3459 * Returns <code>true</code> if the given value is present for some key
3460 * in <i>hsh</i>.
3461 *
3462 * h = { "a" => 100, "b" => 200 }
3463 * h.value?(100) #=> true
3464 * h.value?(999) #=> false
3465 */
3466
3467 static VALUE
3468 rb_hash_has_value(VALUE hash, VALUE val)
3469 {
3470 VALUE data[2];
3471
3472 data[0] = Qfalse;
3473 data[1] = val;
3474 rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
3475 return data[0];
3476 }
3477
3478 struct equal_data {
3479 VALUE result;
3480 VALUE hash;
3481 int eql;
3482 };
3483
3484 static int
3485 eql_i(VALUE key, VALUE val1, VALUE arg)
3486 {
3487 struct equal_data *data = (struct equal_data *)arg;
3488 st_data_t val2;
3489
3490 if (!hash_stlike_lookup(data->hash, key, &val2)) {
3491 data->result = Qfalse;
3492 return ST_STOP;
3493 }
3494 else {
3495 if (!(data->eql ? rb_eql(val1, (VALUE)val2) : (int)rb_equal(val1, (VALUE)val2))) {
3496 data->result = Qfalse;
3497 return ST_STOP;
3498 }
3499 return ST_CONTINUE;
3500 }
3501 }
3502
3503 static VALUE
3504 recursive_eql(VALUE hash, VALUE dt, int recur)
3505 {
3506 struct equal_data *data;
3507
3508 if (recur) return Qtrue; /* Subtle! */
3509 data = (struct equal_data*)dt;
3510 data->result = Qtrue;
3511 rb_hash_foreach(hash, eql_i, dt);
3512
3513 return data->result;
3514 }
3515
3516 static VALUE
3517 hash_equal(VALUE hash1, VALUE hash2, int eql)
3518 {
3519 struct equal_data data;
3520
3521 if (hash1 == hash2) return Qtrue;
3522 if (!RB_TYPE_P(hash2, T_HASH)) {
3523 if (!rb_respond_to(hash2, idTo_hash)) {
3524 return Qfalse;
3525 }
3526 if (eql) {
3527 if (rb_eql(hash2, hash1)) {
3528 return Qtrue;
3529 }
3530 else {
3531 return Qfalse;
3532 }
3533 }
3534 else {
3535 return rb_equal(hash2, hash1);
3536 }
3537 }
3538 if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
3539 return Qfalse;
3540 if (!RHASH_TABLE_EMPTY_P(hash1) && !RHASH_TABLE_EMPTY_P(hash2)) {
3541 if (RHASH_TYPE(hash1) != RHASH_TYPE(hash2)) {
3542 return Qfalse;
3543 }
3544 else {
3545 data.hash = hash2;
3546 data.eql = eql;
3547 return rb_exec_recursive_paired(recursive_eql, hash1, hash2, (VALUE)&data);
3548 }
3549 }
3550
3551 #if 0
3552 if (!(rb_equal(RHASH_IFNONE(hash1), RHASH_IFNONE(hash2)) &&
3553 FL_TEST(hash1, RHASH_PROC_DEFAULT) == FL_TEST(hash2, RHASH_PROC_DEFAULT)))
3554 return Qfalse;
3555 #endif
3556 return Qtrue;
3557 }
3558
3559 /*
3560 * call-seq:
3561 * hsh == other_hash -> true or false
3562 *
3563 * Equality---Two hashes are equal if they each contain the same number
3564 * of keys and if each key-value pair is equal to (according to
3565 * Object#==) the corresponding elements in the other hash.
3566 *
3567 * h1 = { "a" => 1, "c" => 2 }
3568 * h2 = { 7 => 35, "c" => 2, "a" => 1 }
3569 * h3 = { "a" => 1, "c" => 2, 7 => 35 }
3570 * h4 = { "a" => 1, "d" => 2, "f" => 35 }
3571 * h1 == h2 #=> false
3572 * h2 == h3 #=> true
3573 * h3 == h4 #=> false
3574 *
3575 * The orders of each hashes are not compared.
3576 *
3577 * h1 = { "a" => 1, "c" => 2 }
3578 * h2 = { "c" => 2, "a" => 1 }
3579 * h1 == h2 #=> true
3580 *
3581 */
3582
3583 static VALUE
3584 rb_hash_equal(VALUE hash1, VALUE hash2)
3585 {
3586 return hash_equal(hash1, hash2, FALSE);
3587 }
3588
3589 /*
3590 * call-seq:
3591 * hash.eql?(other) -> true or false
3592 *
3593 * Returns <code>true</code> if <i>hash</i> and <i>other</i> are
3594 * both hashes with the same content.
3595 * The orders of each hashes are not compared.
3596 */
3597
3598 static VALUE
3599 rb_hash_eql(VALUE hash1, VALUE hash2)
3600 {
3601 return hash_equal(hash1, hash2, TRUE);
3602 }
3603
3604 static int
3605 hash_i(VALUE key, VALUE val, VALUE arg)
3606 {
3607 st_index_t *hval = (st_index_t *)arg;
3608 st_index_t hdata[2];
3609
3610 hdata[0] = rb_hash(key);
3611 hdata[1] = rb_hash(val);
3612 *hval ^= st_hash(hdata, sizeof(hdata), 0);
3613 return ST_CONTINUE;
3614 }
3615
3616 /*
3617 * call-seq:
3618 * hsh.hash -> integer
3619 *
3620 * Compute a hash-code for this hash. Two hashes with the same content
3621 * will have the same hash code (and will compare using <code>eql?</code>).
3622 *
3623 * See also Object#hash.
3624 */
3625
3626 static VALUE
3627 rb_hash_hash(VALUE hash)
3628 {
3629 st_index_t size = RHASH_SIZE(hash);
3630 st_index_t hval = rb_hash_start(size);
3631 hval = rb_hash_uint(hval, (st_index_t)rb_hash_hash);
3632 if (size) {
3633 rb_hash_foreach(hash, hash_i, (VALUE)&hval);
3634 }
3635 hval = rb_hash_end(hval);
3636 return ST2FIX(hval);
3637 }
3638
3639 static int
3640 rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
3641 {
3642 rb_hash_aset(hash, value, key);
3643 return ST_CONTINUE;
3644 }
3645
3646 /*
3647 * call-seq:
3648 * hsh.invert -> new_hash
3649 *
3650 * Returns a new hash created by using <i>hsh</i>'s values as keys, and
3651 * the keys as values.
3652 * If a key with the same value already exists in the <i>hsh</i>, then
3653 * the last one defined will be used, the earlier value(s) will be discarded.
3654 *
3655 * h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
3656 * h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
3657 *
3658 * If there is no key with the same value, Hash#invert is involutive.
3659 *
3660 * h = { a: 1, b: 3, c: 4 }
3661 * h.invert.invert == h #=> true
3662 *
3663 * The condition, no key with the same value, can be tested by comparing
3664 * the size of inverted hash.
3665 *
3666 * # no key with the same value
3667 * h = { a: 1, b: 3, c: 4 }
3668 * h.size == h.invert.size #=> true
3669 *
3670 * # two (or more) keys has the same value
3671 * h = { a: 1, b: 3, c: 1 }
3672 * h.size == h.invert.size #=> false
3673 *
3674 */
3675
3676 static VALUE
3677 rb_hash_invert(VALUE hash)
3678 {
3679 VALUE h = rb_hash_new_with_size(RHASH_SIZE(hash));
3680
3681 rb_hash_foreach(hash, rb_hash_invert_i, h);
3682 return h;
3683 }
3684
3685 static int
3686 rb_hash_update_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
3687 {
3688 if (existing) {
3689 arg->old_value = *value;
3690 arg->new_value = arg->arg;
3691 }
3692 else {
3693 arg->new_key = *key;
3694 arg->new_value = arg->arg;
3695 }
3696 *value = arg->arg;
3697 return ST_CONTINUE;
3698 }
3699
3700 NOINSERT_UPDATE_CALLBACK(rb_hash_update_callback)
3701
3702 static int
3703 rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
3704 {
3705 RHASH_UPDATE(hash, key, rb_hash_update_callback, value);
3706 return ST_CONTINUE;
3707 }
3708
3709 static int
3710 rb_hash_update_block_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
3711 {
3712 VALUE newvalue = (VALUE)arg->arg;
3713
3714 if (existing) {
3715 newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue);
3716 arg->old_value = *value;
3717 }
3718 else {
3719 arg->new_key = *key;
3720 }
3721 arg->new_value = newvalue;
3722 *value = newvalue;
3723 return ST_CONTINUE;
3724 }
3725
3726 NOINSERT_UPDATE_CALLBACK(rb_hash_update_block_callback)
3727
3728 static int
3729 rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
3730 {
3731 RHASH_UPDATE(hash, key, rb_hash_update_block_callback, value);
3732 return ST_CONTINUE;
3733 }
3734
3735 /*
3736 * call-seq:
3737 * hsh.merge!(other_hash1, other_hash2, ...) -> hsh
3738 * hsh.update(other_hash1, other_hash2, ...) -> hsh
3739 * hsh.merge!(other_hash1, other_hash2, ...) {|key, oldval, newval| block}
3740 * -> hsh
3741 * hsh.update(other_hash1, other_hash2, ...) {|key, oldval, newval| block}
3742 * -> hsh
3743 *
3744 * Adds the contents of the given hashes to the receiver.
3745 *
3746 * If no block is given, entries with duplicate keys are overwritten
3747 * with the values from each +other_hash+ successively,
3748 * otherwise the value for each duplicate key is determined by
3749 * calling the block with the key, its value in the receiver and
3750 * its value in each +other_hash+.
3751 *
3752 * h1 = { "a" => 100, "b" => 200 }
3753 * h1.merge! #=> {"a"=>100, "b"=>200}
3754 * h1 #=> {"a"=>100, "b"=>200}
3755 *
3756 * h1 = { "a" => 100, "b" => 200 }
3757 * h2 = { "b" => 246, "c" => 300 }
3758 * h1.merge!(h2) #=> {"a"=>100, "b"=>246, "c"=>300}
3759 * h1 #=> {"a"=>100, "b"=>246, "c"=>300}
3760 *
3761 * h1 = { "a" => 100, "b" => 200 }
3762 * h2 = { "b" => 246, "c" => 300 }
3763 * h3 = { "b" => 357, "d" => 400 }
3764 * h1.merge!(h2, h3)
3765 * #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
3766 * h1 #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
3767 *
3768 * h1 = { "a" => 100, "b" => 200 }
3769 * h2 = { "b" => 246, "c" => 300 }
3770 * h3 = { "b" => 357, "d" => 400 }
3771 * h1.merge!(h2, h3) {|key, v1, v2| v1 }
3772 * #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
3773 * h1 #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
3774 *
3775 * Hash#update is an alias for Hash#merge!.
3776 */
3777
3778 static VALUE
3779 rb_hash_update(int argc, VALUE *argv, VALUE self)
3780 {
3781 int i;
3782 bool block_given = rb_block_given_p();
3783
3784 rb_hash_modify(self);
3785 for (i = 0; i < argc; i++){
3786 VALUE hash = to_hash(argv[i]);
3787 if (block_given) {
3788 rb_hash_foreach(hash, rb_hash_update_block_i, self);
3789 }
3790 else {
3791 rb_hash_foreach(hash, rb_hash_update_i, self);
3792 }
3793 }
3794 return self;
3795 }
3796
3797 struct update_func_arg {
3798 VALUE hash;
3799 VALUE value;
3800 rb_hash_update_func *func;
3801 };
3802
3803 static int
3804 rb_hash_update_func_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
3805 {
3806 struct update_func_arg *uf_arg = (struct update_func_arg *)arg->arg;
3807 VALUE newvalue = uf_arg->value;
3808
3809 if (existing) {
3810 newvalue = (*uf_arg->func)((VALUE)*key, (VALUE)*value, newvalue);
3811 arg->old_value = *value;
3812 }
3813 else {
3814 arg->new_key = *key;
3815 }
3816 arg->new_value = newvalue;
3817 *value = newvalue;
3818 return ST_CONTINUE;
3819 }
3820
3821 NOINSERT_UPDATE_CALLBACK(rb_hash_update_func_callback)
3822
3823 static int
3824 rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0)
3825 {
3826 struct update_func_arg *arg = (struct update_func_arg *)arg0;
3827 VALUE hash = arg->hash;
3828
3829 arg->value = value;
3830 RHASH_UPDATE(hash, key, rb_hash_update_func_callback, (VALUE)arg);
3831 return ST_CONTINUE;
3832 }
3833
3834 VALUE
3835 rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
3836 {
3837 rb_hash_modify(hash1);
3838 hash2 = to_hash(hash2);
3839 if (func) {
3840 struct update_func_arg arg;
3841 arg.hash = hash1;
3842 arg.func = func;
3843 rb_hash_foreach(hash2, rb_hash_update_func_i, (VALUE)&arg);
3844 }
3845 else {
3846 rb_hash_foreach(hash2, rb_hash_update_i, hash1);
3847 }
3848 return hash1;
3849 }
3850
3851 /*
3852 * call-seq:
3853 * hsh.merge(other_hash1, other_hash2, ...) -> new_hash
3854 * hsh.merge(other_hash1, other_hash2, ...) {|key, oldval, newval| block}
3855 * -> new_hash
3856 *
3857 * Returns a new hash that combines the contents of the receiver and
3858 * the contents of the given hashes.
3859 *
3860 * If no block is given, entries with duplicate keys are overwritten
3861 * with the values from each +other_hash+ successively,
3862 * otherwise the value for each duplicate key is determined by
3863 * calling the block with the key, its value in the receiver and
3864 * its value in each +other_hash+.
3865 *
3866 * When called without any argument, returns a copy of the receiver.
3867 *
3868 * h1 = { "a" => 100, "b" => 200 }
3869 * h2 = { "b" => 246, "c" => 300 }
3870 * h3 = { "b" => 357, "d" => 400 }
3871 * h1.merge #=> {"a"=>100, "b"=>200}
3872 * h1.merge(h2) #=> {"a"=>100, "b"=>246, "c"=>300}
3873 * h1.merge(h2, h3) #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
3874 * h1.merge(h2) {|key, oldval, newval| newval - oldval}
3875 * #=> {"a"=>100, "b"=>46, "c"=>300}
3876 * h1.merge(h2, h3) {|key, oldval, newval| newval - oldval}
3877 * #=> {"a"=>100, "b"=>311, "c"=>300, "d"=>400}
3878 * h1 #=> {"a"=>100, "b"=>200}
3879 *
3880 */
3881
3882 static VALUE
3883 rb_hash_merge(int argc, VALUE *argv, VALUE self)
3884 {
3885 return rb_hash_update(argc, argv, rb_hash_dup(self));
3886 }
3887
3888 static int
3889 assoc_cmp(VALUE a, VALUE b)
3890 {
3891 return !RTEST(rb_equal(a, b));
3892 }
3893
3894 static VALUE
3895 lookup2_call(VALUE arg)
3896 {
3897 VALUE *args = (VALUE *)arg;
3898 return rb_hash_lookup2(args[0], args[1], Qundef);
3899 }
3900
3901 struct reset_hash_type_arg {
3902 VALUE hash;
3903 const struct st_hash_type *orighash;
3904 };
3905
3906 static VALUE
3907 reset_hash_type(VALUE arg)
3908 {
3909 struct reset_hash_type_arg *p = (struct reset_hash_type_arg *)arg;
3910 HASH_ASSERT(RHASH_ST_TABLE_P(p->hash));
3911 RHASH_ST_TABLE(p->hash)->type = p->orighash;
3912 return Qundef;
3913 }
3914
3915 static int
3916 assoc_i(VALUE key, VALUE val, VALUE arg)
3917 {
3918 VALUE *args = (VALUE *)arg;
3919
3920 if (RTEST(rb_equal(args[0], key))) {
3921 args[1] = rb_assoc_new(key, val);
3922 return ST_STOP;
3923 }
3924 return ST_CONTINUE;
3925 }
3926
3927 /*
3928 * call-seq:
3929 * hash.assoc(obj) -> an_array or nil
3930 *
3931 * Searches through the hash comparing _obj_ with the key using <code>==</code>.
3932 * Returns the key-value pair (two elements array) or +nil+
3933 * if no match is found. See Array#assoc.
3934 *
3935 * h = {"colors" => ["red", "blue", "green"],
3936 * "letters" => ["a", "b", "c" ]}
3937 * h.assoc("letters") #=> ["letters", ["a", "b", "c"]]
3938 * h.assoc("foo") #=> nil
3939 */
3940
3941 VALUE
3942 rb_hash_assoc(VALUE hash, VALUE key)
3943 {
3944 st_table *table;
3945 const struct st_hash_type *orighash;
3946 VALUE args[2];
3947
3948 if (RHASH_EMPTY_P(hash)) return Qnil;
3949
3950 ar_force_convert_table(hash, __FILE__, __LINE__);
3951 HASH_ASSERT(RHASH_ST_TABLE_P(hash));
3952 table = RHASH_ST_TABLE(hash);
3953 orighash = table->type;
3954
3955 if (orighash != &identhash) {
3956 VALUE value;
3957 struct reset_hash_type_arg ensure_arg;
3958 struct st_hash_type assochash;
3959
3960 assochash.compare = assoc_cmp;
3961 assochash.hash = orighash->hash;
3962 table->type = &assochash;
3963 args[0] = hash;
3964 args[1] = key;
3965 ensure_arg.hash = hash;
3966 ensure_arg.orighash = orighash;
3967 value = rb_ensure(lookup2_call, (VALUE)&args, reset_hash_type, (VALUE)&ensure_arg);
3968 if (value != Qundef) return rb_assoc_new(key, value);
3969 }
3970
3971 args[0] = key;
3972 args[1] = Qnil;
3973 rb_hash_foreach(hash, assoc_i, (VALUE)args);
3974 return args[1];
3975 }
3976
3977 static int
3978 rassoc_i(VALUE key, VALUE val, VALUE arg)
3979 {
3980 VALUE *args = (VALUE *)arg;
3981
3982 if (RTEST(rb_equal(args[0], val))) {
3983 args[1] = rb_assoc_new(key, val);
3984 return ST_STOP;
3985 }
3986 return ST_CONTINUE;
3987 }
3988
3989 /*
3990 * call-seq:
3991 * hash.rassoc(obj) -> an_array or nil
3992 *
3993 * Searches through the hash comparing _obj_ with the value using <code>==</code>.
3994 * Returns the first key-value pair (two-element array) that matches. See
3995 * also Array#rassoc.
3996 *
3997 * a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
3998 * a.rassoc("two") #=> [2, "two"]
3999 * a.rassoc("four") #=> nil
4000 */
4001
4002 VALUE
4003 rb_hash_rassoc(VALUE hash, VALUE obj)
4004 {
4005 VALUE args[2];
4006
4007 args[0] = obj;
4008 args[1] = Qnil;
4009 rb_hash_foreach(hash, rassoc_i, (VALUE)args);
4010 return args[1];
4011 }
4012
4013 static int
4014 flatten_i(VALUE key, VALUE val, VALUE ary)
4015 {
4016 VALUE pair[2];
4017
4018 pair[0] = key;
4019 pair[1] = val;
4020 rb_ary_cat(ary, pair, 2);
4021
4022 return ST_CONTINUE;
4023 }
4024
4025 /*
4026 * call-seq:
4027 * hash.flatten -> an_array
4028 * hash.flatten(level) -> an_array
4029 *
4030 * Returns a new array that is a one-dimensional flattening of this
4031 * hash. That is, for every key or value that is an array, extract
4032 * its elements into the new array. Unlike Array#flatten, this
4033 * method does not flatten recursively by default. The optional
4034 * <i>level</i> argument determines the level of recursion to flatten.
4035 *
4036 * a = {1=> "one", 2 => [2,"two"], 3 => "three"}
4037 * a.flatten # => [1, "one", 2, [2, "two"], 3, "three"]
4038 * a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
4039 */
4040
4041 static VALUE
4042 rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
4043 {
4044 VALUE ary;
4045
4046 rb_check_arity(argc, 0, 1);
4047
4048 if (argc) {
4049 int level = NUM2INT(argv[0]);
4050
4051 if (level == 0) return rb_hash_to_a(hash);
4052
4053 ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
4054 rb_hash_foreach(hash, flatten_i, ary);
4055 level--;
4056
4057 if (level > 0) {
4058 VALUE ary_flatten_level = INT2FIX(level);
4059 rb_funcallv(ary, id_flatten_bang, 1, &ary_flatten_level);
4060 }
4061 else if (level < 0) {
4062 /* flatten recursively */
4063 rb_funcallv(ary, id_flatten_bang, 0, 0);
4064 }
4065 }
4066 else {
4067 ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
4068 rb_hash_foreach(hash, flatten_i, ary);
4069 }
4070
4071 return ary;
4072 }
4073
4074 static int
4075 delete_if_nil(VALUE key, VALUE value, VALUE hash)
4076 {
4077 if (NIL_P(value)) {
4078 return ST_DELETE;
4079 }
4080 return ST_CONTINUE;
4081 }
4082
4083 static int
4084 set_if_not_nil(VALUE key, VALUE value, VALUE hash)
4085 {
4086 if (!NIL_P(value)) {
4087 rb_hash_aset(hash, key, value);
4088 }
4089 return ST_CONTINUE;
4090 }
4091
4092 /*
4093 * call-seq:
4094 * hsh.compact -> new_hash
4095 *
4096 * Returns a new hash with the nil values/key pairs removed
4097 *
4098 * h = { a: 1, b: false, c: nil }
4099 * h.compact #=> { a: 1, b: false }
4100 * h #=> { a: 1, b: false, c: nil }
4101 *
4102 */
4103
4104 static VALUE
4105 rb_hash_compact(VALUE hash)
4106 {
4107 VALUE result = rb_hash_new();
4108 if (!RHASH_EMPTY_P(hash)) {
4109 rb_hash_foreach(hash, set_if_not_nil, result);
4110 }
4111 return result;
4112 }
4113
4114 /*
4115 * call-seq:
4116 * hsh.compact! -> hsh or nil
4117 *
4118 * Removes all nil values from the hash.
4119 * Returns nil if no changes were made, otherwise returns the hash.
4120 *
4121 * h = { a: 1, b: false, c: nil }
4122 * h.compact! #=> { a: 1, b: false }
4123 *
4124 */
4125
4126 static VALUE
4127 rb_hash_compact_bang(VALUE hash)
4128 {
4129 st_index_t n;
4130 rb_hash_modify_check(hash);
4131 n = RHASH_SIZE(hash);
4132 if (n) {
4133 rb_hash_foreach(hash, delete_if_nil, hash);
4134 if (n != RHASH_SIZE(hash))
4135 return hash;
4136 }
4137 return Qnil;
4138 }
4139
4140 static st_table *rb_init_identtable_with_size(st_index_t size);
4141
4142 /*
4143 * call-seq:
4144 * hsh.compare_by_identity -> hsh
4145 *
4146 * Makes <i>hsh</i> compare its keys by their identity, i.e. it
4147 * will consider exact same objects as same keys.
4148 *
4149 * h1 = { "a" => 100, "b" => 200, :c => "c" }
4150 * h1["a"] #=> 100
4151 * h1.compare_by_identity
4152 * h1.compare_by_identity? #=> true
4153 * h1["a".dup] #=> nil # different objects.
4154 * h1[:c] #=> "c" # same symbols are all same.
4155 *
4156 */
4157
4158 static VALUE
4159 rb_hash_compare_by_id(VALUE hash)
4160 {
4161 VALUE tmp;
4162 st_table *identtable;
4163
4164 if (rb_hash_compare_by_id_p(hash)) return hash;
4165
4166 rb_hash_modify_check(hash);
4167 ar_force_convert_table(hash, __FILE__, __LINE__);
4168 HASH_ASSERT(RHASH_ST_TABLE_P(hash));
4169
4170 tmp = hash_alloc(0);
4171 identtable = rb_init_identtable_with_size(RHASH_SIZE(hash));
4172 RHASH_ST_TABLE_SET(tmp, identtable);
4173 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
4174 st_free_table(RHASH_ST_TABLE(hash));
4175 RHASH_ST_TABLE_SET(hash, identtable);
4176 RHASH_ST_CLEAR(tmp);
4177 rb_gc_force_recycle(tmp);
4178
4179 return hash;
4180 }
4181
4182 /*
4183 * call-seq:
4184 * hsh.compare_by_identity? -> true or false
4185 *
4186 * Returns <code>true</code> if <i>hsh</i> will compare its keys by
4187 * their identity. Also see Hash#compare_by_identity.
4188 *
4189 */
4190
4191 MJIT_FUNC_EXPORTED VALUE
4192 rb_hash_compare_by_id_p(VALUE hash)
4193 {
4194 if (RHASH_ST_TABLE_P(hash) && RHASH_ST_TABLE(hash)->type == &identhash) {
4195 return Qtrue;
4196 }
4197 else {
4198 return Qfalse;
4199 }
4200 }
4201
4202 VALUE
4203 rb_ident_hash_new(void)
4204 {
4205 VALUE hash = rb_hash_new();
4206 RHASH_ST_TABLE_SET(hash, st_init_table(&identhash));
4207 return hash;
4208 }
4209
4210 st_table *
4211 rb_init_identtable(void)
4212 {
4213 return st_init_table(&identhash);
4214 }
4215
4216 static st_table *
4217 rb_init_identtable_with_size(st_index_t size)
4218 {
4219 return st_init_table_with_size(&identhash, size);
4220 }
4221
4222 static int
4223 any_p_i(VALUE key, VALUE value, VALUE arg)
4224 {
4225 VALUE ret = rb_yield(rb_assoc_new(key, value));
4226 if (RTEST(ret)) {
4227 *(VALUE *)arg = Qtrue;
4228 return ST_STOP;
4229 }
4230 return ST_CONTINUE;
4231 }
4232
4233 static int
4234 any_p_i_fast(VALUE key, VALUE value, VALUE arg)
4235 {
4236 VALUE ret = rb_yield_values(2, key, value);
4237 if (RTEST(ret)) {
4238 *(VALUE *)arg = Qtrue;
4239 return ST_STOP;
4240 }
4241 return ST_CONTINUE;
4242 }
4243
4244 static int
4245 any_p_i_pattern(VALUE key, VALUE value, VALUE arg)
4246 {
4247 VALUE ret = rb_funcall(((VALUE *)arg)[1], idEqq, 1, rb_assoc_new(key, value));
4248 if (RTEST(ret)) {
4249 *(VALUE *)arg = Qtrue;
4250 return ST_STOP;
4251 }
4252 return ST_CONTINUE;
4253 }
4254
4255 /*
4256 * call-seq:
4257 * hsh.any? [{ |(key, value)| block }] -> true or false
4258 * hsh.any?(pattern) -> true or false
4259 *
4260 * See also Enumerable#any?
4261 */
4262
4263 static VALUE
4264 rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
4265 {
4266 VALUE args[2];
4267 args[0] = Qfalse;
4268
4269 rb_check_arity(argc, 0, 1);
4270 if (RHASH_EMPTY_P(hash)) return Qfalse;
4271 if (argc) {
4272 if (rb_block_given_p()) {
4273 rb_warn("given block not used");
4274 }
4275 args[1] = argv[0];
4276
4277 rb_hash_foreach(hash, any_p_i_pattern, (VALUE)args);
4278 }
4279 else {
4280 if (!rb_block_given_p()) {
4281 /* yields pairs, never false */
4282 return Qtrue;
4283 }
4284 if (rb_block_arity() > 1)
4285 rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
4286 else
4287 rb_hash_foreach(hash, any_p_i, (VALUE)args);
4288 }
4289 return args[0];
4290 }
4291
4292 /*
4293 * call-seq:
4294 * hsh.dig(key, ...) -> object
4295 *
4296 * Extracts the nested value specified by the sequence of <i>key</i>
4297 * objects by calling +dig+ at each step, returning +nil+ if any
4298 * intermediate step is +nil+.
4299 *
4300 * h = { foo: {bar: {baz: 1}}}
4301 *
4302 * h.dig(:foo, :bar, :baz) #=> 1
4303 * h.dig(:foo, :zot, :xyz) #=> nil
4304 *
4305 * g = { foo: [10, 11, 12] }
4306 * g.dig(:foo, 1) #=> 11
4307 * g.dig(:foo, 1, 0) #=> TypeError: Integer does not have #dig method
4308 * g.dig(:foo, :bar) #=> TypeError: no implicit conversion of Symbol into Integer
4309 */
4310
4311 static VALUE
4312 rb_hash_dig(int argc, VALUE *argv, VALUE self)
4313 {
4314 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
4315 self = rb_hash_aref(self, *argv);
4316 if (!--argc) return self;
4317 ++argv;
4318 return rb_obj_dig(argc, argv, self, Qnil);
4319 }
4320
4321 static int
4322 hash_le_i(VALUE key, VALUE value, VALUE arg)
4323 {
4324 VALUE *args = (VALUE *)arg;
4325 VALUE v = rb_hash_lookup2(args[0], key, Qundef);
4326 if (v != Qundef && rb_equal(value, v)) return ST_CONTINUE;
4327 args[1] = Qfalse;
4328 return ST_STOP;
4329 }
4330
4331 static VALUE
4332 hash_le(VALUE hash1, VALUE hash2)
4333 {
4334 VALUE args[2];
4335 args[0] = hash2;
4336 args[1] = Qtrue;
4337 rb_hash_foreach(hash1, hash_le_i, (VALUE)args);
4338 return args[1];
4339 }
4340
4341 /*
4342 * call-seq:
4343 * hash <= other -> true or false
4344 *
4345 * Returns <code>true</code> if <i>hash</i> is subset of
4346 * <i>other</i> or equals to <i>other</i>.
4347 *
4348 * h1 = {a:1, b:2}
4349 * h2 = {a:1, b:2, c:3}
4350 * h1 <= h2 #=> true
4351 * h2 <= h1 #=> false
4352 * h1 <= h1 #=> true
4353 */
4354 static VALUE
4355 rb_hash_le(VALUE hash, VALUE other)
4356 {
4357 other = to_hash(other);
4358 if (RHASH_SIZE(hash) > RHASH_SIZE(other)) return Qfalse;
4359 return hash_le(hash, other);
4360 }
4361
4362 /*
4363 * call-seq:
4364 * hash < other -> true or false
4365 *
4366 * Returns <code>true</code> if <i>hash</i> is subset of
4367 * <i>other</i>.
4368 *
4369 * h1 = {a:1, b:2}
4370 * h2 = {a:1, b:2, c:3}
4371 * h1 < h2 #=> true
4372 * h2 < h1 #=> false
4373 * h1 < h1 #=> false
4374 */
4375 static VALUE
4376 rb_hash_lt(VALUE hash, VALUE other)
4377 {
4378 other = to_hash(other);
4379 if (RHASH_SIZE(hash) >= RHASH_SIZE(other)) return Qfalse;
4380 return hash_le(hash, other);
4381 }
4382
4383 /*
4384 * call-seq:
4385 * hash >= other -> true or false
4386 *
4387 * Returns <code>true</code> if <i>other</i> is subset of
4388 * <i>hash</i> or equals to <i>hash</i>.
4389 *
4390 * h1 = {a:1, b:2}
4391 * h2 = {a:1, b:2, c:3}
4392 * h1 >= h2 #=> false
4393 * h2 >= h1 #=> true
4394 * h1 >= h1 #=> true
4395 */
4396 static VALUE
4397 rb_hash_ge(VALUE hash, VALUE other)
4398 {
4399 other = to_hash(other);
4400 if (RHASH_SIZE(hash) < RHASH_SIZE(other)) return Qfalse;
4401 return hash_le(other, hash);
4402 }
4403
4404 /*
4405 * call-seq:
4406 * hash > other -> true or false
4407 *
4408 * Returns <code>true</code> if <i>other</i> is subset of
4409 * <i>hash</i>.
4410 *
4411 * h1 = {a:1, b:2}
4412 * h2 = {a:1, b:2, c:3}
4413 * h1 > h2 #=> false
4414 * h2 > h1 #=> true
4415 * h1 > h1 #=> false
4416 */
4417 static VALUE
4418 rb_hash_gt(VALUE hash, VALUE other)
4419 {
4420 other = to_hash(other);
4421 if (RHASH_SIZE(hash) <= RHASH_SIZE(other)) return Qfalse;
4422 return hash_le(other, hash);
4423 }
4424
4425 static VALUE
4426 hash_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(key, hash))
4427 {
4428 rb_check_arity(argc, 1, 1);
4429 return rb_hash_aref(hash, *argv);
4430 }
4431
4432 /*
4433 * call-seq:
4434 * hash.to_proc -> proc
4435 *
4436 * Returns a Proc which maps keys to values.
4437 *
4438 * h = {a:1, b:2}
4439 * hp = h.to_proc
4440 * hp.call(:a) #=> 1
4441 * hp.call(:b) #=> 2
4442 * hp.call(:c) #=> nil
4443 * [:a, :b, :c].map(&h) #=> [1, 2, nil]
4444 */
4445 static VALUE
4446 rb_hash_to_proc(VALUE hash)
4447 {
4448 return rb_func_proc_new(hash_proc_call, hash);
4449 }
4450
4451 static VALUE
4452 rb_hash_deconstruct_keys(VALUE hash, VALUE keys)
4453 {
4454 return hash;
4455 }
4456
4457 static int
4458 add_new_i(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
4459 {
4460 VALUE *args = (VALUE *)arg;
4461 if (existing) return ST_STOP;
4462 RB_OBJ_WRITTEN(args[0], Qundef, (VALUE)*key);
4463 RB_OBJ_WRITE(args[0], (VALUE *)val, args[1]);
4464 return ST_CONTINUE;
4465 }
4466
4467 /*
4468 * add +key+ to +val+ pair if +hash+ does not contain +key+.
4469 * returns non-zero if +key+ was contained.
4470 */
4471 int
4472 rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
4473 {
4474 st_table *tbl;
4475 int ret = 0;
4476 VALUE args[2];
4477 args[0] = hash;
4478 args[1] = val;
4479
4480 if (RHASH_AR_TABLE_P(hash)) {
4481 hash_ar_table(hash);
4482
4483 ret = ar_update(hash, (st_data_t)key, add_new_i, (st_data_t)args);
4484 if (ret != -1) {
4485 return ret;
4486 }
4487 ar_try_convert_table(hash);
4488 }
4489 tbl = RHASH_TBL_RAW(hash);
4490 return st_update(tbl, (st_data_t)key, add_new_i, (st_data_t)args);
4491
4492 }
4493
4494 static st_data_t
4495 key_stringify(VALUE key)
4496 {
4497 return (rb_obj_class(key) == rb_cString && !RB_OBJ_FROZEN(key)) ?
4498 rb_hash_key_str(key) : key;
4499 }
4500
4501 static void
4502 ar_bulk_insert(VALUE hash, long argc, const VALUE *argv)
4503 {
4504 long i;
4505 for (i = 0; i < argc; ) {
4506 st_data_t k = key_stringify(argv[i++]);
4507 st_data_t v = argv[i++];
4508 ar_insert(hash, k, v);
4509 RB_OBJ_WRITTEN(hash, Qundef, k);
4510 RB_OBJ_WRITTEN(hash, Qundef, v);
4511 }
4512 }
4513
4514 void
4515 rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
4516 {
4517 HASH_ASSERT(argc % 2 == 0);
4518 if (argc > 0) {
4519 st_index_t size = argc / 2;
4520
4521 if (RHASH_TABLE_NULL_P(hash)) {
4522 if (size <= RHASH_AR_TABLE_MAX_SIZE) {
4523 hash_ar_table(hash);
4524 }
4525 else {
4526 RHASH_TBL_RAW(hash);
4527 }
4528 }
4529
4530 if (RHASH_AR_TABLE_P(hash) &&
4531 (RHASH_AR_TABLE_SIZE(hash) + size <= RHASH_AR_TABLE_MAX_SIZE)) {
4532 ar_bulk_insert(hash, argc, argv);
4533 }
4534 else {
4535 rb_hash_bulk_insert_into_st_table(argc, argv, hash);
4536 }
4537 }
4538 }
4539
4540 static char **origenviron;
4541 #ifdef _WIN32
4542 #define GET_ENVIRON(e) ((e) = rb_w32_get_environ())
4543 #define FREE_ENVIRON(e) rb_w32_free_environ(e)
4544 static char **my_environ;
4545 #undef environ
4546 #define environ my_environ
4547 #undef getenv
4548 static char *(*w32_getenv)(const char*);
4549 static char *
4550 w32_getenv_unknown(const char *name)
4551 {
4552 char *(*func)(const char*);
4553 if (rb_locale_encindex() == rb_ascii8bit_encindex()) {
4554 func = rb_w32_getenv;
4555 }
4556 else {
4557 func = rb_w32_ugetenv;
4558 }
4559 /* atomic assignment in flat memory model */
4560 return (w32_getenv = func)(name);
4561 }
4562 static char *(*w32_getenv)(const char*) = w32_getenv_unknown;
4563 #define getenv(n) w32_getenv(n)
4564 #elif defined(__APPLE__)
4565 #undef environ
4566 #define environ (*_NSGetEnviron())
4567 #define GET_ENVIRON(e) (e)
4568 #define FREE_ENVIRON(e)
4569 #else
4570 extern char **environ;
4571 #define GET_ENVIRON(e) (e)
4572 #define FREE_ENVIRON(e)
4573 #endif
4574 #ifdef ENV_IGNORECASE
4575 #define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
4576 #define ENVNMATCH(s1, s2, n) (STRNCASECMP((s1), (s2), (n)) == 0)
4577 #else
4578 #define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
4579 #define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
4580 #endif
4581
4582 static VALUE
4583 env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
4584 {
4585 #ifdef _WIN32
4586 rb_encoding *internal = rb_default_internal_encoding();
4587 const int ecflags = ECONV_INVALID_REPLACE | ECONV_UNDEF_REPLACE;
4588 rb_encoding *utf8 = rb_utf8_encoding();
4589 VALUE str = rb_enc_str_new(NULL, 0, (internal ? internal : enc));
4590 if (NIL_P(rb_str_cat_conv_enc_opts(str, 0, ptr, len, utf8, ecflags, Qnil))) {
4591 rb_str_initialize(str, ptr, len, NULL);
4592 }
4593 #else
4594 VALUE str = rb_external_str_new_with_enc(ptr, len, enc);
4595 #endif
4596
4597 rb_obj_freeze(str);
4598 return str;
4599 }
4600
4601 static VALUE
4602 env_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
4603 {
4604 return env_enc_str_new(ptr, strlen(ptr), enc);
4605 }
4606
4607 static VALUE
4608 env_str_new(const char *ptr, long len)
4609 {
4610 return env_enc_str_new(ptr, len, rb_locale_encoding());
4611 }
4612
4613 static VALUE
4614 env_str_new2(const char *ptr)
4615 {
4616 if (!ptr) return Qnil;
4617 return env_str_new(ptr, strlen(ptr));
4618 }
4619
4620 static const char TZ_ENV[] = "TZ";
4621 extern bool ruby_tz_uptodate_p;
4622
4623 static rb_encoding *
4624 env_encoding_for(const char *name, const char *ptr)
4625 {
4626 if (ENVMATCH(name, PATH_ENV)) {
4627 return rb_filesystem_encoding();
4628 }
4629 else {
4630 return rb_locale_encoding();
4631 }
4632 }
4633
4634 static VALUE
4635 env_name_new(const char *name, const char *ptr)
4636 {
4637 return env_enc_str_new_cstr(ptr, env_encoding_for(name, ptr));
4638 }
4639
4640 static void *
4641 get_env_cstr(
4642 #ifdef _WIN32
4643 volatile VALUE *pstr,
4644 #else
4645 VALUE str,
4646 #endif
4647 const char *name)
4648 {
4649 #ifdef _WIN32
4650 VALUE str = *pstr;
4651 #endif
4652 char *var;
4653 rb_encoding *enc = rb_enc_get(str);
4654 if (!rb_enc_asciicompat(enc)) {
4655 rb_raise(rb_eArgError, "bad environment variable %s: ASCII incompatible encoding: %s",
4656 name, rb_enc_name(enc));
4657 }
4658 #ifdef _WIN32
4659 if (!rb_enc_str_asciionly_p(str)) {
4660 *pstr = str = rb_str_conv_enc(str, NULL, rb_utf8_encoding());
4661 }
4662 #endif
4663 var = RSTRING_PTR(str);
4664 if (memchr(var, '\0', RSTRING_LEN(str))) {
4665 rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name);
4666 }
4667 return rb_str_fill_terminator(str, 1); /* ASCII compatible */
4668 }
4669
4670 #ifdef _WIN32
4671 #define get_env_ptr(var, val) \
4672 (var = get_env_cstr(&(val), #var))
4673 #else
4674 #define get_env_ptr(var, val) \
4675 (var = get_env_cstr(val, #var))
4676 #endif
4677
4678 static inline const char *
4679 env_name(volatile VALUE *s)
4680 {
4681 const char *name;
4682 SafeStringValue(*s);
4683 get_env_ptr(name, *s);
4684 return name;
4685 }
4686
4687 #define env_name(s) env_name(&(s))
4688
4689 static VALUE env_aset(VALUE nm, VALUE val);
4690
4691 static VALUE
4692 env_delete(VALUE name)
4693 {
4694 const char *nam, *val;
4695
4696 nam = env_name(name);
4697 val = getenv(nam);
4698
4699 /*
4700 * ENV['TZ'] = nil has a special meaning.
4701 * TZ is no longer considered up-to-date and ruby call tzset() as needed.
4702 * It could be useful if sysadmin change /etc/localtime.
4703 * This hack might works only on Linux glibc.
4704 */
4705 if (ENVMATCH(nam, TZ_ENV)) {
4706 ruby_tz_uptodate_p = FALSE;
4707 }
4708
4709 if (val) {
4710 VALUE value = env_str_new2(val);
4711
4712 ruby_setenv(nam, 0);
4713 if (ENVMATCH(nam, PATH_ENV)) {
4714 RB_GC_GUARD(name);
4715 }
4716 return value;
4717 }
4718 return Qnil;
4719 }
4720
4721 /*
4722 * call-seq:
4723 * ENV.delete(name) -> value
4724 * ENV.delete(name) { |name| block } -> value
4725 *
4726 * Deletes the environment variable with +name+ if it exists and returns its value:
4727 * ENV['foo'] = '0'
4728 * ENV.delete('foo') # => '0'
4729 * Returns +nil+ if the named environment variable does not exist:
4730 * ENV.delete('foo') # => nil
4731 * If a block given and the environment variable does not exist,
4732 * yields +name+ to the block and returns +nil+:
4733 * ENV.delete('foo') { |name| puts name } # => nil
4734 * foo
4735 * If a block given and the environment variable exists,
4736 * deletes the environment variable and returns its value (ignoring the block):
4737 * ENV['foo'] = '0'
4738 * ENV.delete('foo') { |name| fail 'ignored' } # => "0"
4739 * Raises an exception if +name+ is invalid.
4740 * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
4741 */
4742 static VALUE
4743 env_delete_m(VALUE obj, VALUE name)
4744 {
4745 VALUE val;
4746
4747 val = env_delete(name);
4748 if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
4749 return val;
4750 }
4751
4752 /*
4753 * call-seq:
4754 * ENV[name] -> value
4755 *
4756 * Returns the value for the environment variable +name+ if it exists:
4757 * ENV['foo'] = '0'
4758 * ENV['foo'] # => "0"
4759 * Returns nil if the named variable does not exist:
4760 * ENV.clear
4761 * ENV['foo'] # => nil
4762 * Raises an exception if +name+ is invalid.
4763 * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
4764 */
4765 static VALUE
4766 rb_f_getenv(VALUE obj, VALUE name)
4767 {
4768 const char *nam, *env;
4769
4770 nam = env_name(name);
4771 env = getenv(nam);
4772 if (env) {
4773 return env_name_new(nam, env);
4774 }
4775 return Qnil;
4776 }
4777
4778 /*
4779 * call-seq:
4780 * ENV.fetch(name) -> value
4781 * ENV.fetch(name, default) -> value
4782 * ENV.fetch(name) { |name| block } -> value
4783 *
4784 * If +name+ is the name of an environment variable, returns its value:
4785 * ENV['foo'] = '0'
4786 * ENV.fetch('foo') # => '0'
4787 * Otherwise if a block is given (but not a default value),
4788 * yields +name+ to the block and returns the block's return value:
4789 * ENV.fetch('foo') { |name| :need_not_return_a_string } # => :need_not_return_a_string
4790 * Otherwise if a default value is given (but not a block), returns the default value:
4791 * ENV.delete('foo')
4792 * ENV.fetch('foo', :default_need_not_be_a_string) # => :default_need_not_be_a_string
4793 * If the environment variable does not exist and both default and block are given,
4794 * issues a warning ("warning: block supersedes default value argument"),
4795 * yields +name+ to the block, and returns the block's return value:
4796 * ENV.fetch('foo', :default) { |name| :block_return } # => :block_return
4797 * Raises KeyError if +name+ is valid, but not found,
4798 * and neither default value nor block is given:
4799 * ENV.fetch('foo') # Raises KeyError (key not found: "foo")
4800 * Raises an exception if +name+ is invalid.
4801 * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
4802 */
4803 static VALUE
4804 env_fetch(int argc, VALUE *argv, VALUE _)
4805 {
4806 VALUE key;
4807 long block_given;
4808 const char *nam, *env;
4809
4810 rb_check_arity(argc, 1, 2);
4811 key = argv[0];
4812 block_given = rb_block_given_p();
4813 if (block_given && argc == 2) {
4814 rb_warn("block supersedes default value argument");
4815 }
4816 nam = env_name(key);
4817 env = getenv(nam);
4818 if (!env) {
4819 if (block_given) return rb_yield(key);
4820 if (argc == 1) {
4821 rb_key_err_raise(rb_sprintf("key not found: \"%"PRIsVALUE"\"", key), envtbl, key);
4822 }
4823 return argv[1];
4824 }
4825 return env_name_new(nam, env);
4826 }
4827
4828 int
4829 rb_env_path_tainted(void)
4830 {
4831 rb_warning("rb_env_path_tainted is deprecated and will be removed in Ruby 3.2.");
4832 return 0;
4833 }
4834
4835 #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
4836 #elif defined __sun
4837 static int
4838 in_origenv(const char *str)
4839 {
4840 char **env;
4841 for (env = origenviron; *env; ++env) {
4842 if (*env == str) return 1;
4843 }
4844 return 0;
4845 }
4846 #else
4847 static int
4848 envix(const char *nam)
4849 {
4850 register int i, len = strlen(nam);
4851 char **env;
4852
4853 env = GET_ENVIRON(environ);
4854 for (i = 0; env[i]; i++) {
4855 if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
4856 break; /* memcmp must come first to avoid */
4857 } /* potential SEGV's */
4858 FREE_ENVIRON(environ);
4859 return i;
4860 }
4861 #endif
4862
4863 #if defined(_WIN32)
4864 static size_t
4865 getenvsize(const WCHAR* p)
4866 {
4867 const WCHAR* porg = p;
4868 while (*p++) p += lstrlenW(p) + 1;
4869 return p - porg + 1;
4870 }
4871
4872 static size_t
4873 getenvblocksize(void)
4874 {
4875 #ifdef _MAX_ENV
4876 return _MAX_ENV;
4877 #else
4878 return 32767;
4879 #endif
4880 }
4881
4882 static int
4883 check_envsize(size_t n)
4884 {
4885 if (_WIN32_WINNT < 0x0600 && rb_w32_osver() < 6) {
4886 /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx */
4887 /* Windows Server 2003 and Windows XP: The maximum size of the
4888 * environment block for the process is 32,767 characters. */
4889 WCHAR* p = GetEnvironmentStringsW();
4890 if (!p) return -1; /* never happen */
4891 n += getenvsize(p);
4892 FreeEnvironmentStringsW(p);
4893 if (n >= getenvblocksize()) {
4894 return -1;
4895 }
4896 }
4897 return 0;
4898 }
4899 #endif
4900
4901 #if defined(_WIN32) || \
4902 (defined(__sun) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV)))
4903
4904 NORETURN(static void invalid_envname(const char *name));
4905
4906 static void
4907 invalid_envname(const char *name)
4908 {
4909 rb_syserr_fail_str(EINVAL, rb_sprintf("ruby_setenv(%s)", name));
4910 }
4911
4912 static const char *
4913 check_envname(const char *name)
4914 {
4915 if (strchr(name, '=')) {
4916 invalid_envname(name);
4917 }
4918 return name;
4919 }
4920 #endif
4921
4922 void
4923 ruby_setenv(const char *name, const char *value)
4924 {
4925 #if defined(_WIN32)
4926 # if defined(MINGW_HAS_SECURE_API) || RUBY_MSVCRT_VERSION >= 80
4927 # define HAVE__WPUTENV_S 1
4928 # endif
4929 VALUE buf;
4930 WCHAR *wname;
4931 WCHAR *wvalue = 0;
4932 int failed = 0;
4933 int len;
4934 check_envname(name);
4935 len = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
4936 if (value) {
4937 int len2;
4938 len2 = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
4939 if (check_envsize((size_t)len + len2)) { /* len and len2 include '\0' */
4940 goto fail; /* 2 for '=' & '\0' */
4941 }
4942 wname = ALLOCV_N(WCHAR, buf, len + len2);
4943 wvalue = wname + len;
4944 MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
4945 MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, len2);
4946 #ifndef HAVE__WPUTENV_S
4947 wname[len-1] = L'=';
4948 #endif
4949 }
4950 else {
4951 wname = ALLOCV_N(WCHAR, buf, len + 1);
4952 MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
4953 wvalue = wname + len;
4954 *wvalue = L'\0';
4955 #ifndef HAVE__WPUTENV_S
4956 wname[len-1] = L'=';
4957 #endif
4958 }
4959 #ifndef HAVE__WPUTENV_S
4960 failed = _wputenv(wname);
4961 #else
4962 failed = _wputenv_s(wname, wvalue);
4963 #endif
4964 ALLOCV_END(buf);
4965 /* even if putenv() failed, clean up and try to delete the
4966 * variable from the system area. */
4967 if (!value || !*value) {
4968 /* putenv() doesn't handle empty value */
4969 if (!SetEnvironmentVariable(name, value) &&
4970 GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail;
4971 }
4972 if (failed) {
4973 fail:
4974 invalid_envname(name);
4975 }
4976 #elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
4977 if (value) {
4978 if (setenv(name, value, 1))
4979 rb_sys_fail_str(rb_sprintf("setenv(%s)", name));
4980 }
4981 else {
4982 #ifdef VOID_UNSETENV
4983 unsetenv(name);
4984 #else
4985 if (unsetenv(name))
4986 rb_sys_fail_str(rb_sprintf("unsetenv(%s)", name));
4987 #endif
4988 }
4989 #elif defined __sun
4990 /* Solaris 9 (or earlier) does not have setenv(3C) and unsetenv(3C). */
4991 /* The below code was tested on Solaris 10 by:
4992 % ./configure ac_cv_func_setenv=no ac_cv_func_unsetenv=no
4993 */
4994 size_t len, mem_size;
4995 char **env_ptr, *str, *mem_ptr;
4996
4997 check_envname(name);
4998 len = strlen(name);
4999 if (value) {
5000 mem_size = len + strlen(value) + 2;
5001 mem_ptr = malloc(mem_size);
5002 if (mem_ptr == NULL)
5003 rb_sys_fail_str(rb_sprintf("malloc("PRIuSIZE")", mem_size));
5004 snprintf(mem_ptr, mem_size, "%s=%s", name, value);
5005 }
5006 for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) {
5007 if (!strncmp(str, name, len) && str[len] == '=') {
5008 if (!in_origenv(str)) free(str);
5009 while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
5010 break;
5011 }
5012 }
5013 if (value) {
5014 if (putenv(mem_ptr)) {
5015 free(mem_ptr);
5016 rb_sys_fail_str(rb_sprintf("putenv(%s)", name));
5017 }
5018 }
5019 #else /* WIN32 */
5020 size_t len;
5021 int i;
5022
5023 i=envix(name); /* where does it go? */
5024
5025 if (environ == origenviron) { /* need we copy environment? */
5026 int j;
5027 int max;
5028 char **tmpenv;
5029
5030 for (max = i; environ[max]; max++) ;
5031 tmpenv = ALLOC_N(char*, max+2);
5032 for (j=0; j<max; j++) /* copy environment */
5033 tmpenv[j] = ruby_strdup(environ[j]);
5034 tmpenv[max] = 0;
5035 environ = tmpenv; /* tell exec where it is now */
5036 }
5037 if (environ[i]) {
5038 char **envp = origenviron;
5039 while (*envp && *envp != environ[i]) envp++;
5040 if (!*envp)
5041 xfree(environ[i]);
5042 if (!value) {
5043 while (environ[i]) {
5044 environ[i] = environ[i+1];
5045 i++;
5046 }
5047 return;
5048 }
5049 }
5050 else { /* does not exist yet */
5051 if (!value) return;
5052 REALLOC_N(environ, char*, i+2); /* just expand it a bit */
5053 environ[i+1] = 0; /* make sure it's null terminated */
5054 }
5055 len = strlen(name) + strlen(value) + 2;
5056 environ[i] = ALLOC_N(char, len);
5057 snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */
5058 #endif /* WIN32 */
5059 }
5060
5061 void
5062 ruby_unsetenv(const char *name)
5063 {
5064 ruby_setenv(name, 0);
5065 }
5066
5067 /*
5068 * call-seq:
5069 * ENV[name] = value -> value
5070 * ENV.store(name, value) -> value
5071 *
5072 * ENV.store is an alias for ENV.[]=.
5073 *
5074 * Creates, updates, or deletes the named environment variable, returning the value.
5075 * Both +name+ and +value+ may be instances of String.
5076 * See {Valid Names and Values}[#class-ENV-label-Valid+Names+and+Values].
5077 *
5078 * - If the named environment variable does not exist:
5079 * - If +value+ is +nil+, does nothing.
5080 * ENV.clear
5081 * ENV['foo'] = nil # => nil
5082 * ENV.include?('foo') # => false
5083 * ENV.store('bar', nil) # => nil
5084 * ENV.include?('bar') # => false
5085 * - If +value+ is not +nil+, creates the environment variable with +name+ and +value+:
5086 * # Create 'foo' using ENV.[]=.
5087 * ENV['foo'] = '0' # => '0'
5088 * ENV['foo'] # => '0'
5089 * # Create 'bar' using ENV.store.
5090 * ENV.store('bar', '1') # => '1'
5091 * ENV['bar'] # => '1'
5092 * - If the named environment variable exists:
5093 * - If +value+ is not +nil+, updates the environment variable with value +value+:
5094 * # Update 'foo' using ENV.[]=.
5095 * ENV['foo'] = '2' # => '2'
5096 * ENV['foo'] # => '2'
5097 * # Update 'bar' using ENV.store.
5098 * ENV.store('bar', '3') # => '3'
5099 * ENV['bar'] # => '3'
5100 * - If +value+ is +nil+, deletes the environment variable:
5101 * # Delete 'foo' using ENV.[]=.
5102 * ENV['foo'] = nil # => nil
5103 * ENV.include?('foo') # => false
5104 * # Delete 'bar' using ENV.store.
5105 * ENV.store('bar', nil) # => nil
5106 * ENV.include?('bar') # => false
5107 *
5108 * Raises an exception if +name+ or +value+ is invalid.
5109 * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values].
5110 */
5111 static VALUE
5112 env_aset_m(VALUE obj, VALUE nm, VALUE val)
5113 {
5114 return env_aset(nm, val);
5115 }
5116
5117 static VALUE
5118 env_aset(VALUE nm, VALUE val)
5119 {
5120 char *name, *value;
5121
5122 if (NIL_P(val)) {
5123 env_delete(nm);
5124 return Qnil;
5125 }
5126 SafeStringValue(nm);
5127 SafeStringValue(val);
5128 /* nm can be modified in `val.to_str`, don't get `name` before
5129 * check for `val` */
5130 get_env_ptr(name, nm);
5131 get_env_ptr(value, val);
5132
5133 ruby_setenv(name, value);
5134 if (ENVMATCH(name, PATH_ENV)) {
5135 RB_GC_GUARD(nm);
5136 }
5137 else if (ENVMATCH(name, TZ_ENV)) {
5138 ruby_tz_uptodate_p = FALSE;
5139 }
5140 return val;
5141 }
5142
5143 static VALUE
5144 env_keys(void)
5145 {
5146 char **env;
5147 VALUE ary;
5148
5149 ary = rb_ary_new();
5150 env = GET_ENVIRON(environ);
5151 while (*env) {
5152 char *s = strchr(*env, '=');
5153 if (s) {
5154 rb_ary_push(ary, env_str_new(*env, s-*env));
5155 }
5156 env++;
5157 }
5158 FREE_ENVIRON(environ);
5159 return ary;
5160 }
5161
5162 /*
5163 * call-seq:
5164 * ENV.keys -> Array
5165 *
5166 * Returns all variable names in an Array:
5167 * ENV.replace('foo' => '0', 'bar' => '1')
5168 * ENV.keys # => ['bar', 'foo']
5169 * The order of the names is OS-dependent.
5170 * See {About Ordering}[#class-ENV-label-About+Ordering].
5171 *
5172 * Returns the empty Array if ENV is empty:
5173 * ENV.clear
5174 * ENV.keys # => []
5175 */
5176
5177 static VALUE
5178 env_f_keys(VALUE _)
5179 {
5180 return env_keys();
5181 }
5182
5183 static VALUE
5184 rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
5185 {
5186 char **env;
5187 long cnt = 0;
5188
5189 env = GET_ENVIRON(environ);
5190 for (; *env ; ++env) {
5191 if (strchr(*env, '=')) {
5192 cnt++;
5193 }
5194 }
5195 FREE_ENVIRON(environ);
5196 return LONG2FIX(cnt);
5197 }
5198
5199 /*
5200 * call-seq:
5201 * ENV.each_key { |name| block } -> ENV
5202 * ENV.each_key -> Enumerator
5203 *
5204 * Yields each environment variable name:
5205 * ENV.replace('foo' => '0', 'bar' => '1') # => ENV
5206 * names = []
5207 * ENV.each_key { |name| names.push(name) } # => ENV
5208 * names # => ["bar", "foo"]
5209 *
5210 * Returns an Enumerator if no block given:
5211 * e = ENV.each_key # => #<Enumerator: {"bar"=>"1", "foo"=>"0"}:each_key>
5212 * names = []
5213 * e.each { |name| names.push(name) } # => ENV
5214 * names # => ["bar", "foo"]
5215 */
5216 static VALUE
5217 env_each_key(VALUE ehash)
5218 {
5219 VALUE keys;
5220 long i;
5221
5222 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5223 keys = env_keys();
5224 for (i=0; i<RARRAY_LEN(keys); i++) {
5225 rb_yield(RARRAY_AREF(keys, i));
5226 }
5227 return ehash;
5228 }
5229
5230 static VALUE
5231 env_values(void)
5232 {
5233 VALUE ary;
5234 char **env;
5235
5236 ary = rb_ary_new();
5237 env = GET_ENVIRON(environ);
5238 while (*env) {
5239 char *s = strchr(*env, '=');
5240 if (s) {
5241 rb_ary_push(ary, env_str_new2(s+1));
5242 }
5243 env++;
5244 }
5245 FREE_ENVIRON(environ);
5246 return ary;
5247 }
5248
5249 /*
5250 * call-seq:
5251 * ENV.values -> Array
5252 *
5253 * Returns all environment variable values in an Array:
5254 * ENV.replace('foo' => '0', 'bar' => '1')
5255 * ENV.values # => ['1', '0']
5256 * The order of the values is OS-dependent.
5257 * See {About Ordering}[#class-ENV-label-About+Ordering].
5258 *
5259 * Returns the empty Array if ENV is empty:
5260 * ENV.clear
5261 * ENV.values # => []
5262 */
5263 static VALUE
5264 env_f_values(VALUE _)
5265 {
5266 return env_values();
5267 }
5268
5269 /*
5270 * call-seq:
5271 * ENV.each_value { |value| block } -> ENV
5272 * ENV.each_value -> Enumerator
5273 *
5274 * Yields each environment variable value:
5275 * ENV.replace('foo' => '0', 'bar' => '1') # => ENV
5276 * values = []
5277 * ENV.each_value { |value| values.push(value) } # => ENV
5278 * values # => ["1", "0"]
5279 *
5280 * Returns an Enumerator if no block given:
5281 * e = ENV.each_value # => #<Enumerator: {"bar"=>"1", "foo"=>"0"}:each_value>
5282 * values = []
5283 * e.each { |value| values.push(value) } # => ENV
5284 * values # => ["1", "0"]
5285 */
5286 static VALUE
5287 env_each_value(VALUE ehash)
5288 {
5289 VALUE values;
5290 long i;
5291
5292 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5293 values = env_values();
5294 for (i=0; i<RARRAY_LEN(values); i++) {
5295 rb_yield(RARRAY_AREF(values, i));
5296 }
5297 return ehash;
5298 }
5299
5300 /*
5301 * call-seq:
5302 * ENV.each { |name, value| block } -> ENV
5303 * ENV.each -> Enumerator
5304 * ENV.each_pair { |name, value| block } -> ENV
5305 * ENV.each_pair -> Enumerator
5306 *
5307 * Yields each environment variable name and its value as a 2-element Array:
5308 * h = {}
5309 * ENV.each_pair { |name, value| h[name] = value } # => ENV
5310 * h # => {"bar"=>"1", "foo"=>"0"}
5311 *
5312 * Returns an Enumerator if no block given:
5313 * h = {}
5314 * e = ENV.each_pair # => #<Enumerator: {"bar"=>"1", "foo"=>"0"}:each_pair>
5315 * e.each { |name, value| h[name] = value } # => ENV
5316 * h # => {"bar"=>"1", "foo"=>"0"}
5317 */
5318 static VALUE
5319 env_each_pair(VALUE ehash)
5320 {
5321 char **env;
5322 VALUE ary;
5323 long i;
5324
5325 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5326
5327 ary = rb_ary_new();
5328 env = GET_ENVIRON(environ);
5329 while (*env) {
5330 char *s = strchr(*env, '=');
5331 if (s) {
5332 rb_ary_push(ary, env_str_new(*env, s-*env));
5333 rb_ary_push(ary, env_str_new2(s+1));
5334 }
5335 env++;
5336 }
5337 FREE_ENVIRON(environ);
5338
5339 if (rb_block_arity() > 1) {
5340 for (i=0; i<RARRAY_LEN(ary); i+=2) {
5341 rb_yield_values(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1));
5342 }
5343 }
5344 else {
5345 for (i=0; i<RARRAY_LEN(ary); i+=2) {
5346 rb_yield(rb_assoc_new(RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1)));
5347 }
5348 }
5349 return ehash;
5350 }
5351
5352 /*
5353 * call-seq:
5354 * ENV.reject! { |name, value| block } -> ENV or nil
5355 * ENV.reject! -> Enumerator
5356 *
5357 * Similar to ENV.delete_if, but returns +nil+ if no changes were made.
5358 *
5359 * Deletes each environment variable for which the block returns a truthy value,
5360 * returning ENV (if any deletions) or +nil+ (if not):
5361 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5362 * ENV.reject! { |name, value| name.start_with?('b') } # => ENV
5363 * ENV # => {"foo"=>"0"}
5364 * ENV.reject! { |name, value| name.start_with?('b') } # => nil
5365 *
5366 * Returns an Enumerator if no block given:
5367 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5368 * e = ENV.reject! # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:reject!>
5369 * e.each { |name, value| name.start_with?('b') } # => ENV
5370 * ENV # => {"foo"=>"0"}
5371 * e.each { |name, value| name.start_with?('b') } # => nil
5372 */
5373 static VALUE
5374 env_reject_bang(VALUE ehash)
5375 {
5376 VALUE keys;
5377 long i;
5378 int del = 0;
5379
5380 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5381 keys = env_keys();
5382 RBASIC_CLEAR_CLASS(keys);
5383 for (i=0; i<RARRAY_LEN(keys); i++) {
5384 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
5385 if (!NIL_P(val)) {
5386 if (RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
5387 env_delete(RARRAY_AREF(keys, i));
5388 del++;
5389 }
5390 }
5391 }
5392 RB_GC_GUARD(keys);
5393 if (del == 0) return Qnil;
5394 return envtbl;
5395 }
5396
5397 /*
5398 * call-seq:
5399 * ENV.delete_if { |name, value| block } -> ENV
5400 * ENV.delete_if -> Enumerator
5401 *
5402 * Deletes every environment variable for which the block evaluates to +true+.
5403 *
5404 * If no block is given an enumerator is returned instead.
5405 */
5406 static VALUE
5407 env_delete_if(VALUE ehash)
5408 {
5409 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5410 env_reject_bang(ehash);
5411 return envtbl;
5412 }
5413
5414 /*
5415 * call-seq:
5416 * ENV.values_at(name, ...) -> Array
5417 *
5418 * Returns an array containing the environment variable values associated with
5419 * the given names. See also ENV.select.
5420 */
5421 static VALUE
5422 env_values_at(int argc, VALUE *argv, VALUE _)
5423 {
5424 VALUE result;
5425 long i;
5426
5427 result = rb_ary_new();
5428 for (i=0; i<argc; i++) {
5429 rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
5430 }
5431 return result;
5432 }
5433
5434 /*
5435 * call-seq:
5436 * ENV.select { |name, value| block } -> Hash
5437 * ENV.select -> Enumerator
5438 * ENV.filter { |name, value| block } -> Hash
5439 * ENV.filter -> Enumerator
5440 *
5441 * Returns a copy of the environment for entries where the block returns true.
5442 *
5443 * Returns an Enumerator if no block was given.
5444 *
5445 * ENV.filter is an alias for ENV.select.
5446 */
5447 static VALUE
5448 env_select(VALUE ehash)
5449 {
5450 VALUE result;
5451 VALUE keys;
5452 long i;
5453
5454 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5455 result = rb_hash_new();
5456 keys = env_keys();
5457 for (i = 0; i < RARRAY_LEN(keys); ++i) {
5458 VALUE key = RARRAY_AREF(keys, i);
5459 VALUE val = rb_f_getenv(Qnil, key);
5460 if (!NIL_P(val)) {
5461 if (RTEST(rb_yield_values(2, key, val))) {
5462 rb_hash_aset(result, key, val);
5463 }
5464 }
5465 }
5466 RB_GC_GUARD(keys);
5467
5468 return result;
5469 }
5470
5471 /*
5472 * call-seq:
5473 * ENV.select! { |name, value| block } -> ENV or nil
5474 * ENV.select! -> Enumerator
5475 * ENV.filter! { |name, value| block } -> ENV or nil
5476 * ENV.filter! -> Enumerator
5477 *
5478 * Equivalent to ENV.keep_if but returns +nil+ if no changes were made.
5479 *
5480 * ENV.filter! is an alias for ENV.select!.
5481 */
5482 static VALUE
5483 env_select_bang(VALUE ehash)
5484 {
5485 VALUE keys;
5486 long i;
5487 int del = 0;
5488
5489 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5490 keys = env_keys();
5491 RBASIC_CLEAR_CLASS(keys);
5492 for (i=0; i<RARRAY_LEN(keys); i++) {
5493 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
5494 if (!NIL_P(val)) {
5495 if (!RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
5496 env_delete(RARRAY_AREF(keys, i));
5497 del++;
5498 }
5499 }
5500 }
5501 RB_GC_GUARD(keys);
5502 if (del == 0) return Qnil;
5503 return envtbl;
5504 }
5505
5506 /*
5507 * call-seq:
5508 * ENV.keep_if { |name, value| block } -> ENV
5509 * ENV.keep_if -> Enumerator
5510 *
5511 * Deletes every environment variable where the block evaluates to +false+.
5512 *
5513 * Returns an enumerator if no block was given.
5514 */
5515 static VALUE
5516 env_keep_if(VALUE ehash)
5517 {
5518 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5519 env_select_bang(ehash);
5520 return envtbl;
5521 }
5522
5523 /*
5524 * call-seq:
5525 * ENV.slice(*keys) -> a_hash
5526 *
5527 * Returns a hash containing only the given keys from ENV and their values.
5528 *
5529 * ENV.slice("TERM","HOME") #=> {"TERM"=>"xterm-256color", "HOME"=>"/Users/rhc"}
5530 */
5531 static VALUE
5532 env_slice(int argc, VALUE *argv, VALUE _)
5533 {
5534 int i;
5535 VALUE key, value, result;
5536
5537 if (argc == 0) {
5538 return rb_hash_new();
5539 }
5540 result = rb_hash_new_with_size(argc);
5541
5542 for (i = 0; i < argc; i++) {
5543 key = argv[i];
5544 value = rb_f_getenv(Qnil, key);
5545 if (value != Qnil)
5546 rb_hash_aset(result, key, value);
5547 }
5548
5549 return result;
5550 }
5551
5552 VALUE
5553 rb_env_clear(void)
5554 {
5555 VALUE keys;
5556 long i;
5557
5558 keys = env_keys();
5559 for (i=0; i<RARRAY_LEN(keys); i++) {
5560 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
5561 if (!NIL_P(val)) {
5562 env_delete(RARRAY_AREF(keys, i));
5563 }
5564 }
5565 RB_GC_GUARD(keys);
5566 return envtbl;
5567 }
5568
5569 /*
5570 * call-seq:
5571 * ENV.clear -> ENV
5572 *
5573 * Removes every environment variable; returns ENV:
5574 * ENV.replace('foo' => '0', 'bar' => '1')
5575 * ENV.size # => 2
5576 * ENV.clear # => ENV
5577 * ENV.size # => 0
5578 */
5579 static VALUE
5580 env_clear(VALUE _)
5581 {
5582 return rb_env_clear();
5583 }
5584
5585 /*
5586 * call-seq:
5587 * ENV.to_s -> "ENV"
5588 *
5589 * Returns "ENV"
5590 */
5591 static VALUE
5592 env_to_s(VALUE _)
5593 {
5594 return rb_usascii_str_new2("ENV");
5595 }
5596
5597 /*
5598 * call-seq:
5599 * ENV.inspect -> string
5600 *
5601 * Returns the contents of the environment as a String.
5602 */
5603 static VALUE
5604 env_inspect(VALUE _)
5605 {
5606 char **env;
5607 VALUE str, i;
5608
5609 str = rb_str_buf_new2("{");
5610 env = GET_ENVIRON(environ);
5611 while (*env) {
5612 char *s = strchr(*env, '=');
5613
5614 if (env != environ) {
5615 rb_str_buf_cat2(str, ", ");
5616 }
5617 if (s) {
5618 rb_str_buf_cat2(str, "\"");
5619 rb_str_buf_cat(str, *env, s-*env);
5620 rb_str_buf_cat2(str, "\"=>");
5621 i = rb_inspect(rb_str_new2(s+1));
5622 rb_str_buf_append(str, i);
5623 }
5624 env++;
5625 }
5626 FREE_ENVIRON(environ);
5627 rb_str_buf_cat2(str, "}");
5628
5629 return str;
5630 }
5631
5632 /*
5633 * call-seq:
5634 * ENV.to_a -> Array
5635 *
5636 * Converts the environment variables into an array of names and value arrays.
5637 *
5638 * ENV.to_a # => [["TERM", "xterm-color"], ["SHELL", "/bin/bash"], ...]
5639 *
5640 */
5641 static VALUE
5642 env_to_a(VALUE _)
5643 {
5644 char **env;
5645 VALUE ary;
5646
5647 ary = rb_ary_new();
5648 env = GET_ENVIRON(environ);
5649 while (*env) {
5650 char *s = strchr(*env, '=');
5651 if (s) {
5652 rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
5653 env_str_new2(s+1)));
5654 }
5655 env++;
5656 }
5657 FREE_ENVIRON(environ);
5658 return ary;
5659 }
5660
5661 /*
5662 * call-seq:
5663 * ENV.rehash
5664 *
5665 * Re-hashing the environment variables does nothing. It is provided for
5666 * compatibility with Hash.
5667 */
5668 static VALUE
5669 env_none(VALUE _)
5670 {
5671 return Qnil;
5672 }
5673
5674 /*
5675 * call-seq:
5676 * ENV.length
5677 * ENV.size
5678 *
5679 * Returns the number of environment variables.
5680 */
5681 static VALUE
5682 env_size(VALUE _)
5683 {
5684 int i;
5685 char **env;
5686
5687 env = GET_ENVIRON(environ);
5688 for (i=0; env[i]; i++)
5689 ;
5690 FREE_ENVIRON(environ);
5691 return INT2FIX(i);
5692 }
5693
5694 /*
5695 * call-seq:
5696 * ENV.empty? -> true or false
5697 *
5698 * Returns true when there are no environment variables
5699 */
5700 static VALUE
5701 env_empty_p(VALUE _)
5702 {
5703 char **env;
5704
5705 env = GET_ENVIRON(environ);
5706 if (env[0] == 0) {
5707 FREE_ENVIRON(environ);
5708 return Qtrue;
5709 }
5710 FREE_ENVIRON(environ);
5711 return Qfalse;
5712 }
5713
5714 /*
5715 * call-seq:
5716 * ENV.include?(name) -> true or false
5717 * ENV.has_key?(name) -> true or false
5718 * ENV.member?(name) -> true or false
5719 * ENV.key?(name) -> true or false
5720 *
5721 * ENV.has_key?, ENV.member?, and ENV.key? are aliases for ENV.include?.
5722 *
5723 * Returns +true+ if there is an environment variable with the given +name+:
5724 * ENV.replace('foo' => '0', 'bar' => '1')
5725 * ENV.include?('foo') # => true
5726 * Returns +false+ if +name+ is a valid String and there is no such environment variable:
5727 * ENV.include?('baz') # => false
5728 * Returns +false+ if +name+ is the empty String or is a String containing character <code>'='</code>:
5729 * ENV.include?('') # => false
5730 * ENV.include?('=') # => false
5731 * Raises an exception if +name+ is a String containing the NUL character <code>"\0"</code>:
5732 * ENV.include?("\0") # Raises ArgumentError (bad environment variable name: contains null byte)
5733 * Raises an exception if +name+ has an encoding that is not ASCII-compatible:
5734 * ENV.include?("\xa1\xa1".force_encoding(Encoding::UTF_16LE))
5735 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: UTF-16LE)
5736 * Raises an exception if +name+ is not a String:
5737 * ENV.include?(Object.new) # TypeError (no implicit conversion of Object into String)
5738 */
5739 static VALUE
5740 env_has_key(VALUE env, VALUE key)
5741 {
5742 const char *s;
5743
5744 s = env_name(key);
5745 if (getenv(s)) return Qtrue;
5746 return Qfalse;
5747 }
5748
5749 /*
5750 * call-seq:
5751 * ENV.assoc(name) -> Array or nil
5752 *
5753 * Returns a 2-element Array containing the name and value of the environment variable
5754 * for +name+ if it exists:
5755 * ENV.replace('foo' => '0', 'bar' => '1')
5756 * ENV.assoc('foo') # => ['foo' '0']
5757 * Returns +nil+ if +name+ is a valid String and there is no such environment variable:
5758 * ENV.assoc('baz') # => false
5759 * Returns +nil+ if +name+ is the empty String or is a String containing character <code>'='</code>:
5760 * ENV.assoc('') # => false
5761 * ENV.assoc('=') # => false
5762 * Raises an exception if +name+ is a String containing the NUL character <code>"\0"</code>:
5763 * ENV.assoc("\0") # Raises ArgumentError (bad environment variable name: contains null byte)
5764 * Raises an exception if +name+ has an encoding that is not ASCII-compatible:
5765 * ENV.assoc("\xa1\xa1".force_encoding(Encoding::UTF_16LE))
5766 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: UTF-16LE)
5767 * Raises an exception if +name+ is not a String:
5768 * ENV.assoc(Object.new) # TypeError (no implicit conversion of Object into String)
5769 */
5770 static VALUE
5771 env_assoc(VALUE env, VALUE key)
5772 {
5773 const char *s, *e;
5774
5775 s = env_name(key);
5776 e = getenv(s);
5777 if (e) return rb_assoc_new(key, env_str_new2(e));
5778 return Qnil;
5779 }
5780
5781 /*
5782 * call-seq:
5783 * ENV.value?(value) -> true or false
5784 * ENV.has_value?(value) -> true or false
5785 *
5786 * Returns +true+ if there is an environment variable with the given +value+.
5787 */
5788 static VALUE
5789 env_has_value(VALUE dmy, VALUE obj)
5790 {
5791 char **env;
5792
5793 obj = rb_check_string_type(obj);
5794 if (NIL_P(obj)) return Qnil;
5795 env = GET_ENVIRON(environ);
5796 while (*env) {
5797 char *s = strchr(*env, '=');
5798 if (s++) {
5799 long len = strlen(s);
5800 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
5801 FREE_ENVIRON(environ);
5802 return Qtrue;
5803 }
5804 }
5805 env++;
5806 }
5807 FREE_ENVIRON(environ);
5808 return Qfalse;
5809 }
5810
5811 /*
5812 * call-seq:
5813 * ENV.rassoc(value)
5814 *
5815 * Returns an Array of the name and value of the environment variable with
5816 * +value+ or +nil+ if the value cannot be found.
5817 */
5818 static VALUE
5819 env_rassoc(VALUE dmy, VALUE obj)
5820 {
5821 char **env;
5822
5823 obj = rb_check_string_type(obj);
5824 if (NIL_P(obj)) return Qnil;
5825 env = GET_ENVIRON(environ);
5826 while (*env) {
5827 char *s = strchr(*env, '=');
5828 if (s++) {
5829 long len = strlen(s);
5830 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
5831 VALUE result = rb_assoc_new(rb_str_new(*env, s-*env-1), obj);
5832 FREE_ENVIRON(environ);
5833 return result;
5834 }
5835 }
5836 env++;
5837 }
5838 FREE_ENVIRON(environ);
5839 return Qnil;
5840 }
5841
5842 /*
5843 * call-seq:
5844 * ENV.key(value) -> name or nil
5845 *
5846 * Returns the name of the first environment variable with +value+ if it exists:
5847 * ENV.replace('foo' => '0', 'bar' => '1')
5848 * ENV.key('0') # =>'foo'
5849 * The order in which environment variables are examined is OS-dependent.
5850 * See {About Ordering}[#class-ENV-label-About+Ordering].
5851 *
5852 * Returns +nil+ if there is no such value:
5853 * ENV.key('2') # => nil
5854 * Raises an exception if +value+ is not a String:
5855 * ENV.key(Object.new) # raises TypeError (no implicit conversion of Object into String)
5856 */
5857 static VALUE
5858 env_key(VALUE dmy, VALUE value)
5859 {
5860 char **env;
5861 VALUE str;
5862
5863 SafeStringValue(value);
5864 env = GET_ENVIRON(environ);
5865 while (*env) {
5866 char *s = strchr(*env, '=');
5867 if (s++) {
5868 long len = strlen(s);
5869 if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
5870 str = env_str_new(*env, s-*env-1);
5871 FREE_ENVIRON(environ);
5872 return str;
5873 }
5874 }
5875 env++;
5876 }
5877 FREE_ENVIRON(environ);
5878 return Qnil;
5879 }
5880
5881 /*
5882 * call-seq:
5883 * ENV.index(value) -> key
5884 *
5885 * Deprecated method that is equivalent to ENV.key
5886 */
5887 static VALUE
5888 env_index(VALUE dmy, VALUE value)
5889 {
5890 rb_warn_deprecated("ENV.index", "ENV.key");
5891 return env_key(dmy, value);
5892 }
5893
5894 static VALUE
5895 env_to_hash(void)
5896 {
5897 char **env;
5898 VALUE hash;
5899
5900 hash = rb_hash_new();
5901 env = GET_ENVIRON(environ);
5902 while (*env) {
5903 char *s = strchr(*env, '=');
5904 if (s) {
5905 rb_hash_aset(hash, env_str_new(*env, s-*env),
5906 env_str_new2(s+1));
5907 }
5908 env++;
5909 }
5910 FREE_ENVIRON(environ);
5911 return hash;
5912 }
5913
5914 /*
5915 * call-seq:
5916 * ENV.to_hash -> hash
5917 *
5918 * Creates a hash with a copy of the environment variables.
5919 *
5920 */
5921
5922 static VALUE
5923 env_f_to_hash(VALUE _)
5924 {
5925 return env_to_hash();
5926 }
5927
5928 /*
5929 * call-seq:
5930 * ENV.to_h -> hash
5931 * ENV.to_h {|name, value| block } -> hash
5932 *
5933 * Creates a hash with a copy of the environment variables.
5934 *
5935 */
5936 static VALUE
5937 env_to_h(VALUE _)
5938 {
5939 VALUE hash = env_to_hash();
5940 if (rb_block_given_p()) {
5941 hash = rb_hash_to_h_block(hash);
5942 }
5943 return hash;
5944 }
5945
5946 /*
5947 * call-seq:
5948 * ENV.reject { |name, value| block } -> Hash
5949 * ENV.reject -> Enumerator
5950 *
5951 * Same as ENV.delete_if, but works on (and returns) a copy of the
5952 * environment.
5953 */
5954 static VALUE
5955 env_reject(VALUE _)
5956 {
5957 return rb_hash_delete_if(env_to_hash());
5958 }
5959
5960 /*
5961 * call-seq:
5962 * ENV.freeze -> raises TypeError
5963 *
5964 * Ruby does not allow ENV to be frozen, so calling ENV.freeze
5965 * raises TypeError.
5966 */
5967 static VALUE
5968 env_freeze(VALUE self)
5969 {
5970 rb_raise(rb_eTypeError, "cannot freeze ENV");
5971 return self; /* Not reached */
5972 }
5973
5974 /*
5975 * call-seq:
5976 * ENV.shift -> [name, value] or nil
5977 *
5978 * Removes the first environment variable from ENV and returns
5979 * a 2-element Array containing its name and value:
5980 * ENV.replace('foo' => '0', 'bar' => '1')
5981 * ENV.to_hash # => {'bar' => '1', 'foo' => '0'}
5982 * ENV.shift # => ['bar', '1']
5983 * ENV.to_hash # => {'foo' => '0'}
5984 * Exactly which environment variable is "first" is OS-dependent.
5985 * See {About Ordering}[#class-ENV-label-About+Ordering].
5986 *
5987 * Returns +nil+ if the environment is empty:
5988 * ENV.clear
5989 * ENV.shift # => nil
5990 */
5991 static VALUE
5992 env_shift(VALUE _)
5993 {
5994 char **env;
5995 VALUE result = Qnil;
5996
5997 env = GET_ENVIRON(environ);
5998 if (*env) {
5999 char *s = strchr(*env, '=');
6000 if (s) {
6001 VALUE key = env_str_new(*env, s-*env);
6002 VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
6003 env_delete(key);
6004 result = rb_assoc_new(key, val);
6005 }
6006 }
6007 FREE_ENVIRON(environ);
6008 return result;
6009 }
6010
6011 /*
6012 * call-seq:
6013 * ENV.invert -> Hash
6014 *
6015 * Returns a new hash created by using environment variable names as values
6016 * and values as names.
6017 */
6018 static VALUE
6019 env_invert(VALUE _)
6020 {
6021 return rb_hash_invert(env_to_hash());
6022 }
6023
6024 static int
6025 env_replace_i(VALUE key, VALUE val, VALUE keys)
6026 {
6027 env_aset(key, val);
6028 if (rb_ary_includes(keys, key)) {
6029 rb_ary_delete(keys, key);
6030 }
6031 return ST_CONTINUE;
6032 }
6033
6034 /*
6035 * call-seq:
6036 * ENV.replace(hash) -> ENV
6037 *
6038 * Replaces the entire content of the environment variables
6039 * with the name/value pairs in the given +hash+;
6040 * returns ENV.
6041 *
6042 * Replaces the content of ENV with the given pairs:
6043 * ENV.replace('foo' => '0', 'bar' => '1') # => ENV
6044 * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
6045 *
6046 * Raises an exception if a name or value is invalid.
6047 * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
6048 */
6049 static VALUE
6050 env_replace(VALUE env, VALUE hash)
6051 {
6052 VALUE keys;
6053 long i;
6054
6055 keys = env_keys();
6056 if (env == hash) return env;
6057 hash = to_hash(hash);
6058 rb_hash_foreach(hash, env_replace_i, keys);
6059
6060 for (i=0; i<RARRAY_LEN(keys); i++) {
6061 env_delete(RARRAY_AREF(keys, i));
6062 }
6063 RB_GC_GUARD(keys);
6064 return env;
6065 }
6066
6067 static int
6068 env_update_i(VALUE key, VALUE val, VALUE _)
6069 {
6070 env_aset(key, val);
6071 return ST_CONTINUE;
6072 }
6073
6074 static int
6075 env_update_block_i(VALUE key, VALUE val, VALUE _)
6076 {
6077 VALUE oldval = rb_f_getenv(Qnil, key);
6078 if (!NIL_P(oldval)) {
6079 val = rb_yield_values(3, key, oldval, val);
6080 }
6081 env_aset(key, val);
6082 return ST_CONTINUE;
6083 }
6084
6085 /*
6086 * call-seq:
6087 * ENV.update(hash) -> ENV
6088 * ENV.update(hash) { |name, old_value, new_value| block } -> ENV
6089 * ENV.merge!(hash) -> ENV
6090 * ENV.merge!(hash) { |name, old_value, new_value| block } -> ENV
6091 *
6092 * Adds the contents of +hash+ to the environment variables. If no block is
6093 * specified entries with duplicate keys are overwritten, otherwise the value
6094 * of each duplicate name is determined by calling the block with the key, its
6095 * value from the environment and its value from the hash.
6096 */
6097 static VALUE
6098 env_update(VALUE env, VALUE hash)
6099 {
6100 if (env == hash) return env;
6101 hash = to_hash(hash);
6102 rb_foreach_func *func = rb_block_given_p() ?
6103 env_update_block_i : env_update_i;
6104 rb_hash_foreach(hash, func, 0);
6105 return env;
6106 }
6107
6108 /*
6109 * A Hash is a dictionary-like collection of unique keys and their values.
6110 * Also called associative arrays, they are similar to Arrays, but where an
6111 * Array uses integers as its index, a Hash allows you to use any object
6112 * type.
6113 *
6114 * Hashes enumerate their values in the order that the corresponding keys
6115 * were inserted.
6116 *
6117 * A Hash can be easily created by using its implicit form:
6118 *
6119 * grades = { "Jane Doe" => 10, "Jim Doe" => 6 }
6120 *
6121 * Hashes allow an alternate syntax for keys that are symbols.
6122 * Instead of
6123 *
6124 * options = { :font_size => 10, :font_family => "Arial" }
6125 *
6126 * You could write it as:
6127 *
6128 * options = { font_size: 10, font_family: "Arial" }
6129 *
6130 * Each named key is a symbol you can access in hash:
6131 *
6132 * options[:font_size] # => 10
6133 *
6134 * A Hash can also be created through its ::new method:
6135 *
6136 * grades = Hash.new
6137 * grades["Dorothy Doe"] = 9
6138 *
6139 * Hashes have a <em>default value</em> that is returned when accessing
6140 * keys that do not exist in the hash. If no default is set +nil+ is used.
6141 * You can set the default value by sending it as an argument to Hash.new:
6142 *
6143 * grades = Hash.new(0)
6144 *
6145 * Or by using the #default= method:
6146 *
6147 * grades = {"Timmy Doe" => 8}
6148 * grades.default = 0
6149 *
6150 * Accessing a value in a Hash requires using its key:
6151 *
6152 * puts grades["Jane Doe"] # => 0
6153 *
6154 * === Common Uses
6155 *
6156 * Hashes are an easy way to represent data structures, such as
6157 *
6158 * books = {}
6159 * books[:matz] = "The Ruby Programming Language"
6160 * books[:black] = "The Well-Grounded Rubyist"
6161 *
6162 * Hashes are also commonly used as a way to have named parameters in
6163 * functions. Note that no brackets are used below. If a hash is the last
6164 * argument on a method call, no braces are needed, thus creating a really
6165 * clean interface:
6166 *
6167 * Person.create(name: "John Doe", age: 27)
6168 *
6169 * def self.create(params)
6170 * @name = params[:name]
6171 * @age = params[:age]
6172 * end
6173 *
6174 * === Hash Keys
6175 *
6176 * Two objects refer to the same hash key when their <code>hash</code> value
6177 * is identical and the two objects are <code>eql?</code> to each other.
6178 *
6179 * A user-defined class may be used as a hash key if the <code>hash</code>
6180 * and <code>eql?</code> methods are overridden to provide meaningful
6181 * behavior. By default, separate instances refer to separate hash keys.
6182 *
6183 * A typical implementation of <code>hash</code> is based on the
6184 * object's data while <code>eql?</code> is usually aliased to the overridden
6185 * <code>==</code> method:
6186 *
6187 * class Book
6188 * attr_reader :author, :title
6189 *
6190 * def initialize(author, title)
6191 * @author = author
6192 * @title = title
6193 * end
6194 *
6195 * def ==(other)
6196 * self.class === other and
6197 * other.author == @author and
6198 * other.title == @title
6199 * end
6200 *
6201 * alias eql? ==
6202 *
6203 * def hash
6204 * @author.hash ^ @title.hash # XOR
6205 * end
6206 * end
6207 *
6208 * book1 = Book.new 'matz', 'Ruby in a Nutshell'
6209 * book2 = Book.new 'matz', 'Ruby in a Nutshell'
6210 *
6211 * reviews = {}
6212 *
6213 * reviews[book1] = 'Great reference!'
6214 * reviews[book2] = 'Nice and compact!'
6215 *
6216 * reviews.length #=> 1
6217 *
6218 * See also Object#hash and Object#eql?
6219 */
6220
6221 void
6222 Init_Hash(void)
6223 {
6224 #undef rb_intern
6225 #define rb_intern(str) rb_intern_const(str)
6226 id_hash = rb_intern("hash");
6227 id_yield = rb_intern("yield");
6228 id_default = rb_intern("default");
6229 id_flatten_bang = rb_intern("flatten!");
6230 id_hash_iter_lev = rb_make_internal_id();
6231
6232 rb_cHash = rb_define_class("Hash", rb_cObject);
6233
6234 rb_include_module(rb_cHash, rb_mEnumerable);
6235
6236 rb_define_alloc_func(rb_cHash, empty_hash_alloc);
6237 rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
6238 rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
6239 rb_define_method(rb_cHash, "initialize", rb_hash_initialize, -1);
6240 rb_define_method(rb_cHash, "initialize_copy", rb_hash_replace, 1);
6241 rb_define_method(rb_cHash, "rehash", rb_hash_rehash, 0);
6242
6243 rb_define_method(rb_cHash, "to_hash", rb_hash_to_hash, 0);
6244 rb_define_method(rb_cHash, "to_h", rb_hash_to_h, 0);
6245 rb_define_method(rb_cHash, "to_a", rb_hash_to_a, 0);
6246 rb_define_method(rb_cHash, "inspect", rb_hash_inspect, 0);
6247 rb_define_alias(rb_cHash, "to_s", "inspect");
6248 rb_define_method(rb_cHash, "to_proc", rb_hash_to_proc, 0);
6249
6250 rb_define_method(rb_cHash, "==", rb_hash_equal, 1);
6251 rb_define_method(rb_cHash, "[]", rb_hash_aref, 1);
6252 rb_define_method(rb_cHash, "hash", rb_hash_hash, 0);
6253 rb_define_method(rb_cHash, "eql?", rb_hash_eql, 1);
6254 rb_define_method(rb_cHash, "fetch", rb_hash_fetch_m, -1);
6255 rb_define_method(rb_cHash, "[]=", rb_hash_aset, 2);
6256 rb_define_method(rb_cHash, "store", rb_hash_aset, 2);
6257 rb_define_method(rb_cHash, "default", rb_hash_default, -1);
6258 rb_define_method(rb_cHash, "default=", rb_hash_set_default, 1);
6259 rb_define_method(rb_cHash, "default_proc", rb_hash_default_proc, 0);
6260 rb_define_method(rb_cHash, "default_proc=", rb_hash_set_default_proc, 1);
6261 rb_define_method(rb_cHash, "key", rb_hash_key, 1);
6262 rb_define_method(rb_cHash, "index", rb_hash_index, 1);
6263 rb_define_method(rb_cHash, "size", rb_hash_size, 0);
6264 rb_define_method(rb_cHash, "length", rb_hash_size, 0);
6265 rb_define_method(rb_cHash, "empty?", rb_hash_empty_p, 0);
6266
6267 rb_define_method(rb_cHash, "each_value", rb_hash_each_value, 0);
6268 rb_define_method(rb_cHash, "each_key", rb_hash_each_key, 0);
6269 rb_define_method(rb_cHash, "each_pair", rb_hash_each_pair, 0);
6270 rb_define_method(rb_cHash, "each", rb_hash_each_pair, 0);
6271
6272 rb_define_method(rb_cHash, "transform_keys", rb_hash_transform_keys, 0);
6273 rb_define_method(rb_cHash, "transform_keys!", rb_hash_transform_keys_bang, 0);
6274 rb_define_method(rb_cHash, "transform_values", rb_hash_transform_values, 0);
6275 rb_define_method(rb_cHash, "transform_values!", rb_hash_transform_values_bang, 0);
6276
6277 rb_define_method(rb_cHash, "keys", rb_hash_keys, 0);
6278 rb_define_method(rb_cHash, "values", rb_hash_values, 0);
6279 rb_define_method(rb_cHash, "values_at", rb_hash_values_at, -1);
6280 rb_define_method(rb_cHash, "fetch_values", rb_hash_fetch_values, -1);
6281
6282 rb_define_method(rb_cHash, "shift", rb_hash_shift, 0);
6283 rb_define_method(rb_cHash, "delete", rb_hash_delete_m, 1);
6284 rb_define_method(rb_cHash, "delete_if", rb_hash_delete_if, 0);
6285 rb_define_method(rb_cHash, "keep_if", rb_hash_keep_if, 0);
6286 rb_define_method(rb_cHash, "select", rb_hash_select, 0);
6287 rb_define_method(rb_cHash, "select!", rb_hash_select_bang, 0);
6288 rb_define_method(rb_cHash, "filter", rb_hash_select, 0);
6289 rb_define_method(rb_cHash, "filter!", rb_hash_select_bang, 0);
6290 rb_define_method(rb_cHash, "reject", rb_hash_reject, 0);
6291 rb_define_method(rb_cHash, "reject!", rb_hash_reject_bang, 0);
6292 rb_define_method(rb_cHash, "slice", rb_hash_slice, -1);
6293 rb_define_method(rb_cHash, "clear", rb_hash_clear, 0);
6294 rb_define_method(rb_cHash, "invert", rb_hash_invert, 0);
6295 rb_define_method(rb_cHash, "update", rb_hash_update, -1);
6296 rb_define_method(rb_cHash, "replace", rb_hash_replace, 1);
6297 rb_define_method(rb_cHash, "merge!", rb_hash_update, -1);
6298 rb_define_method(rb_cHash, "merge", rb_hash_merge, -1);
6299 rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
6300 rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
6301 rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);
6302 rb_define_method(rb_cHash, "compact", rb_hash_compact, 0);
6303 rb_define_method(rb_cHash, "compact!", rb_hash_compact_bang, 0);
6304
6305 rb_define_method(rb_cHash, "include?", rb_hash_has_key, 1);
6306 rb_define_method(rb_cHash, "member?", rb_hash_has_key, 1);
6307 rb_define_method(rb_cHash, "has_key?", rb_hash_has_key, 1);
6308 rb_define_method(rb_cHash, "has_value?", rb_hash_has_value, 1);
6309 rb_define_method(rb_cHash, "key?", rb_hash_has_key, 1);
6310 rb_define_method(rb_cHash, "value?", rb_hash_has_value, 1);
6311
6312 rb_define_method(rb_cHash, "compare_by_identity", rb_hash_compare_by_id, 0);
6313 rb_define_method(rb_cHash, "compare_by_identity?", rb_hash_compare_by_id_p, 0);
6314
6315 rb_define_method(rb_cHash, "any?", rb_hash_any_p, -1);
6316 rb_define_method(rb_cHash, "dig", rb_hash_dig, -1);
6317
6318 rb_define_method(rb_cHash, "<=", rb_hash_le, 1);
6319 rb_define_method(rb_cHash, "<", rb_hash_lt, 1);
6320 rb_define_method(rb_cHash, ">=", rb_hash_ge, 1);
6321 rb_define_method(rb_cHash, ">", rb_hash_gt, 1);
6322
6323 rb_define_method(rb_cHash, "deconstruct_keys", rb_hash_deconstruct_keys, 1);
6324
6325 /* Document-class: ENV
6326 *
6327 * ENV is a hash-like accessor for environment variables.
6328 *
6329 * === Interaction with the Operating System
6330 *
6331 * The ENV object interacts with the operating system's environment variables:
6332 *
6333 * - When you get the value for a name in ENV, the value is retrieved from among the current environment variables.
6334 * - When you create or set a name-value pair in ENV, the name and value are immediately set in the environment variables.
6335 * - When you delete a name-value pair in ENV, it is immediately deleted from the environment variables.
6336 *
6337 * === Names and Values
6338 *
6339 * Generally, a name or value is a String.
6340 *
6341 * ==== Valid Names and Values
6342 *
6343 * Each name or value must be one of the following:
6344 *
6345 * - A String.
6346 * - An object that responds to \#to_str by returning a String, in which case that String will be used as the name or value.
6347 *
6348 * ==== Invalid Names and Values
6349 *
6350 * A new name:
6351 *
6352 * - May not be the empty string:
6353 * ENV[''] = '0'
6354 * # Raises Errno::EINVAL (Invalid argument - ruby_setenv())
6355 *
6356 * - May not contain character <code>"="</code>:
6357 * ENV['='] = '0'
6358 * # Raises Errno::EINVAL (Invalid argument - ruby_setenv(=))
6359 *
6360 * A new name or value:
6361 *
6362 * - May not be a non-String that does not respond to \#to_str:
6363 *
6364 * ENV['foo'] = Object.new
6365 * # Raises TypeError (no implicit conversion of Object into String)
6366 * ENV[Object.new] = '0'
6367 * # Raises TypeError (no implicit conversion of Object into String)
6368 *
6369 * - May not contain the NUL character <code>"\0"</code>:
6370 *
6371 * ENV['foo'] = "\0"
6372 * # Raises ArgumentError (bad environment variable value: contains null byte)
6373 * ENV["\0"] == '0'
6374 * # Raises ArgumentError (bad environment variable name: contains null byte)
6375 *
6376 * - May not have an ASCII-incompatible encoding such as UTF-16LE or ISO-2022-JP:
6377 *
6378 * ENV['foo'] = '0'.force_encoding(Encoding::ISO_2022_JP)
6379 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: ISO-2022-JP)
6380 * ENV["foo".force_encoding(Encoding::ISO_2022_JP)] = '0'
6381 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: ISO-2022-JP)
6382 *
6383 * === About Ordering
6384 *
6385 * ENV enumerates its name/value pairs in the order found
6386 * in the operating system's environment variables.
6387 * Therefore the ordering of ENV content is OS-dependent, and may be indeterminate.
6388 *
6389 * This will be seen in:
6390 * - A Hash returned by an ENV method.
6391 * - An Enumerator returned by an ENV method.
6392 * - An Array returned by ENV.keys, ENV.values, or ENV.to_a.
6393 * - The String returned by ENV.inspect.
6394 * - The Array returned by ENV.shift.
6395 * - The name returned by ENV.key.
6396 *
6397 * === About the Examples
6398 * Some methods in ENV return ENV itself. Typically, there are many environment variables.
6399 * It's not useful to display a large ENV in the examples here,
6400 * so most example snippets begin by resetting the contents of ENV:
6401 * - ENV.replace replaces ENV with a new collection of entries.
6402 * - ENV.clear empties ENV.
6403 */
6404
6405 /*
6406 * Hack to get RDoc to regard ENV as a class:
6407 * envtbl = rb_define_class("ENV", rb_cObject);
6408 */
6409 origenviron = environ;
6410 envtbl = rb_obj_alloc(rb_cObject);
6411 rb_extend_object(envtbl, rb_mEnumerable);
6412
6413 rb_define_singleton_method(envtbl, "[]", rb_f_getenv, 1);
6414 rb_define_singleton_method(envtbl, "fetch", env_fetch, -1);
6415 rb_define_singleton_method(envtbl, "[]=", env_aset_m, 2);
6416 rb_define_singleton_method(envtbl, "store", env_aset_m, 2);
6417 rb_define_singleton_method(envtbl, "each", env_each_pair, 0);
6418 rb_define_singleton_method(envtbl, "each_pair", env_each_pair, 0);
6419 rb_define_singleton_method(envtbl, "each_key", env_each_key, 0);
6420 rb_define_singleton_method(envtbl, "each_value", env_each_value, 0);
6421 rb_define_singleton_method(envtbl, "delete", env_delete_m, 1);
6422 rb_define_singleton_method(envtbl, "delete_if", env_delete_if, 0);
6423 rb_define_singleton_method(envtbl, "keep_if", env_keep_if, 0);
6424 rb_define_singleton_method(envtbl, "slice", env_slice, -1);
6425 rb_define_singleton_method(envtbl, "clear", env_clear, 0);
6426 rb_define_singleton_method(envtbl, "reject", env_reject, 0);
6427 rb_define_singleton_method(envtbl, "reject!", env_reject_bang, 0);
6428 rb_define_singleton_method(envtbl, "select", env_select, 0);
6429 rb_define_singleton_method(envtbl, "select!", env_select_bang, 0);
6430 rb_define_singleton_method(envtbl, "filter", env_select, 0);
6431 rb_define_singleton_method(envtbl, "filter!", env_select_bang, 0);
6432 rb_define_singleton_method(envtbl, "shift", env_shift, 0);
6433 rb_define_singleton_method(envtbl, "freeze", env_freeze, 0);
6434 rb_define_singleton_method(envtbl, "invert", env_invert, 0);
6435 rb_define_singleton_method(envtbl, "replace", env_replace, 1);
6436 rb_define_singleton_method(envtbl, "update", env_update, 1);
6437 rb_define_singleton_method(envtbl, "merge!", env_update, 1);
6438 rb_define_singleton_method(envtbl, "inspect", env_inspect, 0);
6439 rb_define_singleton_method(envtbl, "rehash", env_none, 0);
6440 rb_define_singleton_method(envtbl, "to_a", env_to_a, 0);
6441 rb_define_singleton_method(envtbl, "to_s", env_to_s, 0);
6442 rb_define_singleton_method(envtbl, "key", env_key, 1);
6443 rb_define_singleton_method(envtbl, "index", env_index, 1);
6444 rb_define_singleton_method(envtbl, "size", env_size, 0);
6445 rb_define_singleton_method(envtbl, "length", env_size, 0);
6446 rb_define_singleton_method(envtbl, "empty?", env_empty_p, 0);
6447 rb_define_singleton_method(envtbl, "keys", env_f_keys, 0);
6448 rb_define_singleton_method(envtbl, "values", env_f_values, 0);
6449 rb_define_singleton_method(envtbl, "values_at", env_values_at, -1);
6450 rb_define_singleton_method(envtbl, "include?", env_has_key, 1);
6451 rb_define_singleton_method(envtbl, "member?", env_has_key, 1);
6452 rb_define_singleton_method(envtbl, "has_key?", env_has_key, 1);
6453 rb_define_singleton_method(envtbl, "has_value?", env_has_value, 1);
6454 rb_define_singleton_method(envtbl, "key?", env_has_key, 1);
6455 rb_define_singleton_method(envtbl, "value?", env_has_value, 1);
6456 rb_define_singleton_method(envtbl, "to_hash", env_f_to_hash, 0);
6457 rb_define_singleton_method(envtbl, "to_h", env_to_h, 0);
6458 rb_define_singleton_method(envtbl, "assoc", env_assoc, 1);
6459 rb_define_singleton_method(envtbl, "rassoc", env_rassoc, 1);
6460
6461 /*
6462 * ENV is a Hash-like accessor for environment variables.
6463 *
6464 * See ENV (the class) for more details.
6465 */
6466 rb_define_global_const("ENV", envtbl);
6467
6468 /* for callcc */
6469 ruby_register_rollback_func_for_ensure(hash_foreach_ensure, hash_foreach_ensure_rollback);
6470
6471 HASH_ASSERT(sizeof(ar_hint_t) * RHASH_AR_TABLE_MAX_SIZE == sizeof(VALUE));
6472 }
rb_yield_values
#define rb_yield_values(argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6584
rb_hash_st_table_set
void rb_hash_st_table_set(VALUE hash, st_table *st)
Definition: hash.c:558
equal_data::eql
int eql
Definition: hash.c:3481
st_foreach_safe
void st_foreach_safe(st_table *table, st_foreach_func *func, st_data_t a)
Definition: hash.c:1272
FLONUM_P
#define FLONUM_P(x)
Definition: ruby.h:430
rehash_arg::hash
VALUE hash
Definition: hash.c:1848
rb_ary_new_capa
VALUE rb_ary_new_capa(long capa)
Definition: array.c:717
rb_hash_update_func
VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value)
Definition: intern.h:573
rb_transient_heap_managed_ptr_p
int rb_transient_heap_managed_ptr_p(const void *ptr)
Definition: transient_heap.c:506
rb_str_ellipsize
VALUE rb_str_ellipsize(VALUE, long)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
Definition: string.c:10185
rb_proc_lambda_p
VALUE rb_proc_lambda_p(VALUE)
Definition: proc.c:275
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
ID
unsigned long ID
Definition: ruby.h:103
rb_to_hash_type
VALUE rb_to_hash_type(VALUE hash)
Definition: hash.c:1818
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:10150
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
equal_data
Definition: hash.c:3478
RHASH_PROC_DEFAULT
@ RHASH_PROC_DEFAULT
Definition: internal.h:819
rb_hash_keep_if
VALUE rb_hash_keep_if(VALUE hash)
Definition: hash.c:2668
rb_raw_obj_info
const char * rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
Definition: gc.c:11419
rb_fstring
VALUE rb_fstring(VALUE)
Definition: string.c:312
rb_method_basic_definition_p
#define rb_method_basic_definition_p(klass, mid)
Definition: rb_mjit_min_header-2.7.0.h:7900
STATIC_SYM_P
#define STATIC_SYM_P(x)
Definition: ruby.h:411
TRUE
#define TRUE
Definition: nkf.h:175
rb_hash_tbl_raw
MJIT_FUNC_EXPORTED struct st_table * rb_hash_tbl_raw(VALUE hash)
Definition: hash.c:1567
rb_check_convert_type_with_id
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2957
rb_block_arity
int rb_block_arity(void)
Definition: proc.c:1144
st_foreach_with_replace
int st_foreach_with_replace(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
Definition: st.c:1700
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
RHASH_AR_TABLE_MAX_SIZE
#define RHASH_AR_TABLE_MAX_SIZE
Definition: internal.h:821
st_update_callback_func
int st_update_callback_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
Definition: st.h:131
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
st_copy
st_table * st_copy(st_table *old_tab)
Definition: st.c:1320
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_enc_name
#define rb_enc_name(enc)
Definition: encoding.h:177
rb_filesystem_encoding
rb_encoding * rb_filesystem_encoding(void)
Definition: encoding.c:1387
rb_str_hash
st_index_t rb_str_hash(VALUE)
Definition: string.c:3163
hash_foreach_arg::hash
VALUE hash
Definition: hash.c:1287
rehash_arg
Definition: hash.c:1847
update_callback_arg
Definition: hash.c:1593
foreach_safe_arg::tbl
st_table * tbl
Definition: hash.c:1252
st_table::num_entries
st_index_t num_entries
Definition: st.h:86
env
#define env
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
update_arg::old_value
VALUE old_value
Definition: hash.c:1618
rb_class_has_methods
int rb_class_has_methods(VALUE c)
Definition: class.c:2201
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4203
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1501
rb_hash_st_table
st_table * rb_hash_st_table(VALUE hash)
Definition: hash.c:551
ST_CHECK
@ ST_CHECK
Definition: st.h:99
rb_hash_resurrect
MJIT_FUNC_EXPORTED VALUE rb_hash_resurrect(VALUE hash)
Definition: hash.c:1548
rb_str_buf_cat2
#define rb_str_buf_cat2
Definition: intern.h:911
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
HASH_ASSERT
#define HASH_ASSERT(expr)
Definition: hash.c:435
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:897
update_arg::arg
st_data_t arg
Definition: hash.c:1613
RHASH_ST_CLEAR
#define RHASH_ST_CLEAR(h)
Definition: internal.h:862
ar_hint_t
unsigned char ar_hint_t
Definition: rb_mjit_min_header-2.7.0.h:6887
uint64_t
#define uint64_t
Definition: siphash.h:15
rb_hash_values
VALUE rb_hash_values(VALUE hash)
Definition: hash.c:3381
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:334
rb_hash_size_num
size_t rb_hash_size_num(VALUE hash)
Definition: hash.c:2872
gc.h
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1981
ST_STOP
@ ST_STOP
Definition: st.h:99
rb_str_buf_cat_ascii
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2926
update_arg::hash
VALUE hash
Definition: hash.c:1614
idEqq
@ idEqq
Definition: id.h:97
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE obj)
Definition: gc.c:7011
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
rb_make_internal_id
ID rb_make_internal_id(void)
Definition: symbol.c:810
rb_hash_clear
VALUE rb_hash_clear(VALUE hash)
Definition: hash.c:2696
RHASH_UPDATE_ITER
#define RHASH_UPDATE_ITER(h, iter_lev, key, func, a)
Definition: hash.c:1663
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
strchr
char * strchr(char *, char)
RHASH_SET_TRANSIENT_FLAG
#define RHASH_SET_TRANSIENT_FLAG(h)
Definition: internal.h:871
st_hash
st_index_t st_hash(const void *ptr, size_t len, st_index_t h)
Definition: st.c:1897
ruby_xmalloc
void * ruby_xmalloc(size_t size)
Definition: gc.c:11950
rb_hash_default_value
VALUE rb_hash_default_value(VALUE hash, VALUE key)
Definition: hash.c:1917
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
st_shift
int st_shift(st_table *tab, st_data_t *key, st_data_t *value)
Definition: st.c:1440
rb_hash_reject
VALUE rb_hash_reject(VALUE hash)
Definition: hash.c:2477
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:1964
rb_equal
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
rb_locale_encoding
rb_encoding * rb_locale_encoding(void)
Definition: encoding.c:1372
RUBY_SPECIAL_SHIFT
@ RUBY_SPECIAL_SHIFT
Definition: ruby.h:460
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_hash_size
VALUE rb_hash_size(VALUE hash)
Definition: hash.c:2866
index
int index
Definition: rb_mjit_min_header-2.7.0.h:11246
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
encoding.h
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
malloc
void * malloc(size_t) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__alloc_size__(1)))
st_delete
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
Definition: st.c:1418
st_foreach_check
int st_foreach_check(st_table *tab, st_foreach_check_callback_func *func, st_data_t arg, st_data_t never ATTRIBUTE_UNUSED)
Definition: st.c:1726
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
hash_foreach_arg
Definition: generator.c:722
shift_var
Definition: hash.c:2322
ENVNMATCH
#define ENVNMATCH(s1, s2, n)
Definition: hash.c:4579
update_arg::new_key
VALUE new_key
Definition: hash.c:1615
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
st_add_direct
void st_add_direct(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1251
id_yield
ID id_yield
Definition: eventids1.c:136
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
update_func_arg::func
rb_hash_update_func * func
Definition: hash.c:3800
rb_obj_hash
VALUE rb_obj_hash(VALUE obj)
Definition: hash.c:291
rb_float_value
double rb_float_value(VALUE v)
Definition: numeric.c:5834
ECONV_UNDEF_REPLACE
#define ECONV_UNDEF_REPLACE
Definition: encoding.h:396
RUBY_DTRACE_CREATE_HOOK
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
Definition: internal.h:2584
st_retval
st_retval
Definition: st.h:99
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
NORETURN
NORETURN(static void no_new_key(void))
id.h
getenv
#define getenv(name)
Definition: win32.c:73
RSYMBOL
#define RSYMBOL(obj)
Definition: symbol.h:33
uint64_t
unsigned long long uint64_t
Definition: sha2.h:102
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
shift_var::val
VALUE val
Definition: hash.c:2324
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:1977
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
putenv
int putenv(char *__string)
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
CHAR_BIT
#define CHAR_BIT
Definition: ruby.h:227
RHASH_ST_TABLE_FLAG
@ RHASH_ST_TABLE_FLAG
Definition: internal.h:820
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
rb_hash_update_by
VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
Definition: hash.c:3835
rb_proc_arity
int rb_proc_arity(VALUE)
Definition: proc.c:1112
rb_hash_keys
MJIT_FUNC_EXPORTED VALUE rb_hash_keys(VALUE hash)
Definition: hash.c:3334
RHASH_AR_TABLE_SIZE_INC
#define RHASH_AR_TABLE_SIZE_INC(h)
Definition: hash.c:607
ptr
struct RIMemo * ptr
Definition: debug.c:74
hash_verify
#define hash_verify(h)
Definition: hash.c:510
T_DATA
#define T_DATA
Definition: ruby.h:538
rb_obj_id
VALUE rb_obj_id(VALUE obj)
Definition: gc.c:3770
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_hash_rassoc
VALUE rb_hash_rassoc(VALUE hash, VALUE obj)
Definition: hash.c:4003
update_func_arg::value
VALUE value
Definition: hash.c:3799
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:271
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:1537
ar_table_pair
struct ar_table_pair_struct ar_table_pair
RB_OBJ_FROZEN
#define RB_OBJ_FROZEN(x)
Definition: ruby.h:1342
rb_hash_assoc
VALUE rb_hash_assoc(VALUE hash, VALUE key)
Definition: hash.c:3942
rb_hash_stlike_lookup
MJIT_FUNC_EXPORTED int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
Definition: hash.c:1944
rb_ary_delete
VALUE rb_ary_delete(VALUE ary, VALUE item)
Definition: array.c:3365
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
rb_hash_select_bang
VALUE rb_hash_select_bang(VALUE hash)
Definition: hash.c:2641
st.h
NUM2LL
#define NUM2LL(x)
NULL
#define NULL
Definition: _sdbm.c:101
ST_DELETE
@ ST_DELETE
Definition: st.h:99
uint32_t
unsigned int uint32_t
Definition: sha2.h:101
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:607
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
functor
Definition: hash.c:906
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1279
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_init_identtable
st_table * rb_init_identtable(void)
Definition: hash.c:4211
rb_hash_ar_table_p
int rb_hash_ar_table_p(VALUE hash)
Definition: hash.c:532
RHASH_AR_TABLE_SIZE_RAW
#define RHASH_AR_TABLE_SIZE_RAW(h)
Definition: internal.h:841
rb_str_cat_conv_enc_opts
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
Definition: string.c:943
hash_foreach_arg::arg
VALUE arg
Definition: hash.c:1289
RHASH_AR_TABLE_SIZE
#define RHASH_AR_TABLE_SIZE(h)
Definition: hash.c:422
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
error
const rb_iseq_t const char * error
Definition: rb_mjit_min_header-2.7.0.h:13506
strlen
size_t strlen(const char *)
rb_hash_bulk_insert_into_st_table
void rb_hash_bulk_insert_into_st_table(long, const VALUE *, VALUE)
Definition: st.c:2380
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:540
rb_hash_set_default_proc
VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc)
Definition: hash.c:2169
rb_ascii8bit_encindex
int rb_ascii8bit_encindex(void)
Definition: encoding.c:1322
strncmp
int strncmp(const char *, const char *, size_t)
foreach_safe_arg::arg
st_data_t arg
Definition: hash.c:1254
rb_big_hash
VALUE rb_big_hash(VALUE x)
Definition: bignum.c:6726
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
L
#define L(x)
Definition: asm.h:125
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1964
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1071
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_eql
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:147
rb_memhash
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1440
rb_hash_new_with_size
MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:1507
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
rb_hash_has_key
MJIT_FUNC_EXPORTED VALUE rb_hash_has_key(VALUE hash, VALUE key)
Definition: hash.c:3432
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.0.h:7899
RHASH_AR_TABLE_BOUND
#define RHASH_AR_TABLE_BOUND(h)
Definition: hash.c:429
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
Definition: intern.h:57
rb_str_fill_terminator
char * rb_str_fill_terminator(VALUE str, const int termlen)
Definition: string.c:2306
st_init_table_with_size
st_table * st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
Definition: st.c:577
rb_hash_delete_entry
VALUE rb_hash_delete_entry(VALUE hash, VALUE key)
Definition: hash.c:2253
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_str_hash_cmp
int rb_str_hash_cmp(VALUE, VALUE)
Definition: string.c:3173
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
reset_hash_type_arg::hash
VALUE hash
Definition: hash.c:3902
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
rb_ivar_set_internal
void rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
Definition: variable.c:1308
rb_hash_stlike_update
int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg)
Definition: hash.c:1624
rb_ident_cmp
#define rb_ident_cmp
Definition: hash.c:302
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
rb_integer_pack
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3547
probes.h
update_callback_arg::arg
st_data_t arg
Definition: hash.c:1595
rb_hash_add_new_element
int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:4472
NOINLINE
NOINLINE(static int ar_equal(VALUE x, VALUE y))
rb_obj_is_proc
VALUE rb_obj_is_proc(VALUE)
Definition: proc.c:152
rb_obj_info
const MJIT_FUNC_EXPORTED char * rb_obj_info(VALUE obj)
Definition: gc.c:11655
PRIuSIZE
#define PRIuSIZE
Definition: ruby.h:208
st_foreach_check_callback_func
int st_foreach_check_callback_func(st_data_t, st_data_t, st_data_t, int)
Definition: st.h:138
ST_REPLACE
@ ST_REPLACE
Definition: st.h:99
OBJ_WB_UNPROTECT
#define OBJ_WB_UNPROTECT(x)
Definition: ruby.h:1495
fprintf
int fprintf(FILE *__restrict, const char *__restrict,...) __attribute__((__format__(__printf__
RHASH_UNSET_TRANSIENT_FLAG
#define RHASH_UNSET_TRANSIENT_FLAG(h)
Definition: internal.h:872
rb_hash_rehash
VALUE rb_hash_rehash(VALUE hash)
Definition: hash.c:1885
st_clear
void st_clear(st_table *tab)
Definition: st.c:698
rb_encoding
const typedef OnigEncodingType rb_encoding
Definition: encoding.h:115
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
rb_hash_transient_heap_evacuate
void rb_hash_transient_heap_evacuate(VALUE hash, int promote)
Definition: hash.c:1222
RHASH_SIZE
#define RHASH_SIZE(hsh)
Definition: fbuffer.h:8
rb_ary_includes
VALUE rb_ary_includes(VALUE ary, VALUE item)
Definition: array.c:4340
rb_hash_compare_by_id_p
MJIT_FUNC_EXPORTED VALUE rb_hash_compare_by_id_p(VALUE hash)
Definition: hash.c:4192
rb_obj_dig
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
Definition: object.c:3791
foreach_safe_arg::func
st_foreach_func * func
Definition: hash.c:1253
rb_convert_type_with_id
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
reset_hash_type_arg
Definition: hash.c:3901
rb_ary_cat
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
Definition: array.c:1208
rb_hash_stlike_delete
int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval)
Definition: hash.c:2237
NOINSERT_UPDATE_CALLBACK
#define NOINSERT_UPDATE_CALLBACK(func)
Definition: hash.c:1598
st_foreach_callback_func
int st_foreach_callback_func(st_data_t, st_data_t, st_data_t)
Definition: st.h:137
functor::func
st_foreach_callback_func * func
Definition: hash.c:907
rb_hash_ar_table_size
size_t rb_hash_ar_table_size(void)
Definition: hash.c:355
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_hash_values_at
VALUE rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
Definition: hash.c:2539
FL_EXIVAR
#define FL_EXIVAR
Definition: ruby.h:1286
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1509
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
Definition: ruby.h:1131
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
rb_hash_tbl
struct st_table * rb_hash_tbl(VALUE hash, const char *file, int line)
Definition: hash.c:1574
RHASH_LEV_MASK
#define RHASH_LEV_MASK
Definition: internal.h:828
rb_hash_fetch_values
VALUE rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
Definition: hash.c:2567
rb_hash_delete_if
VALUE rb_hash_delete_if(VALUE hash)
Definition: hash.c:2420
long
#define long
Definition: rb_mjit_min_header-2.7.0.h:2880
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:1990
bin
char bin[32]
Definition: siphash.c:135
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
st_index_t
st_data_t st_index_t
Definition: st.h:50
st_hash_type
Definition: st.h:61
cnt
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:503
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1434
transient_heap.h
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
RHASH_IFNONE
#define RHASH_IFNONE(h)
Definition: ruby.h:1129
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.0.h:1485
st_hash_type::compare
int(* compare)(st_data_t, st_data_t)
Definition: st.h:62
rb_hash_bulk_insert
void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
Definition: hash.c:4515
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
RBASIC_CLASS
#define RBASIC_CLASS(obj)
Definition: ruby.h:906
rb_copy_generic_ivar
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1447
rb_ary_set_len
void rb_ary_set_len(VALUE ary, long len)
Definition: array.c:1932
INTEGER_PACK_NATIVE_BYTE_ORDER
#define INTEGER_PACK_NATIVE_BYTE_ORDER
Definition: intern.h:155
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
RSHIFT
#define RSHIFT(x, y)
Definition: rb_mjit_min_header-2.7.0.h:414
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
RHASH_TRANSIENT_P
#define RHASH_TRANSIENT_P(hash)
Definition: internal.h:870
rb_transient_heap_alloc
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
Definition: transient_heap.c:359
rb_enc_copy
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:990
symbol.h
size
int size
Definition: encoding.c:58
FALSE
#define FALSE
Definition: nkf.h:174
uint128_t
#define uint128_t
Definition: rb_mjit_min_header-2.7.0.h:235
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
RCLASS_SUPER
#define RCLASS_SUPER(c)
Definition: classext.h:16
RHASH_AR_TABLE_BOUND_MASK
#define RHASH_AR_TABLE_BOUND_MASK
Definition: internal.h:866
rb_to_int
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
rb_env_clear
VALUE rb_env_clear(void)
Definition: hash.c:5553
rb_gc_writebarrier_remember
MJIT_FUNC_EXPORTED void rb_gc_writebarrier_remember(VALUE obj)
Definition: gc.c:6875
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1461
FL_SET_RAW
#define FL_SET_RAW(x, f)
Definition: ruby.h:1358
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1203
RHash::basic
struct RBasic basic
Definition: internal.h:888
getpid
pid_t getpid(void)
RHASH
#define RHASH(obj)
Definition: internal.h:859
rb_default_internal_encoding
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1512
rb_w32_ugetenv
char * rb_w32_ugetenv(const char *)
Definition: win32.c:5230
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1508
ar_table
struct ar_table_struct ar_table
st_update
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:1510
EINVAL
#define EINVAL
Definition: rb_mjit_min_header-2.7.0.h:10959
rb_extend_object
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition: eval.c:1700
rb_cHash
VALUE rb_cHash
Definition: hash.c:92
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:909
ID_SCOPE_SHIFT
#define ID_SCOPE_SHIFT
Definition: id.h:31
key
key
Definition: openssl_missing.h:181
T_HASH
#define T_HASH
Definition: ruby.h:531
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1271
idTo_hash
@ idTo_hash
Definition: rb_mjit_min_header-2.7.0.h:8717
RHASH_ST_TABLE_P
#define RHASH_ST_TABLE_P(h)
Definition: internal.h:861
rb_hashtype_ident
const struct st_hash_type rb_hashtype_ident
Definition: hash.c:322
rb_hash_set_pair
VALUE rb_hash_set_pair(VALUE hash, VALUE arg)
Definition: hash.c:3257
RHash
Definition: internal.h:887
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
rb_str_buf_append
VALUE rb_str_buf_append(VALUE, VALUE)
Definition: string.c:2950
rb_exec_recursive_outer
VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5098
st_values
st_index_t st_values(st_table *tab, st_data_t *values, st_index_t size)
Definition: st.c:1795
crt_externs.h
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
st_foreach
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1718
RHASH_AR_TABLE
#define RHASH_AR_TABLE(hash)
Definition: internal.h:855
RHASH_ST_TABLE_SET
#define RHASH_ST_TABLE_SET(h, s)
Definition: hash.c:432
rb_check_hash_type
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:1825
PATH_ENV
#define PATH_ENV
Definition: defines.h:441
RHASH_AR_TABLE_BOUND_SHIFT
#define RHASH_AR_TABLE_BOUND_SHIFT
Definition: internal.h:867
FL_TEST_RAW
#define FL_TEST_RAW(x, f)
Definition: ruby.h:1352
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
rb_func_proc_new
VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val)
Definition: proc.c:728
fopen
FILE * fopen(const char *__restrict _name, const char *__restrict _type)
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
rb_foreach_func
int rb_foreach_func(VALUE, VALUE, VALUE)
Definition: hash.c:1284
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
foreach_safe_arg
Definition: hash.c:1251
internal.h
update_func_arg
Definition: hash.c:3797
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
f
#define f
RHASH_ST_TABLE
#define RHASH_ST_TABLE(hash)
Definition: internal.h:856
update_arg::new_value
VALUE new_value
Definition: hash.c:1617
ar_table_pair_struct::val
VALUE val
Definition: hash.c:346
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2892
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
ruby_setenv
void ruby_setenv(const char *name, const char *value)
Definition: hash.c:4923
st_init_table
st_table * st_init_table(const struct st_hash_type *type)
Definition: st.c:645
rb_hash_uint
#define rb_hash_uint(h, i)
Definition: intern.h:815
id_hash
ID id_hash
Definition: eventids1.c:53
st_keys
st_index_t st_keys(st_table *tab, st_data_t *keys, st_index_t size)
Definition: st.c:1757
rb_w32_osver
DWORD rb_w32_osver(void)
Definition: win32.c:319
rb_warn_deprecated
void rb_warn_deprecated(const char *fmt, const char *suggest,...)
Definition: error.c:364
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.0.h:5363
rb_utf8_encoding
rb_encoding * rb_utf8_encoding(void)
Definition: encoding.c:1328
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:129
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
shift_var::key
VALUE key
Definition: hash.c:2323
st_index_hash
#define st_index_hash(index)
Definition: hash.c:265
RGENGC_WB_PROTECTED_HASH
#define RGENGC_WB_PROTECTED_HASH
Definition: ruby.h:805
rb_hash_end
#define rb_hash_end(h)
Definition: intern.h:816
ruby_register_rollback_func_for_ensure
void ruby_register_rollback_func_for_ensure(e_proc *ensure_func, e_proc *rollback_func)
Definition: cont.c:1520
debug_counter.h
env_name
#define env_name(s)
Definition: hash.c:4687
keys
const rb_iseq_t const char const VALUE keys
Definition: rb_mjit_min_header-2.7.0.h:13506
functor::arg
st_data_t arg
Definition: hash.c:908
st_table::type
const struct st_hash_type * type
Definition: st.h:84
rb_locale_encindex
int rb_locale_encindex(void)
Definition: encoding.c:1354
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2779
rb_cString
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:2044
RHASH_SET_IFNONE
#define RHASH_SET_IFNONE(h, ifnone)
Definition: ruby.h:1132
update_arg::old_key
VALUE old_key
Definition: hash.c:1616
rb_obj_info_dump
void rb_obj_info_dump(VALUE obj)
Definition: gc.c:11661
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
rb_hash_delete
VALUE rb_hash_delete(VALUE hash, VALUE key)
Definition: hash.c:2271
fail
#define fail()
Definition: date_strptime.c:123
to_hash
#define to_hash
Definition: hash.c:1822
idTo_proc
@ idTo_proc
Definition: rb_mjit_min_header-2.7.0.h:8718
identhash
#define identhash
Definition: hash.c:321
rb_external_str_new_with_enc
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *)
Definition: string.c:1036
argc
int argc
Definition: ruby.c:222
rb_str_initialize
VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc)
Definition: string.c:964
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.0.h:11111
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2799
rb_hash_fetch
VALUE rb_hash_fetch(VALUE hash, VALUE key)
Definition: hash.c:2061
REALLOC_N
#define REALLOC_N(var, type, n)
Definition: ruby.h:1667
GET_ENVIRON
#define GET_ENVIRON(e)
Definition: hash.c:4571
free
#define free(x)
Definition: dln.c:52
RHASH_ITER_LEV
#define RHASH_ITER_LEV(h)
Definition: ruby.h:1128
recur
#define recur(fmt)
Definition: date_strptime.c:152
RHASH_LEV_SHIFT
@ RHASH_LEV_SHIFT
Definition: internal.h:835
update_callback_arg::hash
VALUE hash
Definition: hash.c:1594
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
xfree
#define xfree
Definition: defines.h:216
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
RHASH_TYPE
#define RHASH_TYPE(hash)
Definition: hash.c:433
ruby_strdup
char * ruby_strdup(const char *)
Definition: util.c:527
ar_table_struct::pairs
ar_table_pair pairs[RHASH_AR_TABLE_MAX_SIZE]
Definition: hash.c:351
SET_PROC_DEFAULT
#define SET_PROC_DEFAULT(hash, proc)
Definition: hash.c:50
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
st_hash_t
st_index_t st_hash_t
Definition: hash.c:327
RHASH_AR_TABLE_BOUND_RAW
#define RHASH_AR_TABLE_BOUND_RAW(h)
Definition: hash.c:425
FREE_ENVIRON
#define FREE_ENVIRON(e)
Definition: hash.c:4572
st_foreach_func
int st_foreach_func(st_data_t, st_data_t, st_data_t)
Definition: hash.c:1249
MJIT_FUNC_EXPORTED
#define MJIT_FUNC_EXPORTED
Definition: defines.h:396
_
#define _(args)
Definition: dln.h:28
setenv
int setenv(const char *__string, const char *__value, int __overwrite)
ar_table_struct
Definition: hash.c:349
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_hash_set_ifnone
VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
Definition: hash.c:99
ruby_tz_uptodate_p
bool ruby_tz_uptodate_p
Definition: time.c:674
update_func_arg::hash
VALUE hash
Definition: hash.c:3798
HAS_EXTRA_STATES
#define HAS_EXTRA_STATES(hash, klass)
Definition: hash.c:41
equal_data::result
VALUE result
Definition: hash.c:3479
len
uint8_t len
Definition: escape.c:17
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
rb_hash_ar_table
ar_table * rb_hash_ar_table(VALUE hash)
Definition: hash.c:544
RB_DEBUG_COUNTER_INC
#define RB_DEBUG_COUNTER_INC(type)
Definition: debug_counter.h:375
rb_usascii_str_new2
#define rb_usascii_str_new2
Definition: intern.h:909
tbl_update_func
int(* tbl_update_func)(st_data_t *, st_data_t *, st_data_t, int)
Definition: hash.c:1621
rb_exec_recursive_paired
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5086
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_hash_key_str
VALUE rb_hash_key_str(VALUE key)
Definition: hash.c:2729
MAYBE_UNUSED
#define MAYBE_UNUSED
Definition: ffi_common.h:32
rb_hash_stlike_foreach_with_replace
int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
Definition: hash.c:1431
rb_hash_select
VALUE rb_hash_select(VALUE hash)
Definition: hash.c:2606
hash_foreach_arg::func
rb_foreach_func * func
Definition: hash.c:1288
RHASH_TBL_RAW
#define RHASH_TBL_RAW(h)
Definition: internal.h:1689
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
reset_hash_type_arg::orighash
const struct st_hash_type * orighash
Definition: hash.c:3903
rb_hash_stlike_foreach
int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
Definition: hash.c:1420
SET_DEFAULT
#define SET_DEFAULT(hash, ifnone)
Definition: hash.c:46
update_arg
Definition: hash.c:1612
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1114
COPY_DEFAULT
#define COPY_DEFAULT(hash, hash2)
Definition: hash.c:52
ECONV_INVALID_REPLACE
#define ECONV_INVALID_REPLACE
Definition: encoding.h:394
rb_builtin_class_name
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:797
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
rb_enc_str_asciionly_p
int rb_enc_str_asciionly_p(VALUE)
Definition: string.c:678
RHASH_AR_TABLE_SIZE_SHIFT
#define RHASH_AR_TABLE_SIZE_SHIFT
Definition: internal.h:865
RHASH_AR_TABLE_SIZE_MASK
#define RHASH_AR_TABLE_SIZE_MASK
Definition: internal.h:864
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
ar_table_pair_struct
Definition: hash.c:344
rehash_arg::tbl
st_table * tbl
Definition: hash.c:1849
rb_str_buf_cat
#define rb_str_buf_cat
Definition: intern.h:910
rb_hash_reject_bang
VALUE rb_hash_reject_bang(VALUE hash)
Definition: hash.c:2440
rb_w32_getenv
char * rb_w32_getenv(const char *)
Definition: win32.c:5237
rb_key_err_raise
#define rb_key_err_raise(mesg, recv, name)
Definition: internal.h:1578
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.0.h:5462
st_lookup
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
util.h
ar_table_pair_struct::key
VALUE key
Definition: hash.c:345
ST_DATA_COMPATIBLE_P
#define ST_DATA_COMPATIBLE_P(type)
Definition: st.h:72
RB_FL_ANY_RAW
#define RB_FL_ANY_RAW(x, f)
Definition: ruby.h:1318
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
environ
char ** environ
unsetenv
int unsetenv(const char *)
RARRAY_PTR_USE_TRANSIENT
#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr)
Definition: ruby.h:1084
RHASH_AR_TABLE_MAX_BOUND
#define RHASH_AR_TABLE_MAX_BOUND
Definition: hash.c:339
rb_hash_freeze
VALUE rb_hash_freeze(VALUE hash)
Definition: hash.c:87
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
st_free_table
void st_free_table(st_table *tab)
Definition: st.c:709
st_table
Definition: st.h:79
RHASH_AR_TABLE_P
#define RHASH_AR_TABLE_P(hash)
Definition: internal.h:854
rb_str_conv_enc
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Definition: string.c:1030
RHASH_UPDATE
#define RHASH_UPDATE(hash, key, func, arg)
Definition: hash.c:1667
ruby_assert.h
rb_intern
#define rb_intern(str)
rb_any_to_s
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
Definition: object.c:527
equal_data::hash
VALUE hash
Definition: hash.c:3480
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_dbl_long_hash
long rb_dbl_long_hash(double d)
Definition: hash.c:160
ruby_unsetenv
void ruby_unsetenv(const char *name)
Definition: hash.c:5062
ENVMATCH
#define ENVMATCH(n1, n2)
Definition: hash.c:4578
RTEST
#define RTEST(v)
Definition: ruby.h:481
object_id
#define object_id
Definition: vm_method.c:31
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
rb_str_buf_new2
#define rb_str_buf_new2
Definition: intern.h:908
RHASH_AR_TABLE_REF
#define RHASH_AR_TABLE_REF(hash, n)
Definition: hash.c:341
RHASH_AR_CLEARED_HINT
#define RHASH_AR_CLEARED_HINT
Definition: hash.c:342
__sFILE
Definition: vsnprintf.c:169
get_env_ptr
#define get_env_ptr(var, val)
Definition: hash.c:4674
rb_env_path_tainted
int rb_env_path_tainted(void)
Definition: hash.c:4829
Init_Hash
void Init_Hash(void)
Definition: hash.c:6222
rb_syserr_fail_str
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2787
st_hash_type::hash
st_index_t(* hash)(st_data_t)
Definition: st.h:63
RHASH_LEV_MAX
@ RHASH_LEV_MAX
Definition: internal.h:836
memchr
void * memchr(const void *, int, size_t)
name
const char * name
Definition: nkf.c:208
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:837