19# ifdef HAVE_CRT_EXTERNS_H
33#include "internal/error.h"
37#include "internal/symbol.h"
55#define HAS_EXTRA_STATES(hash, klass) ( \
56 ((klass = has_extra_methods(rb_obj_class(hash))) != 0) || \
57 FL_TEST((hash), FL_EXIVAR|RHASH_PROC_DEFAULT) || \
58 !NIL_P(RHASH_IFNONE(hash)))
60#define SET_DEFAULT(hash, ifnone) ( \
61 FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \
62 RHASH_SET_IFNONE(hash, ifnone))
64#define SET_PROC_DEFAULT(hash, proc) set_proc_default(hash, proc)
66#define COPY_DEFAULT(hash, hash2) copy_default(RHASH(hash), RHASH(hash2))
69copy_default(
struct RHash *hash,
const struct RHash *hash2)
77has_extra_methods(
VALUE klass)
109static ID id_hash, id_default, id_flatten_bang;
110static ID id_hash_iter_lev;
122 if (a == b)
return 0;
136hash_recursive(
VALUE obj,
VALUE arg,
int recurse)
138 if (recurse)
return INT2FIX(0);
172dbl_to_index(
double d)
183 if (d == 0.0) d = 0.0;
184#if SIZEOF_INT == SIZEOF_VOIDP
187 return rb_objid_hash(dbl_to_index(d));
224 hnum = other_func(a);
234obj_any_hash(
VALUE obj)
243 return any_hash(a, obj_any_hash);
252static const uint32_t prime2 = 0x830fcab9;
258#if defined HAVE_UINT128_T
259 uint128_t r = (uint128_t) m1 * (uint128_t) m2;
262 uint64_t hm1 = m1 >> 32, hm2 = m2 >> 32;
265 uint64_t v32_96 = hm1 * lm2 + lm1 * hm2;
268 return (v64_128 + (v32_96 >> 32)) ^ ((v32_96 << 32) + v1_32);
275 return mult_and_mix(
key + seed, prime1);
279#define st_index_hash(index) key64_hash(rb_hash_start(index), prime2)
294#if SIZEOF_LONG == SIZEOF_VOIDP
296#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
307 long hnum = any_hash(obj, objid_hash);
316#define rb_ident_cmp st_numcmp
335#define identhash rb_hashtype_ident
353#define RHASH_AR_TABLE_MAX_BOUND RHASH_AR_TABLE_MAX_SIZE
355#define RHASH_AR_TABLE_REF(hash, n) (&RHASH_AR_TABLE(hash)->pairs[n])
356#define RHASH_AR_CLEARED_HINT 0xff
387ar_hint(
VALUE hash,
unsigned int index)
389 return RHASH(hash)->ar_hint.ary[index];
395 RHASH(hash)->ar_hint.ary[index] = hint;
401 ar_hint_set_hint(hash, index, ar_do_hash_hint(hash_value));
405ar_clear_entry(
VALUE hash,
unsigned int index)
413ar_cleared_entry(
VALUE hash,
unsigned int index)
433 ar_hint_set(hash, index, hash_value);
436#define RHASH_AR_TABLE_SIZE(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
437 RHASH_AR_TABLE_SIZE_RAW(h))
439#define RHASH_AR_TABLE_BOUND_RAW(h) \
440 ((unsigned int)((RBASIC(h)->flags >> RHASH_AR_TABLE_BOUND_SHIFT) & \
441 (RHASH_AR_TABLE_BOUND_MASK >> RHASH_AR_TABLE_BOUND_SHIFT)))
443#define RHASH_AR_TABLE_BOUND(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
444 RHASH_AR_TABLE_BOUND_RAW(h))
446#define RHASH_ST_TABLE_SET(h, s) rb_hash_st_table_set(h, s)
447#define RHASH_TYPE(hash) (RHASH_AR_TABLE_P(hash) ? &objhash : RHASH_ST_TABLE(hash)->type)
449#define HASH_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(HASH_DEBUG, expr, #expr)
452#define hash_verify(hash) hash_verify_(hash, __FILE__, __LINE__)
455rb_hash_dump(
VALUE hash)
459 if (RHASH_AR_TABLE_P(hash)) {
462 fprintf(stderr,
" size:%u bound:%u\n",
465 for (i=0; i<bound; i++) {
468 if (!ar_cleared_entry(hash, i)) {
469 char b1[0x100], b2[0x100];
473 fprintf(stderr,
" %d key:%s val:%s hint:%02x\n", i,
480 fprintf(stderr,
" %d empty\n", i);
487hash_verify_(
VALUE hash,
const char *
file,
int line)
491 if (RHASH_AR_TABLE_P(hash)) {
494 for (i=0; i<bound; i++) {
496 if (!ar_cleared_entry(hash, i)) {
515#if USE_TRANSIENT_HEAP
516 if (RHASH_TRANSIENT_P(hash)) {
519 HASH_ASSERT(rb_transient_heap_managed_ptr_p(RHASH_AR_TABLE(hash)));
526#define hash_verify(h) ((void)0)
530RHASH_TABLE_NULL_P(
VALUE hash)
542RHASH_TABLE_EMPTY_P(
VALUE hash)
563 return RHASH(hash)->as.ar;
570 return RHASH(hash)->as.st;
578 RHASH(hash)->as.st = st;
586 RHASH(hash)->as.ar = ar;
590#define RHASH_SET_ST_FLAG(h) FL_SET_RAW(h, RHASH_ST_TABLE_FLAG)
591#define RHASH_UNSET_ST_FLAG(h) FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG)
599 RBASIC(h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
609 RBASIC(h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
623#define RHASH_AR_TABLE_SIZE_INC(h) HASH_AR_TABLE_SIZE_ADD(h, 1)
626RHASH_AR_TABLE_SIZE_DEC(
VALUE h)
632 RHASH_AR_TABLE_SIZE_SET(h, new_size);
635 RHASH_AR_TABLE_SIZE_SET(h, 0);
636 RHASH_AR_TABLE_BOUND_SET(h, 0);
642RHASH_AR_TABLE_CLEAR(
VALUE h)
644 RBASIC(h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
645 RBASIC(h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
647 hash_ar_table_set(h,
NULL);
651ar_alloc_table(
VALUE hash)
656 RHASH_SET_TRANSIENT_FLAG(hash);
659 RHASH_UNSET_TRANSIENT_FLAG(hash);
663 RHASH_AR_TABLE_SIZE_SET(hash, 0);
664 RHASH_AR_TABLE_BOUND_SET(hash, 0);
665 hash_ar_table_set(hash,
tab);
675 return rb_any_cmp(x, y) == 0;
686 for (i = 0; i < bound; i++) {
687 if (hints[i] == hint) {
689 if (ar_equal(
key, pair->
key)) {
696 static char fname[256];
699 if (pid != getpid()) {
700 snprintf(fname,
sizeof(fname),
"/tmp/ruby-armiss.%d", pid = getpid());
701 if ((fp = fopen(fname,
"w")) ==
NULL)
rb_bug(
"fopen");
707 fprintf(fp,
"miss: hash_eq:%d hints[%d]:%02x hint:%02x\n"
709 " pair->key:%016lx %s\n",
710 h1 == h2, i, hints[i], hint,
724 ar_hint_t hint = ar_do_hash_hint(hash_value);
725 return ar_find_entry_hint(hash, hint,
key);
729ar_free_and_clear_table(
VALUE hash)
734 if (RHASH_TRANSIENT_P(hash)) {
735 RHASH_UNSET_TRANSIENT_FLAG(hash);
740 RHASH_AR_TABLE_CLEAR(hash);
748ar_try_convert_table(
VALUE hash)
750 if (!RHASH_AR_TABLE_P(hash))
return;
767 ar_free_and_clear_table(hash);
773ar_force_convert_table(
VALUE hash,
const char *
file,
int line)
777 if (RHASH_ST_TABLE_P(hash)) {
778 return RHASH_ST_TABLE(hash);
781 if (RHASH_AR_TABLE(hash)) {
784#if RHASH_CONVERT_TABLE_DEBUG
786 fprintf(stderr,
"force_convert: %s:%d\n",
file, line);
792 for (i = 0; i < bound; i++) {
793 if (ar_cleared_entry(hash, i))
continue;
798 ar_free_and_clear_table(hash);
809hash_ar_table(
VALUE hash)
811 if (RHASH_TABLE_NULL_P(hash)) {
812 ar_alloc_table(hash);
814 return RHASH_AR_TABLE(hash);
818ar_compact_table(
VALUE hash)
830 for (i=0; i<bound; i++) {
831 if (ar_cleared_entry(hash, i)) {
833 for (; j<bound; j++) {
834 if (!ar_cleared_entry(hash, j)) {
836 ar_hint_set_hint(hash, i, (
st_hash_t)ar_hint(hash, j));
837 ar_clear_entry(hash, j);
850 RHASH_AR_TABLE_BOUND_SET(hash,
size);
866 bin = ar_compact_table(hash);
871 ar_set_entry(hash,
bin,
key, val, hash_value);
872 RHASH_AR_TABLE_BOUND_SET(hash,
bin+1);
884 for (i = 0; i < bound; i++) {
885 if (ar_cleared_entry(hash, i))
continue;
901 retval = (*replace)(&
key, &val, arg,
TRUE);
910 ar_clear_entry(hash, i);
911 RHASH_AR_TABLE_SIZE_DEC(hash);
922 return ar_general_foreach(hash, func, replace, arg);
933 const struct functor *
f = (
void *)d;
934 return f->func(k, v,
f->arg);
941 return ar_general_foreach(hash, apply_functor,
NULL, (
st_data_t)&
f);
955 for (i = 0; i < bound; i++) {
956 if (ar_cleared_entry(hash, i))
continue;
960 hint = ar_hint(hash, i);
962 retval = (*func)(
key, pair->
val,
arg, 0);
968 if (pair->
key == never)
break;
969 ret = ar_find_entry_hint(hash, hint,
key);
971 retval = (*func)(0, 0,
arg, 1);
981 if (!ar_cleared_entry(hash, i)) {
982 ar_clear_entry(hash, i);
983 RHASH_AR_TABLE_SIZE_DEC(hash);
997 int retval, existing;
1002 if (
UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
1008 bin = ar_find_entry(hash, hash_value,
key);
1012 hash_ar_table(hash);
1022 retval = (*func)(&
key, &value,
arg, existing);
1028 if (ar_add_direct_with_hash(hash,
key, value, hash_value)) {
1034 if (old_key !=
key) {
1042 ar_clear_entry(hash,
bin);
1043 RHASH_AR_TABLE_SIZE_DEC(hash);
1056 if (
UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
1061 hash_ar_table(hash);
1063 bin = ar_find_entry(hash, hash_value,
key);
1069 bin = ar_compact_table(hash);
1070 hash_ar_table(hash);
1074 ar_set_entry(hash,
bin,
key, value, hash_value);
1075 RHASH_AR_TABLE_BOUND_SET(hash,
bin+1);
1093 if (
UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
1097 unsigned bin = ar_find_entry(hash, hash_value,
key);
1104 if (value !=
NULL) {
1118 if (
UNLIKELY(!RHASH_AR_TABLE_P(hash))) {
1123 bin = ar_find_entry(hash, hash_value, *
key);
1126 if (value != 0) *value = 0;
1134 ar_clear_entry(hash,
bin);
1135 RHASH_AR_TABLE_SIZE_DEC(hash);
1146 for (i = 0; i < bound; i++) {
1147 if (!ar_cleared_entry(hash, i)) {
1149 if (value != 0) *value = pair->
val;
1151 ar_clear_entry(hash, i);
1152 RHASH_AR_TABLE_SIZE_DEC(hash);
1157 if (value !=
NULL) *value = 0;
1167 for (i = 0; i < bound; i++) {
1168 if (keys == keys_end) {
1172 if (!ar_cleared_entry(hash, i)) {
1178 return keys - keys_start;
1185 st_data_t *values_start = values, *values_end = values +
size;
1187 for (i = 0; i < bound; i++) {
1188 if (values == values_end) {
1192 if (!ar_cleared_entry(hash, i)) {
1198 return values - values_start;
1204 ar_table *old_tab = RHASH_AR_TABLE(hash2);
1206 if (old_tab !=
NULL) {
1207 ar_table *new_tab = RHASH_AR_TABLE(hash1);
1208 if (new_tab ==
NULL) {
1210 if (new_tab !=
NULL) {
1211 RHASH_SET_TRANSIENT_FLAG(hash1);
1214 RHASH_UNSET_TRANSIENT_FLAG(hash1);
1218 *new_tab = *old_tab;
1219 RHASH(hash1)->ar_hint.word =
RHASH(hash2)->ar_hint.word;
1222 hash_ar_table_set(hash1, new_tab);
1231 if (RHASH_TRANSIENT_P(hash1)) {
1232 RHASH_UNSET_TRANSIENT_FLAG(hash1);
1234 else if (RHASH_AR_TABLE(hash1)) {
1238 hash_ar_table_set(hash1,
NULL);
1248 if (RHASH_AR_TABLE(hash) !=
NULL) {
1249 RHASH_AR_TABLE_SIZE_SET(hash, 0);
1250 RHASH_AR_TABLE_BOUND_SET(hash, 0);
1258#if USE_TRANSIENT_HEAP
1262 if (RHASH_TRANSIENT_P(hash)) {
1264 ar_table *old_tab = RHASH_AR_TABLE(hash);
1273 if (new_tab ==
NULL) promote =
true;
1277 RHASH_UNSET_TRANSIENT_FLAG(hash);
1279 *new_tab = *old_tab;
1280 hash_ar_table_set(hash, new_tab);
1301 status = (*
arg->func)(
key, value,
arg->arg);
1358 tbl = RHASH_ST_TABLE(
arg->hash);
1360 if (RHASH_ST_TABLE(
arg->hash) != tbl) {
1385iter_lev_in_ivar_set(
VALUE hash,
int lev)
1400 int lev = iter_lev_in_flags(
hash);
1403 return iter_lev_in_ivar(
hash);
1413 int lev = iter_lev_in_flags(
hash);
1415 lev = iter_lev_in_ivar(
hash);
1416 iter_lev_in_ivar_set(
hash, lev+1);
1422 iter_lev_in_ivar_set(
hash, lev);
1430 int lev = iter_lev_in_flags(
hash);
1432 lev = iter_lev_in_ivar(
hash);
1434 iter_lev_in_ivar_set(
hash, lev-1);
1445 hash_iter_lev_inc(
hash);
1452 hash_iter_lev_dec(
hash);
1459 if (RHASH_AR_TABLE_P(
hash)) {
1470 if (RHASH_AR_TABLE_P(
hash)) {
1471 return ar_foreach_with_replace(
hash,
func, replace,
arg);
1483 if (RHASH_AR_TABLE_P(
hash)) {
1484 ret = ar_foreach_check(
hash, hash_ar_foreach_iter,
1487 else if (RHASH_ST_TABLE_P(
hash)) {
1502 if (RHASH_TABLE_EMPTY_P(
hash))
1504 hash_iter_lev_inc(
hash);
1524hash_alloc(
VALUE klass)
1526 return hash_alloc_flags(klass, 0,
Qnil);
1530empty_hash_alloc(
VALUE klass)
1534 return hash_alloc(klass);
1551 ar_alloc_table(ret);
1563 if (RHASH_AR_TABLE_P(
hash))
1565 else if (RHASH_ST_TABLE_P(
hash))
1605 return ar_force_convert_table(hash,
file, line);
1616rb_hash_modify(
VALUE hash)
1618 rb_hash_modify_check(hash);
1621NORETURN(
static void no_new_key(
void));
1633#define NOINSERT_UPDATE_CALLBACK(func) \
1635func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1637 if (!existing) no_new_key(); \
1638 return func(key, val, (struct update_arg *)arg, existing); \
1642func##_insert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1644 return func(key, val, (struct update_arg *)arg, existing); \
1661 if (RHASH_AR_TABLE_P(hash)) {
1662 int result = ar_update(hash, (
st_data_t)
key, func, arg);
1664 ar_try_convert_table(hash);
1680 arg.arg = optional_arg;
1696#define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func##_insert)
1698#define RHASH_UPDATE_ITER(h, iter_lev, key, func, a) do { \
1699 tbl_update((h), (key), UPDATE_CALLBACK((iter_lev), func), (st_data_t)(a)); \
1702#define RHASH_UPDATE(hash, key, func, arg) \
1703 RHASH_UPDATE_ITER(hash, RHASH_ITER_LEV(hash), key, func, arg)
1711 if (n != 2 && (n >= 0 || n < -3)) {
1712 if (n < 0) n = -n-1;
1757 rb_hash_modify(
hash);
1807 tmp = rb_hash_s_try_convert(
Qnil,
argv[0]);
1809 hash = hash_alloc(klass);
1810 hash_copy(
hash, tmp);
1818 hash = hash_alloc(klass);
1842 if (
argc % 2 != 0) {
1846 hash = hash_alloc(klass);
1857#define to_hash rb_to_hash_type
1938 if (RHASH_AR_TABLE_P(arg)) {
1968 rb_hash_modify_check(hash);
1969 if (RHASH_AR_TABLE_P(hash)) {
1970 tmp = hash_alloc(0);
1971 ar_alloc_table(tmp);
1973 ar_free_and_clear_table(hash);
1975 ar_free_and_clear_table(tmp);
1977 else if (RHASH_ST_TABLE_P(hash)) {
1978 st_table *old_tab = RHASH_ST_TABLE(hash);
1979 tmp = hash_alloc(0);
1985 RHASH_ST_CLEAR(tmp);
2005 return call_default_proc(ifnone, hash,
key);
2017 if (RHASH_AR_TABLE_P(hash)) {
2018 return ar_lookup(hash,
key, pval);
2028 return hash_stlike_lookup(hash,
key, pval);
2050 if (hash_stlike_lookup(hash,
key, &val)) {
2063 if (hash_stlike_lookup(hash,
key, &val)) {
2112 if (block_given &&
argc == 2) {
2113 rb_warn(
"block supersedes default value argument");
2116 if (hash_stlike_lookup(hash,
key, &val)) {
2123 else if (
argc == 1) {
2140 return rb_hash_fetch_m(1, &
key, hash);
2172 return call_default_proc(ifnone, hash,
argv[0]);
2193 rb_hash_modify_check(hash);
2211rb_hash_default_proc(
VALUE hash)
2238 rb_hash_modify_check(hash);
2246 "wrong default_proc type %s (expected Proc)",
2295 if (RHASH_AR_TABLE_P(hash)) {
2296 return ar_delete(hash, pkey, pval);
2299 return st_delete(RHASH_ST_TABLE(hash), pkey, pval);
2331 if (deleted_value !=
Qundef) {
2332 return deleted_value;
2371 rb_hash_modify_check(hash);
2418rb_hash_shift(
VALUE hash)
2422 rb_hash_modify_check(hash);
2423 if (RHASH_AR_TABLE_P(hash)) {
2426 if (ar_shift(hash, &var.key, &var.val)) {
2438 if (RHASH_ST_TABLE_P(hash)) {
2441 if (
st_shift(RHASH_ST_TABLE(hash), &var.key, &var.val)) {
2460 rb_hash_modify(hash);
2493 rb_hash_modify_check(hash);
2494 if (!RHASH_TABLE_EMPTY_P(hash)) {
2524 rb_hash_modify(hash);
2526 if (!n)
return Qnil;
2600 for (i = 0; i <
argc; i++) {
2628 hash_copy(result, hash);
2630 for (i = 0; i <
argc; i++) {
2657 for (i=0; i<
argc; i++) {
2689 for (i=0; i<
argc; i++) {
2722rb_hash_select(
VALUE hash)
2738 rb_hash_modify(hash);
2764rb_hash_select_bang(
VALUE hash)
2769 rb_hash_modify_check(hash);
2771 if (!n)
return Qnil;
2795rb_hash_keep_if(
VALUE hash)
2798 rb_hash_modify_check(hash);
2799 if (!RHASH_TABLE_EMPTY_P(hash)) {
2821 rb_hash_modify_check(hash);
2826 else if (RHASH_AR_TABLE_P(hash)) {
2865 if (!existing && !RB_OBJ_FROZEN(*
key)) {
2868 return hash_aset(
key,
val, arg, existing);
2905 rb_hash_modify(hash);
2907 if (RHASH_TABLE_NULL_P(hash)) {
2908 if (iter_lev > 0) no_new_key();
2909 ar_alloc_table(hash);
2934 rb_hash_modify_check(hash);
2935 if (hash == hash2)
return hash;
2943 if (RHASH_AR_TABLE_P(hash)) {
2944 if (RHASH_AR_TABLE_P(hash2)) {
2948 ar_free_and_clear_table(hash);
2953 if (RHASH_AR_TABLE_P(hash2)) {
2955 RHASH_ST_CLEAR(hash);
3002rb_hash_empty_p(
VALUE hash)
3039rb_hash_each_value(
VALUE hash)
3077rb_hash_each_key(
VALUE hash)
3130rb_hash_each_pair(
VALUE hash)
3223 if (transarg.
trans) {
3261 rb_hash_modify_check(hash);
3262 if (!RHASH_TABLE_EMPTY_P(hash)) {
3264 VALUE new_keys = hash_alloc(0);
3283 if (!hash_stlike_lookup(new_keys,
key,
NULL)) {
3306 rb_hash_modify(hash);
3332rb_hash_transform_values(
VALUE hash)
3363rb_hash_transform_values_bang(
VALUE hash)
3366 rb_hash_modify_check(hash);
3368 if (!RHASH_TABLE_EMPTY_P(hash)) {
3393rb_hash_to_a(
VALUE hash)
3448rb_hash_inspect(
VALUE hash)
3462rb_hash_to_hash(
VALUE hash)
3493rb_hash_to_h_block(
VALUE hash)
3520rb_hash_to_h(
VALUE hash)
3523 return rb_hash_to_h_block(hash);
3554 if (
size == 0)
return keys;
3558 if (RHASH_AR_TABLE_P(hash)) {
3562 st_table *table = RHASH_ST_TABLE(hash);
3599 if (
size == 0)
return values;
3602 if (RHASH_AR_TABLE_P(hash)) {
3608 else if (RHASH_ST_TABLE_P(hash)) {
3609 st_table *table = RHASH_ST_TABLE(hash);
3640 if (hash_stlike_lookup(hash,
key,
NULL)) {
3690 if (!hash_stlike_lookup(data->
hash,
key, &val2)) {
3721 if (hash1 == hash2)
return Qtrue;
3722 if (!RB_TYPE_P(hash2,
T_HASH)) {
3727 if (
rb_eql(hash2, hash1)) {
3740 if (!RHASH_TABLE_EMPTY_P(hash1) && !RHASH_TABLE_EMPTY_P(hash2)) {
3781 return hash_equal(hash1, hash2,
FALSE);
3806 return hash_equal(hash1, hash2,
TRUE);
3817 *hval ^=
st_hash(hdata,
sizeof(hdata), 0);
3985 rb_hash_modify(self);
3986 for (i = 0; i <
argc; i++){
4038 rb_hash_modify(hash1);
4116lookup2_call(
VALUE arg)
4128reset_hash_type(
VALUE arg)
4168 ar_force_convert_table(
hash, __FILE__, __LINE__);
4170 table = RHASH_ST_TABLE(
hash);
4171 orighash = table->
type;
4178 assochash.
compare = assoc_cmp;
4180 table->
type = &assochash;
4284 if (level == 0)
return rb_hash_to_a(
hash);
4292 rb_funcallv(ary, id_flatten_bang, 1, &ary_flatten_level);
4294 else if (level < 0) {
4319 if (!
NIL_P(value)) {
4360 rb_hash_modify_check(
hash);
4408 rb_hash_modify_check(
hash);
4409 ar_force_convert_table(
hash, __FILE__, __LINE__);
4412 tmp = hash_alloc(0);
4418 RHASH_ST_CLEAR(tmp);
4534 rb_warn(
"given block not used");
4587 if (!--
argc)
return self;
4628 return hash_le(
hash, other);
4647 return hash_le(
hash, other);
4666 return hash_le(other,
hash);
4685 return hash_le(other,
hash);
4742 if (RHASH_AR_TABLE_P(
hash)) {
4743 hash_ar_table(
hash);
4749 ar_try_convert_table(
hash);
4767 for (i = 0; i <
argc; ) {
4770 ar_insert(
hash, k, v);
4783 if (RHASH_TABLE_NULL_P(
hash)) {
4785 hash_ar_table(
hash);
4792 if (RHASH_AR_TABLE_P(
hash) &&
4802static char **origenviron;
4804#define GET_ENVIRON(e) ((e) = rb_w32_get_environ())
4805#define FREE_ENVIRON(e) rb_w32_free_environ(e)
4806static char **my_environ;
4808#define environ my_environ
4810#define getenv(n) rb_w32_ugetenv(n)
4811#elif defined(__APPLE__)
4813#define environ (*_NSGetEnviron())
4814#define GET_ENVIRON(e) (e)
4815#define FREE_ENVIRON(e)
4818#define GET_ENVIRON(e) (e)
4819#define FREE_ENVIRON(e)
4821#ifdef ENV_IGNORECASE
4822#define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
4823#define ENVNMATCH(s1, s2, n) (STRNCASECMP((s1), (s2), (n)) == 0)
4825#define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
4826#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
4855env_str_new(
const char *
ptr,
long len)
4857 return env_enc_str_new(
ptr,
len, env_encoding());
4861env_str_new2(
const char *
ptr)
4867static const char TZ_ENV[] =
"TZ";
4870env_name_new(
const char *
name,
const char *
ptr)
4872 return env_enc_str_new_cstr(
ptr, env_encoding());
4893#define get_env_ptr(var, val) \
4894 (var = get_env_cstr(val, #var))
4896static inline const char *
4905#define env_name(s) env_name(&(s))
4910reset_by_modified_env(
const char *nam)
4927 const char *val =
getenv(nam);
4929 reset_by_modified_env(nam);
4932 VALUE value = env_str_new2(val);
4970 val = env_delete(
name);
4990 const char *nam, *
env;
4995 return env_name_new(nam,
env);
5030 const char *nam, *
env;
5035 if (block_given &&
argc == 2) {
5036 rb_warn(
"block supersedes default value argument");
5047 return env_name_new(nam,
env);
5057#if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
5060in_origenv(
const char *
str)
5064 if (*
env ==
str)
return 1;
5070envix(
const char *nam)
5076 for (i = 0;
env[i]; i++) {
5087getenvsize(
const WCHAR* p)
5089 const WCHAR* porg = p;
5090 while (*p++) p += lstrlenW(p) + 1;
5091 return p - porg + 1;
5095getenvblocksize(
void)
5105check_envsize(
size_t n)
5111 WCHAR* p = GetEnvironmentStringsW();
5114 FreeEnvironmentStringsW(p);
5115 if (n >= getenvblocksize()) {
5123#if defined(_WIN32) || \
5124 (defined(__sun) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV)))
5126NORETURN(
static void invalid_envname(
const char *
name));
5129invalid_envname(
const char *
name)
5135check_envname(
const char *
name)
5138 invalid_envname(
name);
5148# if defined(MINGW_HAS_SECURE_API) || RUBY_MSVCRT_VERSION >= 80
5149# define HAVE__WPUTENV_S 1
5156 check_envname(
name);
5157 len = MultiByteToWideChar(CP_UTF8, 0,
name, -1,
NULL, 0);
5160 len2 = MultiByteToWideChar(CP_UTF8, 0, value, -1,
NULL, 0);
5161 if (check_envsize((
size_t)
len + len2)) {
5165 wvalue = wname +
len;
5166 MultiByteToWideChar(CP_UTF8, 0,
name, -1, wname,
len);
5167 MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, len2);
5168#ifndef HAVE__WPUTENV_S
5169 wname[
len-1] =
L'=';
5174 MultiByteToWideChar(CP_UTF8, 0,
name, -1, wname,
len);
5175 wvalue = wname +
len;
5177#ifndef HAVE__WPUTENV_S
5178 wname[
len-1] =
L'=';
5181#ifndef HAVE__WPUTENV_S
5182 failed = _wputenv(wname);
5184 failed = _wputenv_s(wname, wvalue);
5189 if (!value || !*value) {
5191 if (!SetEnvironmentVariable(
name, value) &&
5192 GetLastError() != ERROR_ENVVAR_NOT_FOUND)
goto fail;
5196 invalid_envname(
name);
5198#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
5200 if (setenv(
name, value, 1))
5216 size_t len, mem_size;
5217 char **env_ptr, *
str, *mem_ptr;
5219 check_envname(
name);
5223 mem_ptr =
malloc(mem_size);
5224 if (mem_ptr ==
NULL)
5231 while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
5236 if (putenv(mem_ptr)) {
5254 for (j=0; j<
max; j++)
5260 char **envp = origenviron;
5261 while (*envp && *envp !=
environ[i]) envp++;
5336 return env_aset(nm, val);
5356 reset_by_modified_env(
name);
5372 const char *p = *
env;
5399 return env_keys(
FALSE);
5436env_each_key(
VALUE ehash)
5442 keys = env_keys(
FALSE);
5483 return env_values();
5504env_each_value(
VALUE ehash)
5510 values = env_values();
5536env_each_pair(
VALUE ehash)
5592env_reject_bang(
VALUE ehash)
5599 keys = env_keys(
FALSE);
5600 RBASIC_CLEAR_CLASS(keys);
5611 if (del == 0)
return Qnil;
5636env_delete_if(
VALUE ehash)
5639 env_reject_bang(ehash);
5667 for (i=0; i<
argc; i++) {
5695env_select(
VALUE ehash)
5703 keys = env_keys(
FALSE);
5756env_select_bang(
VALUE ehash)
5763 keys = env_keys(
FALSE);
5764 RBASIC_CLEAR_CLASS(keys);
5775 if (del == 0)
return Qnil;
5798env_keep_if(
VALUE ehash)
5801 env_select_bang(ehash);
5828 for (i = 0; i <
argc; i++) {
5830 value = rb_f_getenv(
Qnil,
key);
5844 keys = env_keys(
TRUE);
5941 env_str_new2(s+1)));
5980 for (i=0;
env[i]; i++)
6221 return env_to_hash();
6267 for (i = 0; i <
argc; i++) {
6305env_freeze(
VALUE self)
6364 return rb_hash_invert(env_to_hash());
6371 const char *keyptr, *eptr;
6379 if (elen != keylen)
continue;
6380 if (!
ENVNMATCH(keyptr, eptr, elen))
continue;
6392 keylist_delete(keys,
key);
6420 keys = env_keys(
TRUE);
6443 if (!
NIL_P(oldval)) {
6492 env_update_block_i : env_update_i;
6841 id_hash = rb_intern_const(
"hash");
6842 id_default = rb_intern_const(
"default");
6843 id_flatten_bang = rb_intern_const(
"flatten!");
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_ary_delete_at(VALUE ary, long pos)
void rb_ary_set_len(VALUE ary, long len)
VALUE rb_ary_new_capa(long capa)
VALUE rb_check_array_type(VALUE ary)
VALUE rb_ary_tmp_new(long capa)
VALUE rb_ary_clear(VALUE ary)
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
#define UNREACHABLE_RETURN
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
VALUE rb_big_hash(VALUE x)
void ruby_register_rollback_func_for_ensure(e_proc *ensure_func, e_proc *rollback_func)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define RB_DEBUG_COUNTER_INC(type)
char * strchr(char *, char)
#define MJIT_FUNC_EXPORTED
rb_encoding * rb_utf8_encoding(void)
rb_encoding * rb_enc_get(VALUE obj)
void rb_enc_copy(VALUE obj1, VALUE obj2)
rb_encoding * rb_locale_encoding(void)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
void ruby_xfree(void *x)
Deallocates a storage instance.
const char * rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
VALUE rb_obj_id(VALUE obj)
void rb_gc_force_recycle(VALUE obj)
void * ruby_xmalloc(size_t size)
Allocates a storage instance.
void rb_obj_info_dump(VALUE obj)
const char * rb_obj_info(VALUE obj)
void rb_gc_writebarrier_remember(VALUE obj)
void rb_include_module(VALUE klass, VALUE module)
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
int rb_class_has_methods(VALUE c)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
void rb_raise(VALUE exc, const char *fmt,...)
void rb_warn_deprecated_to_remove(const char *fmt, const char *removal,...)
void rb_bug(const char *fmt,...)
void rb_syserr_fail_str(int e, VALUE mesg)
VALUE rb_ident_hash_new(void)
void rb_sys_fail_str(VALUE mesg)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
const char * rb_builtin_class_name(VALUE x)
void rb_warn(const char *fmt,...)
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
VALUE rb_mKernel
Kernel module.
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
VALUE rb_cObject
Object class.
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
VALUE rb_obj_class(VALUE)
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_convert_type_with_id(VALUE v, int t, const char *nam, ID mid)
VALUE rb_equal(VALUE, VALUE)
This function is an optimized version of calling #==.
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
VALUE rb_to_int(VALUE)
Converts val into Integer.
VALUE rb_hash_size(VALUE hash)
VALUE rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
VALUE rb_hash_default_value(VALUE hash, VALUE key)
VALUE rb_to_hash_type(VALUE hash)
void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
VALUE rb_hash_values(VALUE hash)
VALUE rb_hash_resurrect(VALUE hash)
VALUE rb_hash_rassoc(VALUE hash, VALUE obj)
VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
void rb_hash_st_table_set(VALUE hash, st_table *st)
VALUE rb_hash_key_str(VALUE key)
#define RHASH_AR_TABLE_BOUND(h)
size_t rb_hash_ar_table_size(void)
VALUE rb_check_hash_type(VALUE hash)
int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
struct st_table * rb_hash_tbl(VALUE hash, const char *file, int line)
int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval)
#define ENVNMATCH(s1, s2, n)
#define RHASH_ST_TABLE_SET(h, s)
#define RHASH_AR_TABLE_REF(hash, n)
#define RHASH_AR_TABLE_BOUND_RAW(h)
int(* tbl_update_func)(st_data_t *, st_data_t *, st_data_t, int)
void rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
VALUE rb_hash_rehash(VALUE hash)
#define COPY_DEFAULT(hash, hash2)
#define RHASH_AR_TABLE_MAX_BOUND
VALUE rb_hash_has_key(VALUE hash, VALUE key)
int rb_env_path_tainted(void)
#define SET_PROC_DEFAULT(hash, proc)
VALUE rb_hash_set_pair(VALUE hash, VALUE arg)
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
#define NOINSERT_UPDATE_CALLBACK(func)
#define RHASH_AR_TABLE_SIZE(h)
VALUE rb_hash_delete(VALUE hash, VALUE key)
#define RHASH_AR_CLEARED_HINT
#define get_env_ptr(var, val)
VALUE rb_hash_fetch(VALUE hash, VALUE key)
VALUE rb_hash_new_with_size(st_index_t size)
struct st_table * rb_hash_tbl_raw(VALUE hash, const char *file, int line)
struct ar_table_struct ar_table
int st_foreach_func(st_data_t, st_data_t, st_data_t)
VALUE rb_hash_assoc(VALUE hash, VALUE key)
VALUE rb_hash_reject(VALUE hash)
VALUE rb_hash_compare_by_id_p(VALUE hash)
VALUE rb_hash_delete_if(VALUE hash)
VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc)
VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
int rb_hash_ar_table_p(VALUE hash)
VALUE rb_hash_keys(VALUE hash)
#define HAS_EXTRA_STATES(hash, klass)
st_table * rb_hash_st_table(VALUE hash)
int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
VALUE rb_hash_delete_entry(VALUE hash, VALUE key)
VALUE rb_hash_aref(VALUE hash, VALUE key)
struct ar_table_pair_struct ar_table_pair
#define RHASH_AR_TABLE_SIZE_INC(h)
VALUE rb_hash_freeze(VALUE hash)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
VALUE rb_hash_reject_bang(VALUE hash)
void ruby_unsetenv(const char *name)
int rb_foreach_func(VALUE, VALUE, VALUE)
#define RHASH_UPDATE(hash, key, func, arg)
#define st_index_hash(index)
long rb_dbl_long_hash(double d)
VALUE rb_hash_lookup(VALUE hash, VALUE key)
VALUE rb_hash_dup(VALUE hash)
int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg)
VALUE rb_hash_clear(VALUE hash)
const struct st_hash_type rb_hashtype_ident
size_t rb_hash_size_num(VALUE hash)
#define HASH_ASSERT(expr)
#define SET_DEFAULT(hash, ifnone)
int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
st_table * rb_init_identtable(void)
void ruby_setenv(const char *name, const char *value)
#define RHASH_UPDATE_ITER(h, iter_lev, key, func, a)
ar_table * rb_hash_ar_table(VALUE hash)
#define rb_enc_asciicompat(enc)
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *)
Thin wrapper to ruby/config.h.
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
#define INTEGER_PACK_NATIVE_BYTE_ORDER
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
#define UNLIMITED_ARGUMENTS
VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value)
VALUE rb_obj_is_proc(VALUE)
VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE)
VALUE rb_block_proc(void)
VALUE rb_proc_lambda_p(VALUE)
#define rb_hash_uint(h, i)
st_index_t rb_memhash(const void *ptr, long len)
#define rb_str_new(str, len)
st_index_t rb_hash_start(st_index_t)
VALUE rb_check_string_type(VALUE)
#define rb_usascii_str_new2
VALUE rb_str_ellipsize(VALUE, long)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
VALUE rb_str_new_frozen(VALUE)
VALUE rb_str_buf_append(VALUE, VALUE)
int rb_str_hash_cmp(VALUE, VALUE)
#define rb_utf8_str_new(str, len)
st_index_t rb_str_hash(VALUE)
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
void rb_copy_generic_ivar(VALUE, VALUE)
VALUE rb_ivar_get(VALUE, ID)
int rb_respond_to(VALUE, ID)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_define_global_const(const char *, VALUE)
char * ruby_strdup(const char *)
Internal header for Array.
Internal header for Bignums.
Internal header for Class.
Internal header for Fiber.
Internal header for Hash.
#define RHASH_AR_TABLE_MAX_SIZE
@ RHASH_AR_TABLE_BOUND_SHIFT
@ RHASH_AR_TABLE_SIZE_SHIFT
Internal header for Object.
Internal header for Proc.
VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc)
int rb_block_pair_yield_optimizable(void)
char * rb_str_fill_terminator(VALUE str, const int termlen)
ID rb_make_internal_id(void)
Internal header for Time.
void ruby_reset_timezone(void)
Internal header for RubyVM.
VALUE rb_check_funcall_basic_kw(VALUE, ID, VALUE, int, const VALUE *, int)
Calls a method only if it is the basic method of ancestor otherwise returns Qundef;.
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
#define rb_method_basic_definition_p(...)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
VALUE rb_yield_values(int n,...)
VALUE rb_yield_values2(int n, const VALUE *argv)
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RARRAY_AREF(a, i)
#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr)
#define RGENGC_WB_PROTECTED_HASH
#define RB_OBJ_WRITE(a, slot, b)
WB for new reference from ‘a’ to ‘b’.
#define RB_OBJ_WRITTEN(a, oldv, b)
WB for new reference from ‘a’ to ‘b’.
#define RHASH_SET_IFNONE(h, ifnone)
#define RHASH_ITER_LEV(h)
#define SafeStringValue(v)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
const char * rb_obj_classname(VALUE)
unsigned long long uint64_t
rb_atomic_t cnt[RUBY_NSIG]
VALUE rb_sprintf(const char *,...)
int st_foreach_check_callback_func(st_data_t, st_data_t, st_data_t, int)
#define st_init_table_with_size
int st_update_callback_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
#define ST_DATA_COMPATIBLE_P(type)
int st_foreach_callback_func(st_data_t, st_data_t, st_data_t)
#define st_foreach_with_replace
void rb_hash_bulk_insert_into_st_table(long, const VALUE *, VALUE)
size_t strlen(const char *)
ar_table_pair pairs[RHASH_AR_TABLE_MAX_SIZE]
st_foreach_callback_func * func
const struct st_hash_type * orighash
int(* compare)(st_data_t, st_data_t)
st_index_t(* hash)(st_data_t)
const struct st_hash_type * type
rb_hash_update_func * func
#define rb_hash_transient_heap_evacuate(x, y)
#define rb_transient_heap_alloc(o, s)
void error(const char *msg)
if((ID)(DISPID) nameid !=nameid)
int def(FILE *source, FILE *dest, int level)