Ruby 4.1.0dev (2026-05-15 revision 4ec235e0b227d38426aa477e537ac397963c0ee8)
hash.c (4ec235e0b227d38426aa477e537ac397963c0ee8)
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/internal/config.h"
15
16#include <errno.h>
17
18#ifdef __APPLE__
19# ifdef HAVE_CRT_EXTERNS_H
20# include <crt_externs.h>
21# else
22# include "missing/crt_externs.h"
23# endif
24#endif
25
26#include "debug_counter.h"
27#include "id.h"
28#include "internal.h"
29#include "internal/array.h"
30#include "internal/bignum.h"
31#include "internal/basic_operators.h"
32#include "internal/class.h"
33#include "internal/cont.h"
34#include "internal/error.h"
35#include "internal/hash.h"
36#include "internal/object.h"
37#include "internal/proc.h"
38#include "internal/st.h"
39#include "internal/symbol.h"
40#include "internal/thread.h"
41#include "internal/time.h"
42#include "internal/vm.h"
43#include "probes.h"
44#include "ruby/st.h"
45#include "ruby/util.h"
46#include "ruby_assert.h"
47#include "symbol.h"
48#include "ruby/thread_native.h"
49#include "ruby/ractor.h"
50#include "vm_sync.h"
51#include "builtin.h"
52
53/* Flags of RHash
54 *
55 * 1: RHASH_PASS_AS_KEYWORDS
56 * The hash is flagged as Ruby 2 keywords hash.
57 * 2: RHASH_PROC_DEFAULT
58 * The hash has a default proc (rather than a default value).
59 * 3: RHASH_ST_TABLE_FLAG
60 * The hash uses a ST table (rather than an AR table).
61 * 4-7: RHASH_AR_TABLE_SIZE_MASK
62 * The size of the AR table.
63 * 8-11: RHASH_AR_TABLE_BOUND_MASK
64 * The bounds of the AR table.
65 * 13-19: RHASH_LEV_MASK
66 * The iterational level of the hash. Used to prevent modifications
67 * to the hash during iteration.
68 */
69
70#ifndef HASH_DEBUG
71#define HASH_DEBUG 0
72#endif
73
74#define SET_DEFAULT(hash, ifnone) ( \
75 FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \
76 RHASH_SET_IFNONE(hash, ifnone))
77
78#define SET_PROC_DEFAULT(hash, proc) set_proc_default(hash, proc)
79
80#define COPY_DEFAULT(hash, hash2) copy_default(RHASH(hash), RHASH(hash2))
81
82static inline void
83copy_default(struct RHash *hash, const struct RHash *hash2)
84{
85 hash->basic.flags &= ~RHASH_PROC_DEFAULT;
86 hash->basic.flags |= hash2->basic.flags & RHASH_PROC_DEFAULT;
87 RHASH_SET_IFNONE(hash, RHASH_IFNONE((VALUE)hash2));
88}
89
90static VALUE rb_hash_s_try_convert(VALUE, VALUE);
91
92/*
93 * Hash WB strategy:
94 * 1. Check mutate st_* functions
95 * * st_insert()
96 * * st_insert2()
97 * * st_update()
98 * * st_add_direct()
99 * 2. Insert WBs
100 */
101
102/* :nodoc: */
103VALUE
104rb_hash_freeze(VALUE hash)
105{
106 return rb_obj_freeze(hash);
107}
108
110VALUE rb_cHash_empty_frozen;
111
112static VALUE envtbl;
113static ID id_hash, id_flatten_bang;
114static ID id_hash_iter_lev;
115
116#define id_default idDefault
117
118VALUE
119rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
120{
121 RB_OBJ_WRITE(hash, (&RHASH(hash)->ifnone), ifnone);
122 return hash;
123}
124
125int
126rb_any_cmp(VALUE a, VALUE b)
127{
128 if (a == b) return 0;
129 if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString &&
130 RB_TYPE_P(b, T_STRING) && RBASIC(b)->klass == rb_cString) {
131 return rb_str_hash_cmp(a, b);
132 }
133 if (UNDEF_P(a) || UNDEF_P(b)) return -1;
134 if (SYMBOL_P(a) && SYMBOL_P(b)) {
135 return a != b;
136 }
137
138 return !rb_eql(a, b);
139}
140
141static VALUE
142hash_recursive(VALUE obj, VALUE arg, int recurse)
143{
144 if (recurse) return INT2FIX(0);
145 return rb_funcallv(obj, id_hash, 0, 0);
146}
147
148static long rb_objid_hash(st_index_t index);
149
150static st_index_t
151dbl_to_index(double d)
152{
153 union {double d; st_index_t i;} u;
154 u.d = d;
155 return u.i;
156}
157
158long
159rb_dbl_long_hash(double d)
160{
161 /* normalize -0.0 to 0.0 */
162 if (d == 0.0) d = 0.0;
163#if SIZEOF_INT == SIZEOF_VOIDP
164 return rb_memhash(&d, sizeof(d));
165#else
166 return rb_objid_hash(dbl_to_index(d));
167#endif
168}
169
170static inline long
171any_hash(VALUE a, st_index_t (*other_func)(VALUE))
172{
173 VALUE hval;
174 st_index_t hnum;
175
176 switch (TYPE(a)) {
177 case T_SYMBOL:
178 if (STATIC_SYM_P(a)) {
179 hnum = a >> (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT);
180 hnum = rb_hash_start(hnum);
181 }
182 else {
183 hnum = RSHIFT(RSYMBOL(a)->hashval, 1);
184 }
185 break;
186 case T_FIXNUM:
187 case T_TRUE:
188 case T_FALSE:
189 case T_NIL:
190 hnum = rb_objid_hash((st_index_t)a);
191 break;
192 case T_STRING:
193 hnum = rb_str_hash(a);
194 break;
195 case T_BIGNUM:
196 hval = rb_big_hash(a);
197 hnum = FIX2LONG(hval);
198 break;
199 case T_FLOAT: /* prevent pathological behavior: [Bug #10761] */
200 hnum = rb_dbl_long_hash(rb_float_value(a));
201 break;
202 default:
203 hnum = other_func(a);
204 }
205 if ((SIGNED_VALUE)hnum > 0)
206 hnum &= FIXNUM_MAX;
207 else
208 hnum |= FIXNUM_MIN;
209 return (long)hnum;
210}
211
212VALUE rb_obj_hash(VALUE obj);
213VALUE rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *cme, int kw_splat);
214
215static st_index_t
216obj_any_hash(VALUE obj)
217{
218 VALUE hval = Qundef;
219 VALUE klass = CLASS_OF(obj);
220 if (klass) {
221 const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, id_hash);
222 if (cme && METHOD_ENTRY_BASIC(cme)) {
223 // Optimize away the frame push overhead if it's the default Kernel#hash
224 if (cme->def->type == VM_METHOD_TYPE_CFUNC && cme->def->body.cfunc.func == (rb_cfunc_t)rb_obj_hash) {
225 hval = rb_obj_hash(obj);
226 }
227 else if (RBASIC_CLASS(cme->defined_class) == rb_mKernel) {
228 hval = rb_vm_call0(GET_EC(), obj, id_hash, 0, 0, cme, 0);
229 }
230 }
231 }
232
233 if (UNDEF_P(hval)) {
234 hval = rb_exec_recursive_outer_mid(hash_recursive, obj, 0, id_hash);
235 }
236
237 while (!FIXNUM_P(hval)) {
238 if (RB_TYPE_P(hval, T_BIGNUM)) {
239 int sign;
240 unsigned long ul;
241 sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0,
243 if (sign < 0) {
244 hval = LONG2FIX(ul | FIXNUM_MIN);
245 }
246 else {
247 hval = LONG2FIX(ul & FIXNUM_MAX);
248 }
249 }
250 hval = rb_to_int(hval);
251 }
252
253 return FIX2LONG(hval);
254}
255
256st_index_t
257rb_any_hash(VALUE a)
258{
259 return any_hash(a, obj_any_hash);
260}
261
262VALUE
263rb_hash(VALUE obj)
264{
265 return LONG2FIX(any_hash(obj, obj_any_hash));
266}
267
268
269/* Here is a hash function for 64-bit key. It is about 5 times faster
270 (2 times faster when uint128 type is absent) on Haswell than
271 tailored Spooky or City hash function can be. */
272
273/* Here we two primes with random bit generation. */
274static const uint64_t prime1 = ((uint64_t)0x2e0bb864 << 32) | 0xe9ea7df5;
275static const uint32_t prime2 = 0x830fcab9;
276
277
278static inline uint64_t
279mult_and_mix(uint64_t m1, uint64_t m2)
280{
281#if defined HAVE_UINT128_T
282 uint128_t r = (uint128_t) m1 * (uint128_t) m2;
283 return (uint64_t) (r >> 64) ^ (uint64_t) r;
284#else
285 uint64_t hm1 = m1 >> 32, hm2 = m2 >> 32;
286 uint64_t lm1 = m1, lm2 = m2;
287 uint64_t v64_128 = hm1 * hm2;
288 uint64_t v32_96 = hm1 * lm2 + lm1 * hm2;
289 uint64_t v1_32 = lm1 * lm2;
290
291 return (v64_128 + (v32_96 >> 32)) ^ ((v32_96 << 32) + v1_32);
292#endif
293}
294
295static inline uint64_t
296key64_hash(uint64_t key, uint32_t seed)
297{
298 return mult_and_mix(key + seed, prime1);
299}
300
301/* Should cast down the result for each purpose */
302#define st_index_hash(index) key64_hash(rb_hash_start(index), prime2)
303
304static long
305rb_objid_hash(st_index_t index)
306{
307 return (long)st_index_hash(index);
308}
309
310static st_index_t
311objid_hash(VALUE obj)
312{
313 VALUE object_id = rb_obj_id(obj);
314 if (!FIXNUM_P(object_id))
315 object_id = rb_big_hash(object_id);
316
317#if SIZEOF_LONG == SIZEOF_VOIDP
318 return (st_index_t)st_index_hash((st_index_t)NUM2LONG(object_id));
319#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
320 return (st_index_t)st_index_hash((st_index_t)NUM2LL(object_id));
321#endif
322}
323
324/*
325 * call-seq:
326 * hash -> integer
327 *
328 * Returns the integer hash value for +self+;
329 * has the property that if <tt>foo.eql?(bar)</tt>
330 * then <tt>foo.hash == bar.hash</tt>.
331 *
332 * \Class Hash uses both #hash and #eql? to determine whether two objects
333 * used as hash keys are to be treated as the same key.
334 * A hash value that exceeds the capacity of an Integer is truncated before being used.
335 *
336 * Many core classes override method Object#hash;
337 * other core classes (e.g., Integer) calculate the hash internally,
338 * and do not call the #hash method when used as a hash key.
339 *
340 * When implementing #hash for a user-defined class,
341 * best practice is to use Array#hash with the class name and the values
342 * that are important in the instance;
343 * this takes advantage of that method's logic for safely and efficiently
344 * generating a hash value:
345 *
346 * def hash
347 * [self.class, a, b, c].hash
348 * end
349 *
350 * The hash value may differ among invocations or implementations of Ruby.
351 * If you need stable hash-like identifiers across Ruby invocations and implementations,
352 * use a custom method to generate them.
353 */
354VALUE
355rb_obj_hash(VALUE obj)
356{
357 long hnum = any_hash(obj, objid_hash);
358 return ST2FIX(hnum);
359}
360
361static const struct st_hash_type objhash = {
362 rb_any_cmp,
363 rb_any_hash,
364};
365
366#define rb_ident_cmp st_numcmp
367
368static st_index_t
369rb_ident_hash(st_data_t n)
370{
371#ifdef USE_FLONUM /* RUBY */
372 /*
373 * - flonum (on 64-bit) is pathologically bad, mix the actual
374 * float value in, but do not use the float value as-is since
375 * many integers get interpreted as 2.0 or -2.0 [Bug #10761]
376 */
377 if (FLONUM_P(n)) {
378 n ^= dbl_to_index(rb_float_value(n));
379 }
380#endif
381
382 return (st_index_t)st_index_hash((st_index_t)n);
383}
384
385#define identhash rb_hashtype_ident
386const struct st_hash_type rb_hashtype_ident = {
387 rb_ident_cmp,
388 rb_ident_hash,
389};
390
391#define RHASH_IDENTHASH_P(hash) (RHASH_TYPE(hash) == &identhash)
392#define RHASH_STRING_KEY_P(hash, key) (!RHASH_IDENTHASH_P(hash) && (rb_obj_class(key) == rb_cString))
393
394typedef st_index_t st_hash_t;
395
396/*
397 * RHASH_AR_TABLE_P(h):
398 * RHASH_AR_TABLE points to ar_table.
399 *
400 * !RHASH_AR_TABLE_P(h):
401 * RHASH_ST_TABLE points st_table.
402 */
403
404#define RHASH_AR_TABLE_MAX_BOUND RHASH_AR_TABLE_MAX_SIZE
405
406#define RHASH_AR_TABLE_REF(hash, n) (&RHASH_AR_TABLE(hash)->pairs[n])
407#define RHASH_AR_CLEARED_HINT 0xff
408
409static inline st_hash_t
410ar_do_hash(st_data_t key)
411{
412 return (st_hash_t)rb_any_hash(key);
413}
414
415static inline ar_hint_t
416ar_do_hash_hint(st_hash_t hash_value)
417{
418 return (ar_hint_t)hash_value;
419}
420
421static inline ar_hint_t
422ar_hint(VALUE hash, unsigned int index)
423{
424 return RHASH_AR_TABLE(hash)->ar_hint.ary[index];
425}
426
427static inline void
428ar_hint_set_hint(VALUE hash, unsigned int index, ar_hint_t hint)
429{
430 RHASH_AR_TABLE(hash)->ar_hint.ary[index] = hint;
431}
432
433static inline void
434ar_hint_set(VALUE hash, unsigned int index, st_hash_t hash_value)
435{
436 ar_hint_set_hint(hash, index, ar_do_hash_hint(hash_value));
437}
438
439static inline void
440ar_clear_entry(VALUE hash, unsigned int index)
441{
442 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
443 pair->key = Qundef;
444 ar_hint_set_hint(hash, index, RHASH_AR_CLEARED_HINT);
445}
446
447static inline int
448ar_cleared_entry(VALUE hash, unsigned int index)
449{
450 if (ar_hint(hash, index) == RHASH_AR_CLEARED_HINT) {
451 /* RHASH_AR_CLEARED_HINT is only a hint, not mean cleared entry,
452 * so you need to check key == Qundef
453 */
454 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
455 return UNDEF_P(pair->key);
456 }
457 else {
458 return FALSE;
459 }
460}
461
462static inline void
463ar_set_entry(VALUE hash, unsigned int index, st_data_t key, st_data_t val, st_hash_t hash_value)
464{
465 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
466 pair->key = key;
467 pair->val = val;
468 ar_hint_set(hash, index, hash_value);
469}
470
471#define RHASH_AR_TABLE_SIZE(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
472 RHASH_AR_TABLE_SIZE_RAW(h))
473
474#define HASH_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(HASH_DEBUG, expr, #expr)
475
476#if HASH_DEBUG
477#define hash_verify(hash) hash_verify_(hash, __FILE__, __LINE__)
478
479static VALUE
480hash_verify_(VALUE hash, const char *file, int line)
481{
482 HASH_ASSERT(RB_TYPE_P(hash, T_HASH));
483
484 if (RHASH_AR_TABLE_P(hash)) {
485 unsigned i, n = 0, bound = RHASH_AR_TABLE_BOUND(hash);
486
487 for (i=0; i<bound; i++) {
488 st_data_t k, v;
489 if (!ar_cleared_entry(hash, i)) {
490 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
491 k = pair->key;
492 v = pair->val;
493 HASH_ASSERT(!UNDEF_P(k));
494 HASH_ASSERT(!UNDEF_P(v));
495 n++;
496 }
497 }
498 if (n != RHASH_AR_TABLE_SIZE(hash)) {
499 rb_bug("n:%u, RHASH_AR_TABLE_SIZE:%u", n, RHASH_AR_TABLE_SIZE(hash));
500 }
501 }
502 else {
503 HASH_ASSERT(RHASH_ST_TABLE(hash) != NULL);
504 HASH_ASSERT(RHASH_AR_TABLE_SIZE_RAW(hash) == 0);
505 HASH_ASSERT(RHASH_AR_TABLE_BOUND_RAW(hash) == 0);
506 }
507
508 return hash;
509}
510
511#else
512#define hash_verify(h) ((void)0)
513#endif
514
515static inline int
516RHASH_TABLE_EMPTY_P(VALUE hash)
517{
518 return RHASH_SIZE(hash) == 0;
519}
520
521#define RHASH_SET_ST_FLAG(h) FL_SET_RAW(h, RHASH_ST_TABLE_FLAG)
522#define RHASH_UNSET_ST_FLAG(h) FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG)
523
524static void
525hash_st_table_init(VALUE hash, const struct st_hash_type *type, st_index_t size)
526{
527 st_init_existing_table_with_size(RHASH_ST_TABLE(hash), type, size);
528 RHASH_SET_ST_FLAG(hash);
529}
530
531void
532rb_hash_st_table_set(VALUE hash, st_table *st)
533{
534 HASH_ASSERT(st != NULL);
535 RHASH_SET_ST_FLAG(hash);
536
537 *RHASH_ST_TABLE(hash) = *st;
538}
539
540static inline void
541RHASH_AR_TABLE_BOUND_SET(VALUE h, st_index_t n)
542{
543 HASH_ASSERT(RHASH_AR_TABLE_P(h));
544 HASH_ASSERT(n <= RHASH_AR_TABLE_MAX_BOUND);
545
546 RBASIC(h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
547 RBASIC(h)->flags |= n << RHASH_AR_TABLE_BOUND_SHIFT;
548}
549
550static inline void
551RHASH_AR_TABLE_SIZE_SET(VALUE h, st_index_t n)
552{
553 HASH_ASSERT(RHASH_AR_TABLE_P(h));
554 HASH_ASSERT(n <= RHASH_AR_TABLE_MAX_SIZE);
555
556 RBASIC(h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
557 RBASIC(h)->flags |= n << RHASH_AR_TABLE_SIZE_SHIFT;
558}
559
560static inline void
561HASH_AR_TABLE_SIZE_ADD(VALUE h, st_index_t n)
562{
563 HASH_ASSERT(RHASH_AR_TABLE_P(h));
564
565 RHASH_AR_TABLE_SIZE_SET(h, RHASH_AR_TABLE_SIZE(h) + n);
566
567 hash_verify(h);
568}
569
570#define RHASH_AR_TABLE_SIZE_INC(h) HASH_AR_TABLE_SIZE_ADD(h, 1)
571
572static inline void
573RHASH_AR_TABLE_SIZE_DEC(VALUE h)
574{
575 HASH_ASSERT(RHASH_AR_TABLE_P(h));
576 int new_size = RHASH_AR_TABLE_SIZE(h) - 1;
577
578 if (new_size != 0) {
579 RHASH_AR_TABLE_SIZE_SET(h, new_size);
580 }
581 else {
582 RHASH_AR_TABLE_SIZE_SET(h, 0);
583 RHASH_AR_TABLE_BOUND_SET(h, 0);
584 }
585 hash_verify(h);
586}
587
588static inline void
589RHASH_AR_TABLE_CLEAR(VALUE h)
590{
591 RUBY_ASSERT(rb_gc_obj_slot_size(h) >= sizeof(struct RHash) + sizeof(ar_table));
592 RBASIC(h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
593 RBASIC(h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
594
595 memset(RHASH_AR_TABLE(h), 0, sizeof(ar_table));
596}
597
598NOINLINE(static int ar_equal(VALUE x, VALUE y));
599
600static int
601ar_equal(VALUE x, VALUE y)
602{
603 return rb_any_cmp(x, y) == 0;
604}
605
606static unsigned
607ar_find_entry_hint(VALUE hash, ar_hint_t hint, st_data_t key)
608{
609 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
610 const ar_hint_t *hints = RHASH_AR_TABLE(hash)->ar_hint.ary;
611
612 /* if table is NULL, then bound also should be 0 */
613
614 for (i = 0; i < bound; i++) {
615 if (hints[i] == hint) {
616 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
617 if (ar_equal(key, pair->key)) {
618 RB_DEBUG_COUNTER_INC(artable_hint_hit);
619 return i;
620 }
621 else {
622#if 0
623 static int pid;
624 static char fname[256];
625 static FILE *fp;
626
627 if (pid != getpid()) {
628 snprintf(fname, sizeof(fname), "/tmp/ruby-armiss.%d", pid = getpid());
629 if ((fp = fopen(fname, "w")) == NULL) rb_bug("fopen");
630 }
631
632 st_hash_t h1 = ar_do_hash(key);
633 st_hash_t h2 = ar_do_hash(pair->key);
634
635 fprintf(fp, "miss: hash_eq:%d hints[%d]:%02x hint:%02x\n"
636 " key :%016lx %s\n"
637 " pair->key:%016lx %s\n",
638 h1 == h2, i, hints[i], hint,
639 h1, rb_obj_info(key), h2, rb_obj_info(pair->key));
640#endif
641 RB_DEBUG_COUNTER_INC(artable_hint_miss);
642 }
643 }
644 }
645 RB_DEBUG_COUNTER_INC(artable_hint_notfound);
646 return RHASH_AR_TABLE_MAX_BOUND;
647}
648
649static unsigned
650ar_find_entry(VALUE hash, st_hash_t hash_value, st_data_t key)
651{
652 ar_hint_t hint = ar_do_hash_hint(hash_value);
653 return ar_find_entry_hint(hash, hint, key);
654}
655
656static inline void
657hash_ar_free_and_clear_table(VALUE hash)
658{
659 RHASH_AR_TABLE_CLEAR(hash);
660
661 HASH_ASSERT(RHASH_AR_TABLE_SIZE(hash) == 0);
662 HASH_ASSERT(RHASH_AR_TABLE_BOUND(hash) == 0);
663}
664
665void rb_st_add_direct_with_hash(st_table *tab, st_data_t key, st_data_t value, st_hash_t hash); // st.c
666
667enum ar_each_key_type {
668 ar_each_key_copy,
669 ar_each_key_cmp,
670 ar_each_key_insert,
671};
672
673static inline int
674ar_each_key(ar_table *ar, int max, enum ar_each_key_type type, st_data_t *dst_keys, st_table *new_tab, st_hash_t *hashes)
675{
676 for (int i = 0; i < max; i++) {
677 ar_table_pair *pair = &ar->pairs[i];
678
679 switch (type) {
680 case ar_each_key_copy:
681 dst_keys[i] = pair->key;
682 break;
683 case ar_each_key_cmp:
684 if (dst_keys[i] != pair->key) return 1;
685 break;
686 case ar_each_key_insert:
687 if (UNDEF_P(pair->key)) continue; // deleted entry
688 rb_st_add_direct_with_hash(new_tab, pair->key, pair->val, hashes[i]);
689 break;
690 }
691 }
692
693 return 0;
694}
695
696static st_table *
697ar_force_convert_table(VALUE hash, const char *file, int line)
698{
699 if (RHASH_ST_TABLE_P(hash)) {
700 return RHASH_ST_TABLE(hash);
701 }
702 else {
703 ar_table *ar = RHASH_AR_TABLE(hash);
704 st_hash_t hashes[RHASH_AR_TABLE_MAX_SIZE];
705 unsigned int bound, size;
706
707 RUBY_ASSERT(rb_gc_obj_slot_size(hash) >= sizeof(struct RHash) + sizeof(ar_table));
708
709 // prepare hash values
710 do {
711 st_data_t keys[RHASH_AR_TABLE_MAX_SIZE];
712 bound = RHASH_AR_TABLE_BOUND(hash);
713 size = RHASH_AR_TABLE_SIZE(hash);
714 ar_each_key(ar, bound, ar_each_key_copy, keys, NULL, NULL);
715
716 for (unsigned int i = 0; i < bound; i++) {
717 // do_hash calls #hash method and it can modify hash object
718 hashes[i] = UNDEF_P(keys[i]) ? 0 : ar_do_hash(keys[i]);
719 }
720
721 // check if modified
722 if (UNLIKELY(!RHASH_AR_TABLE_P(hash))) return RHASH_ST_TABLE(hash);
723 if (UNLIKELY(RHASH_AR_TABLE_BOUND(hash) != bound)) continue;
724 if (UNLIKELY(ar_each_key(ar, bound, ar_each_key_cmp, keys, NULL, NULL))) continue;
725 } while (0);
726
727 // make st
728 st_table tab;
729 st_table *new_tab = &tab;
730 st_init_existing_table_with_size(new_tab, &objhash, size);
731 ar_each_key(ar, bound, ar_each_key_insert, NULL, new_tab, hashes);
732 hash_ar_free_and_clear_table(hash);
733 RHASH_ST_TABLE_SET(hash, new_tab);
734 return RHASH_ST_TABLE(hash);
735 }
736}
737
738static int
739ar_compact_table(VALUE hash)
740{
741 const unsigned bound = RHASH_AR_TABLE_BOUND(hash);
742 const unsigned size = RHASH_AR_TABLE_SIZE(hash);
743
744 if (size == bound) {
745 return size;
746 }
747 else {
748 unsigned i, j=0;
749 ar_table_pair *pairs = RHASH_AR_TABLE(hash)->pairs;
750
751 for (i=0; i<bound; i++) {
752 if (ar_cleared_entry(hash, i)) {
753 if (j <= i) j = i+1;
754 for (; j<bound; j++) {
755 if (!ar_cleared_entry(hash, j)) {
756 pairs[i] = pairs[j];
757 ar_hint_set_hint(hash, i, (st_hash_t)ar_hint(hash, j));
758 ar_clear_entry(hash, j);
759 j++;
760 goto found;
761 }
762 }
763 /* non-empty is not found */
764 goto done;
765 found:;
766 }
767 }
768 done:
769 HASH_ASSERT(i<=bound);
770
771 RHASH_AR_TABLE_BOUND_SET(hash, size);
772 hash_verify(hash);
773 return size;
774 }
775}
776
777static int
778ar_add_direct_with_hash(VALUE hash, st_data_t key, st_data_t val, st_hash_t hash_value)
779{
780 unsigned bin = RHASH_AR_TABLE_BOUND(hash);
781
782 if (RHASH_AR_TABLE_SIZE(hash) >= RHASH_AR_TABLE_MAX_SIZE) {
783 return 1;
784 }
785 else {
786 if (UNLIKELY(bin >= RHASH_AR_TABLE_MAX_BOUND)) {
787 bin = ar_compact_table(hash);
788 }
789 HASH_ASSERT(bin < RHASH_AR_TABLE_MAX_BOUND);
790
791 ar_set_entry(hash, bin, key, val, hash_value);
792 RHASH_AR_TABLE_BOUND_SET(hash, bin+1);
793 RHASH_AR_TABLE_SIZE_INC(hash);
794 return 0;
795 }
796}
797
798static void
799ensure_ar_table(VALUE hash)
800{
801 if (!RHASH_AR_TABLE_P(hash)) {
802 rb_raise(rb_eRuntimeError, "hash representation was changed during iteration");
803 }
804}
805
806static int
807ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
808{
809 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
810 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
811
812 for (i = 0; i < bound; i++) {
813 if (ar_cleared_entry(hash, i)) continue;
814
815 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
816 st_data_t key = (st_data_t)pair->key;
817 st_data_t val = (st_data_t)pair->val;
818 enum st_retval retval = (*func)(key, val, arg, 0);
819 ensure_ar_table(hash);
820 /* pair may be not valid here because of theap */
821
822 switch (retval) {
823 case ST_CONTINUE:
824 break;
825 case ST_CHECK:
826 case ST_STOP:
827 return 0;
828 case ST_REPLACE:
829 if (replace) {
830 (*replace)(&key, &val, arg, TRUE);
831
832 // Pair should not have moved
833 HASH_ASSERT(pair == RHASH_AR_TABLE_REF(hash, i));
834
835 pair->key = (VALUE)key;
836 pair->val = (VALUE)val;
837 }
838 break;
839 case ST_DELETE:
840 ar_clear_entry(hash, i);
841 RHASH_AR_TABLE_SIZE_DEC(hash);
842 break;
843 }
844 }
845 }
846 return 0;
847}
848
849static int
850ar_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
851{
852 return ar_general_foreach(hash, func, replace, arg);
853}
854
855struct functor {
856 st_foreach_callback_func *func;
857 st_data_t arg;
858};
859
860static int
861apply_functor(st_data_t k, st_data_t v, st_data_t d, int _)
862{
863 const struct functor *f = (void *)d;
864 return f->func(k, v, f->arg);
865}
866
867static int
868ar_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
869{
870 const struct functor f = { func, arg };
871 return ar_general_foreach(hash, apply_functor, NULL, (st_data_t)&f);
872}
873
874static int
875ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg,
876 st_data_t never)
877{
878 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
879 unsigned i, ret = 0, bound = RHASH_AR_TABLE_BOUND(hash);
880 enum st_retval retval;
881 st_data_t key;
882 ar_table_pair *pair;
883 ar_hint_t hint;
884
885 for (i = 0; i < bound; i++) {
886 if (ar_cleared_entry(hash, i)) continue;
887
888 pair = RHASH_AR_TABLE_REF(hash, i);
889 key = pair->key;
890 hint = ar_hint(hash, i);
891
892 retval = (*func)(key, pair->val, arg, 0);
893 ensure_ar_table(hash);
894 hash_verify(hash);
895
896 switch (retval) {
897 case ST_CHECK: {
898 pair = RHASH_AR_TABLE_REF(hash, i);
899 if (pair->key == never) break;
900 ret = ar_find_entry_hint(hash, hint, key);
901 if (ret == RHASH_AR_TABLE_MAX_BOUND) {
902 (*func)(0, 0, arg, 1);
903 return 2;
904 }
905 }
906 case ST_CONTINUE:
907 break;
908 case ST_STOP:
909 case ST_REPLACE:
910 return 0;
911 case ST_DELETE: {
912 if (!ar_cleared_entry(hash, i)) {
913 ar_clear_entry(hash, i);
914 RHASH_AR_TABLE_SIZE_DEC(hash);
915 }
916 break;
917 }
918 }
919 }
920 }
921 return 0;
922}
923
924static int
925ar_update(VALUE hash, st_data_t key,
926 st_update_callback_func *func, st_data_t arg)
927{
928 int retval, existing;
929 unsigned bin = RHASH_AR_TABLE_MAX_BOUND;
930 st_data_t value = 0, old_key;
931 st_hash_t hash_value = ar_do_hash(key);
932
933 if (UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
934 // `#hash` changes ar_table -> st_table
935 return -1;
936 }
937
938 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
939 bin = ar_find_entry(hash, hash_value, key);
940 existing = (bin != RHASH_AR_TABLE_MAX_BOUND) ? TRUE : FALSE;
941 }
942 else {
943 existing = FALSE;
944 }
945
946 if (existing) {
947 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, bin);
948 key = pair->key;
949 value = pair->val;
950 }
951 old_key = key;
952 retval = (*func)(&key, &value, arg, existing);
953 /* pair can be invalid here because of theap */
954 ensure_ar_table(hash);
955
956 switch (retval) {
957 case ST_CONTINUE:
958 if (!existing) {
959 if (ar_add_direct_with_hash(hash, key, value, hash_value)) {
960 return -1;
961 }
962 }
963 else {
964 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, bin);
965 if (old_key != key) {
966 pair->key = key;
967 }
968 pair->val = value;
969 }
970 break;
971 case ST_DELETE:
972 if (existing) {
973 ar_clear_entry(hash, bin);
974 RHASH_AR_TABLE_SIZE_DEC(hash);
975 }
976 break;
977 }
978 return existing;
979}
980
981static int
982ar_insert(VALUE hash, st_data_t key, st_data_t value)
983{
984 unsigned bin = RHASH_AR_TABLE_BOUND(hash);
985 st_hash_t hash_value = ar_do_hash(key);
986
987 if (UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
988 // `#hash` changes ar_table -> st_table
989 return -1;
990 }
991
992 bin = ar_find_entry(hash, hash_value, key);
993 if (bin == RHASH_AR_TABLE_MAX_BOUND) {
994 if (RHASH_AR_TABLE_SIZE(hash) >= RHASH_AR_TABLE_MAX_SIZE) {
995 return -1;
996 }
997 else if (bin >= RHASH_AR_TABLE_MAX_BOUND) {
998 bin = ar_compact_table(hash);
999 }
1000 HASH_ASSERT(bin < RHASH_AR_TABLE_MAX_BOUND);
1001
1002 ar_set_entry(hash, bin, key, value, hash_value);
1003 RHASH_AR_TABLE_BOUND_SET(hash, bin+1);
1004 RHASH_AR_TABLE_SIZE_INC(hash);
1005 return 0;
1006 }
1007 else {
1008 RHASH_AR_TABLE_REF(hash, bin)->val = value;
1009 return 1;
1010 }
1011}
1012
1013static int
1014ar_lookup(VALUE hash, st_data_t key, st_data_t *value)
1015{
1016 if (RHASH_AR_TABLE_SIZE(hash) == 0) {
1017 return 0;
1018 }
1019 else {
1020 st_hash_t hash_value = ar_do_hash(key);
1021 if (UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
1022 // `#hash` changes ar_table -> st_table
1023 return st_lookup(RHASH_ST_TABLE(hash), key, value);
1024 }
1025 unsigned bin = ar_find_entry(hash, hash_value, key);
1026
1027 if (bin == RHASH_AR_TABLE_MAX_BOUND) {
1028 return 0;
1029 }
1030 else {
1031 HASH_ASSERT(bin < RHASH_AR_TABLE_MAX_BOUND);
1032 if (value != NULL) {
1033 *value = RHASH_AR_TABLE_REF(hash, bin)->val;
1034 }
1035 return 1;
1036 }
1037 }
1038}
1039
1040static int
1041ar_delete(VALUE hash, st_data_t *key, st_data_t *value)
1042{
1043 unsigned bin;
1044 st_hash_t hash_value = ar_do_hash(*key);
1045
1046 if (UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
1047 // `#hash` changes ar_table -> st_table
1048 return st_delete(RHASH_ST_TABLE(hash), key, value);
1049 }
1050
1051 bin = ar_find_entry(hash, hash_value, *key);
1052
1053 if (bin == RHASH_AR_TABLE_MAX_BOUND) {
1054 if (value != 0) *value = 0;
1055 return 0;
1056 }
1057 else {
1058 if (value != 0) {
1059 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, bin);
1060 *value = pair->val;
1061 }
1062 ar_clear_entry(hash, bin);
1063 RHASH_AR_TABLE_SIZE_DEC(hash);
1064 return 1;
1065 }
1066}
1067
1068static int
1069ar_shift(VALUE hash, st_data_t *key, st_data_t *value)
1070{
1071 if (RHASH_AR_TABLE_SIZE(hash) > 0) {
1072 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
1073
1074 for (i = 0; i < bound; i++) {
1075 if (!ar_cleared_entry(hash, i)) {
1076 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
1077 if (value != 0) *value = pair->val;
1078 *key = pair->key;
1079 ar_clear_entry(hash, i);
1080 RHASH_AR_TABLE_SIZE_DEC(hash);
1081 return 1;
1082 }
1083 }
1084 }
1085 if (value != NULL) *value = 0;
1086 return 0;
1087}
1088
1089static long
1090ar_keys(VALUE hash, st_data_t *keys, st_index_t size)
1091{
1092 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
1093 st_data_t *keys_start = keys, *keys_end = keys + size;
1094
1095 for (i = 0; i < bound; i++) {
1096 if (keys == keys_end) {
1097 break;
1098 }
1099 else {
1100 if (!ar_cleared_entry(hash, i)) {
1101 *keys++ = RHASH_AR_TABLE_REF(hash, i)->key;
1102 }
1103 }
1104 }
1105
1106 return keys - keys_start;
1107}
1108
1109static long
1110ar_values(VALUE hash, st_data_t *values, st_index_t size)
1111{
1112 unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
1113 st_data_t *values_start = values, *values_end = values + size;
1114
1115 for (i = 0; i < bound; i++) {
1116 if (values == values_end) {
1117 break;
1118 }
1119 else {
1120 if (!ar_cleared_entry(hash, i)) {
1121 *values++ = RHASH_AR_TABLE_REF(hash, i)->val;
1122 }
1123 }
1124 }
1125
1126 return values - values_start;
1127}
1128
1129static ar_table*
1130ar_copy(VALUE hash1, VALUE hash2)
1131{
1132 RUBY_ASSERT(rb_gc_obj_slot_size(hash1) >= sizeof(struct RHash) + sizeof(ar_table));
1133 ar_table *old_tab = RHASH_AR_TABLE(hash2);
1134 ar_table *new_tab = RHASH_AR_TABLE(hash1);
1135
1136 unsigned int bound = RHASH_AR_TABLE_BOUND(hash2);
1137 new_tab->ar_hint.word = old_tab->ar_hint.word;
1138 MEMCPY(&new_tab->pairs, &old_tab->pairs, ar_table_pair, bound);
1139 RHASH_AR_TABLE(hash1)->ar_hint.word = RHASH_AR_TABLE(hash2)->ar_hint.word;
1140 RHASH_AR_TABLE_BOUND_SET(hash1, bound);
1141 RHASH_AR_TABLE_SIZE_SET(hash1, RHASH_AR_TABLE_SIZE(hash2));
1142
1143 rb_gc_writebarrier_remember(hash1);
1144
1145 return new_tab;
1146}
1147
1148static void
1149ar_clear(VALUE hash)
1150{
1151 if (RHASH_AR_TABLE(hash) != NULL) {
1152 RHASH_AR_TABLE_SIZE_SET(hash, 0);
1153 RHASH_AR_TABLE_BOUND_SET(hash, 0);
1154 }
1155 else {
1156 HASH_ASSERT(RHASH_AR_TABLE_SIZE(hash) == 0);
1157 HASH_ASSERT(RHASH_AR_TABLE_BOUND(hash) == 0);
1158 }
1159}
1160
1161static void
1162hash_st_free(VALUE hash)
1163{
1164 HASH_ASSERT(RHASH_ST_TABLE_P(hash));
1165
1166 rb_st_free_embedded_table(RHASH_ST_TABLE(hash));
1167}
1168
1169static void
1170hash_st_free_and_clear_table(VALUE hash)
1171{
1172 hash_st_free(hash);
1173 RHASH_ST_CLEAR(hash);
1174}
1175
1176void
1177rb_hash_free(VALUE hash)
1178{
1179 if (RHASH_ST_TABLE_P(hash)) {
1180 hash_st_free(hash);
1181 }
1182}
1183
1184typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
1185
1187 st_table *tbl;
1188 st_foreach_func *func;
1189 st_data_t arg;
1190};
1191
1192static int
1193foreach_safe_i(st_data_t key, st_data_t value, st_data_t args, int error)
1194{
1195 int status;
1196 struct foreach_safe_arg *arg = (void *)args;
1197
1198 if (error) return ST_STOP;
1199 status = (*arg->func)(key, value, arg->arg);
1200 if (status == ST_CONTINUE) {
1201 return ST_CHECK;
1202 }
1203 return status;
1204}
1205
1206void
1207st_foreach_safe(st_table *table, st_foreach_func *func, st_data_t a)
1208{
1209 struct foreach_safe_arg arg;
1210
1211 arg.tbl = table;
1212 arg.func = (st_foreach_func *)func;
1213 arg.arg = a;
1214 if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) {
1215 rb_raise(rb_eRuntimeError, "hash modified during iteration");
1216 }
1217}
1218
1219typedef int rb_foreach_func(VALUE, VALUE, VALUE);
1220
1222 VALUE hash;
1223 rb_foreach_func *func;
1224 VALUE arg;
1225};
1226
1227static int
1228hash_iter_status_check(int status)
1229{
1230 switch (status) {
1231 case ST_DELETE:
1232 return ST_DELETE;
1233 case ST_CONTINUE:
1234 break;
1235 case ST_STOP:
1236 return ST_STOP;
1237 }
1238
1239 return ST_CHECK;
1240}
1241
1242static int
1243hash_ar_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
1244{
1245 struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
1246
1247 if (error) return ST_STOP;
1248
1249 int status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
1250
1251 return hash_iter_status_check(status);
1252}
1253
1254static int
1255hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
1256{
1257 struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
1258
1259 if (error) return ST_STOP;
1260
1261 int status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
1262
1263 return hash_iter_status_check(status);
1264}
1265
1266static unsigned long
1267iter_lev_in_ivar(VALUE hash)
1268{
1269 VALUE levval = rb_ivar_get(hash, id_hash_iter_lev);
1270 HASH_ASSERT(FIXNUM_P(levval));
1271 long lev = FIX2LONG(levval);
1272 HASH_ASSERT(lev >= 0);
1273 return (unsigned long)lev;
1274}
1275
1276void rb_ivar_set_internal(VALUE obj, ID id, VALUE val);
1277
1278static void
1279iter_lev_in_ivar_set(VALUE hash, unsigned long lev)
1280{
1281 HASH_ASSERT(lev >= RHASH_LEV_MAX);
1282 HASH_ASSERT(POSFIXABLE(lev)); /* POSFIXABLE means fitting to long */
1283 rb_ivar_set_internal(hash, id_hash_iter_lev, LONG2FIX((long)lev));
1284}
1285
1286static inline unsigned long
1287iter_lev_in_flags(VALUE hash)
1288{
1289 return (unsigned long)((RBASIC(hash)->flags >> RHASH_LEV_SHIFT) & RHASH_LEV_MAX);
1290}
1291
1292static inline void
1293iter_lev_in_flags_set(VALUE hash, unsigned long lev)
1294{
1295 HASH_ASSERT(lev <= RHASH_LEV_MAX);
1296 RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((VALUE)lev << RHASH_LEV_SHIFT));
1297}
1298
1299static inline bool
1300hash_iterating_p(VALUE hash)
1301{
1302 return iter_lev_in_flags(hash) > 0;
1303}
1304
1305static void
1306hash_iter_lev_inc(VALUE hash)
1307{
1308 unsigned long lev = iter_lev_in_flags(hash);
1309 if (lev == RHASH_LEV_MAX) {
1310 lev = iter_lev_in_ivar(hash) + 1;
1311 if (!POSFIXABLE(lev)) { /* paranoiac check */
1312 rb_raise(rb_eRuntimeError, "too much nested iterations");
1313 }
1314 }
1315 else {
1316 lev += 1;
1317 iter_lev_in_flags_set(hash, lev);
1318 if (lev < RHASH_LEV_MAX) return;
1319 }
1320 iter_lev_in_ivar_set(hash, lev);
1321}
1322
1323static void
1324hash_iter_lev_dec(VALUE hash)
1325{
1326 unsigned long lev = iter_lev_in_flags(hash);
1327 if (lev == RHASH_LEV_MAX) {
1328 lev = iter_lev_in_ivar(hash);
1329 if (lev > RHASH_LEV_MAX) {
1330 iter_lev_in_ivar_set(hash, lev-1);
1331 return;
1332 }
1333 rb_attr_delete(hash, id_hash_iter_lev);
1334 }
1335 else if (lev == 0) {
1336 rb_raise(rb_eRuntimeError, "iteration level underflow");
1337 }
1338 iter_lev_in_flags_set(hash, lev - 1);
1339}
1340
1341static VALUE
1342hash_foreach_ensure(VALUE hash)
1343{
1344 hash_iter_lev_dec(hash);
1345 return 0;
1346}
1347
1348/* This does not manage iteration level */
1349int
1350rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
1351{
1352 if (RHASH_AR_TABLE_P(hash)) {
1353 return ar_foreach(hash, func, arg);
1354 }
1355 else {
1356 return st_foreach(RHASH_ST_TABLE(hash), func, arg);
1357 }
1358}
1359
1360/* This does not manage iteration level */
1361int
1362rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
1363{
1364 if (RHASH_AR_TABLE_P(hash)) {
1365 return ar_foreach_with_replace(hash, func, replace, arg);
1366 }
1367 else {
1368 return st_foreach_with_replace(RHASH_ST_TABLE(hash), func, replace, arg);
1369 }
1370}
1371
1372static VALUE
1373hash_foreach_call(VALUE arg)
1374{
1375 VALUE hash = ((struct hash_foreach_arg *)arg)->hash;
1376 int ret = 0;
1377 if (RHASH_AR_TABLE_P(hash)) {
1378 ret = ar_foreach_check(hash, hash_ar_foreach_iter,
1379 (st_data_t)arg, (st_data_t)Qundef);
1380 }
1381 else if (RHASH_ST_TABLE_P(hash)) {
1382 ret = st_foreach_check(RHASH_ST_TABLE(hash), hash_foreach_iter,
1383 (st_data_t)arg, (st_data_t)Qundef);
1384 }
1385 if (ret) {
1386 rb_raise(rb_eRuntimeError, "ret: %d, hash modified during iteration", ret);
1387 }
1388 return Qnil;
1389}
1390
1391void
1392rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
1393{
1394 struct hash_foreach_arg arg;
1395
1396 if (RHASH_TABLE_EMPTY_P(hash))
1397 return;
1398 arg.hash = hash;
1399 arg.func = (rb_foreach_func *)func;
1400 arg.arg = farg;
1401 if (RB_OBJ_FROZEN(hash)) {
1402 hash_foreach_call((VALUE)&arg);
1403 }
1404 else {
1405 hash_iter_lev_inc(hash);
1406 rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
1407 }
1408 hash_verify(hash);
1409}
1410
1411void rb_st_compact_table(st_table *tab);
1412
1413static void
1414compact_after_delete(VALUE hash)
1415{
1416 if (!hash_iterating_p(hash) && RHASH_ST_TABLE_P(hash)) {
1417 rb_st_compact_table(RHASH_ST_TABLE(hash));
1418 }
1419}
1420
1421static VALUE
1422hash_alloc_flags(VALUE klass, VALUE flags, VALUE ifnone, bool st)
1423{
1424 const size_t size = sizeof(struct RHash) + (st ? sizeof(st_table) : sizeof(ar_table));
1425 VALUE hash = rb_newobj_of(klass, T_HASH | flags, size);
1426 return rb_hash_set_ifnone(hash, ifnone);
1427}
1428
1429static VALUE
1430hash_alloc(VALUE klass)
1431{
1432 /* Allocate to be able to fit both st_table and ar_table. */
1433 return hash_alloc_flags(klass, 0, Qnil, sizeof(st_table) > sizeof(ar_table));
1434}
1435
1436static VALUE
1437empty_hash_alloc(VALUE klass)
1438{
1439 RUBY_DTRACE_CREATE_HOOK(HASH, 0);
1440
1441 return hash_alloc(klass);
1442}
1443
1444VALUE
1445rb_hash_new(void)
1446{
1447 return hash_alloc(rb_cHash);
1448}
1449
1450static VALUE
1451copy_compare_by_id(VALUE hash, VALUE basis)
1452{
1453 if (rb_hash_compare_by_id_p(basis)) {
1454 return rb_hash_compare_by_id(hash);
1455 }
1456 return hash;
1457}
1458
1459VALUE
1460rb_hash_new_with_size(st_index_t size)
1461{
1462 bool st = size > RHASH_AR_TABLE_MAX_SIZE;
1463 VALUE ret = hash_alloc_flags(rb_cHash, 0, Qnil, st);
1464
1465 if (st) {
1466 hash_st_table_init(ret, &objhash, size);
1467 }
1468
1469 return ret;
1470}
1471
1472VALUE
1473rb_hash_new_with_size_and_type(VALUE klass, st_index_t size, const struct st_hash_type *type)
1474{
1475 VALUE ret = hash_alloc_flags(klass, 0, Qnil, true);
1476 hash_st_table_init(ret, type, size);
1477 return ret;
1478}
1479
1480VALUE
1481rb_hash_new_capa(long capa)
1482{
1483 return rb_hash_new_with_size((st_index_t)capa);
1484}
1485
1486VALUE
1487rb_hash_alloc_fixed_size(VALUE klass, st_index_t size)
1488{
1489 VALUE ret;
1490 if (size > RHASH_AR_TABLE_MAX_SIZE) {
1491 ret = hash_alloc_flags(klass, 0, Qnil, true);
1492 hash_st_table_init(ret, &objhash, size);
1493 }
1494 else {
1495 size_t slot_size = sizeof(struct RHash) + offsetof(ar_table, pairs) + size * sizeof(ar_table_pair);
1496 ret = rb_newobj_of(klass, T_HASH, slot_size);
1497 }
1498
1499 RHASH_SET_IFNONE(ret, Qnil);
1500 return ret;
1501}
1502
1503static VALUE
1504hash_copy(VALUE ret, VALUE hash)
1505{
1506 if (rb_hash_compare_by_id_p(hash)) {
1507 rb_gc_register_pinning_obj(ret);
1508 }
1509
1510 if (RHASH_AR_TABLE_P(hash)) {
1511 if (RHASH_AR_TABLE_P(ret)) {
1512 ar_copy(ret, hash);
1513 }
1514 else {
1515 st_table *tab = RHASH_ST_TABLE(ret);
1516 st_init_existing_table_with_size(tab, &objhash, RHASH_AR_TABLE_SIZE(hash));
1517
1518 int bound = RHASH_AR_TABLE_BOUND(hash);
1519 for (int i = 0; i < bound; i++) {
1520 if (ar_cleared_entry(hash, i)) continue;
1521
1522 ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
1523 st_add_direct(tab, pair->key, pair->val);
1524 RB_OBJ_WRITTEN(ret, Qundef, pair->key);
1525 RB_OBJ_WRITTEN(ret, Qundef, pair->val);
1526 }
1527 }
1528 }
1529 else {
1530 HASH_ASSERT(sizeof(st_table) <= sizeof(ar_table));
1531
1532 RHASH_SET_ST_FLAG(ret);
1533 st_replace(RHASH_ST_TABLE(ret), RHASH_ST_TABLE(hash));
1534
1535 rb_gc_writebarrier_remember(ret);
1536 }
1537 return ret;
1538}
1539
1540static VALUE
1541hash_dup_with_compare_by_id(VALUE hash)
1542{
1543 VALUE dup = hash_alloc_flags(rb_cHash, 0, Qnil, RHASH_ST_TABLE_P(hash));
1544 if (RHASH_ST_TABLE_P(hash)) {
1545 RHASH_SET_ST_FLAG(dup);
1546 }
1547 else {
1548 RHASH_UNSET_ST_FLAG(dup);
1549 }
1550
1551 return hash_copy(dup, hash);
1552}
1553
1554static VALUE
1555hash_dup(VALUE hash, VALUE klass, VALUE flags)
1556{
1557 return hash_copy(hash_alloc_flags(klass, flags, RHASH_IFNONE(hash), !RHASH_EMPTY_P(hash) && RHASH_ST_TABLE_P(hash)),
1558 hash);
1559}
1560
1561VALUE
1562rb_hash_dup(VALUE hash)
1563{
1564 const VALUE flags = RBASIC(hash)->flags;
1565 VALUE ret = hash_dup(hash, rb_obj_class(hash), flags & RHASH_PROC_DEFAULT);
1566
1567 rb_copy_generic_ivar(ret, hash);
1568
1569 return ret;
1570}
1571
1572VALUE
1573rb_hash_resurrect(VALUE hash)
1574{
1575 VALUE ret = hash_dup(hash, rb_cHash, 0);
1576 return ret;
1577}
1578
1579static void
1580rb_hash_modify_check(VALUE hash)
1581{
1582 rb_check_frozen(hash);
1583}
1584
1585struct st_table *
1586rb_hash_tbl_raw(VALUE hash, const char *file, int line)
1587{
1588 return ar_force_convert_table(hash, file, line);
1589}
1590
1591struct st_table *
1592rb_hash_tbl(VALUE hash, const char *file, int line)
1593{
1594 OBJ_WB_UNPROTECT(hash);
1595 return rb_hash_tbl_raw(hash, file, line);
1596}
1597
1598static void
1599rb_hash_modify(VALUE hash)
1600{
1601 rb_hash_modify_check(hash);
1602}
1603
1604NORETURN(static void no_new_key(void));
1605static void
1606no_new_key(void)
1607{
1608 rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
1609}
1610
1612 VALUE hash;
1613 st_data_t arg;
1614};
1615
1616#define NOINSERT_UPDATE_CALLBACK(func) \
1617static int \
1618func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1619{ \
1620 if (!existing) no_new_key(); \
1621 return func(key, val, (struct update_arg *)arg, existing); \
1622} \
1623 \
1624static int \
1625func##_insert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1626{ \
1627 return func(key, val, (struct update_arg *)arg, existing); \
1628}
1629
1631 st_data_t arg;
1632 st_update_callback_func *func;
1633 VALUE hash;
1634 VALUE key;
1635 VALUE value;
1636};
1637
1638typedef int (*tbl_update_func)(st_data_t *, st_data_t *, st_data_t, int);
1639
1640int
1641rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg)
1642{
1643 if (RHASH_AR_TABLE_P(hash)) {
1644 int result = ar_update(hash, key, func, arg);
1645 if (result == -1) {
1646 ar_force_convert_table(hash, __FILE__, __LINE__);
1647 }
1648 else {
1649 return result;
1650 }
1651 }
1652
1653 return st_update(RHASH_ST_TABLE(hash), key, func, arg);
1654}
1655
1656static int
1657tbl_update_modify(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
1658{
1659 struct update_arg *p = (struct update_arg *)arg;
1660 st_data_t old_key = *key;
1661 st_data_t old_value = *val;
1662 VALUE hash = p->hash;
1663 int ret = (p->func)(key, val, arg, existing);
1664 switch (ret) {
1665 default:
1666 break;
1667 case ST_CONTINUE:
1668 if (!existing || *key != old_key || *val != old_value) {
1669 rb_hash_modify(hash);
1670 p->key = *key;
1671 p->value = *val;
1672 }
1673 break;
1674 case ST_DELETE:
1675 if (existing)
1676 rb_hash_modify(hash);
1677 break;
1678 }
1679
1680 return ret;
1681}
1682
1683static int
1684tbl_update(VALUE hash, VALUE key, tbl_update_func func, st_data_t optional_arg)
1685{
1686 struct update_arg arg = {
1687 .arg = optional_arg,
1688 .func = func,
1689 .hash = hash,
1690 .key = key,
1691 .value = 0
1692 };
1693
1694 int ret = rb_hash_stlike_update(hash, key, tbl_update_modify, (st_data_t)&arg);
1695
1696 /* write barrier */
1697 RB_OBJ_WRITTEN(hash, Qundef, arg.key);
1698 if (arg.value) RB_OBJ_WRITTEN(hash, Qundef, arg.value);
1699
1700 return ret;
1701}
1702
1703#define UPDATE_CALLBACK(iter_p, func) ((iter_p) ? func##_noinsert : func##_insert)
1704
1705#define RHASH_UPDATE_ITER(h, iter_p, key, func, a) do { \
1706 tbl_update((h), (key), UPDATE_CALLBACK(iter_p, func), (st_data_t)(a)); \
1707} while (0)
1708
1709#define RHASH_UPDATE(hash, key, func, arg) \
1710 RHASH_UPDATE_ITER(hash, hash_iterating_p(hash), key, func, arg)
1711
1712static void
1713set_proc_default(VALUE hash, VALUE proc)
1714{
1715 if (rb_proc_lambda_p(proc)) {
1716 int n = rb_proc_arity(proc);
1717
1718 if (n != 2 && (n >= 0 || n < -3)) {
1719 if (n < 0) n = -n-1;
1720 rb_raise(rb_eTypeError, "default_proc takes two arguments (2 for %d)", n);
1721 }
1722 }
1723
1724 FL_SET_RAW(hash, RHASH_PROC_DEFAULT);
1725 RHASH_SET_IFNONE(hash, proc);
1726}
1727
1728static VALUE
1729rb_hash_init(rb_execution_context_t *ec, VALUE hash, VALUE capa_value, VALUE ifnone_unset, VALUE ifnone, VALUE block)
1730{
1731 rb_hash_modify(hash);
1732
1733 if (capa_value != INT2FIX(0)) {
1734 long capa = NUM2LONG(capa_value);
1735 if (capa > 0 && RHASH_SIZE(hash) == 0 && RHASH_AR_TABLE_P(hash)) {
1736 hash_st_table_init(hash, &objhash, capa);
1737 }
1738 }
1739
1740 if (!NIL_P(block)) {
1741 if (ifnone_unset != Qtrue) {
1742 rb_check_arity(1, 0, 0);
1743 }
1744 else {
1745 SET_PROC_DEFAULT(hash, block);
1746 }
1747 }
1748 else {
1749 RHASH_SET_IFNONE(hash, ifnone_unset == Qtrue ? Qnil : ifnone);
1750 }
1751
1752 hash_verify(hash);
1753 return hash;
1754}
1755
1756static VALUE rb_hash_to_a(VALUE hash);
1757
1758/*
1759 * call-seq:
1760 * Hash[] -> new_empty_hash
1761 * Hash[other_hash] -> new_hash
1762 * Hash[ [*2_element_arrays] ] -> new_hash
1763 * Hash[*objects] -> new_hash
1764 *
1765 * Returns a new \Hash object populated with the given objects, if any.
1766 * See Hash::new.
1767 *
1768 * With no argument given, returns a new empty hash.
1769 *
1770 * With a single argument +other_hash+ given that is a hash,
1771 * returns a new hash initialized with the entries from that hash
1772 * (but not with its +default+ or +default_proc+):
1773 *
1774 * h = {foo: 0, bar: 1, baz: 2}
1775 * Hash[h] # => {foo: 0, bar: 1, baz: 2}
1776 *
1777 * With a single argument +2_element_arrays+ given that is an array of 2-element arrays,
1778 * returns a new hash wherein each given 2-element array forms a
1779 * key-value entry:
1780 *
1781 * Hash[ [ [:foo, 0], [:bar, 1] ] ] # => {foo: 0, bar: 1}
1782 *
1783 * With an even number of arguments +objects+ given,
1784 * returns a new hash wherein each successive pair of arguments
1785 * is a key-value entry:
1786 *
1787 * Hash[:foo, 0, :bar, 1] # => {foo: 0, bar: 1}
1788 *
1789 * Raises ArgumentError if the argument list does not conform to any
1790 * of the above.
1791 *
1792 * See also {Methods for Creating a Hash}[rdoc-ref:Hash@Methods+for+Creating+a+Hash].
1793 */
1794
1795static VALUE
1796rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
1797{
1798 VALUE hash, tmp;
1799
1800 if (argc == 1) {
1801 tmp = rb_hash_s_try_convert(Qnil, argv[0]);
1802 if (!NIL_P(tmp)) {
1803 if (!RHASH_EMPTY_P(tmp) && rb_hash_compare_by_id_p(tmp)) {
1804 /* hash_copy for non-empty hash will copy compare_by_identity
1805 flag, but we don't want it copied. Work around by
1806 converting hash to flattened array and using that. */
1807 tmp = rb_hash_to_a(tmp);
1808 }
1809 else {
1810 hash = hash_alloc(klass);
1811 if (!RHASH_EMPTY_P(tmp))
1812 hash_copy(hash, tmp);
1813 return hash;
1814 }
1815 }
1816 else {
1817 tmp = rb_check_array_type(argv[0]);
1818 }
1819
1820 if (!NIL_P(tmp)) {
1821 long i;
1822
1823 hash = hash_alloc(klass);
1824 for (i = 0; i < RARRAY_LEN(tmp); ++i) {
1825 VALUE e = RARRAY_AREF(tmp, i);
1827 VALUE key, val = Qnil;
1828
1829 if (NIL_P(v)) {
1830 rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
1831 rb_builtin_class_name(e), i);
1832 }
1833 switch (RARRAY_LEN(v)) {
1834 default:
1835 rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
1836 RARRAY_LEN(v));
1837 case 2:
1838 val = RARRAY_AREF(v, 1);
1839 case 1:
1840 key = RARRAY_AREF(v, 0);
1841 rb_hash_aset(hash, key, val);
1842 }
1843 }
1844 return hash;
1845 }
1846 }
1847 if (argc % 2 != 0) {
1848 rb_raise(rb_eArgError, "odd number of arguments for Hash");
1849 }
1850
1851 hash = hash_alloc(klass);
1852 rb_hash_bulk_insert(argc, argv, hash);
1853 hash_verify(hash);
1854 return hash;
1855}
1856
1857VALUE
1858rb_to_hash_type(VALUE hash)
1859{
1860 return rb_convert_type_with_id(hash, T_HASH, "Hash", idTo_hash);
1861}
1862#define to_hash rb_to_hash_type
1863
1864VALUE
1865rb_check_hash_type(VALUE hash)
1866{
1867 return rb_check_convert_type_with_id(hash, T_HASH, "Hash", idTo_hash);
1868}
1869
1870/*
1871 * call-seq:
1872 * Hash.try_convert(object) -> object, new_hash, or nil
1873 *
1874 * If +object+ is a hash, returns +object+.
1875 *
1876 * Otherwise if +object+ responds to +:to_hash+,
1877 * calls <tt>object.to_hash</tt>;
1878 * returns the result if it is a hash, or raises TypeError if not.
1879 *
1880 * Otherwise if +object+ does not respond to +:to_hash+, returns +nil+.
1881 */
1882static VALUE
1883rb_hash_s_try_convert(VALUE dummy, VALUE hash)
1884{
1885 return rb_check_hash_type(hash);
1886}
1887
1888/*
1889 * call-seq:
1890 * Hash.ruby2_keywords_hash?(hash) -> true or false
1891 *
1892 * Checks if a given hash is flagged by Module#ruby2_keywords (or
1893 * Proc#ruby2_keywords).
1894 * This method is not for casual use; debugging, researching, and
1895 * some truly necessary cases like serialization of arguments.
1896 *
1897 * ruby2_keywords def foo(*args)
1898 * Hash.ruby2_keywords_hash?(args.last)
1899 * end
1900 * foo(k: 1) #=> true
1901 * foo({k: 1}) #=> false
1902 */
1903static VALUE
1904rb_hash_s_ruby2_keywords_hash_p(VALUE dummy, VALUE hash)
1905{
1906 Check_Type(hash, T_HASH);
1907 return RBOOL(RHASH(hash)->basic.flags & RHASH_PASS_AS_KEYWORDS);
1908}
1909
1910/*
1911 * call-seq:
1912 * Hash.ruby2_keywords_hash(hash) -> hash
1913 *
1914 * Duplicates a given hash and adds a ruby2_keywords flag.
1915 * This method is not for casual use; debugging, researching, and
1916 * some truly necessary cases like deserialization of arguments.
1917 *
1918 * h = {k: 1}
1919 * h = Hash.ruby2_keywords_hash(h)
1920 * def foo(k: 42)
1921 * k
1922 * end
1923 * foo(*[h]) #=> 1 with neither a warning or an error
1924 */
1925static VALUE
1926rb_hash_s_ruby2_keywords_hash(VALUE dummy, VALUE hash)
1927{
1928 Check_Type(hash, T_HASH);
1929 VALUE tmp = rb_hash_dup(hash);
1930 if (RHASH_EMPTY_P(hash) && rb_hash_compare_by_id_p(hash)) {
1931 rb_hash_compare_by_id(tmp);
1932 }
1933 RHASH(tmp)->basic.flags |= RHASH_PASS_AS_KEYWORDS;
1934 return tmp;
1935}
1936
1938 VALUE hash;
1939 st_table *tbl;
1940};
1941
1942static int
1943rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
1944{
1945 if (RHASH_AR_TABLE_P(arg)) {
1946 ar_insert(arg, (st_data_t)key, (st_data_t)value);
1947 }
1948 else {
1949 st_insert(RHASH_ST_TABLE(arg), (st_data_t)key, (st_data_t)value);
1950 }
1951
1952 RB_OBJ_WRITTEN(arg, Qundef, key);
1953 RB_OBJ_WRITTEN(arg, Qundef, value);
1954 return ST_CONTINUE;
1955}
1956
1957/*
1958 * call-seq:
1959 * rehash -> self
1960 *
1961 * Rebuilds the hash table for +self+ by recomputing the hash index for each key;
1962 * returns <tt>self</tt>.
1963 * Calling this method ensures that the hash table is valid.
1964 *
1965 * The hash table becomes invalid if the hash value of a key
1966 * has changed after the entry was created.
1967 * See {Modifying an Active Hash Key}[rdoc-ref:Hash@Modifying+an+Active+Hash+Key].
1968 */
1969
1970VALUE
1971rb_hash_rehash(VALUE hash)
1972{
1973 VALUE tmp;
1974 st_table *tbl;
1975
1976 if (hash_iterating_p(hash)) {
1977 rb_raise(rb_eRuntimeError, "rehash during iteration");
1978 }
1979 rb_hash_modify_check(hash);
1980 if (RHASH_AR_TABLE_P(hash)) {
1981 tmp = hash_alloc(0);
1982 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
1983
1984 hash_ar_free_and_clear_table(hash);
1985 ar_copy(hash, tmp);
1986 }
1987 else if (RHASH_ST_TABLE_P(hash)) {
1988 st_table *old_tab = RHASH_ST_TABLE(hash);
1989 tmp = hash_alloc(0);
1990
1991 hash_st_table_init(tmp, old_tab->type, old_tab->num_entries);
1992 tbl = RHASH_ST_TABLE(tmp);
1993
1994 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
1995
1996 hash_st_free(hash);
1997 RHASH_ST_TABLE_SET(hash, tbl);
1998 RHASH_ST_CLEAR(tmp);
1999 }
2000 hash_verify(hash);
2001 return hash;
2002}
2003
2004static VALUE
2005call_default_proc(VALUE proc, VALUE hash, VALUE key)
2006{
2007 VALUE args[2] = {hash, key};
2008 return rb_proc_call_with_block(proc, 2, args, Qnil);
2009}
2010
2011bool
2012rb_hash_default_unredefined(VALUE hash)
2013{
2014 VALUE klass = RBASIC_CLASS(hash);
2015 if (LIKELY(klass == rb_cHash)) {
2016 return !!BASIC_OP_UNREDEFINED_P(BOP_DEFAULT, HASH_REDEFINED_OP_FLAG);
2017 }
2018 else {
2019 return LIKELY(rb_method_basic_definition_p(klass, id_default));
2020 }
2021}
2022
2023VALUE
2024rb_hash_default_value(VALUE hash, VALUE key)
2025{
2027
2028 if (LIKELY(rb_hash_default_unredefined(hash))) {
2029 VALUE ifnone = RHASH_IFNONE(hash);
2030 if (LIKELY(!FL_TEST_RAW(hash, RHASH_PROC_DEFAULT))) return ifnone;
2031 if (UNDEF_P(key)) return Qnil;
2032 return call_default_proc(ifnone, hash, key);
2033 }
2034 else {
2035 return rb_funcall(hash, id_default, 1, key);
2036 }
2037}
2038
2039static inline int
2040hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
2041{
2042 hash_verify(hash);
2043
2044 if (RHASH_AR_TABLE_P(hash)) {
2045 return ar_lookup(hash, key, pval);
2046 }
2047 else {
2048 extern st_index_t rb_iseq_cdhash_hash(VALUE);
2049 RUBY_ASSERT(RHASH_ST_TABLE(hash)->type->hash == rb_any_hash ||
2050 RHASH_ST_TABLE(hash)->type->hash == rb_ident_hash ||
2051 RHASH_ST_TABLE(hash)->type->hash == rb_iseq_cdhash_hash);
2052 return st_lookup(RHASH_ST_TABLE(hash), key, pval);
2053 }
2054}
2055
2056int
2057rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
2058{
2059 return hash_stlike_lookup(hash, key, pval);
2060}
2061
2062/*
2063 * call-seq:
2064 * self[key] -> object
2065 *
2066 * Searches for a hash key equivalent to the given +key+;
2067 * see {Hash Key Equivalence}[rdoc-ref:Hash@Hash+Key+Equivalence].
2068 *
2069 * If the key is found, returns its value:
2070 *
2071 * {foo: 0, bar: 1, baz: 2}
2072 * h[:bar] # => 1
2073 *
2074 * Otherwise, returns a default value (see {Hash Default}[rdoc-ref:Hash@Hash+Default]).
2075 *
2076 * Related: #[]=; see also {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
2077 */
2078
2079VALUE
2080rb_hash_aref(VALUE hash, VALUE key)
2081{
2082 st_data_t val;
2083
2084 if (hash_stlike_lookup(hash, key, &val)) {
2085 return (VALUE)val;
2086 }
2087 else {
2088 return rb_hash_default_value(hash, key);
2089 }
2090}
2091
2092VALUE
2093rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
2094{
2095 st_data_t val;
2096
2097 if (hash_stlike_lookup(hash, key, &val)) {
2098 return (VALUE)val;
2099 }
2100 else {
2101 return def; /* without Hash#default */
2102 }
2103}
2104
2105VALUE
2106rb_hash_lookup(VALUE hash, VALUE key)
2107{
2108 return rb_hash_lookup2(hash, key, Qnil);
2109}
2110
2111/*
2112 * call-seq:
2113 * fetch(key) -> object
2114 * fetch(key, default_value) -> object
2115 * fetch(key) {|key| ... } -> object
2116 *
2117 * With no block given, returns the value for the given +key+, if found;
2118 *
2119 * h = {foo: 0, bar: 1, baz: 2}
2120 * h.fetch(:bar) # => 1
2121 *
2122 * If the key is not found, returns +default_value+, if given,
2123 * or raises KeyError otherwise:
2124 *
2125 * h.fetch(:nosuch, :default) # => :default
2126 * h.fetch(:nosuch) # Raises KeyError.
2127 *
2128 * With a block given, calls the block with +key+ and returns the block's return value:
2129 *
2130 * {}.fetch(:nosuch) {|key| "No key #{key}"} # => "No key nosuch"
2131 *
2132 * Note that this method does not use the values of either #default or #default_proc.
2133 *
2134 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
2135 */
2136
2137static VALUE
2138rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
2139{
2140 VALUE key;
2141 st_data_t val;
2142 long block_given;
2143
2144 rb_check_arity(argc, 1, 2);
2145 key = argv[0];
2146
2147 block_given = rb_block_given_p();
2148 if (block_given && argc == 2) {
2149 rb_warn("block supersedes default value argument");
2150 }
2151
2152 if (hash_stlike_lookup(hash, key, &val)) {
2153 return (VALUE)val;
2154 }
2155 else {
2156 if (block_given) {
2157 return rb_yield(key);
2158 }
2159 else if (argc == 1) {
2160 VALUE desc = rb_protect(rb_inspect, key, 0);
2161 if (NIL_P(desc)) {
2162 desc = rb_any_to_s(key);
2163 }
2164 desc = rb_str_ellipsize(desc, 65);
2165 rb_key_err_raise(rb_sprintf("key not found: %"PRIsVALUE, desc), hash, key);
2166 }
2167 else {
2168 return argv[1];
2169 }
2170 }
2171}
2172
2173VALUE
2174rb_hash_fetch(VALUE hash, VALUE key)
2175{
2176 return rb_hash_fetch_m(1, &key, hash);
2177}
2178
2179/*
2180 * call-seq:
2181 * default -> object
2182 * default(key) -> object
2183 *
2184 * Returns the default value for the given +key+.
2185 * The returned value will be determined either by the default proc or by the default value.
2186 * See {Hash Default}[rdoc-ref:Hash@Hash+Default].
2187 *
2188 * With no argument, returns the current default value:
2189 * h = {}
2190 * h.default # => nil
2191 *
2192 * If +key+ is given, returns the default value for +key+,
2193 * regardless of whether that key exists:
2194 * h = Hash.new { |hash, key| hash[key] = "No key #{key}"}
2195 * h[:foo] = "Hello"
2196 * h.default(:foo) # => "No key foo"
2197 */
2198
2199static VALUE
2200rb_hash_default(int argc, VALUE *argv, VALUE hash)
2201{
2202 VALUE ifnone;
2203
2204 rb_check_arity(argc, 0, 1);
2205 ifnone = RHASH_IFNONE(hash);
2206 if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
2207 if (argc == 0) return Qnil;
2208 return call_default_proc(ifnone, hash, argv[0]);
2209 }
2210 return ifnone;
2211}
2212
2213/*
2214 * call-seq:
2215 * default = value -> object
2216 *
2217 * Sets the default value to +value+; returns +value+:
2218 * h = {}
2219 * h.default # => nil
2220 * h.default = false # => false
2221 * h.default # => false
2222 *
2223 * See {Hash Default}[rdoc-ref:Hash@Hash+Default].
2224 */
2225
2226VALUE
2227rb_hash_set_default(VALUE hash, VALUE ifnone)
2228{
2229 rb_hash_modify_check(hash);
2230 SET_DEFAULT(hash, ifnone);
2231 return ifnone;
2232}
2233
2234/*
2235 * call-seq:
2236 * default_proc -> proc or nil
2237 *
2238 * Returns the default proc for +self+
2239 * (see {Hash Default}[rdoc-ref:Hash@Hash+Default]):
2240 * h = {}
2241 * h.default_proc # => nil
2242 * h.default_proc = proc {|hash, key| "Default value for #{key}" }
2243 * h.default_proc.class # => Proc
2244 */
2245
2246static VALUE
2247rb_hash_default_proc(VALUE hash)
2248{
2249 if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
2250 return RHASH_IFNONE(hash);
2251 }
2252 return Qnil;
2253}
2254
2255/*
2256 * call-seq:
2257 * default_proc = proc -> proc
2258 *
2259 * Sets the default proc for +self+ to +proc+
2260 * (see {Hash Default}[rdoc-ref:Hash@Hash+Default]):
2261 * h = {}
2262 * h.default_proc # => nil
2263 * h.default_proc = proc { |hash, key| "Default value for #{key}" }
2264 * h.default_proc.class # => Proc
2265 * h.default_proc = nil
2266 * h.default_proc # => nil
2267 */
2268
2269VALUE
2270rb_hash_set_default_proc(VALUE hash, VALUE proc)
2271{
2272 VALUE b;
2273
2274 rb_hash_modify_check(hash);
2275 if (NIL_P(proc)) {
2276 SET_DEFAULT(hash, proc);
2277 return proc;
2278 }
2279 b = rb_check_convert_type_with_id(proc, T_DATA, "Proc", idTo_proc);
2280 if (NIL_P(b) || !rb_obj_is_proc(b)) {
2281 rb_raise(rb_eTypeError,
2282 "wrong default_proc type %s (expected Proc)",
2283 rb_obj_classname(proc));
2284 }
2285 proc = b;
2286 SET_PROC_DEFAULT(hash, proc);
2287 return proc;
2288}
2289
2290static int
2291key_i(VALUE key, VALUE value, VALUE arg)
2292{
2293 VALUE *args = (VALUE *)arg;
2294
2295 if (rb_equal(value, args[0])) {
2296 args[1] = key;
2297 return ST_STOP;
2298 }
2299 return ST_CONTINUE;
2300}
2301
2302/*
2303 * call-seq:
2304 * key(value) -> key or nil
2305 *
2306 * Returns the key for the first-found entry with the given +value+
2307 * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
2308 *
2309 * h = {foo: 0, bar: 2, baz: 2}
2310 * h.key(0) # => :foo
2311 * h.key(2) # => :bar
2312 *
2313 * Returns +nil+ if no such value is found.
2314 *
2315 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
2316 */
2317
2318static VALUE
2319rb_hash_key(VALUE hash, VALUE value)
2320{
2321 VALUE args[2];
2322
2323 args[0] = value;
2324 args[1] = Qnil;
2325
2326 rb_hash_foreach(hash, key_i, (VALUE)args);
2327
2328 return args[1];
2329}
2330
2331int
2332rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval)
2333{
2334 if (RHASH_AR_TABLE_P(hash)) {
2335 return ar_delete(hash, pkey, pval);
2336 }
2337 else {
2338 return st_delete(RHASH_ST_TABLE(hash), pkey, pval);
2339 }
2340}
2341
2342/*
2343 * delete a specified entry by a given key.
2344 * if there is the corresponding entry, return a value of the entry.
2345 * if there is no corresponding entry, return Qundef.
2346 */
2347VALUE
2348rb_hash_delete_entry(VALUE hash, VALUE key)
2349{
2350 st_data_t ktmp = (st_data_t)key, val;
2351
2352 if (rb_hash_stlike_delete(hash, &ktmp, &val)) {
2353 return (VALUE)val;
2354 }
2355 else {
2356 return Qundef;
2357 }
2358}
2359
2360/*
2361 * delete a specified entry by a given key.
2362 * if there is the corresponding entry, return a value of the entry.
2363 * if there is no corresponding entry, return Qnil.
2364 */
2365VALUE
2366rb_hash_delete(VALUE hash, VALUE key)
2367{
2368 VALUE deleted_value = rb_hash_delete_entry(hash, key);
2369
2370 if (!UNDEF_P(deleted_value)) { /* likely pass */
2371 return deleted_value;
2372 }
2373 else {
2374 return Qnil;
2375 }
2376}
2377
2378/*
2379 * call-seq:
2380 * delete(key) -> value or nil
2381 * delete(key) {|key| ... } -> object
2382 *
2383 * If an entry for the given +key+ is found,
2384 * deletes the entry and returns its associated value;
2385 * otherwise returns +nil+ or calls the given block.
2386 *
2387 * With no block given and +key+ found, deletes the entry and returns its value:
2388 *
2389 * h = {foo: 0, bar: 1, baz: 2}
2390 * h.delete(:bar) # => 1
2391 * h # => {foo: 0, baz: 2}
2392 *
2393 * With no block given and +key+ not found, returns +nil+.
2394 *
2395 * With a block given and +key+ found, ignores the block,
2396 * deletes the entry, and returns its value:
2397 *
2398 * h = {foo: 0, bar: 1, baz: 2}
2399 * h.delete(:baz) { |key| raise 'Will never happen'} # => 2
2400 * h # => {foo: 0, bar: 1}
2401 *
2402 * With a block given and +key+ not found,
2403 * calls the block and returns the block's return value:
2404 *
2405 * h = {foo: 0, bar: 1, baz: 2}
2406 * h.delete(:nosuch) { |key| "Key #{key} not found" } # => "Key nosuch not found"
2407 * h # => {foo: 0, bar: 1, baz: 2}
2408 *
2409 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2410 */
2411
2412static VALUE
2413rb_hash_delete_m(VALUE hash, VALUE key)
2414{
2415 VALUE val;
2416
2417 rb_hash_modify_check(hash);
2418 val = rb_hash_delete_entry(hash, key);
2419
2420 if (!UNDEF_P(val)) {
2421 compact_after_delete(hash);
2422 return val;
2423 }
2424 else {
2425 if (rb_block_given_p()) {
2426 return rb_yield(key);
2427 }
2428 else {
2429 return Qnil;
2430 }
2431 }
2432}
2433
2435 VALUE key;
2436 VALUE val;
2437};
2438
2439static int
2440shift_i_safe(VALUE key, VALUE value, VALUE arg)
2441{
2442 struct shift_var *var = (struct shift_var *)arg;
2443
2444 var->key = key;
2445 var->val = value;
2446 return ST_STOP;
2447}
2448
2449/*
2450 * call-seq:
2451 * shift -> [key, value] or nil
2452 *
2453 * Removes and returns the first entry of +self+ as a 2-element array;
2454 * see {Entry Order}[rdoc-ref:Hash@Entry+Order]:
2455 *
2456 * h = {foo: 0, bar: 1, baz: 2}
2457 * h.shift # => [:foo, 0]
2458 * h # => {bar: 1, baz: 2}
2459 *
2460 * Returns +nil+ if +self+ is empty.
2461 *
2462 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2463 */
2464
2465static VALUE
2466rb_hash_shift(VALUE hash)
2467{
2468 struct shift_var var;
2469
2470 rb_hash_modify_check(hash);
2471 if (RHASH_AR_TABLE_P(hash)) {
2472 var.key = Qundef;
2473 if (!hash_iterating_p(hash)) {
2474 if (ar_shift(hash, &var.key, &var.val)) {
2475 return rb_assoc_new(var.key, var.val);
2476 }
2477 }
2478 else {
2479 rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
2480 if (!UNDEF_P(var.key)) {
2481 rb_hash_delete_entry(hash, var.key);
2482 return rb_assoc_new(var.key, var.val);
2483 }
2484 }
2485 }
2486 if (RHASH_ST_TABLE_P(hash)) {
2487 var.key = Qundef;
2488 if (!hash_iterating_p(hash)) {
2489 if (st_shift(RHASH_ST_TABLE(hash), &var.key, &var.val)) {
2490 return rb_assoc_new(var.key, var.val);
2491 }
2492 }
2493 else {
2494 rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
2495 if (!UNDEF_P(var.key)) {
2496 rb_hash_delete_entry(hash, var.key);
2497 return rb_assoc_new(var.key, var.val);
2498 }
2499 }
2500 }
2501 return Qnil;
2502}
2503
2504static int
2505delete_if_i(VALUE key, VALUE value, VALUE hash)
2506{
2507 if (RTEST(rb_yield_values(2, key, value))) {
2508 rb_hash_modify(hash);
2509 return ST_DELETE;
2510 }
2511 return ST_CONTINUE;
2512}
2513
2514static VALUE
2515hash_enum_size(VALUE hash, VALUE args, VALUE eobj)
2516{
2517 return rb_hash_size(hash);
2518}
2519
2520/*
2521 * call-seq:
2522 * delete_if {|key, value| ... } -> self
2523 * delete_if -> new_enumerator
2524 *
2525 * With a block given, calls the block with each key-value pair,
2526 * deletes each entry for which the block returns a truthy value,
2527 * and returns +self+:
2528 *
2529 * h = {foo: 0, bar: 1, baz: 2}
2530 * h.delete_if {|key, value| value > 0 } # => {foo: 0}
2531 *
2532 * With no block given, returns a new Enumerator.
2533 *
2534 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2535 */
2536
2537VALUE
2538rb_hash_delete_if(VALUE hash)
2539{
2540 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2541 rb_hash_modify_check(hash);
2542 if (!RHASH_TABLE_EMPTY_P(hash)) {
2543 rb_hash_foreach(hash, delete_if_i, hash);
2544 compact_after_delete(hash);
2545 }
2546 return hash;
2547}
2548
2549/*
2550 * call-seq:
2551 * reject! {|key, value| ... } -> self or nil
2552 * reject! -> new_enumerator
2553 *
2554 * With a block given, calls the block with each entry's key and value;
2555 * removes the entry from +self+ if the block returns a truthy value.
2556 *
2557 * Return +self+ if any entries were removed, +nil+ otherwise:
2558 *
2559 * h = {foo: 0, bar: 1, baz: 2}
2560 * h.reject! {|key, value| value < 2 } # => {baz: 2}
2561 * h.reject! {|key, value| value < 2 } # => nil
2562 *
2563 * With no block given, returns a new Enumerator.
2564 *
2565 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2566 */
2567
2568static VALUE
2569rb_hash_reject_bang(VALUE hash)
2570{
2571 st_index_t n;
2572
2573 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2574 rb_hash_modify(hash);
2575 n = RHASH_SIZE(hash);
2576 if (!n) return Qnil;
2577 rb_hash_foreach(hash, delete_if_i, hash);
2578 if (n == RHASH_SIZE(hash)) return Qnil;
2579 return hash;
2580}
2581
2582/*
2583 * call-seq:
2584 * reject {|key, value| ... } -> new_hash
2585 * reject -> new_enumerator
2586 *
2587 * With a block given, returns a copy of +self+ with zero or more entries removed;
2588 * calls the block with each key-value pair;
2589 * excludes the entry in the copy if the block returns a truthy value,
2590 * includes it otherwise:
2591 *
2592 * h = {foo: 0, bar: 1, baz: 2}
2593 * h.reject {|key, value| key.start_with?('b') }
2594 * # => {foo: 0}
2595 *
2596 * With no block given, returns a new Enumerator.
2597 *
2598 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2599 */
2600
2601static VALUE
2602rb_hash_reject(VALUE hash)
2603{
2604 VALUE result;
2605
2606 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2607 result = hash_dup_with_compare_by_id(hash);
2608 if (!RHASH_EMPTY_P(hash)) {
2609 rb_hash_foreach(result, delete_if_i, result);
2610 compact_after_delete(result);
2611 }
2612 return result;
2613}
2614
2615/*
2616 * call-seq:
2617 * slice(*keys) -> new_hash
2618 *
2619 * Returns a new hash containing the entries from +self+ for the given +keys+;
2620 * ignores any keys that are not found:
2621 *
2622 * h = {foo: 0, bar: 1, baz: 2}
2623 * h.slice(:baz, :foo, :nosuch) # => {baz: 2, foo: 0}
2624 *
2625 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2626 */
2627
2628static VALUE
2629rb_hash_slice(int argc, VALUE *argv, VALUE hash)
2630{
2631 int i;
2632 VALUE key, value, result;
2633
2634 if (argc == 0 || RHASH_EMPTY_P(hash)) {
2635 return copy_compare_by_id(rb_hash_new(), hash);
2636 }
2637 result = copy_compare_by_id(rb_hash_new_with_size(argc), hash);
2638
2639 for (i = 0; i < argc; i++) {
2640 key = argv[i];
2641 value = rb_hash_lookup2(hash, key, Qundef);
2642 if (!UNDEF_P(value))
2643 rb_hash_aset(result, key, value);
2644 }
2645
2646 return result;
2647}
2648
2649/*
2650 * call-seq:
2651 * except(*keys) -> new_hash
2652 *
2653 * Returns a copy of +self+ that excludes entries for the given +keys+;
2654 * any +keys+ that are not found are ignored:
2655 *
2656 * h = {foo:0, bar: 1, baz: 2} # => {foo: 0, bar: 1, baz: 2}
2657 * h.except(:baz, :foo) # => {bar: 1}
2658 * h.except(:bar, :nosuch) # => {foo: 0, baz: 2}
2659 *
2660 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2661 */
2662
2663static VALUE
2664rb_hash_except(int argc, VALUE *argv, VALUE hash)
2665{
2666 int i;
2667 VALUE key, result;
2668
2669 result = hash_dup_with_compare_by_id(hash);
2670
2671 for (i = 0; i < argc; i++) {
2672 key = argv[i];
2673 rb_hash_delete(result, key);
2674 }
2675 compact_after_delete(result);
2676
2677 return result;
2678}
2679
2680/*
2681 * call-seq:
2682 * values_at(*keys) -> new_array
2683 *
2684 * Returns a new array containing values for the given +keys+:
2685 *
2686 * h = {foo: 0, bar: 1, baz: 2}
2687 * h.values_at(:baz, :foo) # => [2, 0]
2688 *
2689 * The {hash default}[rdoc-ref:Hash@Hash+Default] is returned
2690 * for each key that is not found:
2691 *
2692 * h.values_at(:hello, :foo) # => [nil, 0]
2693 *
2694 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
2695 */
2696
2697static VALUE
2698rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
2699{
2700 VALUE result = rb_ary_new2(argc);
2701 long i;
2702
2703 for (i=0; i<argc; i++) {
2704 rb_ary_push(result, rb_hash_aref(hash, argv[i]));
2705 }
2706 return result;
2707}
2708
2709/*
2710 * call-seq:
2711 * fetch_values(*keys) -> new_array
2712 * fetch_values(*keys) {|key| ... } -> new_array
2713 *
2714 * When all given +keys+ are found,
2715 * returns a new array containing the values associated with the given +keys+:
2716 *
2717 * h = {foo: 0, bar: 1, baz: 2}
2718 * h.fetch_values(:baz, :foo) # => [2, 0]
2719 *
2720 * When any given +keys+ are not found and a block is given,
2721 * calls the block with each unfound key and uses the block's return value
2722 * as the value for that key:
2723 *
2724 * h.fetch_values(:bar, :foo, :bad, :bam) {|key| key.to_s}
2725 * # => [1, 0, "bad", "bam"]
2726 *
2727 * When any given +keys+ are not found and no block is given,
2728 * raises KeyError.
2729 *
2730 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
2731 */
2732
2733static VALUE
2734rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
2735{
2736 VALUE result = rb_ary_new2(argc);
2737 long i;
2738
2739 for (i=0; i<argc; i++) {
2740 rb_ary_push(result, rb_hash_fetch(hash, argv[i]));
2741 }
2742 return result;
2743}
2744
2745static int
2746keep_if_i(VALUE key, VALUE value, VALUE hash)
2747{
2748 if (!RTEST(rb_yield_values(2, key, value))) {
2749 rb_hash_modify(hash);
2750 return ST_DELETE;
2751 }
2752 return ST_CONTINUE;
2753}
2754
2755/*
2756 * call-seq:
2757 * select {|key, value| ... } -> new_hash
2758 * select -> new_enumerator
2759 *
2760 * With a block given, calls the block with each entry's key and value;
2761 * returns a new hash whose entries are those for which the block returns a truthy value:
2762 *
2763 * h = {foo: 0, bar: 1, baz: 2}
2764 * h.select {|key, value| value < 2 } # => {foo: 0, bar: 1}
2765 *
2766 * With no block given, returns a new Enumerator.
2767 *
2768 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2769 */
2770
2771static VALUE
2772rb_hash_select(VALUE hash)
2773{
2774 VALUE result;
2775
2776 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2777 result = hash_dup_with_compare_by_id(hash);
2778 if (!RHASH_EMPTY_P(hash)) {
2779 rb_hash_foreach(result, keep_if_i, result);
2780 compact_after_delete(result);
2781 }
2782 return result;
2783}
2784
2785/*
2786 * call-seq:
2787 * select! {|key, value| ... } -> self or nil
2788 * select! -> new_enumerator
2789 *
2790 * With a block given, calls the block with each entry's key and value;
2791 * removes from +self+ each entry for which the block returns +false+ or +nil+.
2792 *
2793 * Returns +self+ if any entries were removed, +nil+ otherwise:
2794 *
2795 * h = {foo: 0, bar: 1, baz: 2}
2796 * h.select! {|key, value| value < 2 } # => {foo: 0, bar: 1}
2797 * h.select! {|key, value| value < 2 } # => nil
2798 *
2799 *
2800 * With no block given, returns a new Enumerator.
2801 *
2802 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2803 */
2804
2805static VALUE
2806rb_hash_select_bang(VALUE hash)
2807{
2808 st_index_t n;
2809
2810 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2811 rb_hash_modify_check(hash);
2812 n = RHASH_SIZE(hash);
2813 if (!n) return Qnil;
2814 rb_hash_foreach(hash, keep_if_i, hash);
2815 if (n == RHASH_SIZE(hash)) return Qnil;
2816 return hash;
2817}
2818
2819/*
2820 * call-seq:
2821 * keep_if {|key, value| ... } -> self
2822 * keep_if -> new_enumerator
2823 *
2824 * With a block given, calls the block for each key-value pair;
2825 * retains the entry if the block returns a truthy value;
2826 * otherwise deletes the entry; returns +self+:
2827 *
2828 * h = {foo: 0, bar: 1, baz: 2}
2829 * h.keep_if { |key, value| key.start_with?('b') } # => {bar: 1, baz: 2}
2830 *
2831 * With no block given, returns a new Enumerator.
2832 *
2833 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2834 */
2835
2836static VALUE
2837rb_hash_keep_if(VALUE hash)
2838{
2839 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
2840 rb_hash_modify_check(hash);
2841 if (!RHASH_TABLE_EMPTY_P(hash)) {
2842 rb_hash_foreach(hash, keep_if_i, hash);
2843 }
2844 return hash;
2845}
2846
2847static int
2848clear_i(VALUE key, VALUE value, VALUE dummy)
2849{
2850 return ST_DELETE;
2851}
2852
2853/*
2854 * call-seq:
2855 * clear -> self
2856 *
2857 * Removes all entries from +self+; returns emptied +self+.
2858 *
2859 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
2860 */
2861
2862VALUE
2863rb_hash_clear(VALUE hash)
2864{
2865 rb_hash_modify_check(hash);
2866
2867 if (hash_iterating_p(hash)) {
2868 rb_hash_foreach(hash, clear_i, 0);
2869 }
2870 else if (RHASH_AR_TABLE_P(hash)) {
2871 ar_clear(hash);
2872 }
2873 else {
2874 st_clear(RHASH_ST_TABLE(hash));
2875 compact_after_delete(hash);
2876 }
2877
2878 return hash;
2879}
2880
2881static int
2882hash_aset(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
2883{
2884 *val = arg->arg;
2885 return ST_CONTINUE;
2886}
2887
2888VALUE
2889rb_hash_key_str(VALUE key)
2890{
2891 if (!rb_obj_gen_fields_p(key) && RBASIC_CLASS(key) == rb_cString) {
2892 return rb_fstring(key);
2893 }
2894 else {
2895 return rb_str_new_frozen(key);
2896 }
2897}
2898
2899static int
2900hash_aset_str(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
2901{
2902 if (!existing && !RB_OBJ_FROZEN(*key)) {
2903 *key = rb_hash_key_str(*key);
2904 }
2905 return hash_aset(key, val, arg, existing);
2906}
2907
2908NOINSERT_UPDATE_CALLBACK(hash_aset)
2909NOINSERT_UPDATE_CALLBACK(hash_aset_str)
2910
2911/*
2912 * call-seq:
2913 * self[key] = object -> object
2914 *
2915 * Associates the given +object+ with the given +key+; returns +object+.
2916 *
2917 * Searches for a hash key equivalent to the given +key+;
2918 * see {Hash Key Equivalence}[rdoc-ref:Hash@Hash+Key+Equivalence].
2919 *
2920 * If the key is found, replaces its value with the given +object+;
2921 * the ordering is not affected
2922 * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
2923 *
2924 * h = {foo: 0, bar: 1}
2925 * h[:foo] = 2 # => 2
2926 * h[:foo] # => 2
2927 *
2928 * If +key+ is not found, creates a new entry for the given +key+ and +object+;
2929 * the new entry is last in the order
2930 * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
2931 *
2932 * h = {foo: 0, bar: 1}
2933 * h[:baz] = 2 # => 2
2934 * h[:baz] # => 2
2935 * h # => {foo: 0, bar: 1, baz: 2}
2936 *
2937 * Related: #[]; see also {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
2938 */
2939
2940VALUE
2941rb_hash_aset(VALUE hash, VALUE key, VALUE val)
2942{
2943 bool iter_p = hash_iterating_p(hash);
2944
2945 rb_hash_modify(hash);
2946
2947 if (!RHASH_STRING_KEY_P(hash, key)) {
2948 RHASH_UPDATE_ITER(hash, iter_p, key, hash_aset, val);
2949 }
2950 else {
2951 RHASH_UPDATE_ITER(hash, iter_p, key, hash_aset_str, val);
2952 }
2953 return val;
2954}
2955
2956/*
2957 * call-seq:
2958 * replace(other_hash) -> self
2959 *
2960 * Replaces the entire contents of +self+ with the contents of +other_hash+;
2961 * returns +self+:
2962 *
2963 * h = {foo: 0, bar: 1, baz: 2}
2964 * h.replace({bat: 3, bam: 4}) # => {bat: 3, bam: 4}
2965 *
2966 * Also replaces the default value or proc of +self+ with the default value
2967 * or proc of +other_hash+.
2968 *
2969 * h = {}
2970 * other = Hash.new(:ok)
2971 * h.replace(other)
2972 * h.default # => :ok
2973 *
2974 * Related: see {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
2975 */
2976
2977static VALUE
2978rb_hash_replace(VALUE hash, VALUE hash2)
2979{
2980 rb_hash_modify_check(hash);
2981 if (hash == hash2) return hash;
2982 if (hash_iterating_p(hash)) {
2983 rb_raise(rb_eRuntimeError, "can't replace hash during iteration");
2984 }
2985 hash2 = to_hash(hash2);
2986
2987 COPY_DEFAULT(hash, hash2);
2988
2989 if (RHASH_AR_TABLE_P(hash)) {
2990 hash_ar_free_and_clear_table(hash);
2991 }
2992 else {
2993 hash_st_free_and_clear_table(hash);
2994 }
2995
2996 hash_copy(hash, hash2);
2997
2998 return hash;
2999}
3000
3001/*
3002 * call-seq:
3003 * size -> integer
3004 *
3005 * Returns the count of entries in +self+:
3006 *
3007 * {foo: 0, bar: 1, baz: 2}.size # => 3
3008 *
3009 * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
3010 */
3011
3012VALUE
3013rb_hash_size(VALUE hash)
3014{
3015 return INT2FIX(RHASH_SIZE(hash));
3016}
3017
3018size_t
3019rb_hash_size_num(VALUE hash)
3020{
3021 return (long)RHASH_SIZE(hash);
3022}
3023
3024/*
3025 * call-seq:
3026 * empty? -> true or false
3027 *
3028 * Returns +true+ if there are no hash entries, +false+ otherwise:
3029 *
3030 * {}.empty? # => true
3031 * {foo: 0}.empty? # => false
3032 *
3033 * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
3034 */
3035
3036VALUE
3037rb_hash_empty_p(VALUE hash)
3038{
3039 return RBOOL(RHASH_EMPTY_P(hash));
3040}
3041
3042static int
3043each_value_i(VALUE key, VALUE value, VALUE _)
3044{
3045 rb_yield(value);
3046 return ST_CONTINUE;
3047}
3048
3049/*
3050 * call-seq:
3051 * each_value {|value| ... } -> self
3052 * each_value -> new_enumerator
3053 *
3054 * With a block given, calls the block with each value; returns +self+:
3055 *
3056 * h = {foo: 0, bar: 1, baz: 2}
3057 * h.each_value {|value| puts value } # => {foo: 0, bar: 1, baz: 2}
3058 *
3059 * Output:
3060 * 0
3061 * 1
3062 * 2
3063 *
3064 * With no block given, returns a new Enumerator.
3065 *
3066 * Related: see {Methods for Iterating}[rdoc-ref:Hash@Methods+for+Iterating].
3067 */
3068
3069static VALUE
3070rb_hash_each_value(VALUE hash)
3071{
3072 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3073 rb_hash_foreach(hash, each_value_i, 0);
3074 return hash;
3075}
3076
3077static int
3078each_key_i(VALUE key, VALUE value, VALUE _)
3079{
3080 rb_yield(key);
3081 return ST_CONTINUE;
3082}
3083
3084/*
3085 * call-seq:
3086 * each_key {|key| ... } -> self
3087 * each_key -> new_enumerator
3088 *
3089 * With a block given, calls the block with each key; returns +self+:
3090 *
3091 * h = {foo: 0, bar: 1, baz: 2}
3092 * h.each_key {|key| puts key } # => {foo: 0, bar: 1, baz: 2}
3093 *
3094 * Output:
3095 * foo
3096 * bar
3097 * baz
3098 *
3099 * With no block given, returns a new Enumerator.
3100 *
3101 * Related: see {Methods for Iterating}[rdoc-ref:Hash@Methods+for+Iterating].
3102 */
3103static VALUE
3104rb_hash_each_key(VALUE hash)
3105{
3106 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3107 rb_hash_foreach(hash, each_key_i, 0);
3108 return hash;
3109}
3110
3111static int
3112each_pair_i(VALUE key, VALUE value, VALUE _)
3113{
3114 rb_yield(rb_assoc_new(key, value));
3115 return ST_CONTINUE;
3116}
3117
3118static int
3119each_pair_i_fast(VALUE key, VALUE value, VALUE _)
3120{
3121 VALUE argv[2];
3122 argv[0] = key;
3123 argv[1] = value;
3124 rb_yield_values2(2, argv);
3125 return ST_CONTINUE;
3126}
3127
3128/*
3129 * call-seq:
3130 * each_pair {|key, value| ... } -> self
3131 * each_pair -> new_enumerator
3132 *
3133 * With a block given, calls the block with each key-value pair; returns +self+:
3134 *
3135 * h = {foo: 0, bar: 1, baz: 2}
3136 * h.each_pair {|key, value| puts "#{key}: #{value}"} # => {foo: 0, bar: 1, baz: 2}
3137 *
3138 * Output:
3139 *
3140 * foo: 0
3141 * bar: 1
3142 * baz: 2
3143 *
3144 * With no block given, returns a new Enumerator.
3145 *
3146 * Related: see {Methods for Iterating}[rdoc-ref:Hash@Methods+for+Iterating].
3147 */
3148
3149static VALUE
3150rb_hash_each_pair(VALUE hash)
3151{
3152 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3153 if (rb_block_pair_yield_optimizable())
3154 rb_hash_foreach(hash, each_pair_i_fast, 0);
3155 else
3156 rb_hash_foreach(hash, each_pair_i, 0);
3157 return hash;
3158}
3159
3161 VALUE trans;
3162 VALUE result;
3163 int block_given;
3164};
3165
3166static int
3167transform_keys_hash_i(VALUE key, VALUE value, VALUE transarg)
3168{
3169 struct transform_keys_args *p = (void *)transarg;
3170 VALUE trans = p->trans, result = p->result;
3171 VALUE new_key = rb_hash_lookup2(trans, key, Qundef);
3172 if (UNDEF_P(new_key)) {
3173 if (p->block_given)
3174 new_key = rb_yield(key);
3175 else
3176 new_key = key;
3177 }
3178 rb_hash_aset(result, new_key, value);
3179 return ST_CONTINUE;
3180}
3181
3182static int
3183transform_keys_i(VALUE key, VALUE value, VALUE result)
3184{
3185 VALUE new_key = rb_yield(key);
3186 rb_hash_aset(result, new_key, value);
3187 return ST_CONTINUE;
3188}
3189
3190/*
3191 * call-seq:
3192 * transform_keys {|old_key| ... } -> new_hash
3193 * transform_keys(other_hash) -> new_hash
3194 * transform_keys(other_hash) {|old_key| ...} -> new_hash
3195 * transform_keys -> new_enumerator
3196 *
3197 * With an argument, a block, or both given,
3198 * derives a new hash +new_hash+ from +self+, the argument, and/or the block;
3199 * all, some, or none of its keys may be different from those in +self+.
3200 *
3201 * With a block given and no argument,
3202 * +new_hash+ has keys determined only by the block.
3203 *
3204 * For each key/value pair <tt>old_key/value</tt> in +self+, calls the block with +old_key+;
3205 * the block's return value becomes +new_key+;
3206 * sets <tt>new_hash[new_key] = value</tt>;
3207 * a duplicate key overwrites:
3208 *
3209 * h = {foo: 0, bar: 1, baz: 2}
3210 * h.transform_keys {|old_key| old_key.to_s }
3211 * # => {"foo" => 0, "bar" => 1, "baz" => 2}
3212 * h.transform_keys {|old_key| 'xxx' }
3213 * # => {"xxx" => 2}
3214 *
3215 * With argument +other_hash+ given and no block,
3216 * +new_hash+ may have new keys provided by +other_hash+
3217 * and unchanged keys provided by +self+.
3218 *
3219 * For each key/value pair <tt>old_key/old_value</tt> in +self+,
3220 * looks for key +old_key+ in +other_hash+:
3221 *
3222 * - If +old_key+ is found, its value <tt>other_hash[old_key]</tt> is taken as +new_key+;
3223 * sets <tt>new_hash[new_key] = value</tt>;
3224 * a duplicate key overwrites:
3225 *
3226 * h = {foo: 0, bar: 1, baz: 2}
3227 * h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO)
3228 * # => {FOO: 0, BAR: 1, BAZ: 2}
3229 * h.transform_keys(baz: :FOO, bar: :FOO, foo: :FOO)
3230 * # => {FOO: 2}
3231 *
3232 * - If +old_key+ is not found,
3233 * sets <tt>new_hash[old_key] = value</tt>;
3234 * a duplicate key overwrites:
3235 *
3236 * h = {foo: 0, bar: 1, baz: 2}
3237 * h.transform_keys({})
3238 * # => {foo: 0, bar: 1, baz: 2}
3239 * h.transform_keys(baz: :foo)
3240 * # => {foo: 2, bar: 1}
3241 *
3242 * Unused keys in +other_hash+ are ignored:
3243 *
3244 * h = {foo: 0, bar: 1, baz: 2}
3245 * h.transform_keys(bat: 3)
3246 * # => {foo: 0, bar: 1, baz: 2}
3247 *
3248 * With both argument +other_hash+ and a block given,
3249 * +new_hash+ has new keys specified by +other_hash+ or by the block,
3250 * and unchanged keys provided by +self+.
3251 *
3252 * For each pair +old_key+ and +value+ in +self+:
3253 *
3254 * - If +other_hash+ has key +old_key+ (with value +new_key+),
3255 * does not call the block for that key;
3256 * sets <tt>new_hash[new_key] = value</tt>;
3257 * a duplicate key overwrites:
3258 *
3259 * h = {foo: 0, bar: 1, baz: 2}
3260 * h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
3261 * # => {FOO: 0, BAR: 1, BAZ: 2}
3262 *
3263 * - If +other_hash+ does not have key +old_key+,
3264 * calls the block with +old_key+ and takes its return value as +new_key+;
3265 * sets <tt>new_hash[new_key] = value</tt>;
3266 * a duplicate key overwrites:
3267 *
3268 * h = {foo: 0, bar: 1, baz: 2}
3269 * h.transform_keys(baz: :BAZ) {|key| key.to_s.reverse }
3270 * # => {"oof" => 0, "rab" => 1, BAZ: 2}
3271 * h.transform_keys(baz: :BAZ) {|key| 'ook' }
3272 * # => {"ook" => 1, BAZ: 2}
3273 *
3274 * With no argument and no block given, returns a new Enumerator.
3275 *
3276 * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
3277 */
3278static VALUE
3279rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash)
3280{
3281 VALUE result;
3282 struct transform_keys_args transarg = {0};
3283
3284 argc = rb_check_arity(argc, 0, 1);
3285 if (argc > 0) {
3286 transarg.trans = to_hash(argv[0]);
3287 transarg.block_given = rb_block_given_p();
3288 }
3289 else {
3290 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3291 }
3292 result = rb_hash_new();
3293 if (!RHASH_EMPTY_P(hash)) {
3294 if (transarg.trans) {
3295 transarg.result = result;
3296 rb_hash_foreach(hash, transform_keys_hash_i, (VALUE)&transarg);
3297 }
3298 else {
3299 rb_hash_foreach(hash, transform_keys_i, result);
3300 }
3301 }
3302
3303 return result;
3304}
3305
3306static int flatten_i(VALUE key, VALUE val, VALUE ary);
3307
3308/*
3309 * call-seq:
3310 * transform_keys! {|old_key| ... } -> self
3311 * transform_keys!(other_hash) -> self
3312 * transform_keys!(other_hash) {|old_key| ...} -> self
3313 * transform_keys! -> new_enumerator
3314 *
3315 * With an argument, a block, or both given,
3316 * derives keys from the argument, the block, and +self+;
3317 * all, some, or none of the keys in +self+ may be changed.
3318 *
3319 * With a block given and no argument,
3320 * derives keys only from the block;
3321 * all, some, or none of the keys in +self+ may be changed.
3322 *
3323 * For each key/value pair <tt>old_key/value</tt> in +self+, calls the block with +old_key+;
3324 * the block's return value becomes +new_key+;
3325 * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3326 * sets <tt>self[new_key] = value</tt>;
3327 * a duplicate key overwrites:
3328 *
3329 * h = {foo: 0, bar: 1, baz: 2}
3330 * h.transform_keys! {|old_key| old_key.to_s }
3331 * # => {"foo" => 0, "bar" => 1, "baz" => 2}
3332 * h = {foo: 0, bar: 1, baz: 2}
3333 * h.transform_keys! {|old_key| 'xxx' }
3334 * # => {"xxx" => 2}
3335 *
3336 * With argument +other_hash+ given and no block,
3337 * derives keys for +self+ from +other_hash+ and +self+;
3338 * all, some, or none of the keys in +self+ may be changed.
3339 *
3340 * For each key/value pair <tt>old_key/old_value</tt> in +self+,
3341 * looks for key +old_key+ in +other_hash+:
3342 *
3343 * - If +old_key+ is found, takes value <tt>other_hash[old_key]</tt> as +new_key+;
3344 * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3345 * sets <tt>self[new_key] = value</tt>;
3346 * a duplicate key overwrites:
3347 *
3348 * h = {foo: 0, bar: 1, baz: 2}
3349 * h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO)
3350 * # => {FOO: 0, BAR: 1, BAZ: 2}
3351 * h = {foo: 0, bar: 1, baz: 2}
3352 * h.transform_keys!(baz: :FOO, bar: :FOO, foo: :FOO)
3353 * # => {FOO: 2}
3354 *
3355 * - If +old_key+ is not found, does nothing:
3356 *
3357 * h = {foo: 0, bar: 1, baz: 2}
3358 * h.transform_keys!({})
3359 * # => {foo: 0, bar: 1, baz: 2}
3360 * h.transform_keys!(baz: :foo)
3361 * # => {foo: 2, bar: 1}
3362 *
3363 * Unused keys in +other_hash+ are ignored:
3364 *
3365 * h = {foo: 0, bar: 1, baz: 2}
3366 * h.transform_keys!(bat: 3)
3367 * # => {foo: 0, bar: 1, baz: 2}
3368 *
3369 * With both argument +other_hash+ and a block given,
3370 * derives keys from +other_hash+, the block, and +self+;
3371 * all, some, or none of the keys in +self+ may be changed.
3372 *
3373 * For each pair +old_key+ and +value+ in +self+:
3374 *
3375 * - If +other_hash+ has key +old_key+ (with value +new_key+),
3376 * does not call the block for that key;
3377 * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3378 * sets <tt>self[new_key] = value</tt>;
3379 * a duplicate key overwrites:
3380 *
3381 * h = {foo: 0, bar: 1, baz: 2}
3382 * h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
3383 * # => {FOO: 0, BAR: 1, BAZ: 2}
3384 *
3385 * - If +other_hash+ does not have key +old_key+,
3386 * calls the block with +old_key+ and takes its return value as +new_key+;
3387 * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
3388 * sets <tt>self[new_key] = value</tt>;
3389 * a duplicate key overwrites:
3390 *
3391 * h = {foo: 0, bar: 1, baz: 2}
3392 * h.transform_keys!(baz: :BAZ) {|key| key.to_s.reverse }
3393 * # => {"oof" => 0, "rab" => 1, BAZ: 2}
3394 * h = {foo: 0, bar: 1, baz: 2}
3395 * h.transform_keys!(baz: :BAZ) {|key| 'ook' }
3396 * # => {"ook" => 1, BAZ: 2}
3397 *
3398 * With no argument and no block given, returns a new Enumerator.
3399 *
3400 * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
3401 */
3402static VALUE
3403rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
3404{
3405 VALUE trans = 0;
3406 int block_given = 0;
3407
3408 argc = rb_check_arity(argc, 0, 1);
3409 if (argc > 0) {
3410 trans = to_hash(argv[0]);
3411 block_given = rb_block_given_p();
3412 }
3413 else {
3414 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3415 }
3416 rb_hash_modify_check(hash);
3417 if (!RHASH_TABLE_EMPTY_P(hash)) {
3418 long i;
3419 VALUE new_keys = hash_alloc(0);
3420 VALUE pairs = rb_ary_hidden_new(RHASH_SIZE(hash) * 2);
3421 rb_hash_foreach(hash, flatten_i, pairs);
3422 for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
3423 VALUE key = RARRAY_AREF(pairs, i), new_key, val;
3424
3425 if (!trans) {
3426 new_key = rb_yield(key);
3427 }
3428 else if (!UNDEF_P(new_key = rb_hash_lookup2(trans, key, Qundef))) {
3429 /* use the transformed key */
3430 }
3431 else if (block_given) {
3432 new_key = rb_yield(key);
3433 }
3434 else {
3435 new_key = key;
3436 }
3437 val = RARRAY_AREF(pairs, i+1);
3438 if (!hash_stlike_lookup(new_keys, key, NULL)) {
3439 rb_hash_stlike_delete(hash, &key, NULL);
3440 }
3441 rb_hash_aset(hash, new_key, val);
3442 rb_hash_aset(new_keys, new_key, Qnil);
3443 }
3444 rb_ary_clear(pairs);
3445 rb_hash_clear(new_keys);
3446 }
3447 compact_after_delete(hash);
3448 return hash;
3449}
3450
3451static int
3452transform_values_foreach_func(st_data_t key, st_data_t value, st_data_t argp, int error)
3453{
3454 return ST_REPLACE;
3455}
3456
3457static int
3458transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
3459{
3460 VALUE new_value = rb_yield((VALUE)*value);
3461 VALUE hash = (VALUE)argp;
3462 rb_hash_modify(hash);
3463 RB_OBJ_WRITE(hash, value, new_value);
3464 return ST_CONTINUE;
3465}
3466
3467static VALUE
3468transform_values_call(VALUE hash)
3469{
3470 rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, hash);
3471 return hash;
3472}
3473
3474static void
3475transform_values(VALUE hash)
3476{
3477 hash_iter_lev_inc(hash);
3478 rb_ensure(transform_values_call, hash, hash_foreach_ensure, hash);
3479}
3480
3481/*
3482 * call-seq:
3483 * transform_values {|value| ... } -> new_hash
3484 * transform_values -> new_enumerator
3485 *
3486 * With a block given, returns a new hash +new_hash+;
3487 * for each pair +key+/+value+ in +self+,
3488 * calls the block with +value+ and captures its return as +new_value+;
3489 * adds to +new_hash+ the entry +key+/+new_value+:
3490 *
3491 * h = {foo: 0, bar: 1, baz: 2}
3492 * h1 = h.transform_values {|value| value * 100}
3493 * h1 # => {foo: 0, bar: 100, baz: 200}
3494 *
3495 * With no block given, returns a new Enumerator.
3496 *
3497 * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
3498 */
3499static VALUE
3500rb_hash_transform_values(VALUE hash)
3501{
3502 VALUE result;
3503
3504 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3505 result = hash_dup_with_compare_by_id(hash);
3506 SET_DEFAULT(result, Qnil);
3507
3508 if (!RHASH_EMPTY_P(hash)) {
3509 transform_values(result);
3510 compact_after_delete(result);
3511 }
3512
3513 return result;
3514}
3515
3516/*
3517 * call-seq:
3518 * transform_values! {|old_value| ... } -> self
3519 * transform_values! -> new_enumerator
3520 *
3521 *
3522 * With a block given, changes the values of +self+ as determined by the block;
3523 * returns +self+.
3524 *
3525 * For each entry +key+/+old_value+ in +self+,
3526 * calls the block with +old_value+,
3527 * captures its return value as +new_value+,
3528 * and sets <tt>self[key] = new_value</tt>:
3529 *
3530 * h = {foo: 0, bar: 1, baz: 2}
3531 * h.transform_values! {|value| value * 100} # => {foo: 0, bar: 100, baz: 200}
3532 *
3533 * With no block given, returns a new Enumerator.
3534 *
3535 * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
3536 */
3537static VALUE
3538rb_hash_transform_values_bang(VALUE hash)
3539{
3540 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
3541 rb_hash_modify_check(hash);
3542
3543 if (!RHASH_TABLE_EMPTY_P(hash)) {
3544 transform_values(hash);
3545 }
3546
3547 return hash;
3548}
3549
3550static int
3551to_a_i(VALUE key, VALUE value, VALUE ary)
3552{
3553 rb_ary_push(ary, rb_assoc_new(key, value));
3554 return ST_CONTINUE;
3555}
3556
3557/*
3558 * call-seq:
3559 * to_a -> new_array
3560 *
3561 * Returns all elements of +self+ as an array of 2-element arrays;
3562 * each nested array contains a key-value pair from +self+:
3563 *
3564 * h = {foo: 0, bar: 1, baz: 2}
3565 * h.to_a # => [[:foo, 0], [:bar, 1], [:baz, 2]]
3566 *
3567 * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
3568 */
3569
3570static VALUE
3571rb_hash_to_a(VALUE hash)
3572{
3573 VALUE ary;
3574
3575 ary = rb_ary_new_capa(RHASH_SIZE(hash));
3576 rb_hash_foreach(hash, to_a_i, ary);
3577
3578 return ary;
3579}
3580
3581static bool
3582symbol_key_needs_quote(VALUE str)
3583{
3584 long len = RSTRING_LEN(str);
3585 if (len == 0 || !rb_str_symname_p(str)) return true;
3586 const char *s = RSTRING_PTR(str);
3587 char first = s[0];
3588 if (first == '@' || first == '$' || first == '!') return true;
3589 if (!at_char_boundary(s, s + len - 1, RSTRING_END(str), rb_enc_get(str))) return false;
3590 switch (s[len - 1]) {
3591 case '+':
3592 case '-':
3593 case '*':
3594 case '/':
3595 case '`':
3596 case '%':
3597 case '^':
3598 case '&':
3599 case '|':
3600 case ']':
3601 case '<':
3602 case '=':
3603 case '>':
3604 case '~':
3605 case '@':
3606 return true;
3607 default:
3608 return false;
3609 }
3610}
3611
3612static int
3613inspect_i(VALUE key, VALUE value, VALUE str)
3614{
3615 VALUE str2;
3616
3617 bool is_symbol = SYMBOL_P(key);
3618 bool quote = false;
3619 if (is_symbol) {
3620 str2 = rb_sym2str(key);
3621 quote = symbol_key_needs_quote(str2);
3622 }
3623 else {
3624 str2 = rb_inspect(key);
3625 }
3626 if (RSTRING_LEN(str) > 1) {
3627 rb_str_buf_cat_ascii(str, ", ");
3628 }
3629 else {
3630 rb_enc_copy(str, str2);
3631 }
3632 if (quote) {
3634 }
3635 else {
3636 rb_str_buf_append(str, str2);
3637 }
3638
3639 rb_str_buf_cat_ascii(str, is_symbol ? ": " : " => ");
3640 str2 = rb_inspect(value);
3641 rb_str_buf_append(str, str2);
3642
3643 return ST_CONTINUE;
3644}
3645
3646static VALUE
3647inspect_hash(VALUE hash, VALUE dummy, int recur)
3648{
3649 VALUE str;
3650
3651 if (recur) return rb_usascii_str_new2("{...}");
3652 str = rb_str_buf_new2("{");
3653 rb_hash_foreach(hash, inspect_i, str);
3654 rb_str_buf_cat2(str, "}");
3655
3656 return str;
3657}
3658
3659/*
3660 * call-seq:
3661 * inspect -> new_string
3662 *
3663 * Returns a new string containing the hash entries:
3664 *
3665 * h = {foo: 0, bar: 1, baz: 2}
3666 * h.inspect # => "{foo: 0, bar: 1, baz: 2}"
3667 *
3668 * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
3669 */
3670
3671static VALUE
3672rb_hash_inspect(VALUE hash)
3673{
3674 if (RHASH_EMPTY_P(hash))
3675 return rb_usascii_str_new2("{}");
3676 return rb_exec_recursive(inspect_hash, hash, 0);
3677}
3678
3679/*
3680 * call-seq:
3681 * to_hash -> self
3682 *
3683 * Returns +self+.
3684 *
3685 * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
3686 */
3687static VALUE
3688rb_hash_to_hash(VALUE hash)
3689{
3690 return hash;
3691}
3692
3693VALUE
3694rb_hash_set_pair(VALUE hash, VALUE arg)
3695{
3696 VALUE pair;
3697
3698 pair = rb_check_array_type(arg);
3699 if (NIL_P(pair)) {
3700 rb_raise(rb_eTypeError, "wrong element type %s (expected array)",
3701 rb_builtin_class_name(arg));
3702 }
3703 if (RARRAY_LEN(pair) != 2) {
3704 rb_raise(rb_eArgError, "element has wrong array length (expected 2, was %ld)",
3705 RARRAY_LEN(pair));
3706 }
3707 rb_hash_aset(hash, RARRAY_AREF(pair, 0), RARRAY_AREF(pair, 1));
3708 return hash;
3709}
3710
3711static int
3712to_h_i(VALUE key, VALUE value, VALUE hash)
3713{
3714 rb_hash_set_pair(hash, rb_yield_values(2, key, value));
3715 return ST_CONTINUE;
3716}
3717
3718static VALUE
3719rb_hash_to_h_block(VALUE hash)
3720{
3721 VALUE h = rb_hash_new_with_size(RHASH_SIZE(hash));
3722 rb_hash_foreach(hash, to_h_i, h);
3723 return h;
3724}
3725
3726/*
3727 * call-seq:
3728 * to_h {|key, value| ... } -> new_hash
3729 * to_h -> self or new_hash
3730 *
3731 * With a block given, returns a new hash whose content is based on the block;
3732 * the block is called with each entry's key and value;
3733 * the block should return a 2-element array
3734 * containing the key and value to be included in the returned array:
3735 *
3736 * h = {foo: 0, bar: 1, baz: 2}
3737 * h.to_h {|key, value| [value, key] }
3738 * # => {0 => :foo, 1 => :bar, 2 => :baz}
3739 *
3740 * With no block given, returns +self+ if +self+ is an instance of +Hash+;
3741 * if +self+ is a subclass of +Hash+, returns a new hash containing the content of +self+.
3742 *
3743 * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
3744 */
3745
3746static VALUE
3747rb_hash_to_h(VALUE hash)
3748{
3749 if (rb_block_given_p()) {
3750 return rb_hash_to_h_block(hash);
3751 }
3752 if (rb_obj_class(hash) != rb_cHash) {
3753 const VALUE flags = RBASIC(hash)->flags;
3754 hash = hash_dup(hash, rb_cHash, flags & RHASH_PROC_DEFAULT);
3755 }
3756 return hash;
3757}
3758
3759static int
3760keys_i(VALUE key, VALUE value, VALUE ary)
3761{
3762 rb_ary_push(ary, key);
3763 return ST_CONTINUE;
3764}
3765
3766/*
3767 * call-seq:
3768 * keys -> new_array
3769 *
3770 * Returns a new array containing all keys in +self+:
3771 *
3772 * h = {foo: 0, bar: 1, baz: 2}
3773 * h.keys # => [:foo, :bar, :baz]
3774 *
3775 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
3776 */
3777
3778VALUE
3779rb_hash_keys(VALUE hash)
3780{
3781 st_index_t size = RHASH_SIZE(hash);
3782 VALUE keys = rb_ary_new_capa(size);
3783
3784 if (size == 0) return keys;
3785
3786 if (ST_DATA_COMPATIBLE_P(VALUE)) {
3787 RARRAY_PTR_USE(keys, ptr, {
3788 if (RHASH_AR_TABLE_P(hash)) {
3789 size = ar_keys(hash, ptr, size);
3790 }
3791 else {
3792 st_table *table = RHASH_ST_TABLE(hash);
3793 size = st_keys(table, ptr, size);
3794 }
3795 });
3796 rb_gc_writebarrier_remember(keys);
3797 rb_ary_set_len(keys, size);
3798 }
3799 else {
3800 rb_hash_foreach(hash, keys_i, keys);
3801 }
3802
3803 return keys;
3804}
3805
3806static int
3807values_i(VALUE key, VALUE value, VALUE ary)
3808{
3809 rb_ary_push(ary, value);
3810 return ST_CONTINUE;
3811}
3812
3813/*
3814 * call-seq:
3815 * values -> new_array
3816 *
3817 * Returns a new array containing all values in +self+:
3818 *
3819 * h = {foo: 0, bar: 1, baz: 2}
3820 * h.values # => [0, 1, 2]
3821 *
3822 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
3823 */
3824
3825VALUE
3826rb_hash_values(VALUE hash)
3827{
3828 VALUE values;
3829 st_index_t size = RHASH_SIZE(hash);
3830
3831 values = rb_ary_new_capa(size);
3832 if (size == 0) return values;
3833
3834 if (ST_DATA_COMPATIBLE_P(VALUE)) {
3835 if (RHASH_AR_TABLE_P(hash)) {
3836 rb_gc_writebarrier_remember(values);
3837 RARRAY_PTR_USE(values, ptr, {
3838 size = ar_values(hash, ptr, size);
3839 });
3840 }
3841 else if (RHASH_ST_TABLE_P(hash)) {
3842 st_table *table = RHASH_ST_TABLE(hash);
3843 rb_gc_writebarrier_remember(values);
3844 RARRAY_PTR_USE(values, ptr, {
3845 size = st_values(table, ptr, size);
3846 });
3847 }
3848 rb_ary_set_len(values, size);
3849 }
3850 else {
3851 rb_hash_foreach(hash, values_i, values);
3852 }
3853
3854 return values;
3855}
3856
3857/*
3858 * call-seq:
3859 * include?(key) -> true or false
3860 *
3861 * Returns whether +key+ is a key in +self+:
3862 *
3863 * h = {foo: 0, bar: 1, baz: 2}
3864 * h.include?(:bar) # => true
3865 * h.include?(:BAR) # => false
3866 *
3867 * Related: {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
3868 */
3869
3870VALUE
3871rb_hash_has_key(VALUE hash, VALUE key)
3872{
3873 return RBOOL(hash_stlike_lookup(hash, key, NULL));
3874}
3875
3876static int
3877rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
3878{
3879 VALUE *data = (VALUE *)arg;
3880
3881 if (rb_equal(value, data[1])) {
3882 data[0] = Qtrue;
3883 return ST_STOP;
3884 }
3885 return ST_CONTINUE;
3886}
3887
3888/*
3889 * call-seq:
3890 * has_value?(value) -> true or false
3891 *
3892 * Returns whether +value+ is a value in +self+.
3893 *
3894 * Related: {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
3895 */
3896
3897static VALUE
3898rb_hash_has_value(VALUE hash, VALUE val)
3899{
3900 VALUE data[2];
3901
3902 data[0] = Qfalse;
3903 data[1] = val;
3904 rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
3905 return data[0];
3906}
3907
3909 VALUE result;
3910 VALUE hash;
3911 int eql;
3912};
3913
3914static int
3915eql_i(VALUE key, VALUE val1, VALUE arg)
3916{
3917 struct equal_data *data = (struct equal_data *)arg;
3918 st_data_t val2;
3919
3920 if (!hash_stlike_lookup(data->hash, key, &val2)) {
3921 data->result = Qfalse;
3922 return ST_STOP;
3923 }
3924 else {
3925 if (!(data->eql ? rb_eql(val1, (VALUE)val2) : (int)rb_equal(val1, (VALUE)val2))) {
3926 data->result = Qfalse;
3927 return ST_STOP;
3928 }
3929 return ST_CONTINUE;
3930 }
3931}
3932
3933static VALUE
3934recursive_eql(VALUE hash, VALUE dt, int recur)
3935{
3936 struct equal_data *data;
3937
3938 if (recur) return Qtrue; /* Subtle! */
3939 data = (struct equal_data*)dt;
3940 data->result = Qtrue;
3941 rb_hash_foreach(hash, eql_i, dt);
3942
3943 return data->result;
3944}
3945
3946static VALUE
3947hash_equal(VALUE hash1, VALUE hash2, int eql)
3948{
3949 struct equal_data data;
3950
3951 if (hash1 == hash2) return Qtrue;
3952 if (!RB_TYPE_P(hash2, T_HASH)) {
3953 if (!rb_respond_to(hash2, idTo_hash)) {
3954 return Qfalse;
3955 }
3956 if (eql) {
3957 if (rb_eql(hash2, hash1)) {
3958 return Qtrue;
3959 }
3960 else {
3961 return Qfalse;
3962 }
3963 }
3964 else {
3965 return rb_equal(hash2, hash1);
3966 }
3967 }
3968 if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
3969 return Qfalse;
3970 if (!RHASH_TABLE_EMPTY_P(hash1) && !RHASH_TABLE_EMPTY_P(hash2)) {
3971 if (RHASH_TYPE(hash1) != RHASH_TYPE(hash2)) {
3972 return Qfalse;
3973 }
3974 else {
3975 data.hash = hash2;
3976 data.eql = eql;
3977 return rb_exec_recursive_paired(recursive_eql, hash1, hash2, (VALUE)&data);
3978 }
3979 }
3980
3981#if 0
3982 if (!(rb_equal(RHASH_IFNONE(hash1), RHASH_IFNONE(hash2)) &&
3983 FL_TEST(hash1, RHASH_PROC_DEFAULT) == FL_TEST(hash2, RHASH_PROC_DEFAULT)))
3984 return Qfalse;
3985#endif
3986 return Qtrue;
3987}
3988
3989/*
3990 * call-seq:
3991 * self == other -> true or false
3992 *
3993 * Returns whether all of the following are true:
3994 *
3995 * - +other+ is a +Hash+ object (or can be converted to one).
3996 * - +self+ and +other+ have the same keys (regardless of order).
3997 * - For each key +key+, <tt>self[key] == other[key]</tt>.
3998 *
3999 * Examples:
4000 *
4001 * h = {foo: 0, bar: 1}
4002 * h == {foo: 0, bar: 1} # => true # Equal entries (same order)
4003 * h == {bar: 1, foo: 0} # => true # Equal entries (different order).
4004 * h == 1 # => false # Object not a hash.
4005 * h == {} # => false # Different number of entries.
4006 * h == {foo: 0, bar: 1} # => false # Different key.
4007 * h == {foo: 0, bar: 1} # => false # Different value.
4008 *
4009 * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
4010 */
4011
4012static VALUE
4013rb_hash_equal(VALUE hash1, VALUE hash2)
4014{
4015 return hash_equal(hash1, hash2, FALSE);
4016}
4017
4018/*
4019 * call-seq:
4020 * eql?(object) -> true or false
4021 *
4022 * Returns +true+ if all of the following are true:
4023 *
4024 * - The given +object+ is a +Hash+ object.
4025 * - +self+ and +object+ have the same keys (regardless of order).
4026 * - For each key +key+, <tt>self[key].eql?(object[key])</tt>.
4027 *
4028 * Otherwise, returns +false+.
4029 *
4030 * h1 = {foo: 0, bar: 1, baz: 2}
4031 * h2 = {foo: 0, bar: 1, baz: 2}
4032 * h1.eql? h2 # => true
4033 * h3 = {baz: 2, bar: 1, foo: 0}
4034 * h1.eql? h3 # => true
4035 *
4036 * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
4037 */
4038
4039static VALUE
4040rb_hash_eql(VALUE hash1, VALUE hash2)
4041{
4042 return hash_equal(hash1, hash2, TRUE);
4043}
4044
4045static int
4046hash_i(VALUE key, VALUE val, VALUE arg)
4047{
4048 st_index_t *hval = (st_index_t *)arg;
4049 st_index_t hdata[2];
4050
4051 hdata[0] = rb_hash(key);
4052 hdata[1] = rb_hash(val);
4053 *hval ^= st_hash(hdata, sizeof(hdata), 0);
4054 return ST_CONTINUE;
4055}
4056
4057/*
4058 * call-seq:
4059 * hash -> an_integer
4060 *
4061 * Returns the integer hash-code for the hash.
4062 *
4063 * Two hashes have the same hash-code if their content is the same
4064 * (regardless of order):
4065 *
4066 * h1 = {foo: 0, bar: 1, baz: 2}
4067 * h2 = {baz: 2, bar: 1, foo: 0}
4068 * h2.hash == h1.hash # => true
4069 * h2.eql? h1 # => true
4070 *
4071 * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
4072 */
4073
4074static VALUE
4075rb_hash_hash(VALUE hash)
4076{
4077 st_index_t size = RHASH_SIZE(hash);
4078 st_index_t hval = rb_hash_start(size);
4079 hval = rb_hash_uint(hval, (st_index_t)rb_hash_hash);
4080 if (size) {
4081 rb_hash_foreach(hash, hash_i, (VALUE)&hval);
4082 }
4083 hval = rb_hash_end(hval);
4084 return ST2FIX(hval);
4085}
4086
4087static int
4088rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
4089{
4090 rb_hash_aset(hash, value, key);
4091 return ST_CONTINUE;
4092}
4093
4094/*
4095 * call-seq:
4096 * invert -> new_hash
4097 *
4098 * Returns a new hash with each key-value pair inverted:
4099 *
4100 * h = {foo: 0, bar: 1, baz: 2}
4101 * h1 = h.invert
4102 * h1 # => {0=>:foo, 1=>:bar, 2=>:baz}
4103 *
4104 * Overwrites any repeated new keys
4105 * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
4106 *
4107 * h = {foo: 0, bar: 0, baz: 0}
4108 * h.invert # => {0=>:baz}
4109 *
4110 * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
4111 */
4112
4113static VALUE
4114rb_hash_invert(VALUE hash)
4115{
4116 VALUE h = rb_hash_new_with_size(RHASH_SIZE(hash));
4117
4118 rb_hash_foreach(hash, rb_hash_invert_i, h);
4119 return h;
4120}
4121
4122static int
4123rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
4124{
4125 rb_hash_aset(hash, key, value);
4126 return ST_CONTINUE;
4127}
4128
4130 VALUE hash, newvalue, *argv;
4131 int argc;
4132 bool block_given;
4133 bool iterating;
4134};
4135
4136static int
4137rb_hash_update_block_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
4138{
4139 VALUE k = (VALUE)*key, v = (VALUE)*value;
4140 struct update_call_args *ua = (void *)arg->arg;
4141 VALUE newvalue = ua->newvalue, hash = arg->hash;
4142
4143 if (existing) {
4144 hash_iter_lev_inc(hash);
4145 ua->iterating = true;
4146 newvalue = rb_yield_values(3, k, v, newvalue);
4147 hash_iter_lev_dec(hash);
4148 ua->iterating = false;
4149 }
4150 else if (RHASH_STRING_KEY_P(hash, k) && !RB_OBJ_FROZEN(k)) {
4151 *key = (st_data_t)rb_hash_key_str(k);
4152 }
4153 *value = (st_data_t)newvalue;
4154 return ST_CONTINUE;
4155}
4156
4157NOINSERT_UPDATE_CALLBACK(rb_hash_update_block_callback)
4158
4159static int
4160rb_hash_update_block_i(VALUE key, VALUE value, VALUE args)
4161{
4162 struct update_call_args *ua = (void *)args;
4163 ua->newvalue = value;
4164 RHASH_UPDATE(ua->hash, key, rb_hash_update_block_callback, args);
4165 return ST_CONTINUE;
4166}
4167
4168static VALUE
4169rb_hash_update_call(VALUE args)
4170{
4171 struct update_call_args *arg = (void *)args;
4172
4173 for (int i = 0; i < arg->argc; i++){
4174 VALUE hash = to_hash(arg->argv[i]);
4175 if (arg->block_given) {
4176 rb_hash_foreach(hash, rb_hash_update_block_i, args);
4177 }
4178 else {
4179 rb_hash_foreach(hash, rb_hash_update_i, arg->hash);
4180 }
4181 }
4182 return arg->hash;
4183}
4184
4185static VALUE
4186rb_hash_update_ensure(VALUE args)
4187{
4188 struct update_call_args *ua = (void *)args;
4189 if (ua->iterating) hash_iter_lev_dec(ua->hash);
4190 return Qnil;
4191}
4192
4193/*
4194 * call-seq:
4195 * update(*other_hashes) -> self
4196 * update(*other_hashes) { |key, old_value, new_value| ... } -> self
4197 *
4198 * Updates values and/or adds entries to +self+; returns +self+.
4199 *
4200 * Each argument +other_hash+ in +other_hashes+ must be a hash.
4201 *
4202 * With no block given, for each successive entry +key+/+new_value+ in each successive +other_hash+:
4203 *
4204 * - If +key+ is in +self+, sets <tt>self[key] = new_value</tt>, whose position is unchanged:
4205 *
4206 * h0 = {foo: 0, bar: 1, baz: 2}
4207 * h1 = {bar: 3, foo: -1}
4208 * h0.update(h1) # => {foo: -1, bar: 3, baz: 2}
4209 *
4210 * - If +key+ is not in +self+, adds the entry at the end of +self+:
4211 *
4212 * h = {foo: 0, bar: 1, baz: 2}
4213 * h.update({bam: 3, bah: 4}) # => {foo: 0, bar: 1, baz: 2, bam: 3, bah: 4}
4214 *
4215 * With a block given, for each successive entry +key+/+new_value+ in each successive +other_hash+:
4216 *
4217 * - If +key+ is in +self+, fetches +old_value+ from <tt>self[key]</tt>,
4218 * calls the block with +key+, +old_value+, and +new_value+,
4219 * and sets <tt>self[key] = new_value</tt>, whose position is unchanged :
4220 *
4221 * season = {AB: 75, H: 20, HR: 3, SO: 17, W: 11, HBP: 3}
4222 * today = {AB: 3, H: 1, W: 1}
4223 * yesterday = {AB: 4, H: 2, HR: 1}
4224 * season.update(yesterday, today) {|key, old_value, new_value| old_value + new_value }
4225 * # => {AB: 82, H: 23, HR: 4, SO: 17, W: 12, HBP: 3}
4226 *
4227 * - If +key+ is not in +self+, adds the entry at the end of +self+:
4228 *
4229 * h = {foo: 0, bar: 1, baz: 2}
4230 * h.update({bat: 3}) { fail 'Cannot happen' }
4231 * # => {foo: 0, bar: 1, baz: 2, bat: 3}
4232 *
4233 * Related: see {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
4234 */
4235
4236static VALUE
4237rb_hash_update(int argc, VALUE *argv, VALUE self)
4238{
4239 struct update_call_args args = {
4240 .hash = self,
4241 .argv = argv,
4242 .argc = argc,
4243 .block_given = rb_block_given_p(),
4244 .iterating = false,
4245 };
4246 VALUE arg = (VALUE)&args;
4247
4248 rb_hash_modify(self);
4249 return rb_ensure(rb_hash_update_call, arg, rb_hash_update_ensure, arg);
4250}
4251
4253 VALUE hash;
4254 VALUE value;
4255 rb_hash_update_func *func;
4256};
4257
4258static int
4259rb_hash_update_func_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
4260{
4261 struct update_func_arg *uf_arg = (struct update_func_arg *)arg->arg;
4262 VALUE newvalue = uf_arg->value;
4263
4264 if (existing) {
4265 newvalue = (*uf_arg->func)((VALUE)*key, (VALUE)*value, newvalue);
4266 }
4267 *value = newvalue;
4268 return ST_CONTINUE;
4269}
4270
4271NOINSERT_UPDATE_CALLBACK(rb_hash_update_func_callback)
4272
4273static int
4274rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0)
4275{
4276 struct update_func_arg *arg = (struct update_func_arg *)arg0;
4277 VALUE hash = arg->hash;
4278
4279 arg->value = value;
4280 RHASH_UPDATE(hash, key, rb_hash_update_func_callback, (VALUE)arg);
4281 return ST_CONTINUE;
4282}
4283
4284VALUE
4285rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
4286{
4287 rb_hash_modify(hash1);
4288 hash2 = to_hash(hash2);
4289 if (func) {
4290 struct update_func_arg arg;
4291 arg.hash = hash1;
4292 arg.func = func;
4293 rb_hash_foreach(hash2, rb_hash_update_func_i, (VALUE)&arg);
4294 }
4295 else {
4296 rb_hash_foreach(hash2, rb_hash_update_i, hash1);
4297 }
4298 return hash1;
4299}
4300
4301/*
4302 * call-seq:
4303 * merge(*other_hashes) -> new_hash
4304 * merge(*other_hashes) { |key, old_value, new_value| ... } -> new_hash
4305 *
4306 * Each argument +other_hash+ in +other_hashes+ must be a hash.
4307 *
4308 * With arguments +other_hashes+ given and no block,
4309 * returns the new hash formed by merging each successive +other_hash+
4310 * into a copy of +self+;
4311 * returns that copy;
4312 * for each successive entry in +other_hash+:
4313 *
4314 * - For a new key, the entry is added at the end of +self+.
4315 * - For duplicate key, the entry overwrites the entry in +self+,
4316 * whose position is unchanged.
4317 *
4318 * Example:
4319 *
4320 * h = {foo: 0, bar: 1, baz: 2}
4321 * h1 = {bat: 3, bar: 4}
4322 * h2 = {bam: 5, bat:6}
4323 * h.merge(h1, h2) # => {foo: 0, bar: 4, baz: 2, bat: 6, bam: 5}
4324 *
4325 * With arguments +other_hashes+ and a block given, behaves as above
4326 * except that for a duplicate key
4327 * the overwriting entry takes it value not from the entry in +other_hash+,
4328 * but instead from the block:
4329 *
4330 * - The block is called with the duplicate key and the values
4331 * from both +self+ and +other_hash+.
4332 * - The block's return value becomes the new value for the entry in +self+.
4333 *
4334 * Example:
4335 *
4336 * h = {foo: 0, bar: 1, baz: 2}
4337 * h1 = {bat: 3, bar: 4}
4338 * h2 = {bam: 5, bat:6}
4339 * h.merge(h1, h2) { |key, old_value, new_value| old_value + new_value }
4340 * # => {foo: 0, bar: 5, baz: 2, bat: 9, bam: 5}
4341 *
4342 * With no arguments, returns a copy of +self+; the block, if given, is ignored.
4343 *
4344 * Related: see {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
4345 */
4346
4347static VALUE
4348rb_hash_merge(int argc, VALUE *argv, VALUE self)
4349{
4350 return rb_hash_update(argc, argv, copy_compare_by_id(rb_hash_dup(self), self));
4351}
4352
4353static int
4354assoc_cmp(VALUE a, VALUE b)
4355{
4356 return !RTEST(rb_equal(a, b));
4357}
4358
4360 st_table *tbl;
4361 st_data_t key;
4362};
4363
4364static VALUE
4365assoc_lookup(VALUE arg)
4366{
4367 struct assoc_arg *p = (struct assoc_arg*)arg;
4368 st_data_t data;
4369 if (st_lookup(p->tbl, p->key, &data)) return (VALUE)data;
4370 return Qundef;
4371}
4372
4373static int
4374assoc_i(VALUE key, VALUE val, VALUE arg)
4375{
4376 VALUE *args = (VALUE *)arg;
4377
4378 if (RTEST(rb_equal(args[0], key))) {
4379 args[1] = rb_assoc_new(key, val);
4380 return ST_STOP;
4381 }
4382 return ST_CONTINUE;
4383}
4384
4385/*
4386 * call-seq:
4387 * assoc(key) -> entry or nil
4388 *
4389 * If the given +key+ is found, returns its entry as a 2-element array
4390 * containing that key and its value:
4391 *
4392 * h = {foo: 0, bar: 1, baz: 2}
4393 * h.assoc(:bar) # => [:bar, 1]
4394 *
4395 * Returns +nil+ if the key is not found.
4396 *
4397 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
4398 */
4399
4400static VALUE
4401rb_hash_assoc(VALUE hash, VALUE key)
4402{
4403 VALUE args[2];
4404
4405 if (RHASH_EMPTY_P(hash)) return Qnil;
4406
4407 if (RHASH_ST_TABLE_P(hash) && !RHASH_IDENTHASH_P(hash)) {
4408 VALUE value = Qundef;
4409 st_table assoctable = *RHASH_ST_TABLE(hash);
4410 assoctable.type = &(struct st_hash_type){
4411 .compare = assoc_cmp,
4412 .hash = assoctable.type->hash,
4413 };
4414 VALUE arg = (VALUE)&(struct assoc_arg){
4415 .tbl = &assoctable,
4416 .key = (st_data_t)key,
4417 };
4418
4419 if (RB_OBJ_FROZEN(hash)) {
4420 value = assoc_lookup(arg);
4421 }
4422 else {
4423 hash_iter_lev_inc(hash);
4424 value = rb_ensure(assoc_lookup, arg, hash_foreach_ensure, hash);
4425 }
4426 hash_verify(hash);
4427 if (!UNDEF_P(value)) return rb_assoc_new(key, value);
4428 }
4429
4430 args[0] = key;
4431 args[1] = Qnil;
4432 rb_hash_foreach(hash, assoc_i, (VALUE)args);
4433 return args[1];
4434}
4435
4436static int
4437rassoc_i(VALUE key, VALUE val, VALUE arg)
4438{
4439 VALUE *args = (VALUE *)arg;
4440
4441 if (RTEST(rb_equal(args[0], val))) {
4442 args[1] = rb_assoc_new(key, val);
4443 return ST_STOP;
4444 }
4445 return ST_CONTINUE;
4446}
4447
4448/*
4449 * call-seq:
4450 * rassoc(value) -> new_array or nil
4451 *
4452 * Searches +self+ for the first entry whose value is <tt>==</tt> to the given +value+;
4453 * see {Entry Order}[rdoc-ref:Hash@Entry+Order].
4454 *
4455 * If the entry is found, returns its key and value as a 2-element array;
4456 * returns +nil+ if not found:
4457 *
4458 * h = {foo: 0, bar: 1, baz: 1}
4459 * h.rassoc(1) # => [:bar, 1]
4460 *
4461 * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
4462 */
4463
4464static VALUE
4465rb_hash_rassoc(VALUE hash, VALUE obj)
4466{
4467 VALUE args[2];
4468
4469 args[0] = obj;
4470 args[1] = Qnil;
4471 rb_hash_foreach(hash, rassoc_i, (VALUE)args);
4472 return args[1];
4473}
4474
4475static int
4476flatten_i(VALUE key, VALUE val, VALUE ary)
4477{
4478 VALUE pair[2];
4479
4480 pair[0] = key;
4481 pair[1] = val;
4482 rb_ary_cat(ary, pair, 2);
4483
4484 return ST_CONTINUE;
4485}
4486
4487/*
4488 * call-seq:
4489 * flatten(depth = 1) -> new_array
4490 *
4491 * With positive integer +depth+,
4492 * returns a new array that is a recursive flattening of +self+ to the given +depth+.
4493 *
4494 * At each level of recursion:
4495 *
4496 * - Each element whose value is an array is "flattened" (that is, replaced by its individual array elements);
4497 * see Array#flatten.
4498 * - Each element whose value is not an array is unchanged.
4499 * even if the value is an object that has instance method flatten (such as a hash).
4500 *
4501 * Examples; note that entry <tt>foo: {bar: 1, baz: 2}</tt> is never flattened.
4502 *
4503 * h = {foo: {bar: 1, baz: 2}, bat: [:bam, [:bap, [:bah]]]}
4504 * h.flatten(1) # => [:foo, {bar: 1, baz: 2}, :bat, [:bam, [:bap, [:bah]]]]
4505 * h.flatten(2) # => [:foo, {bar: 1, baz: 2}, :bat, :bam, [:bap, [:bah]]]
4506 * h.flatten(3) # => [:foo, {bar: 1, baz: 2}, :bat, :bam, :bap, [:bah]]
4507 * h.flatten(4) # => [:foo, {bar: 1, baz: 2}, :bat, :bam, :bap, :bah]
4508 * h.flatten(5) # => [:foo, {bar: 1, baz: 2}, :bat, :bam, :bap, :bah]
4509 *
4510 * With negative integer +depth+,
4511 * flattens all levels:
4512 *
4513 * h.flatten(-1) # => [:foo, {bar: 1, baz: 2}, :bat, :bam, :bap, :bah]
4514 *
4515 * With +depth+ zero,
4516 * returns the equivalent of #to_a:
4517 *
4518 * h.flatten(0) # => [[:foo, {bar: 1, baz: 2}], [:bat, [:bam, [:bap, [:bah]]]]]
4519 *
4520 * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
4521 */
4522
4523static VALUE
4524rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
4525{
4526 VALUE ary;
4527
4528 rb_check_arity(argc, 0, 1);
4529
4530 if (argc) {
4531 int level = NUM2INT(argv[0]);
4532
4533 if (level == 0) return rb_hash_to_a(hash);
4534
4535 ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
4536 rb_hash_foreach(hash, flatten_i, ary);
4537 level--;
4538
4539 if (level > 0) {
4540 VALUE ary_flatten_level = INT2FIX(level);
4541 rb_funcallv(ary, id_flatten_bang, 1, &ary_flatten_level);
4542 }
4543 else if (level < 0) {
4544 /* flatten recursively */
4545 rb_funcallv(ary, id_flatten_bang, 0, 0);
4546 }
4547 }
4548 else {
4549 ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
4550 rb_hash_foreach(hash, flatten_i, ary);
4551 }
4552
4553 return ary;
4554}
4555
4556static int
4557delete_if_nil(VALUE key, VALUE value, VALUE hash)
4558{
4559 if (NIL_P(value)) {
4560 return ST_DELETE;
4561 }
4562 return ST_CONTINUE;
4563}
4564
4565/*
4566 * call-seq:
4567 * compact -> new_hash
4568 *
4569 * Returns a copy of +self+ with all +nil+-valued entries removed:
4570 *
4571 * h = {foo: 0, bar: nil, baz: 2, bat: nil}
4572 * h.compact # => {foo: 0, baz: 2}
4573 *
4574 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
4575 */
4576
4577static VALUE
4578rb_hash_compact(VALUE hash)
4579{
4580 VALUE result = rb_hash_dup(hash);
4581 if (!RHASH_EMPTY_P(hash)) {
4582 rb_hash_foreach(result, delete_if_nil, result);
4583 compact_after_delete(result);
4584 }
4585 else if (rb_hash_compare_by_id_p(hash)) {
4586 result = rb_hash_compare_by_id(result);
4587 }
4588 return result;
4589}
4590
4591/*
4592 * call-seq:
4593 * compact! -> self or nil
4594 *
4595 * If +self+ contains any +nil+-valued entries,
4596 * returns +self+ with all +nil+-valued entries removed;
4597 * returns +nil+ otherwise:
4598 *
4599 * h = {foo: 0, bar: nil, baz: 2, bat: nil}
4600 * h.compact!
4601 * h # => {foo: 0, baz: 2}
4602 * h.compact! # => nil
4603 *
4604 * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
4605 */
4606
4607static VALUE
4608rb_hash_compact_bang(VALUE hash)
4609{
4610 st_index_t n;
4611 rb_hash_modify_check(hash);
4612 n = RHASH_SIZE(hash);
4613 if (n) {
4614 rb_hash_foreach(hash, delete_if_nil, hash);
4615 if (n != RHASH_SIZE(hash))
4616 return hash;
4617 }
4618 return Qnil;
4619}
4620
4621/*
4622 * call-seq:
4623 * compare_by_identity -> self
4624 *
4625 * Sets +self+ to compare keys using _identity_ (rather than mere _equality_);
4626 * returns +self+:
4627 *
4628 * By default, two keys are considered to be the same key
4629 * if and only if they are _equal_ objects (per method #eql?):
4630 *
4631 * h = {}
4632 * h['x'] = 0
4633 * h['x'] = 1 # Overwrites.
4634 * h # => {"x"=>1}
4635 *
4636 * When this method has been called, two keys are considered to be the same key
4637 * if and only if they are the _same_ object:
4638 *
4639 * h.compare_by_identity
4640 * h['x'] = 2 # Does not overwrite.
4641 * h # => {"x"=>1, "x"=>2}
4642 *
4643 * Related: #compare_by_identity?;
4644 * see also {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
4645 */
4646
4647VALUE
4648rb_hash_compare_by_id(VALUE hash)
4649{
4650 VALUE tmp;
4651 st_table *identtable;
4652
4653 if (rb_hash_compare_by_id_p(hash)) return hash;
4654
4655 rb_hash_modify_check(hash);
4656 if (hash_iterating_p(hash)) {
4657 rb_raise(rb_eRuntimeError, "compare_by_identity during iteration");
4658 }
4659
4660 if (RHASH_TABLE_EMPTY_P(hash)) {
4661 // Fast path: There's nothing to rehash, so we don't need a `tmp` table.
4662 // We're most likely an AR table, so this will need an allocation.
4663 ar_force_convert_table(hash, __FILE__, __LINE__);
4664 HASH_ASSERT(RHASH_ST_TABLE_P(hash));
4665
4666 RHASH_ST_TABLE(hash)->type = &identhash;
4667 }
4668 else {
4669 // Slow path: Need to rehash the members of `self` into a new
4670 // `tmp` table using the new `identhash` compare/hash functions.
4671 tmp = hash_alloc(0);
4672 hash_st_table_init(tmp, &identhash, RHASH_SIZE(hash));
4673 identtable = RHASH_ST_TABLE(tmp);
4674
4675 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
4676 rb_hash_free(hash);
4677
4678 // We know for sure `identtable` is an st table,
4679 // so we can skip `ar_force_convert_table` here.
4680 RHASH_ST_TABLE_SET(hash, identtable);
4681 RHASH_ST_CLEAR(tmp);
4682 }
4683
4684 rb_gc_register_pinning_obj(hash);
4685
4686 return hash;
4687}
4688
4689/*
4690 * call-seq:
4691 * compare_by_identity? -> true or false
4692 *
4693 * Returns whether #compare_by_identity has been called:
4694 *
4695 * h = {}
4696 * h.compare_by_identity? # => false
4697 * h.compare_by_identity
4698 * h.compare_by_identity? # => true
4699 *
4700 * Related: #compare_by_identity;
4701 * see also {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
4702 */
4703
4704VALUE
4705rb_hash_compare_by_id_p(VALUE hash)
4706{
4707 return RBOOL(RHASH_IDENTHASH_P(hash));
4708}
4709
4710VALUE
4711rb_ident_hash_new(void)
4712{
4713 VALUE hash = rb_hash_new();
4714 hash_st_table_init(hash, &identhash, 0);
4715 rb_gc_register_pinning_obj(hash);
4716 return hash;
4717}
4718
4719VALUE
4720rb_ident_hash_new_with_size(st_index_t size)
4721{
4722 VALUE hash = rb_hash_new();
4723 hash_st_table_init(hash, &identhash, size);
4724 rb_gc_register_pinning_obj(hash);
4725 return hash;
4726}
4727
4728st_table *
4729rb_init_identtable(void)
4730{
4731 return st_init_table(&identhash);
4732}
4733
4734static int
4735any_p_i(VALUE key, VALUE value, VALUE arg)
4736{
4737 VALUE ret = rb_yield(rb_assoc_new(key, value));
4738 if (RTEST(ret)) {
4739 *(VALUE *)arg = Qtrue;
4740 return ST_STOP;
4741 }
4742 return ST_CONTINUE;
4743}
4744
4745static int
4746any_p_i_fast(VALUE key, VALUE value, VALUE arg)
4747{
4748 VALUE ret = rb_yield_values(2, key, value);
4749 if (RTEST(ret)) {
4750 *(VALUE *)arg = Qtrue;
4751 return ST_STOP;
4752 }
4753 return ST_CONTINUE;
4754}
4755
4756static int
4757any_p_i_pattern(VALUE key, VALUE value, VALUE arg)
4758{
4759 VALUE ret = rb_funcall(((VALUE *)arg)[1], idEqq, 1, rb_assoc_new(key, value));
4760 if (RTEST(ret)) {
4761 *(VALUE *)arg = Qtrue;
4762 return ST_STOP;
4763 }
4764 return ST_CONTINUE;
4765}
4766
4767/*
4768 * call-seq:
4769 * any? -> true or false
4770 * any?(entry) -> true or false
4771 * any? {|key, value| ... } -> true or false
4772 *
4773 * Returns +true+ if any element satisfies a given criterion;
4774 * +false+ otherwise.
4775 *
4776 * If +self+ has no element, returns +false+ and argument or block are not used;
4777 * otherwise behaves as below.
4778 *
4779 * With no argument and no block,
4780 * returns +true+ if +self+ is non-empty, +false+ otherwise.
4781 *
4782 * With argument +entry+ and no block,
4783 * returns +true+ if for any key +key+
4784 * <tt>self.assoc(key) == entry</tt>, +false+ otherwise:
4785 *
4786 * h = {foo: 0, bar: 1, baz: 2}
4787 * h.assoc(:bar) # => [:bar, 1]
4788 * h.any?([:bar, 1]) # => true
4789 * h.any?([:bar, 0]) # => false
4790 *
4791 * With no argument and a block given,
4792 * calls the block with each key-value pair;
4793 * returns +true+ if the block returns a truthy value,
4794 * +false+ otherwise:
4795 *
4796 * h = {foo: 0, bar: 1, baz: 2}
4797 * h.any? {|key, value| value < 3 } # => true
4798 * h.any? {|key, value| value > 3 } # => false
4799 *
4800 * With both argument +entry+ and a block given,
4801 * issues a warning and ignores the block.
4802 *
4803 * Related: Enumerable#any? (which this method overrides);
4804 * see also {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
4805 */
4806
4807static VALUE
4808rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
4809{
4810 VALUE args[2];
4811 args[0] = Qfalse;
4812
4813 rb_check_arity(argc, 0, 1);
4814 if (RHASH_EMPTY_P(hash)) return Qfalse;
4815 if (argc) {
4816 if (rb_block_given_p()) {
4817 rb_warn("given block not used");
4818 }
4819 args[1] = argv[0];
4820
4821 rb_hash_foreach(hash, any_p_i_pattern, (VALUE)args);
4822 }
4823 else {
4824 if (!rb_block_given_p()) {
4825 /* yields pairs, never false */
4826 return Qtrue;
4827 }
4828 if (rb_block_pair_yield_optimizable())
4829 rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
4830 else
4831 rb_hash_foreach(hash, any_p_i, (VALUE)args);
4832 }
4833 return args[0];
4834}
4835
4836/*
4837 * call-seq:
4838 * dig(key, *identifiers) -> object
4839 *
4840 * Finds and returns an object found in nested objects,
4841 * as specified by +key+ and +identifiers+.
4842 *
4843 * The nested objects may be instances of various classes.
4844 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
4845 *
4846 * Nested hashes:
4847 *
4848 * h = {foo: {bar: {baz: 2}}}
4849 * h.dig(:foo) # => {bar: {baz: 2}}
4850 * h.dig(:foo, :bar) # => {baz: 2}
4851 * h.dig(:foo, :bar, :baz) # => 2
4852 * h.dig(:foo, :bar, :BAZ) # => nil
4853 *
4854 * Nested hashes and arrays:
4855 *
4856 * h = {foo: {bar: [:a, :b, :c]}}
4857 * h.dig(:foo, :bar, 2) # => :c
4858 *
4859 * If no such object is found,
4860 * returns the {hash default}[rdoc-ref:Hash@Hash+Default]:
4861 *
4862 * h = {foo: {bar: [:a, :b, :c]}}
4863 * h.dig(:hello) # => nil
4864 * h.default_proc = -> (hash, _key) { hash }
4865 * h.dig(:hello, :world)
4866 * # => {foo: {bar: [:a, :b, :c]}}
4867 *
4868 * Related: {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
4869 */
4870
4871static VALUE
4872rb_hash_dig(int argc, VALUE *argv, VALUE self)
4873{
4875 self = rb_hash_aref(self, *argv);
4876 if (!--argc) return self;
4877 ++argv;
4878 return rb_obj_dig(argc, argv, self, Qnil);
4879}
4880
4881static int
4882hash_le_i(VALUE key, VALUE value, VALUE arg)
4883{
4884 VALUE *args = (VALUE *)arg;
4885 VALUE v = rb_hash_lookup2(args[0], key, Qundef);
4886 if (!UNDEF_P(v) && rb_equal(value, v)) return ST_CONTINUE;
4887 args[1] = Qfalse;
4888 return ST_STOP;
4889}
4890
4891static VALUE
4892hash_le(VALUE hash1, VALUE hash2)
4893{
4894 VALUE args[2];
4895 args[0] = hash2;
4896 args[1] = Qtrue;
4897 rb_hash_foreach(hash1, hash_le_i, (VALUE)args);
4898 return args[1];
4899}
4900
4901/*
4902 * call-seq:
4903 * self <= other -> true or false
4904 *
4905 * Returns whether the entries of +self+ are a subset of the entries of +other+:
4906 *
4907 * h0 = {foo: 0, bar: 1}
4908 * h1 = {foo: 0, bar: 1, baz: 2}
4909 * h0 <= h0 # => true
4910 * h0 <= h1 # => true
4911 * h1 <= h0 # => false
4912 *
4913 * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
4914 *
4915 * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
4916 *
4917 * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
4918 */
4919static VALUE
4920rb_hash_le(VALUE hash, VALUE other)
4921{
4922 other = to_hash(other);
4923 if (RHASH_SIZE(hash) > RHASH_SIZE(other)) return Qfalse;
4924 return hash_le(hash, other);
4925}
4926
4927/*
4928 * call-seq:
4929 * self < other -> true or false
4930 *
4931 * Returns whether the entries of +self+ are a proper subset of the entries of +other+:
4932 *
4933 * h = {foo: 0, bar: 1}
4934 * h < {foo: 0, bar: 1, baz: 2} # => true # Proper subset.
4935 * h < {baz: 2, bar: 1, foo: 0} # => true # Order may differ.
4936 * h < h # => false # Not a proper subset.
4937 * h < {bar: 1, foo: 0} # => false # Not a proper subset.
4938 * h < {foo: 0, bar: 1, baz: 2} # => false # Different key.
4939 * h < {foo: 0, bar: 1, baz: 2} # => false # Different value.
4940 *
4941 * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
4942 *
4943 * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
4944 *
4945 * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
4946 */
4947static VALUE
4948rb_hash_lt(VALUE hash, VALUE other)
4949{
4950 other = to_hash(other);
4951 if (RHASH_SIZE(hash) >= RHASH_SIZE(other)) return Qfalse;
4952 return hash_le(hash, other);
4953}
4954
4955/*
4956 * call-seq:
4957 * self >= other -> true or false
4958 *
4959 * Returns whether the entries of +self+ are a superset of the entries of +other+:
4960 *
4961 * h0 = {foo: 0, bar: 1, baz: 2}
4962 * h1 = {foo: 0, bar: 1}
4963 * h0 >= h1 # => true
4964 * h0 >= h0 # => true
4965 * h1 >= h0 # => false
4966 *
4967 * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
4968 *
4969 * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
4970 *
4971 * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
4972 */
4973static VALUE
4974rb_hash_ge(VALUE hash, VALUE other)
4975{
4976 other = to_hash(other);
4977 if (RHASH_SIZE(hash) < RHASH_SIZE(other)) return Qfalse;
4978 return hash_le(other, hash);
4979}
4980
4981/*
4982 * call-seq:
4983 * self > other -> true or false
4984 *
4985 * Returns whether the entries of +self+ are a proper superset of the entries of +other+:
4986 *
4987 * h = {foo: 0, bar: 1, baz: 2}
4988 * h > {foo: 0, bar: 1} # => true # Proper superset.
4989 * h > {bar: 1, foo: 0} # => true # Order may differ.
4990 * h > h # => false # Not a proper superset.
4991 * h > {baz: 2, bar: 1, foo: 0} # => false # Not a proper superset.
4992 * h > {foo: 0, bar: 1} # => false # Different key.
4993 * h > {foo: 0, bar: 1} # => false # Different value.
4994 *
4995 * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
4996 *
4997 * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
4998 *
4999 * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
5000 */
5001static VALUE
5002rb_hash_gt(VALUE hash, VALUE other)
5003{
5004 other = to_hash(other);
5005 if (RHASH_SIZE(hash) <= RHASH_SIZE(other)) return Qfalse;
5006 return hash_le(other, hash);
5007}
5008
5009static VALUE
5010hash_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(key, hash))
5011{
5012 rb_check_arity(argc, 1, 1);
5013 return rb_hash_aref(hash, *argv);
5014}
5015
5016/*
5017 * call-seq:
5018 * to_proc -> proc
5019 *
5020 * Returns a Proc object that maps a key to its value:
5021 *
5022 * h = {foo: 0, bar: 1, baz: 2}
5023 * proc = h.to_proc
5024 * proc.class # => Proc
5025 * proc.call(:foo) # => 0
5026 * proc.call(:bar) # => 1
5027 * proc.call(:nosuch) # => nil
5028 * h.default_proc = proc { |hash, key| "Missing key: #{key}" } # This affect the existing proc object
5029 * proc.call(:nosuch) # => "Missing key: #{nosuch}"
5030 *
5031 * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
5032 */
5033static VALUE
5034rb_hash_to_proc(VALUE hash)
5035{
5036 return rb_func_lambda_new(hash_proc_call, hash, 1, 1);
5037}
5038
5039/* :nodoc: */
5040static VALUE
5041rb_hash_deconstruct_keys(VALUE hash, VALUE keys)
5042{
5043 return hash;
5044}
5045
5046static int
5047add_new_i(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
5048{
5049 if (existing) return ST_STOP;
5050 *val = arg;
5051 return ST_CONTINUE;
5052}
5053
5054/*
5055 * add +key+ to +val+ pair if +hash+ does not contain +key+.
5056 * returns non-zero if +key+ was contained.
5057 */
5058int
5059rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
5060{
5061 st_table *tbl;
5062 int ret = -1;
5063
5064 if (RHASH_AR_TABLE_P(hash)) {
5065 ret = ar_update(hash, (st_data_t)key, add_new_i, (st_data_t)val);
5066 if (ret == -1) {
5067 ar_force_convert_table(hash, __FILE__, __LINE__);
5068 }
5069 }
5070
5071 if (ret == -1) {
5072 tbl = RHASH_TBL_RAW(hash);
5073 ret = st_update(tbl, (st_data_t)key, add_new_i, (st_data_t)val);
5074 }
5075 if (!ret) {
5076 // Newly inserted
5077 RB_OBJ_WRITTEN(hash, Qundef, key);
5078 RB_OBJ_WRITTEN(hash, Qundef, val);
5079 }
5080 return ret;
5081}
5082
5083static st_data_t
5084key_stringify(VALUE key)
5085{
5086 return (rb_obj_class(key) == rb_cString && !RB_OBJ_FROZEN(key)) ?
5087 rb_hash_key_str(key) : key;
5088}
5089
5090static void
5091ar_bulk_insert(VALUE hash, long argc, const VALUE *argv)
5092{
5093 long i;
5094 for (i = 0; i < argc; ) {
5095 st_data_t k = key_stringify(argv[i++]);
5096 st_data_t v = argv[i++];
5097 ar_insert(hash, k, v);
5098 RB_OBJ_WRITTEN(hash, Qundef, k);
5099 RB_OBJ_WRITTEN(hash, Qundef, v);
5100 }
5101}
5102
5103void
5104rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
5105{
5106 HASH_ASSERT(argc % 2 == 0);
5107 if (argc > 0) {
5108 st_index_t size = argc / 2;
5109
5110 if (RHASH_AR_TABLE_P(hash) &&
5111 (RHASH_AR_TABLE_SIZE(hash) + size <= RHASH_AR_TABLE_MAX_SIZE)) {
5112 ar_bulk_insert(hash, argc, argv);
5113 }
5114 else {
5115 rb_hash_bulk_insert_into_st_table(argc, argv, hash);
5116 }
5117 }
5118}
5119
5120static char **origenviron;
5121#ifdef _WIN32
5122#define GET_ENVIRON(e) ((e) = rb_w32_get_environ())
5123#define FREE_ENVIRON(e) rb_w32_free_environ(e)
5124static char **my_environ;
5125#undef environ
5126#define environ my_environ
5127#undef getenv
5128#define getenv(n) rb_w32_ugetenv(n)
5129#elif defined(__APPLE__)
5130#undef environ
5131#define environ (*_NSGetEnviron())
5132#define GET_ENVIRON(e) (e)
5133#define FREE_ENVIRON(e)
5134#else
5135extern char **environ;
5136#define GET_ENVIRON(e) (e)
5137#define FREE_ENVIRON(e)
5138#endif
5139#ifdef ENV_IGNORECASE
5140#define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
5141#define ENVNMATCH(s1, s2, n) (STRNCASECMP((s1), (s2), (n)) == 0)
5142#else
5143#define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
5144#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
5145#endif
5146
5147#define ENV_LOCKING() RB_VM_LOCKING()
5148
5149static inline rb_encoding *
5150env_encoding(void)
5151{
5152#ifdef _WIN32
5153 return rb_utf8_encoding();
5154#else
5155 return rb_locale_encoding();
5156#endif
5157}
5158
5159static VALUE
5160env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
5161{
5162 VALUE str = rb_external_str_new_with_enc(ptr, len, enc);
5163
5164 rb_obj_freeze(str);
5165 return str;
5166}
5167
5168static VALUE
5169env_str_new(const char *ptr, long len, rb_encoding *enc)
5170{
5171 return env_enc_str_new(ptr, len, enc);
5172}
5173
5174static VALUE
5175env_str_new2(const char *ptr, rb_encoding *enc)
5176{
5177 if (!ptr) return Qnil;
5178 return env_str_new(ptr, strlen(ptr), enc);
5179}
5180
5181static VALUE
5182getenv_with_lock(const char *name)
5183{
5184 VALUE ret;
5185 rb_encoding *enc = env_encoding();
5186 ENV_LOCKING() {
5187 const char *val = getenv(name);
5188 ret = env_str_new2(val, enc);
5189 }
5190 return ret;
5191}
5192
5193static bool
5194has_env_with_lock(const char *name)
5195{
5196 const char *val;
5197
5198 ENV_LOCKING() {
5199 val = getenv(name);
5200 }
5201
5202 return val ? true : false;
5203}
5204
5205static const char TZ_ENV[] = "TZ";
5206
5207static void *
5208get_env_cstr(VALUE str, const char *name)
5209{
5210 char *var;
5211 rb_encoding *enc = rb_enc_get(str);
5212 if (!rb_enc_asciicompat(enc)) {
5213 rb_raise(rb_eArgError, "bad environment variable %s: ASCII incompatible encoding: %s",
5214 name, rb_enc_name(enc));
5215 }
5216 var = RSTRING_PTR(str);
5217 if (memchr(var, '\0', RSTRING_LEN(str))) {
5218 rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name);
5219 }
5220 return rb_str_fill_terminator(str, 1); /* ASCII compatible */
5221}
5222
5223#define get_env_ptr(var, val) \
5224 (var = get_env_cstr(val, #var))
5225
5226static inline const char *
5227env_name(volatile VALUE *s)
5228{
5229 const char *name;
5230 StringValue(*s);
5231 get_env_ptr(name, *s);
5232 return name;
5233}
5234
5235#define env_name(s) env_name(&(s))
5236
5237static VALUE env_aset(VALUE nm, VALUE val);
5238
5239static void
5240reset_by_modified_env(const char *nam, const char *val)
5241{
5242 /*
5243 * ENV['TZ'] = nil has a special meaning.
5244 * TZ is no longer considered up-to-date and ruby call tzset() as needed.
5245 * It could be useful if sysadmin change /etc/localtime.
5246 * This hack might works only on Linux glibc.
5247 */
5248 if (ENVMATCH(nam, TZ_ENV)) {
5249 ruby_reset_timezone(val);
5250 }
5251}
5252
5253static VALUE
5254env_delete(VALUE name)
5255{
5256 const char *nam = env_name(name);
5257 reset_by_modified_env(nam, NULL);
5258 VALUE val = getenv_with_lock(nam);
5259
5260 if (!NIL_P(val)) {
5261 ruby_setenv(nam, 0);
5262 }
5263 return val;
5264}
5265
5266/*
5267 * call-seq:
5268 * ENV.delete(name) -> value
5269 * ENV.delete(name) { |name| block } -> value
5270 * ENV.delete(missing_name) -> nil
5271 * ENV.delete(missing_name) { |name| block } -> block_value
5272 *
5273 * Deletes the environment variable with +name+ if it exists and returns its value:
5274 * ENV['foo'] = '0'
5275 * ENV.delete('foo') # => '0'
5276 *
5277 * If a block is not given and the named environment variable does not exist, returns +nil+.
5278 *
5279 * If a block given and the environment variable does not exist,
5280 * yields +name+ to the block and returns the value of the block:
5281 * ENV.delete('foo') { |name| name * 2 } # => "foofoo"
5282 *
5283 * If a block given and the environment variable exists,
5284 * deletes the environment variable and returns its value (ignoring the block):
5285 * ENV['foo'] = '0'
5286 * ENV.delete('foo') { |name| raise 'ignored' } # => "0"
5287 *
5288 * Raises an exception if +name+ is invalid.
5289 * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
5290 */
5291static VALUE
5292env_delete_m(VALUE obj, VALUE name)
5293{
5294 VALUE val;
5295
5296 val = env_delete(name);
5297 if (NIL_P(val) && rb_block_given_p()) val = rb_yield(name);
5298 return val;
5299}
5300
5301/*
5302 * call-seq:
5303 * ENV[name] -> value
5304 *
5305 * Returns the value for the environment variable +name+ if it exists:
5306 * ENV['foo'] = '0'
5307 * ENV['foo'] # => "0"
5308 * Returns +nil+ if the named variable does not exist.
5309 *
5310 * Raises an exception if +name+ is invalid.
5311 * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
5312 */
5313static VALUE
5314rb_f_getenv(VALUE obj, VALUE name)
5315{
5316 const char *nam = env_name(name);
5317 VALUE env = getenv_with_lock(nam);
5318 return env;
5319}
5320
5321/*
5322 * call-seq:
5323 * ENV.fetch(name) -> value
5324 * ENV.fetch(name, default) -> value
5325 * ENV.fetch(name) { |name| block } -> value
5326 *
5327 * If +name+ is the name of an environment variable, returns its value:
5328 * ENV['foo'] = '0'
5329 * ENV.fetch('foo') # => '0'
5330 * Otherwise if a block is given (but not a default value),
5331 * yields +name+ to the block and returns the block's return value:
5332 * ENV.fetch('foo') { |name| :need_not_return_a_string } # => :need_not_return_a_string
5333 * Otherwise if a default value is given (but not a block), returns the default value:
5334 * ENV.delete('foo')
5335 * ENV.fetch('foo', :default_need_not_be_a_string) # => :default_need_not_be_a_string
5336 * If the environment variable does not exist and both default and block are given,
5337 * issues a warning ("warning: block supersedes default value argument"),
5338 * yields +name+ to the block, and returns the block's return value:
5339 * ENV.fetch('foo', :default) { |name| :block_return } # => :block_return
5340 * Raises KeyError if +name+ is valid, but not found,
5341 * and neither default value nor block is given:
5342 * ENV.fetch('foo') # Raises KeyError (key not found: "foo")
5343 * Raises an exception if +name+ is invalid.
5344 * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
5345 */
5346static VALUE
5347env_fetch(int argc, VALUE *argv, VALUE _)
5348{
5349 VALUE key;
5350 int block_given;
5351 const char *nam;
5352 VALUE env;
5353
5354 rb_check_arity(argc, 1, 2);
5355 key = argv[0];
5356 block_given = rb_block_given_p();
5357 if (block_given && argc == 2) {
5358 rb_warn("block supersedes default value argument");
5359 }
5360 nam = env_name(key);
5361 env = getenv_with_lock(nam);
5362
5363 if (NIL_P(env)) {
5364 if (block_given) return rb_yield(key);
5365 if (argc == 1) {
5366 rb_key_err_raise(rb_sprintf("key not found: \"%"PRIsVALUE"\"", key), envtbl, key);
5367 }
5368 return argv[1];
5369 }
5370 return env;
5371}
5372
5373/*
5374 * call-seq:
5375 * ENV.fetch_values(*names) -> array of values
5376 * ENV.fetch_values(*names) {|name| ... } -> array of values
5377 *
5378 * Returns an Array containing the environment variable values associated with
5379 * the given names:
5380 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5381 * ENV.fetch_values('foo', 'baz') # => ["0", "2"]
5382 *
5383 * Otherwise if a block is given yields +name+ to
5384 * the block and returns the block's return value:
5385 * ENV.fetch_values('foo', 'bam') {|key| key.to_s} # => ["0", "bam"]
5386 *
5387 * Raises KeyError if +name+ is valid, but not found and block is not given:
5388 * ENV.fetch_values('foo', 'bam') # Raises KeyError (key not found: "bam")
5389 *
5390 * Returns an empty Array if no names given.
5391 *
5392 * Raises an exception if any name is invalid.
5393 * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
5394 */
5395
5396static VALUE
5397env_fetch_values(int argc, VALUE *argv, VALUE ehash)
5398{
5399 VALUE result = rb_ary_new2(argc);
5400 long i;
5401
5402 for (i=0; i<argc; i++) {
5403 rb_ary_push(result, env_fetch(1, &argv[i], ehash));
5404 }
5405
5406 return result;
5407}
5408
5409#if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
5410#elif defined __sun
5411static int
5412in_origenv(const char *str)
5413{
5414 char **env;
5415 for (env = origenviron; *env; ++env) {
5416 if (*env == str) return 1;
5417 }
5418 return 0;
5419}
5420#else
5421static int
5422envix(const char *nam)
5423{
5424 // should be locked
5425
5426 register int i, len = strlen(nam);
5427 char **env;
5428
5429 env = GET_ENVIRON(environ);
5430 for (i = 0; env[i]; i++) {
5431 if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
5432 break; /* memcmp must come first to avoid */
5433 } /* potential SEGV's */
5434 FREE_ENVIRON(environ);
5435 return i;
5436}
5437#endif
5438
5439#if defined(_WIN32) || \
5440 (defined(__sun) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV)))
5441
5442NORETURN(static void invalid_envname(const char *name));
5443
5444static void
5445invalid_envname(const char *name)
5446{
5447 rb_syserr_fail_str(EINVAL, rb_sprintf("ruby_setenv(%s)", name));
5448}
5449
5450static const char *
5451check_envname(const char *name)
5452{
5453 if (strchr(name, '=')) {
5454 invalid_envname(name);
5455 }
5456 return name;
5457}
5458#endif
5459
5460void
5461ruby_setenv(const char *name, const char *value)
5462{
5463#if defined(_WIN32)
5464 VALUE buf;
5465 WCHAR *wname;
5466 WCHAR *wvalue = 0;
5467 int failed = 0;
5468 int len;
5469 check_envname(name);
5470 len = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
5471 if (value) {
5472 int len2;
5473 len2 = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
5474 wname = ALLOCV_N(WCHAR, buf, len + len2);
5475 wvalue = wname + len;
5476 MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
5477 MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, len2);
5478 }
5479 else {
5480 wname = ALLOCV_N(WCHAR, buf, len + 1);
5481 MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
5482 wvalue = wname + len;
5483 *wvalue = L'\0';
5484 }
5485
5486 ENV_LOCKING() {
5487 /* Use _wputenv_s() instead of SetEnvironmentVariableW() to make sure
5488 * special variables like "TZ" are interpret by libc. */
5489 failed = _wputenv_s(wname, wvalue);
5490 }
5491
5492 ALLOCV_END(buf);
5493 /* even if putenv() failed, clean up and try to delete the
5494 * variable from the system area. */
5495 if (!value || !*value) {
5496 /* putenv() doesn't handle empty value */
5497 if (!SetEnvironmentVariableW(wname, value ? wvalue : NULL) &&
5498 GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail;
5499 }
5500 if (failed) {
5501 fail:
5502 invalid_envname(name);
5503 }
5504#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
5505 if (value) {
5506 int ret;
5507 ENV_LOCKING() {
5508 ret = setenv(name, value, 1);
5509 }
5510
5511 if (ret) rb_sys_fail_sprintf("setenv(%s)", name);
5512 }
5513 else {
5514#ifdef VOID_UNSETENV
5515 ENV_LOCKING() {
5516 unsetenv(name);
5517 }
5518#else
5519 int ret;
5520 ENV_LOCKING() {
5521 ret = unsetenv(name);
5522 }
5523
5524 if (ret) rb_sys_fail_sprintf("unsetenv(%s)", name);
5525#endif
5526 }
5527#elif defined __sun
5528 /* Solaris 9 (or earlier) does not have setenv(3C) and unsetenv(3C). */
5529 /* The below code was tested on Solaris 10 by:
5530 % ./configure ac_cv_func_setenv=no ac_cv_func_unsetenv=no
5531 */
5532 size_t len, mem_size;
5533 char **env_ptr, *str, *mem_ptr;
5534
5535 check_envname(name);
5536 len = strlen(name);
5537 if (value) {
5538 mem_size = len + strlen(value) + 2;
5539 mem_ptr = malloc(mem_size);
5540 if (mem_ptr == NULL)
5541 rb_sys_fail_sprintf("malloc(%"PRIuSIZE")", mem_size);
5542 snprintf(mem_ptr, mem_size, "%s=%s", name, value);
5543 }
5544
5545 ENV_LOCKING() {
5546 for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) {
5547 if (!strncmp(str, name, len) && str[len] == '=') {
5548 if (!in_origenv(str)) free(str);
5549 while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
5550 break;
5551 }
5552 }
5553 }
5554
5555 if (value) {
5556 int ret;
5557 ENV_LOCKING() {
5558 ret = putenv(mem_ptr);
5559 }
5560
5561 if (ret) {
5562 free(mem_ptr);
5563 rb_sys_fail_sprintf("putenv(%s)", name);
5564 }
5565 }
5566#else /* WIN32 */
5567 size_t len;
5568 int i;
5569
5570 ENV_LOCKING() {
5571 i = envix(name); /* where does it go? */
5572
5573 if (environ == origenviron) { /* need we copy environment? */
5574 int j;
5575 int max;
5576 char **tmpenv;
5577
5578 for (max = i; environ[max]; max++) ;
5579 tmpenv = ALLOC_N(char*, max+2);
5580 for (j=0; j<max; j++) /* copy environment */
5581 tmpenv[j] = ruby_strdup(environ[j]);
5582 tmpenv[max] = 0;
5583 environ = tmpenv; /* tell exec where it is now */
5584 }
5585
5586 if (environ[i]) {
5587 char **envp = origenviron;
5588 while (*envp && *envp != environ[i]) envp++;
5589 if (!*envp)
5590 xfree(environ[i]);
5591 if (!value) {
5592 while (environ[i]) {
5593 environ[i] = environ[i+1];
5594 i++;
5595 }
5596 goto finish;
5597 }
5598 }
5599 else { /* does not exist yet */
5600 if (!value) goto finish;
5601 REALLOC_N(environ, char*, i+2); /* just expand it a bit */
5602 environ[i+1] = 0; /* make sure it's null terminated */
5603 }
5604
5605 len = strlen(name) + strlen(value) + 2;
5606 environ[i] = ALLOC_N(char, len);
5607 snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */
5608
5609 finish:;
5610 }
5611#endif /* WIN32 */
5612}
5613
5614void
5615ruby_unsetenv(const char *name)
5616{
5617 ruby_setenv(name, 0);
5618}
5619
5620/*
5621 * call-seq:
5622 * ENV[name] = value -> value
5623 * ENV.store(name, value) -> value
5624 *
5625 * Creates, updates, or deletes the named environment variable, returning the value.
5626 * Both +name+ and +value+ may be instances of String.
5627 * See {Valid Names and Values}[rdoc-ref:ENV@Valid+Names+and+Values].
5628 *
5629 * - If the named environment variable does not exist:
5630 * - If +value+ is +nil+, does nothing.
5631 * ENV.clear
5632 * ENV['foo'] = nil # => nil
5633 * ENV.include?('foo') # => false
5634 * ENV.store('bar', nil) # => nil
5635 * ENV.include?('bar') # => false
5636 * - If +value+ is not +nil+, creates the environment variable with +name+ and +value+:
5637 * # Create 'foo' using ENV.[]=.
5638 * ENV['foo'] = '0' # => '0'
5639 * ENV['foo'] # => '0'
5640 * # Create 'bar' using ENV.store.
5641 * ENV.store('bar', '1') # => '1'
5642 * ENV['bar'] # => '1'
5643 * - If the named environment variable exists:
5644 * - If +value+ is not +nil+, updates the environment variable with value +value+:
5645 * # Update 'foo' using ENV.[]=.
5646 * ENV['foo'] = '2' # => '2'
5647 * ENV['foo'] # => '2'
5648 * # Update 'bar' using ENV.store.
5649 * ENV.store('bar', '3') # => '3'
5650 * ENV['bar'] # => '3'
5651 * - If +value+ is +nil+, deletes the environment variable:
5652 * # Delete 'foo' using ENV.[]=.
5653 * ENV['foo'] = nil # => nil
5654 * ENV.include?('foo') # => false
5655 * # Delete 'bar' using ENV.store.
5656 * ENV.store('bar', nil) # => nil
5657 * ENV.include?('bar') # => false
5658 *
5659 * Raises an exception if +name+ or +value+ is invalid.
5660 * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
5661 */
5662static VALUE
5663env_aset_m(VALUE obj, VALUE nm, VALUE val)
5664{
5665 return env_aset(nm, val);
5666}
5667
5668static VALUE
5669env_aset(VALUE nm, VALUE val)
5670{
5671 char *name, *value;
5672
5673 if (NIL_P(val)) {
5674 env_delete(nm);
5675 return Qnil;
5676 }
5677 StringValue(nm);
5678 StringValue(val);
5679 /* nm can be modified in `val.to_str`, don't get `name` before
5680 * check for `val` */
5681 get_env_ptr(name, nm);
5682 get_env_ptr(value, val);
5683
5684 ruby_setenv(name, value);
5685 reset_by_modified_env(name, value);
5686 return val;
5687}
5688
5689static VALUE
5690env_keys(int raw)
5691{
5692 rb_encoding *enc = raw ? 0 : rb_locale_encoding();
5693 VALUE ary = rb_ary_new();
5694
5695 ENV_LOCKING() {
5696 char **env = GET_ENVIRON(environ);
5697 while (*env) {
5698 char *s = strchr(*env, '=');
5699 if (s) {
5700 const char *p = *env;
5701 size_t l = s - p;
5702 VALUE e = raw ? rb_utf8_str_new(p, l) : env_enc_str_new(p, l, enc);
5703 rb_ary_push(ary, e);
5704 }
5705 env++;
5706 }
5707 FREE_ENVIRON(environ);
5708 }
5709
5710 return ary;
5711}
5712
5713/*
5714 * call-seq:
5715 * ENV.keys -> array of names
5716 *
5717 * Returns all variable names in an Array:
5718 * ENV.replace('foo' => '0', 'bar' => '1')
5719 * ENV.keys # => ['bar', 'foo']
5720 * The order of the names is OS-dependent.
5721 * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
5722 *
5723 * Returns the empty Array if ENV is empty.
5724 */
5725
5726static VALUE
5727env_f_keys(VALUE _)
5728{
5729 return env_keys(FALSE);
5730}
5731
5732static VALUE
5733rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
5734{
5735 char **env;
5736 long cnt = 0;
5737
5738 ENV_LOCKING() {
5739 env = GET_ENVIRON(environ);
5740 for (; *env ; ++env) {
5741 if (strchr(*env, '=')) {
5742 cnt++;
5743 }
5744 }
5745 FREE_ENVIRON(environ);
5746 }
5747
5748 return LONG2FIX(cnt);
5749}
5750
5751/*
5752 * call-seq:
5753 * ENV.each_key { |name| block } -> ENV
5754 * ENV.each_key -> an_enumerator
5755 *
5756 * Yields each environment variable name:
5757 * ENV.replace('foo' => '0', 'bar' => '1') # => ENV
5758 * names = []
5759 * ENV.each_key { |name| names.push(name) } # => ENV
5760 * names # => ["bar", "foo"]
5761 *
5762 * Returns an Enumerator if no block given:
5763 * e = ENV.each_key # => #<Enumerator: {"bar"=>"1", "foo"=>"0"}:each_key>
5764 * names = []
5765 * e.each { |name| names.push(name) } # => ENV
5766 * names # => ["bar", "foo"]
5767 */
5768static VALUE
5769env_each_key(VALUE ehash)
5770{
5771 VALUE keys;
5772 long i;
5773
5774 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5775 keys = env_keys(FALSE);
5776 for (i=0; i<RARRAY_LEN(keys); i++) {
5777 rb_yield(RARRAY_AREF(keys, i));
5778 }
5779 return ehash;
5780}
5781
5782static VALUE
5783env_values(void)
5784{
5785 VALUE ary = rb_ary_new();
5786
5787 rb_encoding *enc = env_encoding();
5788 ENV_LOCKING() {
5789 char **env = GET_ENVIRON(environ);
5790
5791 while (*env) {
5792 char *s = strchr(*env, '=');
5793 if (s) {
5794 rb_ary_push(ary, env_str_new2(s+1, enc));
5795 }
5796 env++;
5797 }
5798 FREE_ENVIRON(environ);
5799 }
5800
5801 return ary;
5802}
5803
5804/*
5805 * call-seq:
5806 * ENV.values -> array of values
5807 *
5808 * Returns all environment variable values in an Array:
5809 * ENV.replace('foo' => '0', 'bar' => '1')
5810 * ENV.values # => ['1', '0']
5811 * The order of the values is OS-dependent.
5812 * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
5813 *
5814 * Returns the empty Array if ENV is empty.
5815 */
5816static VALUE
5817env_f_values(VALUE _)
5818{
5819 return env_values();
5820}
5821
5822/*
5823 * call-seq:
5824 * ENV.each_value { |value| block } -> ENV
5825 * ENV.each_value -> an_enumerator
5826 *
5827 * Yields each environment variable value:
5828 * ENV.replace('foo' => '0', 'bar' => '1') # => ENV
5829 * values = []
5830 * ENV.each_value { |value| values.push(value) } # => ENV
5831 * values # => ["1", "0"]
5832 *
5833 * Returns an Enumerator if no block given:
5834 * e = ENV.each_value # => #<Enumerator: {"bar"=>"1", "foo"=>"0"}:each_value>
5835 * values = []
5836 * e.each { |value| values.push(value) } # => ENV
5837 * values # => ["1", "0"]
5838 */
5839static VALUE
5840env_each_value(VALUE ehash)
5841{
5842 VALUE values;
5843 long i;
5844
5845 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5846 values = env_values();
5847 for (i=0; i<RARRAY_LEN(values); i++) {
5848 rb_yield(RARRAY_AREF(values, i));
5849 }
5850 return ehash;
5851}
5852
5853/*
5854 * call-seq:
5855 * ENV.each { |name, value| block } -> ENV
5856 * ENV.each -> an_enumerator
5857 * ENV.each_pair { |name, value| block } -> ENV
5858 * ENV.each_pair -> an_enumerator
5859 *
5860 * Yields each environment variable name and its value as a 2-element Array:
5861 * h = {}
5862 * ENV.each_pair { |name, value| h[name] = value } # => ENV
5863 * h # => {"bar"=>"1", "foo"=>"0"}
5864 *
5865 * Returns an Enumerator if no block given:
5866 * h = {}
5867 * e = ENV.each_pair # => #<Enumerator: {"bar"=>"1", "foo"=>"0"}:each_pair>
5868 * e.each { |name, value| h[name] = value } # => ENV
5869 * h # => {"bar"=>"1", "foo"=>"0"}
5870 */
5871static VALUE
5872env_each_pair(VALUE ehash)
5873{
5874 long i;
5875
5876 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5877
5878 VALUE ary = rb_ary_new();
5879
5880 rb_encoding *enc = env_encoding();
5881 ENV_LOCKING() {
5882 char **env = GET_ENVIRON(environ);
5883
5884 while (*env) {
5885 char *s = strchr(*env, '=');
5886 if (s) {
5887 rb_ary_push(ary, env_str_new(*env, s-*env, enc));
5888 rb_ary_push(ary, env_str_new2(s+1, enc));
5889 }
5890 env++;
5891 }
5892 FREE_ENVIRON(environ);
5893 }
5894
5895 if (rb_block_pair_yield_optimizable()) {
5896 for (i=0; i<RARRAY_LEN(ary); i+=2) {
5897 rb_yield_values(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1));
5898 }
5899 }
5900 else {
5901 for (i=0; i<RARRAY_LEN(ary); i+=2) {
5902 rb_yield(rb_assoc_new(RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1)));
5903 }
5904 }
5905
5906 return ehash;
5907}
5908
5909/*
5910 * call-seq:
5911 * ENV.reject! { |name, value| block } -> ENV or nil
5912 * ENV.reject! -> an_enumerator
5913 *
5914 * Similar to ENV.delete_if, but returns +nil+ if no changes were made.
5915 *
5916 * Yields each environment variable name and its value as a 2-element Array,
5917 * deleting each environment variable for which the block returns a truthy value,
5918 * and returning ENV (if any deletions) or +nil+ (if not):
5919 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5920 * ENV.reject! { |name, value| name.start_with?('b') } # => ENV
5921 * ENV # => {"foo"=>"0"}
5922 * ENV.reject! { |name, value| name.start_with?('b') } # => nil
5923 *
5924 * Returns an Enumerator if no block given:
5925 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5926 * e = ENV.reject! # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:reject!>
5927 * e.each { |name, value| name.start_with?('b') } # => ENV
5928 * ENV # => {"foo"=>"0"}
5929 * e.each { |name, value| name.start_with?('b') } # => nil
5930 */
5931static VALUE
5932env_reject_bang(VALUE ehash)
5933{
5934 VALUE keys;
5935 long i;
5936 int del = 0;
5937
5938 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5939 keys = env_keys(FALSE);
5940 RBASIC_CLEAR_CLASS(keys);
5941 for (i=0; i<RARRAY_LEN(keys); i++) {
5942 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
5943 if (!NIL_P(val)) {
5944 if (RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
5945 env_delete(RARRAY_AREF(keys, i));
5946 del++;
5947 }
5948 }
5949 }
5950 RB_GC_GUARD(keys);
5951 if (del == 0) return Qnil;
5952 return envtbl;
5953}
5954
5955/*
5956 * call-seq:
5957 * ENV.delete_if { |name, value| block } -> ENV
5958 * ENV.delete_if -> an_enumerator
5959 *
5960 * Yields each environment variable name and its value as a 2-element Array,
5961 * deleting each environment variable for which the block returns a truthy value,
5962 * and returning ENV (regardless of whether any deletions):
5963 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5964 * ENV.delete_if { |name, value| name.start_with?('b') } # => ENV
5965 * ENV # => {"foo"=>"0"}
5966 * ENV.delete_if { |name, value| name.start_with?('b') } # => ENV
5967 *
5968 * Returns an Enumerator if no block given:
5969 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5970 * e = ENV.delete_if # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:delete_if!>
5971 * e.each { |name, value| name.start_with?('b') } # => ENV
5972 * ENV # => {"foo"=>"0"}
5973 * e.each { |name, value| name.start_with?('b') } # => ENV
5974 */
5975static VALUE
5976env_delete_if(VALUE ehash)
5977{
5978 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
5979 env_reject_bang(ehash);
5980 return envtbl;
5981}
5982
5983/*
5984 * call-seq:
5985 * ENV.values_at(*names) -> array of values
5986 *
5987 * Returns an Array containing the environment variable values associated with
5988 * the given names:
5989 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
5990 * ENV.values_at('foo', 'baz') # => ["0", "2"]
5991 *
5992 * Returns +nil+ in the Array for each name that is not an ENV name:
5993 * ENV.values_at('foo', 'bat', 'bar', 'bam') # => ["0", nil, "1", nil]
5994 *
5995 * Returns an empty Array if no names given.
5996 *
5997 * Raises an exception if any name is invalid.
5998 * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
5999 */
6000static VALUE
6001env_values_at(int argc, VALUE *argv, VALUE _)
6002{
6003 VALUE result;
6004 long i;
6005
6006 result = rb_ary_new();
6007 for (i=0; i<argc; i++) {
6008 rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
6009 }
6010 return result;
6011}
6012
6013/*
6014 * call-seq:
6015 * ENV.select { |name, value| block } -> hash of name/value pairs
6016 * ENV.select -> an_enumerator
6017 * ENV.filter { |name, value| block } -> hash of name/value pairs
6018 * ENV.filter -> an_enumerator
6019 *
6020 * Yields each environment variable name and its value as a 2-element Array,
6021 * returning a Hash of the names and values for which the block returns a truthy value:
6022 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6023 * ENV.select { |name, value| name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
6024 * ENV.filter { |name, value| name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
6025 *
6026 * Returns an Enumerator if no block given:
6027 * e = ENV.select # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:select>
6028 * e.each { |name, value | name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
6029 * e = ENV.filter # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:filter>
6030 * e.each { |name, value | name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
6031 */
6032static VALUE
6033env_select(VALUE ehash)
6034{
6035 VALUE result;
6036 VALUE keys;
6037 long i;
6038
6039 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
6040 result = rb_hash_new();
6041 keys = env_keys(FALSE);
6042 for (i = 0; i < RARRAY_LEN(keys); ++i) {
6043 VALUE key = RARRAY_AREF(keys, i);
6044 VALUE val = rb_f_getenv(Qnil, key);
6045 if (!NIL_P(val)) {
6046 if (RTEST(rb_yield_values(2, key, val))) {
6047 rb_hash_aset(result, key, val);
6048 }
6049 }
6050 }
6051 RB_GC_GUARD(keys);
6052
6053 return result;
6054}
6055
6056/*
6057 * call-seq:
6058 * ENV.select! { |name, value| block } -> ENV or nil
6059 * ENV.select! -> an_enumerator
6060 * ENV.filter! { |name, value| block } -> ENV or nil
6061 * ENV.filter! -> an_enumerator
6062 *
6063 * Yields each environment variable name and its value as a 2-element Array,
6064 * deleting each entry for which the block returns +false+ or +nil+,
6065 * and returning ENV if any deletions made, or +nil+ otherwise:
6066 *
6067 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6068 * ENV.select! { |name, value| name.start_with?('b') } # => ENV
6069 * ENV # => {"bar"=>"1", "baz"=>"2"}
6070 * ENV.select! { |name, value| true } # => nil
6071 *
6072 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6073 * ENV.filter! { |name, value| name.start_with?('b') } # => ENV
6074 * ENV # => {"bar"=>"1", "baz"=>"2"}
6075 * ENV.filter! { |name, value| true } # => nil
6076 *
6077 * Returns an Enumerator if no block given:
6078 *
6079 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6080 * e = ENV.select! # => #<Enumerator: {"bar"=>"1", "baz"=>"2"}:select!>
6081 * e.each { |name, value| name.start_with?('b') } # => ENV
6082 * ENV # => {"bar"=>"1", "baz"=>"2"}
6083 * e.each { |name, value| true } # => nil
6084 *
6085 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6086 * e = ENV.filter! # => #<Enumerator: {"bar"=>"1", "baz"=>"2"}:filter!>
6087 * e.each { |name, value| name.start_with?('b') } # => ENV
6088 * ENV # => {"bar"=>"1", "baz"=>"2"}
6089 * e.each { |name, value| true } # => nil
6090 */
6091static VALUE
6092env_select_bang(VALUE ehash)
6093{
6094 VALUE keys;
6095 long i;
6096 int del = 0;
6097
6098 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
6099 keys = env_keys(FALSE);
6100 RBASIC_CLEAR_CLASS(keys);
6101 for (i=0; i<RARRAY_LEN(keys); i++) {
6102 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
6103 if (!NIL_P(val)) {
6104 if (!RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
6105 env_delete(RARRAY_AREF(keys, i));
6106 del++;
6107 }
6108 }
6109 }
6110 RB_GC_GUARD(keys);
6111 if (del == 0) return Qnil;
6112 return envtbl;
6113}
6114
6115/*
6116 * call-seq:
6117 * ENV.keep_if { |name, value| block } -> ENV
6118 * ENV.keep_if -> an_enumerator
6119 *
6120 * Yields each environment variable name and its value as a 2-element Array,
6121 * deleting each environment variable for which the block returns +false+ or +nil+,
6122 * and returning ENV:
6123 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6124 * ENV.keep_if { |name, value| name.start_with?('b') } # => ENV
6125 * ENV # => {"bar"=>"1", "baz"=>"2"}
6126 *
6127 * Returns an Enumerator if no block given:
6128 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6129 * e = ENV.keep_if # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:keep_if>
6130 * e.each { |name, value| name.start_with?('b') } # => ENV
6131 * ENV # => {"bar"=>"1", "baz"=>"2"}
6132 */
6133static VALUE
6134env_keep_if(VALUE ehash)
6135{
6136 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
6137 env_select_bang(ehash);
6138 return envtbl;
6139}
6140
6141/*
6142 * call-seq:
6143 * ENV.slice(*names) -> hash of name/value pairs
6144 *
6145 * Returns a Hash of the given ENV names and their corresponding values:
6146 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2', 'bat' => '3')
6147 * ENV.slice('foo', 'baz') # => {"foo"=>"0", "baz"=>"2"}
6148 * ENV.slice('baz', 'foo') # => {"baz"=>"2", "foo"=>"0"}
6149 * Raises an exception if any of the +names+ is invalid
6150 * (see {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values]):
6151 * ENV.slice('foo', 'bar', :bat) # Raises TypeError (no implicit conversion of Symbol into String)
6152 */
6153static VALUE
6154env_slice(int argc, VALUE *argv, VALUE _)
6155{
6156 int i;
6157 VALUE key, value, result;
6158
6159 if (argc == 0) {
6160 return rb_hash_new();
6161 }
6162 result = rb_hash_new_with_size(argc);
6163
6164 for (i = 0; i < argc; i++) {
6165 key = argv[i];
6166 value = rb_f_getenv(Qnil, key);
6167 if (value != Qnil)
6168 rb_hash_aset(result, key, value);
6169 }
6170
6171 return result;
6172}
6173
6174VALUE
6175rb_env_clear(void)
6176{
6177 VALUE keys;
6178 long i;
6179
6180 keys = env_keys(TRUE);
6181 for (i=0; i<RARRAY_LEN(keys); i++) {
6182 VALUE key = RARRAY_AREF(keys, i);
6183 const char *nam = RSTRING_PTR(key);
6184 ruby_setenv(nam, 0);
6185 }
6186 RB_GC_GUARD(keys);
6187 return envtbl;
6188}
6189
6190/*
6191 * call-seq:
6192 * ENV.clear -> ENV
6193 *
6194 * Removes every environment variable; returns ENV:
6195 * ENV.replace('foo' => '0', 'bar' => '1')
6196 * ENV.size # => 2
6197 * ENV.clear # => ENV
6198 * ENV.size # => 0
6199 */
6200static VALUE
6201env_clear(VALUE _)
6202{
6203 return rb_env_clear();
6204}
6205
6206/*
6207 * call-seq:
6208 * ENV.to_s -> "ENV"
6209 *
6210 * Returns String 'ENV':
6211 * ENV.to_s # => "ENV"
6212 */
6213static VALUE
6214env_to_s(VALUE _)
6215{
6216 return rb_usascii_str_new2("ENV");
6217}
6218
6219/*
6220 * call-seq:
6221 * ENV.inspect -> a_string
6222 *
6223 * Returns the contents of the environment as a String:
6224 * ENV.replace('foo' => '0', 'bar' => '1')
6225 * ENV.inspect # => "{\"bar\"=>\"1\", \"foo\"=>\"0\"}"
6226 */
6227static VALUE
6228env_inspect(VALUE _)
6229{
6230 VALUE str = rb_str_buf_new2("{");
6231 rb_encoding *enc = env_encoding();
6232
6233 ENV_LOCKING() {
6234 char **env = GET_ENVIRON(environ);
6235 while (*env) {
6236 const char *s = strchr(*env, '=');
6237
6238 if (env != environ) {
6239 rb_str_buf_cat2(str, ", ");
6240 }
6241 if (s) {
6242 rb_str_buf_append(str, rb_str_inspect(env_enc_str_new(*env, s-*env, enc)));
6243 rb_str_buf_cat2(str, " => ");
6244 s++;
6245 rb_str_buf_append(str, rb_str_inspect(env_enc_str_new(s, strlen(s), enc)));
6246 }
6247 env++;
6248 }
6249 FREE_ENVIRON(environ);
6250 }
6251
6252 rb_str_buf_cat2(str, "}");
6253
6254 return str;
6255}
6256
6257/*
6258 * call-seq:
6259 * ENV.to_a -> array of 2-element arrays
6260 *
6261 * Returns the contents of ENV as an Array of 2-element Arrays,
6262 * each of which is a name/value pair:
6263 * ENV.replace('foo' => '0', 'bar' => '1')
6264 * ENV.to_a # => [["bar", "1"], ["foo", "0"]]
6265 */
6266static VALUE
6267env_to_a(VALUE _)
6268{
6269 VALUE ary = rb_ary_new();
6270
6271 rb_encoding *enc = env_encoding();
6272 ENV_LOCKING() {
6273 char **env = GET_ENVIRON(environ);
6274 while (*env) {
6275 char *s = strchr(*env, '=');
6276 if (s) {
6277 rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env, enc),
6278 env_str_new2(s+1, enc)));
6279 }
6280 env++;
6281 }
6282 FREE_ENVIRON(environ);
6283 }
6284
6285 return ary;
6286}
6287
6288/*
6289 * call-seq:
6290 * ENV.rehash -> nil
6291 *
6292 * (Provided for compatibility with Hash.)
6293 *
6294 * Does not modify ENV; returns +nil+.
6295 */
6296static VALUE
6297env_none(VALUE _)
6298{
6299 return Qnil;
6300}
6301
6302static int
6303env_size_with_lock(void)
6304{
6305 int i = 0;
6306
6307 ENV_LOCKING() {
6308 char **env = GET_ENVIRON(environ);
6309 while (env[i]) i++;
6310 FREE_ENVIRON(environ);
6311 }
6312
6313 return i;
6314}
6315
6316/*
6317 * call-seq:
6318 * ENV.length -> an_integer
6319 * ENV.size -> an_integer
6320 *
6321 * Returns the count of environment variables:
6322 * ENV.replace('foo' => '0', 'bar' => '1')
6323 * ENV.length # => 2
6324 * ENV.size # => 2
6325 */
6326static VALUE
6327env_size(VALUE _)
6328{
6329 return INT2FIX(env_size_with_lock());
6330}
6331
6332/*
6333 * call-seq:
6334 * ENV.empty? -> true or false
6335 *
6336 * Returns +true+ when there are no environment variables, +false+ otherwise:
6337 * ENV.clear
6338 * ENV.empty? # => true
6339 * ENV['foo'] = '0'
6340 * ENV.empty? # => false
6341 */
6342static VALUE
6343env_empty_p(VALUE _)
6344{
6345 bool empty = true;
6346
6347 ENV_LOCKING() {
6348 char **env = GET_ENVIRON(environ);
6349 if (env[0] != 0) {
6350 empty = false;
6351 }
6352 FREE_ENVIRON(environ);
6353 }
6354
6355 return RBOOL(empty);
6356}
6357
6358/*
6359 * call-seq:
6360 * ENV.include?(name) -> true or false
6361 * ENV.has_key?(name) -> true or false
6362 * ENV.member?(name) -> true or false
6363 * ENV.key?(name) -> true or false
6364 *
6365 * Returns +true+ if there is an environment variable with the given +name+:
6366 * ENV.replace('foo' => '0', 'bar' => '1')
6367 * ENV.include?('foo') # => true
6368 * Returns +false+ if +name+ is a valid String and there is no such environment variable:
6369 * ENV.include?('baz') # => false
6370 * Returns +false+ if +name+ is the empty String or is a String containing character <code>'='</code>:
6371 * ENV.include?('') # => false
6372 * ENV.include?('=') # => false
6373 * Raises an exception if +name+ is a String containing the NUL character <code>"\0"</code>:
6374 * ENV.include?("\0") # Raises ArgumentError (bad environment variable name: contains null byte)
6375 * Raises an exception if +name+ has an encoding that is not ASCII-compatible:
6376 * ENV.include?("\xa1\xa1".force_encoding(Encoding::UTF_16LE))
6377 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: UTF-16LE)
6378 * Raises an exception if +name+ is not a String:
6379 * ENV.include?(Object.new) # TypeError (no implicit conversion of Object into String)
6380 */
6381static VALUE
6382env_has_key(VALUE env, VALUE key)
6383{
6384 const char *s = env_name(key);
6385 return RBOOL(has_env_with_lock(s));
6386}
6387
6388/*
6389 * call-seq:
6390 * ENV.assoc(name) -> [name, value] or nil
6391 *
6392 * Returns a 2-element Array containing the name and value of the environment variable
6393 * for +name+ if it exists:
6394 * ENV.replace('foo' => '0', 'bar' => '1')
6395 * ENV.assoc('foo') # => ['foo', '0']
6396 * Returns +nil+ if +name+ is a valid String and there is no such environment variable.
6397 *
6398 * Returns +nil+ if +name+ is the empty String or is a String containing character <code>'='</code>.
6399 *
6400 * Raises an exception if +name+ is a String containing the NUL character <code>"\0"</code>:
6401 * ENV.assoc("\0") # Raises ArgumentError (bad environment variable name: contains null byte)
6402 * Raises an exception if +name+ has an encoding that is not ASCII-compatible:
6403 * ENV.assoc("\xa1\xa1".force_encoding(Encoding::UTF_16LE))
6404 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: UTF-16LE)
6405 * Raises an exception if +name+ is not a String:
6406 * ENV.assoc(Object.new) # TypeError (no implicit conversion of Object into String)
6407 */
6408static VALUE
6409env_assoc(VALUE env, VALUE key)
6410{
6411 const char *s = env_name(key);
6412 VALUE e = getenv_with_lock(s);
6413
6414 if (!NIL_P(e)) {
6415 return rb_assoc_new(key, e);
6416 }
6417 else {
6418 return Qnil;
6419 }
6420}
6421
6422/*
6423 * call-seq:
6424 * ENV.value?(value) -> true or false
6425 * ENV.has_value?(value) -> true or false
6426 *
6427 * Returns +true+ if +value+ is the value for some environment variable name, +false+ otherwise:
6428 * ENV.replace('foo' => '0', 'bar' => '1')
6429 * ENV.value?('0') # => true
6430 * ENV.has_value?('0') # => true
6431 * ENV.value?('2') # => false
6432 * ENV.has_value?('2') # => false
6433 */
6434static VALUE
6435env_has_value(VALUE dmy, VALUE obj)
6436{
6437 obj = rb_check_string_type(obj);
6438 if (NIL_P(obj)) return Qnil;
6439
6440 VALUE ret = Qfalse;
6441
6442 ENV_LOCKING() {
6443 char **env = GET_ENVIRON(environ);
6444 while (*env) {
6445 char *s = strchr(*env, '=');
6446 if (s++) {
6447 long len = strlen(s);
6448 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
6449 ret = Qtrue;
6450 break;
6451 }
6452 }
6453 env++;
6454 }
6455 FREE_ENVIRON(environ);
6456 }
6457
6458 return ret;
6459}
6460
6461/*
6462 * call-seq:
6463 * ENV.rassoc(value) -> [name, value] or nil
6464 *
6465 * Returns a 2-element Array containing the name and value of the
6466 * *first* *found* environment variable that has value +value+, if one
6467 * exists:
6468 * ENV.replace('foo' => '0', 'bar' => '0')
6469 * ENV.rassoc('0') # => ["bar", "0"]
6470 * The order in which environment variables are examined is OS-dependent.
6471 * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
6472 *
6473 * Returns +nil+ if there is no such environment variable.
6474 */
6475static VALUE
6476env_rassoc(VALUE dmy, VALUE obj)
6477{
6478 obj = rb_check_string_type(obj);
6479 if (NIL_P(obj)) return Qnil;
6480
6481 VALUE result = Qnil;
6482
6483 ENV_LOCKING() {
6484 char **env = GET_ENVIRON(environ);
6485
6486 while (*env) {
6487 const char *p = *env;
6488 const char *s = strchr(p, '=');
6489 if (s++) {
6490 long len = strlen(s);
6491 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
6492 result = rb_assoc_new(rb_str_new(p, s-p-1), obj);
6493 break;
6494 }
6495 }
6496 env++;
6497 }
6498 FREE_ENVIRON(environ);
6499 }
6500
6501 return result;
6502}
6503
6504/*
6505 * call-seq:
6506 * ENV.key(value) -> name or nil
6507 *
6508 * Returns the name of the first environment variable with +value+, if it exists:
6509 * ENV.replace('foo' => '0', 'bar' => '0')
6510 * ENV.key('0') # => "foo"
6511 * The order in which environment variables are examined is OS-dependent.
6512 * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
6513 *
6514 * Returns +nil+ if there is no such value.
6515 *
6516 * Raises an exception if +value+ is invalid:
6517 * ENV.key(Object.new) # raises TypeError (no implicit conversion of Object into String)
6518 * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values].
6519 */
6520static VALUE
6521env_key(VALUE dmy, VALUE value)
6522{
6523 StringValue(value);
6524 VALUE str = Qnil;
6525
6526 rb_encoding *enc = env_encoding();
6527 ENV_LOCKING() {
6528 char **env = GET_ENVIRON(environ);
6529 while (*env) {
6530 char *s = strchr(*env, '=');
6531 if (s++) {
6532 long len = strlen(s);
6533 if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
6534 str = env_str_new(*env, s-*env-1, enc);
6535 break;
6536 }
6537 }
6538 env++;
6539 }
6540 FREE_ENVIRON(environ);
6541 }
6542
6543 return str;
6544}
6545
6546static VALUE
6547env_to_hash(void)
6548{
6549 VALUE hash = rb_hash_new();
6550
6551 rb_encoding *enc = env_encoding();
6552 ENV_LOCKING() {
6553 char **env = GET_ENVIRON(environ);
6554 while (*env) {
6555 char *s = strchr(*env, '=');
6556 if (s) {
6557 rb_hash_aset(hash, env_str_new(*env, s-*env, enc),
6558 env_str_new2(s+1, enc));
6559 }
6560 env++;
6561 }
6562 FREE_ENVIRON(environ);
6563 }
6564
6565 return hash;
6566}
6567
6568VALUE
6569rb_envtbl(void)
6570{
6571 return envtbl;
6572}
6573
6574VALUE
6575rb_env_to_hash(void)
6576{
6577 return env_to_hash();
6578}
6579
6580/*
6581 * call-seq:
6582 * ENV.to_hash -> hash of name/value pairs
6583 *
6584 * Returns a Hash containing all name/value pairs from ENV:
6585 * ENV.replace('foo' => '0', 'bar' => '1')
6586 * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
6587 */
6588
6589static VALUE
6590env_f_to_hash(VALUE _)
6591{
6592 return env_to_hash();
6593}
6594
6595/*
6596 * call-seq:
6597 * ENV.to_h -> hash of name/value pairs
6598 * ENV.to_h {|name, value| block } -> hash of name/value pairs
6599 *
6600 * With no block, returns a Hash containing all name/value pairs from ENV:
6601 * ENV.replace('foo' => '0', 'bar' => '1')
6602 * ENV.to_h # => {"bar"=>"1", "foo"=>"0"}
6603 * With a block, returns a Hash whose items are determined by the block.
6604 * Each name/value pair in ENV is yielded to the block.
6605 * The block must return a 2-element Array (name/value pair)
6606 * that is added to the return Hash as a key and value:
6607 * ENV.to_h { |name, value| [name.to_sym, value.to_i] } # => {bar: 1, foo: 0}
6608 * Raises an exception if the block does not return an Array:
6609 * ENV.to_h { |name, value| name } # Raises TypeError (wrong element type String (expected array))
6610 * Raises an exception if the block returns an Array of the wrong size:
6611 * ENV.to_h { |name, value| [name] } # Raises ArgumentError (element has wrong array length (expected 2, was 1))
6612 */
6613static VALUE
6614env_to_h(VALUE _)
6615{
6616 VALUE hash = env_to_hash();
6617 if (rb_block_given_p()) {
6618 hash = rb_hash_to_h_block(hash);
6619 }
6620 return hash;
6621}
6622
6623/*
6624 * call-seq:
6625 * ENV.except(*keys) -> a_hash
6626 *
6627 * Returns a hash except the given keys from ENV and their values.
6628 *
6629 * ENV #=> {"LANG"=>"en_US.UTF-8", "TERM"=>"xterm-256color", "HOME"=>"/Users/rhc"}
6630 * ENV.except("TERM","HOME") #=> {"LANG"=>"en_US.UTF-8"}
6631 */
6632static VALUE
6633env_except(int argc, VALUE *argv, VALUE _)
6634{
6635 int i;
6636 VALUE key, hash = env_to_hash();
6637
6638 for (i = 0; i < argc; i++) {
6639 key = argv[i];
6640 rb_hash_delete(hash, key);
6641 }
6642
6643 return hash;
6644}
6645
6646/*
6647 * call-seq:
6648 * ENV.reject { |name, value| block } -> hash of name/value pairs
6649 * ENV.reject -> an_enumerator
6650 *
6651 * Yields each environment variable name and its value as a 2-element Array.
6652 * Returns a Hash whose items are determined by the block.
6653 * When the block returns a truthy value, the name/value pair is added to the return Hash;
6654 * otherwise the pair is ignored:
6655 * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
6656 * ENV.reject { |name, value| name.start_with?('b') } # => {"foo"=>"0"}
6657 * Returns an Enumerator if no block given:
6658 * e = ENV.reject
6659 * e.each { |name, value| name.start_with?('b') } # => {"foo"=>"0"}
6660 */
6661static VALUE
6662env_reject(VALUE _)
6663{
6664 return rb_hash_delete_if(env_to_hash());
6665}
6666
6667NORETURN(static VALUE env_freeze(VALUE self));
6668/*
6669 * call-seq:
6670 * ENV.freeze
6671 *
6672 * Raises an exception:
6673 * ENV.freeze # Raises TypeError (cannot freeze ENV)
6674 */
6675static VALUE
6676env_freeze(VALUE self)
6677{
6678 rb_raise(rb_eTypeError, "cannot freeze ENV");
6679 UNREACHABLE_RETURN(self);
6680}
6681
6682/*
6683 * call-seq:
6684 * ENV.shift -> [name, value] or nil
6685 *
6686 * Removes the first environment variable from ENV and returns
6687 * a 2-element Array containing its name and value:
6688 * ENV.replace('foo' => '0', 'bar' => '1')
6689 * ENV.to_hash # => {'bar' => '1', 'foo' => '0'}
6690 * ENV.shift # => ['bar', '1']
6691 * ENV.to_hash # => {'foo' => '0'}
6692 * Exactly which environment variable is "first" is OS-dependent.
6693 * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
6694 *
6695 * Returns +nil+ if the environment is empty.
6696 */
6697static VALUE
6698env_shift(VALUE _)
6699{
6700 VALUE result = Qnil;
6701 VALUE key = Qnil;
6702
6703 rb_encoding *enc = env_encoding();
6704 ENV_LOCKING() {
6705 char **env = GET_ENVIRON(environ);
6706 if (*env) {
6707 const char *p = *env;
6708 const char *s = strchr(p, '=');
6709 if (s) {
6710 key = env_str_new(p, s-p, enc);
6711 VALUE val = env_str_new2(getenv(RSTRING_PTR(key)), enc);
6712 result = rb_assoc_new(key, val);
6713 }
6714 }
6715 FREE_ENVIRON(environ);
6716 }
6717
6718 if (!NIL_P(key)) {
6719 env_delete(key);
6720 }
6721
6722 return result;
6723}
6724
6725/*
6726 * call-seq:
6727 * ENV.invert -> hash of value/name pairs
6728 *
6729 * Returns a Hash whose keys are the ENV values,
6730 * and whose values are the corresponding ENV names:
6731 * ENV.replace('foo' => '0', 'bar' => '1')
6732 * ENV.invert # => {"1"=>"bar", "0"=>"foo"}
6733 * For a duplicate ENV value, overwrites the hash entry:
6734 * ENV.replace('foo' => '0', 'bar' => '0')
6735 * ENV.invert # => {"0"=>"foo"}
6736 * Note that the order of the ENV processing is OS-dependent,
6737 * which means that the order of overwriting is also OS-dependent.
6738 * See {About Ordering}[rdoc-ref:ENV@About+Ordering].
6739 */
6740static VALUE
6741env_invert(VALUE _)
6742{
6743 return rb_hash_invert(env_to_hash());
6744}
6745
6746static void
6747keylist_delete(VALUE keys, VALUE key)
6748{
6749 long keylen, elen;
6750 const char *keyptr, *eptr;
6751 RSTRING_GETMEM(key, keyptr, keylen);
6752 /* Don't stop at first key, as it is possible to have
6753 multiple environment values with the same key.
6754 */
6755 for (long i=0; i<RARRAY_LEN(keys); i++) {
6756 VALUE e = RARRAY_AREF(keys, i);
6757 RSTRING_GETMEM(e, eptr, elen);
6758 if (elen != keylen) continue;
6759 if (!ENVNMATCH(keyptr, eptr, elen)) continue;
6760 rb_ary_delete_at(keys, i);
6761 i--;
6762 }
6763}
6764
6765static int
6766env_replace_i(VALUE key, VALUE val, VALUE keys)
6767{
6768 env_name(key);
6769 env_aset(key, val);
6770
6771 keylist_delete(keys, key);
6772 return ST_CONTINUE;
6773}
6774
6775/*
6776 * call-seq:
6777 * ENV.replace(hash) -> ENV
6778 *
6779 * Replaces the entire content of the environment variables
6780 * with the name/value pairs in the given +hash+;
6781 * returns ENV.
6782 *
6783 * Replaces the content of ENV with the given pairs:
6784 * ENV.replace('foo' => '0', 'bar' => '1') # => ENV
6785 * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
6786 *
6787 * Raises an exception if a name or value is invalid
6788 * (see {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values]):
6789 * ENV.replace('foo' => '0', :bar => '1') # Raises TypeError (no implicit conversion of Symbol into String)
6790 * ENV.replace('foo' => '0', 'bar' => 1) # Raises TypeError (no implicit conversion of Integer into String)
6791 * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
6792 */
6793static VALUE
6794env_replace(VALUE env, VALUE hash)
6795{
6796 VALUE keys;
6797 long i;
6798
6799 keys = env_keys(TRUE);
6800 if (env == hash) return env;
6801 hash = to_hash(hash);
6802 rb_hash_foreach(hash, env_replace_i, keys);
6803
6804 for (i=0; i<RARRAY_LEN(keys); i++) {
6805 env_delete(RARRAY_AREF(keys, i));
6806 }
6807 RB_GC_GUARD(keys);
6808 return env;
6809}
6810
6811static int
6812env_update_i(VALUE key, VALUE val, VALUE _)
6813{
6814 env_aset(key, val);
6815 return ST_CONTINUE;
6816}
6817
6818static int
6819env_update_block_i(VALUE key, VALUE val, VALUE _)
6820{
6821 VALUE oldval = rb_f_getenv(Qnil, key);
6822 if (!NIL_P(oldval)) {
6823 val = rb_yield_values(3, key, oldval, val);
6824 }
6825 env_aset(key, val);
6826 return ST_CONTINUE;
6827}
6828
6829/*
6830 * call-seq:
6831 * ENV.update -> ENV
6832 * ENV.update(*hashes) -> ENV
6833 * ENV.update(*hashes) { |name, env_val, hash_val| block } -> ENV
6834 * ENV.merge! -> ENV
6835 * ENV.merge!(*hashes) -> ENV
6836 * ENV.merge!(*hashes) { |name, env_val, hash_val| block } -> ENV
6837 *
6838 * Adds to ENV each key/value pair in the given +hash+; returns ENV:
6839 * ENV.replace('foo' => '0', 'bar' => '1')
6840 * ENV.merge!('baz' => '2', 'bat' => '3') # => {"bar"=>"1", "bat"=>"3", "baz"=>"2", "foo"=>"0"}
6841 * Deletes the ENV entry for a hash value that is +nil+:
6842 * ENV.merge!('baz' => nil, 'bat' => nil) # => {"bar"=>"1", "foo"=>"0"}
6843 * For an already-existing name, if no block given, overwrites the ENV value:
6844 * ENV.merge!('foo' => '4') # => {"bar"=>"1", "foo"=>"4"}
6845 * For an already-existing name, if block given,
6846 * yields the name, its ENV value, and its hash value;
6847 * the block's return value becomes the new name:
6848 * ENV.merge!('foo' => '5') { |name, env_val, hash_val | env_val + hash_val } # => {"bar"=>"1", "foo"=>"45"}
6849 * Raises an exception if a name or value is invalid
6850 * (see {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values]);
6851 * ENV.replace('foo' => '0', 'bar' => '1')
6852 * ENV.merge!('foo' => '6', :bar => '7', 'baz' => '9') # Raises TypeError (no implicit conversion of Symbol into String)
6853 * ENV # => {"bar"=>"1", "foo"=>"6"}
6854 * ENV.merge!('foo' => '7', 'bar' => 8, 'baz' => '9') # Raises TypeError (no implicit conversion of Integer into String)
6855 * ENV # => {"bar"=>"1", "foo"=>"7"}
6856 * Raises an exception if the block returns an invalid name:
6857 * (see {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values]):
6858 * ENV.merge!('bat' => '8', 'foo' => '9') { |name, env_val, hash_val | 10 } # Raises TypeError (no implicit conversion of Integer into String)
6859 * ENV # => {"bar"=>"1", "bat"=>"8", "foo"=>"7"}
6860 *
6861 * Note that for the exceptions above,
6862 * hash pairs preceding an invalid name or value are processed normally;
6863 * those following are ignored.
6864 */
6865static VALUE
6866env_update(int argc, VALUE *argv, VALUE env)
6867{
6868 rb_foreach_func *func = rb_block_given_p() ?
6869 env_update_block_i : env_update_i;
6870 for (int i = 0; i < argc; ++i) {
6871 VALUE hash = argv[i];
6872 if (env == hash) continue;
6873 hash = to_hash(hash);
6874 rb_hash_foreach(hash, func, 0);
6875 }
6876 return env;
6877}
6878
6879NORETURN(static VALUE env_clone(int, VALUE *, VALUE));
6880/*
6881 * call-seq:
6882 * ENV.clone(freeze: nil) # raises TypeError
6883 *
6884 * Raises TypeError, because ENV is a wrapper for the process-wide
6885 * environment variables and a clone is useless.
6886 * Use #to_h to get a copy of ENV data as a hash.
6887 */
6888static VALUE
6889env_clone(int argc, VALUE *argv, VALUE obj)
6890{
6891 if (argc) {
6892 VALUE opt;
6893 if (rb_scan_args(argc, argv, "0:", &opt) < argc) {
6894 rb_get_freeze_opt(1, &opt);
6895 }
6896 }
6897
6898 rb_raise(rb_eTypeError, "Cannot clone ENV, use ENV.to_h to get a copy of ENV as a hash");
6899}
6900
6901NORETURN(static VALUE env_dup(VALUE));
6902/*
6903 * call-seq:
6904 * ENV.dup # raises TypeError
6905 *
6906 * Raises TypeError, because ENV is a singleton object.
6907 * Use #to_h to get a copy of ENV data as a hash.
6908 */
6909static VALUE
6910env_dup(VALUE obj)
6911{
6912 rb_raise(rb_eTypeError, "Cannot dup ENV, use ENV.to_h to get a copy of ENV as a hash");
6913}
6914
6915static const rb_data_type_t env_data_type = {
6916 "ENV",
6917 {
6918 NULL,
6919 NULL,
6920 NULL,
6921 NULL,
6922 },
6923 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
6924};
6925
6926/*
6927 * A \Hash object maps each of its unique keys to a specific value.
6928 *
6929 * A hash has certain similarities to an Array, but:
6930 *
6931 * - An array index is always an integer.
6932 * - A hash key can be (almost) any object.
6933 *
6934 * === \Hash \Data Syntax
6935 *
6936 * The original syntax for a hash entry uses the "hash rocket," <tt>=></tt>:
6937 *
6938 * h = {:foo => 0, :bar => 1, :baz => 2}
6939 * h # => {foo: 0, bar: 1, baz: 2}
6940 *
6941 * Alternatively, but only for a key that's a symbol,
6942 * you can use a newer JSON-style syntax,
6943 * where each bareword becomes a symbol:
6944 *
6945 * h = {foo: 0, bar: 1, baz: 2}
6946 * h # => {foo: 0, bar: 1, baz: 2}
6947 *
6948 * You can also use a string in place of a bareword:
6949 *
6950 * h = {'foo': 0, 'bar': 1, 'baz': 2}
6951 * h # => {foo: 0, bar: 1, baz: 2}
6952 *
6953 * And you can mix the styles:
6954 *
6955 * h = {foo: 0, :bar => 1, 'baz': 2}
6956 * h # => {foo: 0, bar: 1, baz: 2}
6957 *
6958 * But it's an error to try the JSON-style syntax
6959 * for a key that's not a bareword or a string:
6960 *
6961 * # Raises SyntaxError (syntax error, unexpected ':', expecting =>):
6962 * h = {0: 'zero'}
6963 *
6964 * The value can be omitted, meaning that value will be fetched from the context
6965 * by the name of the key:
6966 *
6967 * x = 0
6968 * y = 100
6969 * h = {x:, y:}
6970 * h # => {x: 0, y: 100}
6971 *
6972 * === Common Uses
6973 *
6974 * You can use a hash to give names to objects:
6975 *
6976 * person = {name: 'Matz', language: 'Ruby'}
6977 * person # => {name: "Matz", language: "Ruby"}
6978 *
6979 * You can use a hash to give names to method arguments:
6980 *
6981 * def some_method(hash)
6982 * p hash
6983 * end
6984 * some_method({foo: 0, bar: 1, baz: 2}) # => {foo: 0, bar: 1, baz: 2}
6985 *
6986 * Note: when the last argument in a method call is a hash,
6987 * the curly braces may be omitted:
6988 *
6989 * some_method(foo: 0, bar: 1, baz: 2) # => {foo: 0, bar: 1, baz: 2}
6990 *
6991 * You can use a hash to initialize an object:
6992 *
6993 * class Dev
6994 * attr_accessor :name, :language
6995 * def initialize(hash)
6996 * self.name = hash[:name]
6997 * self.language = hash[:language]
6998 * end
6999 * end
7000 * matz = Dev.new(name: 'Matz', language: 'Ruby')
7001 * matz # => #<Dev: @name="Matz", @language="Ruby">
7002 *
7003 * === Creating a \Hash
7004 *
7005 * You can create a \Hash object explicitly with:
7006 *
7007 * - A {hash literal}[rdoc-ref:syntax/literals.rdoc@Hash+Literals].
7008 *
7009 * You can convert certain objects to hashes with:
7010 *
7011 * - Method Kernel#Hash.
7012 *
7013 * You can create a hash by calling method Hash.new:
7014 *
7015 * # Create an empty hash.
7016 * h = Hash.new
7017 * h # => {}
7018 * h.class # => Hash
7019 *
7020 * You can create a hash by calling method Hash.[]:
7021 *
7022 * # Create an empty hash.
7023 * h = Hash[]
7024 * h # => {}
7025 * # Create a hash with initial entries.
7026 * h = Hash[foo: 0, bar: 1, baz: 2]
7027 * h # => {foo: 0, bar: 1, baz: 2}
7028 *
7029 * You can create a hash by using its literal form (curly braces):
7030 *
7031 * # Create an empty hash.
7032 * h = {}
7033 * h # => {}
7034 * # Create a +Hash+ with initial entries.
7035 * h = {foo: 0, bar: 1, baz: 2}
7036 * h # => {foo: 0, bar: 1, baz: 2}
7037 *
7038 * === \Hash Value Basics
7039 *
7040 * The simplest way to retrieve a hash value (instance method #[]):
7041 *
7042 * h = {foo: 0, bar: 1, baz: 2}
7043 * h[:foo] # => 0
7044 *
7045 * The simplest way to create or update a hash value (instance method #[]=):
7046 *
7047 * h = {foo: 0, bar: 1, baz: 2}
7048 * h[:bat] = 3 # => 3
7049 * h # => {foo: 0, bar: 1, baz: 2, bat: 3}
7050 * h[:foo] = 4 # => 4
7051 * h # => {foo: 4, bar: 1, baz: 2, bat: 3}
7052 *
7053 * The simplest way to delete a hash entry (instance method #delete):
7054 *
7055 * h = {foo: 0, bar: 1, baz: 2}
7056 * h.delete(:bar) # => 1
7057 * h # => {foo: 0, baz: 2}
7058 *
7059 * === Entry Order
7060 *
7061 * A \Hash object presents its entries in the order of their creation. This is seen in:
7062 *
7063 * - Iterative methods such as <tt>each</tt>, <tt>each_key</tt>, <tt>each_pair</tt>, <tt>each_value</tt>.
7064 * - Other order-sensitive methods such as <tt>shift</tt>, <tt>keys</tt>, <tt>values</tt>.
7065 * - The string returned by method <tt>inspect</tt>.
7066 *
7067 * A new hash has its initial ordering per the given entries:
7068 *
7069 * h = Hash[foo: 0, bar: 1]
7070 * h # => {foo: 0, bar: 1}
7071 *
7072 * New entries are added at the end:
7073 *
7074 * h[:baz] = 2
7075 * h # => {foo: 0, bar: 1, baz: 2}
7076 *
7077 * Updating a value does not affect the order:
7078 *
7079 * h[:baz] = 3
7080 * h # => {foo: 0, bar: 1, baz: 3}
7081 *
7082 * But re-creating a deleted entry can affect the order:
7083 *
7084 * h.delete(:foo)
7085 * h[:foo] = 5
7086 * h # => {bar: 1, baz: 3, foo: 5}
7087 *
7088 * === +Hash+ Keys
7089 *
7090 * ==== +Hash+ Key Equivalence
7091 *
7092 * Two objects are treated as the same \hash key when their <code>hash</code> value
7093 * is identical and the two objects are <code>eql?</code> to each other.
7094 *
7095 * ==== Modifying an Active +Hash+ Key
7096 *
7097 * Modifying a +Hash+ key while it is in use damages the hash's index.
7098 *
7099 * This +Hash+ has keys that are Arrays:
7100 *
7101 * a0 = [ :foo, :bar ]
7102 * a1 = [ :baz, :bat ]
7103 * h = {a0 => 0, a1 => 1}
7104 * h.include?(a0) # => true
7105 * h[a0] # => 0
7106 * a0.hash # => 110002110
7107 *
7108 * Modifying array element <tt>a0[0]</tt> changes its hash value:
7109 *
7110 * a0[0] = :bam
7111 * a0.hash # => 1069447059
7112 *
7113 * And damages the +Hash+ index:
7114 *
7115 * h.include?(a0) # => false
7116 * h[a0] # => nil
7117 *
7118 * You can repair the hash index using method +rehash+:
7119 *
7120 * h.rehash # => {[:bam, :bar]=>0, [:baz, :bat]=>1}
7121 * h.include?(a0) # => true
7122 * h[a0] # => 0
7123 *
7124 * A String key is always safe.
7125 * That's because an unfrozen String
7126 * passed as a key will be replaced by a duplicated and frozen String:
7127 *
7128 * s = 'foo'
7129 * s.frozen? # => false
7130 * h = {s => 0}
7131 * first_key = h.keys.first
7132 * first_key.frozen? # => true
7133 *
7134 * ==== User-Defined +Hash+ Keys
7135 *
7136 * To be usable as a +Hash+ key, objects must implement the methods <code>hash</code> and <code>eql?</code>.
7137 * Note: this requirement does not apply if the +Hash+ uses #compare_by_identity since comparison will then
7138 * rely on the keys' object id instead of <code>hash</code> and <code>eql?</code>.
7139 *
7140 * Object defines basic implementation for <code>hash</code> and <code>eq?</code> that makes each object
7141 * a distinct key. Typically, user-defined classes will want to override these methods to provide meaningful
7142 * behavior, or for example inherit Struct that has useful definitions for these.
7143 *
7144 * A typical implementation of <code>hash</code> is based on the
7145 * object's data while <code>eql?</code> is usually aliased to the overridden
7146 * <code>==</code> method:
7147 *
7148 * class Book
7149 * attr_reader :author, :title
7150 *
7151 * def initialize(author, title)
7152 * @author = author
7153 * @title = title
7154 * end
7155 *
7156 * def ==(other)
7157 * self.class === other &&
7158 * other.author == @author &&
7159 * other.title == @title
7160 * end
7161 *
7162 * alias eql? ==
7163 *
7164 * def hash
7165 * [self.class, @author, @title].hash
7166 * end
7167 * end
7168 *
7169 * book1 = Book.new 'matz', 'Ruby in a Nutshell'
7170 * book2 = Book.new 'matz', 'Ruby in a Nutshell'
7171 *
7172 * reviews = {}
7173 *
7174 * reviews[book1] = 'Great reference!'
7175 * reviews[book2] = 'Nice and compact!'
7176 *
7177 * reviews.length #=> 1
7178 *
7179 * === Key Not Found?
7180 *
7181 * When a method tries to retrieve and return the value for a key and that key <i>is found</i>,
7182 * the returned value is the value associated with the key.
7183 *
7184 * But what if the key <i>is not found</i>?
7185 * In that case, certain methods will return a default value while other will raise a \KeyError.
7186 *
7187 * ==== Nil Return Value
7188 *
7189 * If you want +nil+ returned for a not-found key, you can call:
7190 *
7191 * - #[](key) (usually written as <tt>#[key]</tt>.
7192 * - #assoc(key).
7193 * - #dig(key, *identifiers).
7194 * - #values_at(*keys).
7195 *
7196 * You can override these behaviors for #[], #dig, and #values_at (but not #assoc);
7197 * see {Hash Default}[rdoc-ref:Hash@Hash+Default].
7198 *
7199 * ==== \KeyError
7200 *
7201 * If you want KeyError raised for a not-found key, you can call:
7202 *
7203 * - #fetch(key).
7204 * - #fetch_values(*keys).
7205 *
7206 * ==== \Hash Default
7207 *
7208 * For certain methods (#[], #dig, and #values_at),
7209 * the return value for a not-found key is determined by two hash properties:
7210 *
7211 * - <i>default value</i>: returned by method #default.
7212 * - <i>default proc</i>: returned by method #default_proc.
7213 *
7214 * In the simple case, both values are +nil+,
7215 * and the methods return +nil+ for a not-found key;
7216 * see {Nil Return Value}[rdoc-ref:Hash@Nil+Return+Value] above.
7217 *
7218 * Note that this entire section ("Hash Default"):
7219 *
7220 * - Applies _only_ to methods #[], #dig, and #values_at.
7221 * - Does _not_ apply to methods #assoc, #fetch, or #fetch_values,
7222 * which are not affected by the default value or default proc.
7223 *
7224 * ===== Any-Key Default
7225 *
7226 * You can define an any-key default for a hash;
7227 * that is, a value that will be returned for _any_ not-found key:
7228 *
7229 * - The value of #default_proc <i>must be</i> +nil+.
7230 * - The value of #default (which may be any object, including +nil+)
7231 * will be returned for a not-found key.
7232 *
7233 * You can set the default value when the hash is created with Hash.new and option +default_value+,
7234 * or later with method #default=.
7235 *
7236 * Note: although the value of #default may be any object,
7237 * it may not be a good idea to use a mutable object.
7238 *
7239 * ===== Per-Key Defaults
7240 *
7241 * You can define a per-key default for a hash;
7242 * that is, a Proc that will return a value based on the key itself.
7243 *
7244 * You can set the default proc when the hash is created with Hash.new and a block,
7245 * or later with method #default_proc=.
7246 *
7247 * Note that the proc can modify +self+,
7248 * but modifying +self+ in this way is not thread-safe;
7249 * multiple threads can concurrently call into the default proc
7250 * for the same key.
7251 *
7252 * ==== \Method Default
7253 *
7254 * For two methods, you can specify a default value for a not-found key
7255 * that has effect only for a single method call
7256 * (and not for any subsequent calls):
7257 *
7258 * - For method #fetch, you can specify an any-key default:
7259 * - For either method #fetch or method #fetch_values,
7260 * you can specify a per-key default via a block.
7261 *
7262 * === What's Here
7263 *
7264 * First, what's elsewhere. Class +Hash+:
7265 *
7266 * - Inherits from {class Object}[rdoc-ref:Object@Whats+Here].
7267 * - Includes {module Enumerable}[rdoc-ref:Enumerable@Whats+Here],
7268 * which provides dozens of additional methods.
7269 *
7270 * Here, class +Hash+ provides methods that are useful for:
7271 *
7272 * - {Creating a Hash}[rdoc-ref:Hash@Methods+for+Creating+a+Hash]
7273 * - {Setting Hash State}[rdoc-ref:Hash@Methods+for+Setting+Hash+State]
7274 * - {Querying}[rdoc-ref:Hash@Methods+for+Querying]
7275 * - {Comparing}[rdoc-ref:Hash@Methods+for+Comparing]
7276 * - {Fetching}[rdoc-ref:Hash@Methods+for+Fetching]
7277 * - {Assigning}[rdoc-ref:Hash@Methods+for+Assigning]
7278 * - {Deleting}[rdoc-ref:Hash@Methods+for+Deleting]
7279 * - {Iterating}[rdoc-ref:Hash@Methods+for+Iterating]
7280 * - {Converting}[rdoc-ref:Hash@Methods+for+Converting]
7281 * - {Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values]
7282 *
7283 * Class +Hash+ also includes methods from module Enumerable.
7284 *
7285 * ==== Methods for Creating a +Hash+
7286 *
7287 * - ::[]: Returns a new hash populated with given objects.
7288 * - ::new: Returns a new empty hash.
7289 * - ::try_convert: Returns a new hash created from a given object.
7290 *
7291 * ==== Methods for Setting +Hash+ State
7292 *
7293 * - #compare_by_identity: Sets +self+ to consider only identity in comparing keys.
7294 * - #default=: Sets the default to a given value.
7295 * - #default_proc=: Sets the default proc to a given proc.
7296 * - #rehash: Rebuilds the hash table by recomputing the hash index for each key.
7297 *
7298 * ==== Methods for Querying
7299 *
7300 * - #any?: Returns whether any element satisfies a given criterion.
7301 * - #compare_by_identity?: Returns whether the hash considers only identity when comparing keys.
7302 * - #default: Returns the default value, or the default value for a given key.
7303 * - #default_proc: Returns the default proc.
7304 * - #empty?: Returns whether there are no entries.
7305 * - #eql?: Returns whether a given object is equal to +self+.
7306 * - #hash: Returns the integer hash code.
7307 * - #has_value? (aliased as #value?): Returns whether a given object is a value in +self+.
7308 * - #include? (aliased as #has_key?, #member?, #key?): Returns whether a given object is a key in +self+.
7309 * - #size (aliased as #length): Returns the count of entries.
7310 *
7311 * ==== Methods for Comparing
7312 *
7313 * - #<: Returns whether +self+ is a proper subset of a given object.
7314 * - #<=: Returns whether +self+ is a subset of a given object.
7315 * - #==: Returns whether a given object is equal to +self+.
7316 * - #>: Returns whether +self+ is a proper superset of a given object
7317 * - #>=: Returns whether +self+ is a superset of a given object.
7318 *
7319 * ==== Methods for Fetching
7320 *
7321 * - #[]: Returns the value associated with a given key.
7322 * - #assoc: Returns a 2-element array containing a given key and its value.
7323 * - #dig: Returns the object in nested objects that is specified
7324 * by a given key and additional arguments.
7325 * - #fetch: Returns the value for a given key.
7326 * - #fetch_values: Returns array containing the values associated with given keys.
7327 * - #key: Returns the key for the first-found entry with a given value.
7328 * - #keys: Returns an array containing all keys in +self+.
7329 * - #rassoc: Returns a 2-element array consisting of the key and value
7330 * of the first-found entry having a given value.
7331 * - #values: Returns an array containing all values in +self+.
7332 * - #values_at: Returns an array containing values for given keys.
7333 *
7334 * ==== Methods for Assigning
7335 *
7336 * - #[]= (aliased as #store): Associates a given key with a given value.
7337 * - #merge: Returns the hash formed by merging each given hash into a copy of +self+.
7338 * - #update (aliased as #merge!): Merges each given hash into +self+.
7339 * - #replace (aliased as #initialize_copy): Replaces the entire contents of +self+ with the contents of a given hash.
7340 *
7341 * ==== Methods for Deleting
7342 *
7343 * These methods remove entries from +self+:
7344 *
7345 * - #clear: Removes all entries from +self+.
7346 * - #compact!: Removes all +nil+-valued entries from +self+.
7347 * - #delete: Removes the entry for a given key.
7348 * - #delete_if: Removes entries selected by a given block.
7349 * - #select! (aliased as #filter!): Keep only those entries selected by a given block.
7350 * - #keep_if: Keep only those entries selected by a given block.
7351 * - #reject!: Removes entries selected by a given block.
7352 * - #shift: Removes and returns the first entry.
7353 *
7354 * These methods return a copy of +self+ with some entries removed:
7355 *
7356 * - #compact: Returns a copy of +self+ with all +nil+-valued entries removed.
7357 * - #except: Returns a copy of +self+ with entries removed for specified keys.
7358 * - #select (aliased as #filter): Returns a copy of +self+ with only those entries selected by a given block.
7359 * - #reject: Returns a copy of +self+ with entries removed as specified by a given block.
7360 * - #slice: Returns a hash containing the entries for given keys.
7361 *
7362 * ==== Methods for Iterating
7363 * - #each_pair (aliased as #each): Calls a given block with each key-value pair.
7364 * - #each_key: Calls a given block with each key.
7365 * - #each_value: Calls a given block with each value.
7366 *
7367 * ==== Methods for Converting
7368 *
7369 * - #flatten: Returns an array that is a 1-dimensional flattening of +self+.
7370 * - #inspect (aliased as #to_s): Returns a new String containing the hash entries.
7371 * - #to_a: Returns a new array of 2-element arrays;
7372 * each nested array contains a key-value pair from +self+.
7373 * - #to_h: Returns +self+ if a +Hash+;
7374 * if a subclass of +Hash+, returns a +Hash+ containing the entries from +self+.
7375 * - #to_hash: Returns +self+.
7376 * - #to_proc: Returns a proc that maps a given key to its value.
7377 *
7378 * ==== Methods for Transforming Keys and Values
7379 *
7380 * - #invert: Returns a hash with the each key-value pair inverted.
7381 * - #transform_keys: Returns a copy of +self+ with modified keys.
7382 * - #transform_keys!: Modifies keys in +self+
7383 * - #transform_values: Returns a copy of +self+ with modified values.
7384 * - #transform_values!: Modifies values in +self+.
7385 *
7386 */
7387
7388void
7389Init_Hash(void)
7390{
7391 id_hash = rb_intern_const("hash");
7392 id_flatten_bang = rb_intern_const("flatten!");
7393 id_hash_iter_lev = rb_make_internal_id();
7394
7396
7398
7399 rb_define_alloc_func(rb_cHash, empty_hash_alloc);
7400 rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
7401 rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
7402 rb_define_method(rb_cHash, "initialize_copy", rb_hash_replace, 1);
7403 rb_define_method(rb_cHash, "rehash", rb_hash_rehash, 0);
7404 rb_define_method(rb_cHash, "freeze", rb_hash_freeze, 0);
7405
7406 rb_define_method(rb_cHash, "to_hash", rb_hash_to_hash, 0);
7407 rb_define_method(rb_cHash, "to_h", rb_hash_to_h, 0);
7408 rb_define_method(rb_cHash, "to_a", rb_hash_to_a, 0);
7409 rb_define_method(rb_cHash, "inspect", rb_hash_inspect, 0);
7410 rb_define_alias(rb_cHash, "to_s", "inspect");
7411 rb_define_method(rb_cHash, "to_proc", rb_hash_to_proc, 0);
7412
7413 rb_define_method(rb_cHash, "==", rb_hash_equal, 1);
7414 rb_define_method(rb_cHash, "[]", rb_hash_aref, 1);
7415 rb_define_method(rb_cHash, "hash", rb_hash_hash, 0);
7416 rb_define_method(rb_cHash, "eql?", rb_hash_eql, 1);
7417 rb_define_method(rb_cHash, "fetch", rb_hash_fetch_m, -1);
7418 rb_define_method(rb_cHash, "[]=", rb_hash_aset, 2);
7419 rb_define_method(rb_cHash, "store", rb_hash_aset, 2);
7420 rb_define_method(rb_cHash, "default", rb_hash_default, -1);
7421 rb_define_method(rb_cHash, "default=", rb_hash_set_default, 1);
7422 rb_define_method(rb_cHash, "default_proc", rb_hash_default_proc, 0);
7423 rb_define_method(rb_cHash, "default_proc=", rb_hash_set_default_proc, 1);
7424 rb_define_method(rb_cHash, "key", rb_hash_key, 1);
7425 rb_define_method(rb_cHash, "size", rb_hash_size, 0);
7426 rb_define_method(rb_cHash, "length", rb_hash_size, 0);
7427 rb_define_method(rb_cHash, "empty?", rb_hash_empty_p, 0);
7428
7429 rb_define_method(rb_cHash, "each_value", rb_hash_each_value, 0);
7430 rb_define_method(rb_cHash, "each_key", rb_hash_each_key, 0);
7431 rb_define_method(rb_cHash, "each_pair", rb_hash_each_pair, 0);
7432 rb_define_method(rb_cHash, "each", rb_hash_each_pair, 0);
7433
7434 rb_define_method(rb_cHash, "transform_keys", rb_hash_transform_keys, -1);
7435 rb_define_method(rb_cHash, "transform_keys!", rb_hash_transform_keys_bang, -1);
7436 rb_define_method(rb_cHash, "transform_values", rb_hash_transform_values, 0);
7437 rb_define_method(rb_cHash, "transform_values!", rb_hash_transform_values_bang, 0);
7438
7439 rb_define_method(rb_cHash, "keys", rb_hash_keys, 0);
7440 rb_define_method(rb_cHash, "values", rb_hash_values, 0);
7441 rb_define_method(rb_cHash, "values_at", rb_hash_values_at, -1);
7442 rb_define_method(rb_cHash, "fetch_values", rb_hash_fetch_values, -1);
7443
7444 rb_define_method(rb_cHash, "shift", rb_hash_shift, 0);
7445 rb_define_method(rb_cHash, "delete", rb_hash_delete_m, 1);
7446 rb_define_method(rb_cHash, "delete_if", rb_hash_delete_if, 0);
7447 rb_define_method(rb_cHash, "keep_if", rb_hash_keep_if, 0);
7448 rb_define_method(rb_cHash, "select", rb_hash_select, 0);
7449 rb_define_method(rb_cHash, "select!", rb_hash_select_bang, 0);
7450 rb_define_method(rb_cHash, "filter", rb_hash_select, 0);
7451 rb_define_method(rb_cHash, "filter!", rb_hash_select_bang, 0);
7452 rb_define_method(rb_cHash, "reject", rb_hash_reject, 0);
7453 rb_define_method(rb_cHash, "reject!", rb_hash_reject_bang, 0);
7454 rb_define_method(rb_cHash, "slice", rb_hash_slice, -1);
7455 rb_define_method(rb_cHash, "except", rb_hash_except, -1);
7456 rb_define_method(rb_cHash, "clear", rb_hash_clear, 0);
7457 rb_define_method(rb_cHash, "invert", rb_hash_invert, 0);
7458 rb_define_method(rb_cHash, "update", rb_hash_update, -1);
7459 rb_define_method(rb_cHash, "replace", rb_hash_replace, 1);
7460 rb_define_method(rb_cHash, "merge!", rb_hash_update, -1);
7461 rb_define_method(rb_cHash, "merge", rb_hash_merge, -1);
7462 rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
7463 rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
7464 rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);
7465 rb_define_method(rb_cHash, "compact", rb_hash_compact, 0);
7466 rb_define_method(rb_cHash, "compact!", rb_hash_compact_bang, 0);
7467
7468 rb_define_method(rb_cHash, "include?", rb_hash_has_key, 1);
7469 rb_define_method(rb_cHash, "member?", rb_hash_has_key, 1);
7470 rb_define_method(rb_cHash, "has_key?", rb_hash_has_key, 1);
7471 rb_define_method(rb_cHash, "has_value?", rb_hash_has_value, 1);
7472 rb_define_method(rb_cHash, "key?", rb_hash_has_key, 1);
7473 rb_define_method(rb_cHash, "value?", rb_hash_has_value, 1);
7474
7475 rb_define_method(rb_cHash, "compare_by_identity", rb_hash_compare_by_id, 0);
7476 rb_define_method(rb_cHash, "compare_by_identity?", rb_hash_compare_by_id_p, 0);
7477
7478 rb_define_method(rb_cHash, "any?", rb_hash_any_p, -1);
7479 rb_define_method(rb_cHash, "dig", rb_hash_dig, -1);
7480
7481 rb_define_method(rb_cHash, "<=", rb_hash_le, 1);
7482 rb_define_method(rb_cHash, "<", rb_hash_lt, 1);
7483 rb_define_method(rb_cHash, ">=", rb_hash_ge, 1);
7484 rb_define_method(rb_cHash, ">", rb_hash_gt, 1);
7485
7486 rb_define_method(rb_cHash, "deconstruct_keys", rb_hash_deconstruct_keys, 1);
7487
7488 rb_define_singleton_method(rb_cHash, "ruby2_keywords_hash?", rb_hash_s_ruby2_keywords_hash_p, 1);
7489 rb_define_singleton_method(rb_cHash, "ruby2_keywords_hash", rb_hash_s_ruby2_keywords_hash, 1);
7490
7491 rb_cHash_empty_frozen = rb_hash_freeze(rb_hash_alloc_fixed_size(rb_cHash, 0));
7492 RB_OBJ_SET_SHAREABLE(rb_cHash_empty_frozen);
7493 rb_vm_register_global_object(rb_cHash_empty_frozen);
7494
7495 /* Document-class: ENV
7496 *
7497 * +ENV+ is a hash-like accessor for environment variables.
7498 *
7499 * === Interaction with the Operating System
7500 *
7501 * The +ENV+ object interacts with the operating system's environment variables:
7502 *
7503 * - When you get the value for a name in +ENV+, the value is retrieved from among the current environment variables.
7504 * - When you create or set a name-value pair in +ENV+, the name and value are immediately set in the environment variables.
7505 * - When you delete a name-value pair in +ENV+, it is immediately deleted from the environment variables.
7506 *
7507 * === Names and Values
7508 *
7509 * Generally, a name or value is a String.
7510 *
7511 * ==== Valid Names and Values
7512 *
7513 * Each name or value must be one of the following:
7514 *
7515 * - A String.
7516 * - An object that responds to \#to_str by returning a String, in which case that String will be used as the name or value.
7517 *
7518 * ==== Invalid Names and Values
7519 *
7520 * A new name:
7521 *
7522 * - May not be the empty string:
7523 * ENV[''] = '0'
7524 * # Raises Errno::EINVAL (Invalid argument - ruby_setenv())
7525 *
7526 * - May not contain character <code>"="</code>:
7527 * ENV['='] = '0'
7528 * # Raises Errno::EINVAL (Invalid argument - ruby_setenv(=))
7529 *
7530 * A new name or value:
7531 *
7532 * - May not be a non-String that does not respond to \#to_str:
7533 *
7534 * ENV['foo'] = Object.new
7535 * # Raises TypeError (no implicit conversion of Object into String)
7536 * ENV[Object.new] = '0'
7537 * # Raises TypeError (no implicit conversion of Object into String)
7538 *
7539 * - May not contain the NUL character <code>"\0"</code>:
7540 *
7541 * ENV['foo'] = "\0"
7542 * # Raises ArgumentError (bad environment variable value: contains null byte)
7543 * ENV["\0"] == '0'
7544 * # Raises ArgumentError (bad environment variable name: contains null byte)
7545 *
7546 * - May not have an ASCII-incompatible encoding such as UTF-16LE or ISO-2022-JP:
7547 *
7548 * ENV['foo'] = '0'.force_encoding(Encoding::ISO_2022_JP)
7549 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: ISO-2022-JP)
7550 * ENV["foo".force_encoding(Encoding::ISO_2022_JP)] = '0'
7551 * # Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: ISO-2022-JP)
7552 *
7553 * === About Ordering
7554 *
7555 * +ENV+ enumerates its name/value pairs in the order found
7556 * in the operating system's environment variables.
7557 * Therefore the ordering of +ENV+ content is OS-dependent, and may be indeterminate.
7558 *
7559 * This will be seen in:
7560 * - A Hash returned by an +ENV+ method.
7561 * - An Enumerator returned by an +ENV+ method.
7562 * - An Array returned by ENV.keys, ENV.values, or ENV.to_a.
7563 * - The String returned by ENV.inspect.
7564 * - The Array returned by ENV.shift.
7565 * - The name returned by ENV.key.
7566 *
7567 * === About the Examples
7568 * Some methods in +ENV+ return +ENV+ itself. Typically, there are many environment variables.
7569 * It's not useful to display a large +ENV+ in the examples here,
7570 * so most example snippets begin by resetting the contents of +ENV+:
7571 * - ENV.replace replaces +ENV+ with a new collection of entries.
7572 * - ENV.clear empties +ENV+.
7573 *
7574 * === What's Here
7575 *
7576 * First, what's elsewhere. Class +ENV+:
7577 *
7578 * - Inherits from {class Object}[rdoc-ref:Object@Whats+Here].
7579 * - Extends {module Enumerable}[rdoc-ref:Enumerable@Whats+Here],
7580 *
7581 * Here, class +ENV+ provides methods that are useful for:
7582 *
7583 * - {Querying}[rdoc-ref:ENV@Methods+for+Querying]
7584 * - {Assigning}[rdoc-ref:ENV@Methods+for+Assigning]
7585 * - {Deleting}[rdoc-ref:ENV@Methods+for+Deleting]
7586 * - {Iterating}[rdoc-ref:ENV@Methods+for+Iterating]
7587 * - {Converting}[rdoc-ref:ENV@Methods+for+Converting]
7588 * - {And more ....}[rdoc-ref:ENV@More+Methods]
7589 *
7590 * ==== Methods for Querying
7591 *
7592 * - ::[]: Returns the value for the given environment variable name if it exists:
7593 * - ::empty?: Returns whether +ENV+ is empty.
7594 * - ::has_value?, ::value?: Returns whether the given value is in +ENV+.
7595 * - ::include?, ::has_key?, ::key?, ::member?: Returns whether the given name
7596 is in +ENV+.
7597 * - ::key: Returns the name of the first entry with the given value.
7598 * - ::size, ::length: Returns the number of entries.
7599 * - ::value?: Returns whether any entry has the given value.
7600 *
7601 * ==== Methods for Assigning
7602 *
7603 * - ::[]=, ::store: Creates, updates, or deletes the named environment variable.
7604 * - ::clear: Removes every environment variable; returns +ENV+:
7605 * - ::update, ::merge!: Adds to +ENV+ each key/value pair in the given hash.
7606 * - ::replace: Replaces the entire content of the +ENV+
7607 * with the name/value pairs in the given hash.
7608 *
7609 * ==== Methods for Deleting
7610 *
7611 * - ::delete: Deletes the named environment variable name if it exists.
7612 * - ::delete_if: Deletes entries selected by the block.
7613 * - ::keep_if: Deletes entries not selected by the block.
7614 * - ::reject!: Similar to #delete_if, but returns +nil+ if no change was made.
7615 * - ::select!, ::filter!: Deletes entries selected by the block.
7616 * - ::shift: Removes and returns the first entry.
7617 *
7618 * ==== Methods for Iterating
7619 *
7620 * - ::each, ::each_pair: Calls the block with each name/value pair.
7621 * - ::each_key: Calls the block with each name.
7622 * - ::each_value: Calls the block with each value.
7623 *
7624 * ==== Methods for Converting
7625 *
7626 * - ::assoc: Returns a 2-element array containing the name and value
7627 * of the named environment variable if it exists:
7628 * - ::clone: Raises an exception.
7629 * - ::except: Returns a hash of all name/value pairs except those given.
7630 * - ::fetch: Returns the value for the given name.
7631 * - ::fetch_values: Returns array containing the values associated with given names.
7632 * - ::inspect: Returns the contents of +ENV+ as a string.
7633 * - ::invert: Returns a hash whose keys are the +ENV+ values,
7634 and whose values are the corresponding +ENV+ names.
7635 * - ::keys: Returns an array of all names.
7636 * - ::rassoc: Returns the name and value of the first found entry
7637 * that has the given value.
7638 * - ::reject: Returns a hash of those entries not rejected by the block.
7639 * - ::select, ::filter: Returns a hash of name/value pairs selected by the block.
7640 * - ::slice: Returns a hash of the given names and their corresponding values.
7641 * - ::to_a: Returns the entries as an array of 2-element Arrays.
7642 * - ::to_h: Returns a hash of entries selected by the block.
7643 * - ::to_hash: Returns a hash of all entries.
7644 * - ::to_s: Returns the string <tt>'ENV'</tt>.
7645 * - ::values: Returns all values as an array.
7646 * - ::values_at: Returns an array of the values for the given name.
7647 *
7648 * ==== More Methods
7649 *
7650 * - ::dup: Raises an exception.
7651 * - ::freeze: Raises an exception.
7652 * - ::rehash: Returns +nil+, without modifying +ENV+.
7653 *
7654 */
7655
7656 /*
7657 * Hack to get RDoc to regard ENV as a class:
7658 * envtbl = rb_define_class("ENV", rb_cObject);
7659 */
7660 origenviron = environ;
7661 envtbl = TypedData_Wrap_Struct(rb_cObject, &env_data_type, NULL);
7663 RB_OBJ_SET_SHAREABLE(envtbl);
7664
7665 rb_define_singleton_method(envtbl, "[]", rb_f_getenv, 1);
7666 rb_define_singleton_method(envtbl, "fetch", env_fetch, -1);
7667 rb_define_singleton_method(envtbl, "fetch_values", env_fetch_values, -1);
7668 rb_define_singleton_method(envtbl, "[]=", env_aset_m, 2);
7669 rb_define_singleton_method(envtbl, "store", env_aset_m, 2);
7670 rb_define_singleton_method(envtbl, "each", env_each_pair, 0);
7671 rb_define_singleton_method(envtbl, "each_pair", env_each_pair, 0);
7672 rb_define_singleton_method(envtbl, "each_key", env_each_key, 0);
7673 rb_define_singleton_method(envtbl, "each_value", env_each_value, 0);
7674 rb_define_singleton_method(envtbl, "delete", env_delete_m, 1);
7675 rb_define_singleton_method(envtbl, "delete_if", env_delete_if, 0);
7676 rb_define_singleton_method(envtbl, "keep_if", env_keep_if, 0);
7677 rb_define_singleton_method(envtbl, "slice", env_slice, -1);
7678 rb_define_singleton_method(envtbl, "except", env_except, -1);
7679 rb_define_singleton_method(envtbl, "clear", env_clear, 0);
7680 rb_define_singleton_method(envtbl, "reject", env_reject, 0);
7681 rb_define_singleton_method(envtbl, "reject!", env_reject_bang, 0);
7682 rb_define_singleton_method(envtbl, "select", env_select, 0);
7683 rb_define_singleton_method(envtbl, "select!", env_select_bang, 0);
7684 rb_define_singleton_method(envtbl, "filter", env_select, 0);
7685 rb_define_singleton_method(envtbl, "filter!", env_select_bang, 0);
7686 rb_define_singleton_method(envtbl, "shift", env_shift, 0);
7687 rb_define_singleton_method(envtbl, "freeze", env_freeze, 0);
7688 rb_define_singleton_method(envtbl, "invert", env_invert, 0);
7689 rb_define_singleton_method(envtbl, "replace", env_replace, 1);
7690 rb_define_singleton_method(envtbl, "update", env_update, -1);
7691 rb_define_singleton_method(envtbl, "merge!", env_update, -1);
7692 rb_define_singleton_method(envtbl, "inspect", env_inspect, 0);
7693 rb_define_singleton_method(envtbl, "rehash", env_none, 0);
7694 rb_define_singleton_method(envtbl, "to_a", env_to_a, 0);
7695 rb_define_singleton_method(envtbl, "to_s", env_to_s, 0);
7696 rb_define_singleton_method(envtbl, "key", env_key, 1);
7697 rb_define_singleton_method(envtbl, "size", env_size, 0);
7698 rb_define_singleton_method(envtbl, "length", env_size, 0);
7699 rb_define_singleton_method(envtbl, "empty?", env_empty_p, 0);
7700 rb_define_singleton_method(envtbl, "keys", env_f_keys, 0);
7701 rb_define_singleton_method(envtbl, "values", env_f_values, 0);
7702 rb_define_singleton_method(envtbl, "values_at", env_values_at, -1);
7703 rb_define_singleton_method(envtbl, "include?", env_has_key, 1);
7704 rb_define_singleton_method(envtbl, "member?", env_has_key, 1);
7705 rb_define_singleton_method(envtbl, "has_key?", env_has_key, 1);
7706 rb_define_singleton_method(envtbl, "has_value?", env_has_value, 1);
7707 rb_define_singleton_method(envtbl, "key?", env_has_key, 1);
7708 rb_define_singleton_method(envtbl, "value?", env_has_value, 1);
7709 rb_define_singleton_method(envtbl, "to_hash", env_f_to_hash, 0);
7710 rb_define_singleton_method(envtbl, "to_h", env_to_h, 0);
7711 rb_define_singleton_method(envtbl, "assoc", env_assoc, 1);
7712 rb_define_singleton_method(envtbl, "rassoc", env_rassoc, 1);
7713 rb_define_singleton_method(envtbl, "clone", env_clone, -1);
7714 rb_define_singleton_method(envtbl, "dup", env_dup, 0);
7715
7716 VALUE envtbl_class = rb_singleton_class(envtbl);
7717 rb_undef_method(envtbl_class, "initialize");
7718 rb_undef_method(envtbl_class, "initialize_clone");
7719 rb_undef_method(envtbl_class, "initialize_copy");
7720 rb_undef_method(envtbl_class, "initialize_dup");
7721
7722 /*
7723 * +ENV+ is a Hash-like accessor for environment variables.
7724 *
7725 * See ENV (the class) for more details.
7726 */
7727 rb_define_global_const("ENV", envtbl);
7728
7729 HASH_ASSERT(sizeof(ar_hint_t) * RHASH_AR_TABLE_MAX_SIZE == sizeof(VALUE));
7730}
7731
7732#include "hash.rbinc"
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
static bool RB_OBJ_FROZEN(VALUE obj)
Checks if an object is frozen.
Definition fl_type.h:711
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
Definition class.c:1603
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition class.c:1396
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition eval.c:1868
VALUE rb_singleton_class(VALUE obj)
Finds or creates the singleton class of the passed object.
Definition class.c:2728
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition class.c:2771
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
Definition class.c:2581
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition class.c:3061
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1018
#define TYPE(_)
Old name of rb_type.
Definition value_type.h:108
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1683
#define NUM2LL
Old name of RB_NUM2LL.
Definition long_long.h:34
#define REALLOC_N
Old name of RB_REALLOC_N.
Definition memory.h:403
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define xfree
Old name of ruby_xfree.
Definition xmalloc.h:58
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
#define T_NIL
Old name of RUBY_T_NIL.
Definition value_type.h:72
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition value_type.h:64
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition value_type.h:57
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
Definition string.h:1680
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition value_type.h:63
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
#define T_DATA
Old name of RUBY_T_DATA.
Definition value_type.h:60
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:205
#define LONG2FIX
Old name of RB_INT2FIX.
Definition long.h:49
#define STATIC_SYM_P
Old name of RB_STATIC_SYM_P.
#define T_TRUE
Old name of RUBY_T_TRUE.
Definition value_type.h:81
#define T_HASH
Old name of RUBY_T_HASH.
Definition value_type.h:65
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition memory.h:399
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:128
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1681
#define T_FALSE
Old name of RUBY_T_FALSE.
Definition value_type.h:61
#define FIXNUM_MIN
Old name of RUBY_FIXNUM_MIN.
Definition fixnum.h:27
#define FLONUM_P
Old name of RB_FLONUM_P.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
Definition st_data_t.h:33
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
Definition fixnum.h:26
#define NUM2INT
Old name of RB_NUM2INT.
Definition int.h:44
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition long.h:46
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:405
#define POSFIXABLE
Old name of RB_POSFIXABLE.
Definition fixnum.h:29
#define T_SYMBOL
Old name of RUBY_T_SYMBOL.
Definition value_type.h:80
#define FL_TEST
Old name of RB_FL_TEST.
Definition fl_type.h:127
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define OBJ_WB_UNPROTECT
Old name of RB_OBJ_WB_UNPROTECT.
Definition gc.h:474
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition array.h:657
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:126
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition memory.h:406
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition value_type.h:88
void rb_syserr_fail_str(int e, VALUE mesg)
Identical to rb_syserr_fail(), except it takes the message in Ruby's String instead of C's.
Definition error.c:3973
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1427
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1425
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:467
VALUE rb_mKernel
Kernel module.
Definition object.c:60
VALUE rb_cObject
Object class.
Definition object.c:61
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
Definition object.c:646
VALUE rb_mEnumerable
Enumerable module.
Definition enum.c:27
int rb_eql(VALUE lhs, VALUE rhs)
Checks for equality of the passed objects, in terms of Object#eql?.
Definition object.c:154
VALUE rb_cHash
Hash class.
Definition hash.c:109
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:235
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition object.c:657
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:141
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition object.c:1313
VALUE rb_cString
String class.
Definition string.c:81
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition object.c:3335
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition gc.h:468
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:456
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *enc)
Identical to rb_external_str_new(), except it additionally takes an encoding.
Definition string.c:1350
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1121
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_delete_at(VALUE ary, long pos)
Destructively removes an element which resides at the specific index of the passed array.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
#define INTEGER_PACK_NATIVE_BYTE_ORDER
Means either INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST, depending on the host processor'...
Definition bignum.h:550
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition enumerator.h:208
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:284
VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value)
Type of callback functions to pass to rb_hash_update_by().
Definition hash.h:269
#define st_foreach_safe
Just another name of rb_st_foreach_safe.
Definition hash.h:51
VALUE rb_proc_lambda_p(VALUE recv)
Queries if the given object is a lambda.
Definition proc.c:247
VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc)
Identical to rb_proc_call(), except you can additionally pass another proc object,...
Definition proc.c:1174
int rb_proc_arity(VALUE recv)
Queries the number of mandatory arguments of the given Proc.
Definition proc.c:1281
VALUE rb_obj_is_proc(VALUE recv)
Queries if the given object is a proc.
Definition proc.c:122
#define rb_hash_uint(h, i)
Just another name of st_hash_uint.
Definition string.h:943
#define rb_hash_end(h)
Just another name of st_hash_end.
Definition string.h:946
int rb_str_hash_cmp(VALUE str1, VALUE str2)
Compares two strings.
Definition string.c:4199
VALUE rb_str_ellipsize(VALUE str, long len)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
Definition string.c:11699
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
Definition random.c:1791
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
Definition string.h:1499
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
Definition string.c:1520
st_index_t rb_str_hash(VALUE str)
Calculates a hash value of a string.
Definition string.c:4185
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
Definition string.c:3802
st_index_t rb_hash_start(st_index_t i)
Starts a series of hashing.
Definition random.c:1785
VALUE rb_str_inspect(VALUE str)
Generates a "readable" version of the receiver.
Definition string.c:7267
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src)
Identical to rb_str_cat_cstr(), except it additionally assumes the source string be a NUL terminated ...
Definition string.c:3778
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:2976
#define rb_utf8_str_new(str, len)
Identical to rb_str_new, except it generates a string of "UTF-8" encoding.
Definition string.h:1550
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
VALUE rb_exec_recursive_paired(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h)
Identical to rb_exec_recursive(), except it checks for the recursion on the ordered pair of { g,...
VALUE rb_ivar_get(VALUE obj, ID name)
Identical to rb_iv_get(), except it accepts the name as an ID instead of a C string.
Definition variable.c:1515
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition vm_method.c:3485
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition symbol.h:285
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
Definition symbol.c:1024
void rb_define_global_const(const char *name, VALUE val)
Identical to rb_define_const(), except it defines that of "global", i.e.
Definition variable.c:4125
int capa
Designed capacity of the buffer.
Definition io.h:11
int len
Length of the buffer.
Definition io.h:8
char * ruby_strdup(const char *str)
This is our own version of strdup(3) that uses ruby_xmalloc() instead of system malloc (benefits our ...
Definition util.c:515
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition iterator.h:58
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
Definition vm_eval.c:1399
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
Definition vm_eval.c:1421
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1376
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:167
VALUE type(ANYARGS)
ANYARGS-ed function type.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
void rb_copy_generic_ivar(VALUE clone, VALUE obj)
Copies the list of instance variables.
Definition variable.c:2275
#define RARRAY_LEN
Just another name of rb_array_len.
Definition rarray.h:51
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
Definition rarray.h:348
#define RARRAY_AREF(a, i)
Definition rarray.h:403
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
Definition rbasic.h:166
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
#define RHASH_SET_IFNONE(h, ifnone)
Destructively updates the default value of the hash.
Definition rhash.h:92
#define RHASH_IFNONE(h)
Definition rhash.h:59
#define RHASH_SIZE(h)
Queries the size of the hash.
Definition rhash.h:69
#define RHASH_EMPTY_P(h)
Checks if the hash is empty.
Definition rhash.h:79
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
Definition rstring.h:409
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
Definition rstring.h:450
#define RUBY_TYPED_FREE_IMMEDIATELY
Macros to see if each corresponding flag is defined.
Definition rtypeddata.h:122
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
Definition rtypeddata.h:531
const char * rb_obj_classname(VALUE obj)
Queries the name of the class of the passed object.
Definition variable.c:515
@ RUBY_SPECIAL_SHIFT
Least significant 8 bits are reserved.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
VALUE flags
Per-object flags.
Definition rbasic.h:81
Definition hash.h:53
Definition method.h:63
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:229
Definition st.h:79
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition value.h:63
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition value_type.h:433
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376