26# ifdef HAVE_CRT_EXTERNS_H
41#define HAS_EXTRA_STATES(hash, klass) ( \
42 ((klass = has_extra_methods(rb_obj_class(hash))) != 0) || \
43 FL_TEST((hash), FL_EXIVAR|RHASH_PROC_DEFAULT) || \
44 !NIL_P(RHASH_IFNONE(hash)))
46#define SET_DEFAULT(hash, ifnone) ( \
47 FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \
48 RHASH_SET_IFNONE(hash, ifnone))
50#define SET_PROC_DEFAULT(hash, proc) set_proc_default(hash, proc)
52#define COPY_DEFAULT(hash, hash2) copy_default(RHASH(hash), RHASH(hash2))
55copy_default(
struct RHash *hash,
const struct RHash *hash2)
57 hash->
basic.flags &= ~RHASH_PROC_DEFAULT;
96static ID id_hash_iter_lev;
108 if (a == b)
return 0;
124 if (recurse)
return INT2FIX(0);
152dbl_to_index(
double d)
163 if (d == 0.0) d = 0.0;
164#if SIZEOF_INT == SIZEOF_VOIDP
167 return rb_objid_hash(dbl_to_index(d));
204 hnum = other_func(a);
207#if SIZEOF_LONG < SIZEOF_ST_INDEX_T
209 hnum &= (
unsigned long)-1 >> 2;
211 hnum |= ~((
unsigned long)-1 >> 2);
229 return any_hash(a, obj_any_hash);
238static const uint32_t prime2 = 0x830fcab9;
244#if defined HAVE_UINT128_T
248 uint64_t hm1 = m1 >> 32, hm2 = m2 >> 32;
251 uint64_t v32_96 = hm1 * lm2 + lm1 * hm2;
254 return (v64_128 + (v32_96 >> 32)) ^ ((v32_96 << 32) + v1_32);
261 return mult_and_mix(
key + seed, prime1);
265#define st_index_hash(index) key64_hash(rb_hash_start(index), prime2)
280#if SIZEOF_LONG == SIZEOF_VOIDP
282#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
293 long hnum = any_hash(
obj, objid_hash);
302#define rb_ident_cmp st_numcmp
321#define identhash rb_hashtype_ident
339#define RHASH_AR_TABLE_MAX_BOUND RHASH_AR_TABLE_MAX_SIZE
341#define RHASH_AR_TABLE_REF(hash, n) (&RHASH_AR_TABLE(hash)->pairs[n])
342#define RHASH_AR_CLEARED_HINT 0xff
387 ar_hint_set_hint(hash,
index, ar_do_hash_hint(hash_value));
399ar_cleared_entry(
VALUE hash,
unsigned int index)
419 ar_hint_set(hash,
index, hash_value);
422#define RHASH_AR_TABLE_SIZE(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
423 RHASH_AR_TABLE_SIZE_RAW(h))
425#define RHASH_AR_TABLE_BOUND_RAW(h) \
426 ((unsigned int)((RBASIC(h)->flags >> RHASH_AR_TABLE_BOUND_SHIFT) & \
427 (RHASH_AR_TABLE_BOUND_MASK >> RHASH_AR_TABLE_BOUND_SHIFT)))
429#define RHASH_AR_TABLE_BOUND(h) (HASH_ASSERT(RHASH_AR_TABLE_P(h)), \
430 RHASH_AR_TABLE_BOUND_RAW(h))
432#define RHASH_ST_TABLE_SET(h, s) rb_hash_st_table_set(h, s)
433#define RHASH_TYPE(hash) (RHASH_AR_TABLE_P(hash) ? &objhash : RHASH_ST_TABLE(hash)->type)
435#define HASH_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(HASH_DEBUG, expr, #expr)
438#define hash_verify(hash) hash_verify_(hash, __FILE__, __LINE__)
441rb_hash_dump(
VALUE hash)
451 for (
i=0;
i<bound;
i++) {
454 if (!ar_cleared_entry(hash,
i)) {
455 char b1[0x100], b2[0x100];
473hash_verify_(
VALUE hash,
const char *file,
int line)
480 for (
i=0;
i<bound;
i++) {
482 if (!ar_cleared_entry(hash,
i)) {
510#define hash_verify(h) ((void)0)
514RHASH_TABLE_NULL_P(
VALUE hash)
526RHASH_TABLE_EMPTY_P(
VALUE hash)
547 return RHASH(hash)->as.ar;
554 return RHASH(hash)->as.st;
570 RHASH(hash)->as.ar = ar;
574#define RHASH_SET_ST_FLAG(h) FL_SET_RAW(h, RHASH_ST_TABLE_FLAG)
575#define RHASH_UNSET_ST_FLAG(h) FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG)
583 RBASIC(
h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
593 RBASIC(
h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
607#define RHASH_AR_TABLE_SIZE_INC(h) HASH_AR_TABLE_SIZE_ADD(h, 1)
610RHASH_AR_TABLE_SIZE_DEC(
VALUE h)
616 RHASH_AR_TABLE_SIZE_SET(
h, new_size);
619 RHASH_AR_TABLE_SIZE_SET(
h, 0);
620 RHASH_AR_TABLE_BOUND_SET(
h, 0);
626RHASH_AR_TABLE_CLEAR(
VALUE h)
628 RBASIC(
h)->flags &= ~RHASH_AR_TABLE_SIZE_MASK;
629 RBASIC(
h)->flags &= ~RHASH_AR_TABLE_BOUND_MASK;
631 hash_ar_table_set(
h,
NULL);
635ar_alloc_table(
VALUE hash)
647 RHASH_AR_TABLE_SIZE_SET(hash, 0);
648 RHASH_AR_TABLE_BOUND_SET(hash, 0);
649 hash_ar_table_set(hash, tab);
659 return rb_any_cmp(x, y) == 0;
670 for (
i = 0;
i < bound;
i++) {
671 if (hints[
i] == hint) {
673 if (ar_equal(
key, pair->
key)) {
680 static char fname[256];
684 snprintf(fname,
sizeof(fname),
"/tmp/ruby-armiss.%d", pid =
getpid());
691 fprintf(fp,
"miss: hash_eq:%d hints[%d]:%02x hint:%02x\n"
693 " pair->key:%016lx %s\n",
694 h1 == h2,
i, hints[
i], hint,
708 ar_hint_t hint = ar_do_hash_hint(hash_value);
709 return ar_find_entry_hint(hash, hint,
key);
713ar_free_and_clear_table(
VALUE hash)
724 RHASH_AR_TABLE_CLEAR(hash);
732ar_try_convert_table(
VALUE hash)
751 ar_free_and_clear_table(hash);
757ar_force_convert_table(
VALUE hash,
const char *file,
int line)
768#if RHASH_CONVERT_TABLE_DEBUG
776 for (
i = 0;
i < bound;
i++) {
777 if (ar_cleared_entry(hash,
i))
continue;
782 ar_free_and_clear_table(hash);
793hash_ar_table(
VALUE hash)
795 if (RHASH_TABLE_NULL_P(hash)) {
796 ar_alloc_table(hash);
802ar_compact_table(
VALUE hash)
814 for (
i=0;
i<bound;
i++) {
815 if (ar_cleared_entry(hash,
i)) {
817 for (; j<bound; j++) {
818 if (!ar_cleared_entry(hash, j)) {
820 ar_hint_set_hint(hash,
i, (
st_hash_t)ar_hint(hash, j));
821 ar_clear_entry(hash, j);
834 RHASH_AR_TABLE_BOUND_SET(hash,
size);
850 bin = ar_compact_table(hash);
855 ar_set_entry(hash,
bin,
key, val, hash_value);
856 RHASH_AR_TABLE_BOUND_SET(hash,
bin+1);
868 for (
i = 0;
i < bound;
i++) {
869 if (ar_cleared_entry(hash,
i))
continue;
894 ar_clear_entry(hash,
i);
895 RHASH_AR_TABLE_SIZE_DEC(hash);
906 return ar_general_foreach(hash, func, replace,
arg);
917 const struct functor *
f = (
void *)d;
918 return f->func(k,
v,
f->arg);
925 return ar_general_foreach(hash, apply_functor,
NULL, (
st_data_t)&
f);
939 for (
i = 0;
i < bound;
i++) {
940 if (ar_cleared_entry(hash,
i))
continue;
944 hint = ar_hint(hash,
i);
946 retval = (*func)(
key, pair->
val,
arg, 0);
952 if (pair->
key == never)
break;
953 ret = ar_find_entry_hint(hash, hint,
key);
955 retval = (*func)(0, 0,
arg, 1);
965 if (!ar_cleared_entry(hash,
i)) {
966 ar_clear_entry(hash,
i);
967 RHASH_AR_TABLE_SIZE_DEC(hash);
981 int retval, existing;
992 bin = ar_find_entry(hash, hash_value,
key);
1006 retval = (*func)(&
key, &value,
arg, existing);
1012 if (ar_add_direct_with_hash(hash,
key, value, hash_value)) {
1018 if (old_key !=
key) {
1026 ar_clear_entry(hash,
bin);
1027 RHASH_AR_TABLE_SIZE_DEC(hash);
1045 hash_ar_table(hash);
1047 bin = ar_find_entry(hash, hash_value,
key);
1053 bin = ar_compact_table(hash);
1054 hash_ar_table(hash);
1058 ar_set_entry(hash,
bin,
key, value, hash_value);
1059 RHASH_AR_TABLE_BOUND_SET(hash,
bin+1);
1081 unsigned bin = ar_find_entry(hash, hash_value,
key);
1088 if (value !=
NULL) {
1107 bin = ar_find_entry(hash, hash_value, *
key);
1110 if (value != 0) *value = 0;
1118 ar_clear_entry(hash,
bin);
1119 RHASH_AR_TABLE_SIZE_DEC(hash);
1130 for (
i = 0;
i < bound;
i++) {
1131 if (!ar_cleared_entry(hash,
i)) {
1133 if (value != 0) *value = pair->
val;
1135 ar_clear_entry(hash,
i);
1136 RHASH_AR_TABLE_SIZE_DEC(hash);
1141 if (value !=
NULL) *value = 0;
1151 for (
i = 0;
i < bound;
i++) {
1152 if (
keys == keys_end) {
1156 if (!ar_cleared_entry(hash,
i)) {
1162 return keys - keys_start;
1169 st_data_t *values_start = values, *values_end = values +
size;
1171 for (
i = 0;
i < bound;
i++) {
1172 if (values == values_end) {
1176 if (!ar_cleared_entry(hash,
i)) {
1182 return values - values_start;
1190 if (old_tab !=
NULL) {
1192 if (new_tab ==
NULL) {
1194 if (new_tab !=
NULL) {
1202 *new_tab = *old_tab;
1203 RHASH(hash1)->ar_hint.word =
RHASH(hash2)->ar_hint.word;
1206 hash_ar_table_set(hash1, new_tab);
1222 hash_ar_table_set(hash1,
NULL);
1233 RHASH_AR_TABLE_SIZE_SET(hash, 0);
1234 RHASH_AR_TABLE_BOUND_SET(hash, 0);
1242#if USE_TRANSIENT_HEAP
1262 if (new_tab ==
NULL)
goto promote;
1264 *new_tab = *old_tab;
1265 hash_ar_table_set(hash, new_tab);
1286 status = (*
arg->func)(
key, value,
arg->arg);
1370iter_lev_in_ivar_set(
VALUE hash,
int lev)
1385 int lev = iter_lev_in_flags(
hash);
1388 return iter_lev_in_ivar(
hash);
1398 int lev = iter_lev_in_flags(
hash);
1400 lev = iter_lev_in_ivar(
hash);
1401 iter_lev_in_ivar_set(
hash, lev+1);
1407 iter_lev_in_ivar_set(
hash, lev);
1415 int lev = iter_lev_in_flags(
hash);
1417 lev = iter_lev_in_ivar(
hash);
1419 iter_lev_in_ivar_set(
hash, lev-1);
1430 hash_iter_lev_inc(
hash);
1437 hash_iter_lev_dec(
hash);
1456 return ar_foreach_with_replace(
hash,
func, replace,
arg);
1469 ret = ar_foreach_check(
hash, hash_ar_foreach_iter,
1487 if (RHASH_TABLE_EMPTY_P(
hash))
1489 hash_iter_lev_inc(
hash);
1511 return hash_alloc_flags(
klass, 0,
Qnil);
1519 return hash_alloc(
klass);
1536 ar_alloc_table(ret);
1588#if RHASH_CONVERT_TABLE_DEBUG
1591 return ar_force_convert_table(hash, file, line);
1596 return ar_force_convert_table(hash,
NULL, 0);
1608rb_hash_modify(
VALUE hash)
1610 rb_hash_modify_check(hash);
1625#define NOINSERT_UPDATE_CALLBACK(func) \
1627func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1629 if (!existing) no_new_key(); \
1630 return func(key, val, (struct update_arg *)arg, existing); \
1634func##_insert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
1636 return func(key, val, (struct update_arg *)arg, existing); \
1656 ar_try_convert_table(hash);
1672 arg.arg = optional_arg;
1688#define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func##_insert)
1690#define RHASH_UPDATE_ITER(h, iter_lev, key, func, a) do { \
1691 tbl_update((h), (key), UPDATE_CALLBACK((iter_lev), func), (st_data_t)(a)); \
1694#define RHASH_UPDATE(hash, key, func, arg) \
1695 RHASH_UPDATE_ITER(hash, RHASH_ITER_LEV(hash), key, func, arg)
1703 if (
n != 2 && (
n >= 0 ||
n < -3)) {
1704 if (
n < 0)
n = -
n-1;
1753 rb_hash_modify(
hash);
1794 tmp = rb_hash_s_try_convert(
Qnil,
argv[0]);
1834 if (
argc % 2 != 0) {
1849#define to_hash rb_to_hash_type
1966 rb_hash_modify_check(hash);
1968 tmp = hash_alloc(0);
1969 ar_alloc_table(tmp);
1971 ar_free_and_clear_table(hash);
1973 ar_free_and_clear_table(tmp);
1977 tmp = hash_alloc(0);
2009 return ar_lookup(hash,
key, pval);
2019 return hash_stlike_lookup(hash,
key, pval);
2041 if (hash_stlike_lookup(hash,
key, &val)) {
2054 if (hash_stlike_lookup(hash,
key, &val)) {
2108 if (block_given &&
argc == 2) {
2109 rb_warn(
"block supersedes default value argument");
2112 if (hash_stlike_lookup(hash,
key, &val)) {
2119 else if (
argc == 1) {
2136 return rb_hash_fetch_m(1, &
key, hash);
2163 VALUE args[2], ifnone;
2199 rb_hash_modify_check(hash);
2220rb_hash_default_proc(
VALUE hash)
2246 rb_hash_modify_check(hash);
2254 "wrong default_proc type %s (expected Proc)",
2306 return rb_hash_key(hash, value);
2313 return ar_delete(hash, pkey, pval);
2348 if (deleted_value !=
Qundef) {
2349 return deleted_value;
2379 rb_hash_modify_check(hash);
2424rb_hash_shift(
VALUE hash)
2428 rb_hash_modify_check(hash);
2432 if (ar_shift(hash, &var.key, &var.val)) {
2496 rb_hash_modify_check(hash);
2497 if (!RHASH_TABLE_EMPTY_P(hash)) {
2518 rb_hash_modify(hash);
2520 if (!
n)
return Qnil;
2719 rb_hash_modify_check(hash);
2721 if (!
n)
return Qnil;
2744 rb_hash_modify_check(hash);
2745 if (!RHASH_TABLE_EMPTY_P(hash)) {
2771 rb_hash_modify_check(hash);
2790 arg->new_value =
arg->arg;
2795 arg->new_value =
arg->arg;
2818 return hash_aset(
key,
val,
arg, existing);
2856 rb_hash_modify(hash);
2858 if (RHASH_TABLE_NULL_P(hash)) {
2859 if (iter_lev > 0) no_new_key();
2860 ar_alloc_table(hash);
2887 rb_hash_modify_check(hash);
2888 if (hash == hash2)
return hash;
2901 ar_free_and_clear_table(hash);
2961rb_hash_empty_p(
VALUE hash)
2993rb_hash_each_value(
VALUE hash)
3026rb_hash_each_key(
VALUE hash)
3073rb_hash_each_pair(
VALUE hash)
3109rb_hash_transform_keys(
VALUE hash)
3142rb_hash_transform_keys_bang(
VALUE hash)
3145 rb_hash_modify_check(hash);
3146 if (!RHASH_TABLE_EMPTY_P(hash)) {
3148 VALUE pairs = rb_hash_flatten(0,
NULL, hash);
3192rb_hash_transform_values(
VALUE hash)
3197 result = hash_copy(hash_alloc(
rb_cHash), hash);
3225rb_hash_transform_values_bang(
VALUE hash)
3228 rb_hash_modify_check(hash);
3230 if (!RHASH_TABLE_EMPTY_P(hash)) {
3256rb_hash_to_a(
VALUE hash)
3311rb_hash_inspect(
VALUE hash)
3326rb_hash_to_hash(
VALUE hash)
3357rb_hash_to_h_block(
VALUE hash)
3377rb_hash_to_h(
VALUE hash)
3380 return rb_hash_to_h_block(hash);
3462 if (
size == 0)
return values;
3509 if (hash_stlike_lookup(hash,
key,
NULL)) {
3565 if (!hash_stlike_lookup(data->
hash,
key, &val2)) {
3596 if (hash1 == hash2)
return Qtrue;
3602 if (
rb_eql(hash2, hash1)) {
3615 if (!RHASH_TABLE_EMPTY_P(hash1) && !RHASH_TABLE_EMPTY_P(hash2)) {
3661 return hash_equal(hash1, hash2,
FALSE);
3676 return hash_equal(hash1, hash2,
TRUE);
3687 *hval ^=
st_hash(hdata,
sizeof(hdata), 0);
3764 arg->old_value = *value;
3765 arg->new_value =
arg->arg;
3769 arg->new_value =
arg->arg;
3791 arg->old_value = *value;
3796 arg->new_value = newvalue;
3859 rb_hash_modify(
self);
3891 arg->new_value = newvalue;
3912 rb_hash_modify(hash1);
4025 ar_force_convert_table(
hash, __FILE__, __LINE__);
4028 orighash = table->
type;
4035 assochash.
compare = assoc_cmp;
4037 table->
type = &assochash;
4126 if (level == 0)
return rb_hash_to_a(
hash);
4134 rb_funcallv(ary, id_flatten_bang, 1, &ary_flatten_level);
4136 else if (level < 0) {
4161 if (!
NIL_P(value)) {
4205 rb_hash_modify_check(
hash);
4241 rb_hash_modify_check(
hash);
4242 ar_force_convert_table(
hash, __FILE__, __LINE__);
4245 tmp = hash_alloc(0);
4348 rb_warn(
"given block not used");
4391 if (!--
argc)
return self;
4434 return hash_le(
hash, other);
4455 return hash_le(
hash, other);
4476 return hash_le(other,
hash);
4497 return hash_le(other,
hash);
4556 hash_ar_table(
hash);
4562 ar_try_convert_table(
hash);
4580 for (
i = 0;
i <
argc; ) {
4583 ar_insert(
hash, k,
v);
4596 if (RHASH_TABLE_NULL_P(
hash)) {
4598 hash_ar_table(
hash);
4615static char **origenviron;
4617#define GET_ENVIRON(e) ((e) = rb_w32_get_environ())
4618#define FREE_ENVIRON(e) rb_w32_free_environ(e)
4619static char **my_environ;
4621#define environ my_environ
4623static char *(*w32_getenv)(
const char*);
4625w32_getenv_unknown(
const char *
name)
4627 char *(*func)(
const char*);
4635 return (w32_getenv = func)(
name);
4637static char *(*w32_getenv)(
const char*) = w32_getenv_unknown;
4638#define getenv(n) w32_getenv(n)
4639#elif defined(__APPLE__)
4641#define environ (*_NSGetEnviron())
4642#define GET_ENVIRON(e) (e)
4643#define FREE_ENVIRON(e)
4646#define GET_ENVIRON(e) (e)
4647#define FREE_ENVIRON(e)
4649#ifdef ENV_IGNORECASE
4650#define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
4651#define ENVNMATCH(s1, s2, n) (STRNCASECMP((s1), (s2), (n)) == 0)
4653#define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
4654#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
4683env_str_new(
const char *
ptr,
long len)
4689env_str_new2(
const char *
ptr)
4695static const char TZ_ENV[] =
"TZ";
4699env_encoding_for(
const char *
name,
const char *
ptr)
4710env_name_new(
const char *
name,
const char *
ptr)
4712 return env_enc_str_new_cstr(
ptr, env_encoding_for(
name,
ptr));
4718 volatile VALUE *pstr,
4746#define get_env_ptr(var, val) \
4747 (var = get_env_cstr(&(val), #var))
4749#define get_env_ptr(var, val) \
4750 (var = get_env_cstr(val, #var))
4753static inline const char *
4762#define env_name(s) env_name(&(s))
4769 const char *nam, *val;
4785 VALUE value = env_str_new2(val);
4822 val = env_delete(
name);
4843 const char *nam, *
env;
4848 return env_name_new(nam,
env);
4883 const char *nam, *
env;
4888 if (block_given &&
argc == 2) {
4889 rb_warn(
"block supersedes default value argument");
4900 return env_name_new(nam,
env);
4906 rb_warning(
"rb_env_path_tainted is deprecated and will be removed in Ruby 3.2.");
4910#if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
4913in_origenv(
const char *
str)
4917 if (*
env ==
str)
return 1;
4923envix(
const char *nam)
4929 for (
i = 0;
env[
i];
i++) {
4940getenvsize(
const WCHAR* p)
4942 const WCHAR* porg = p;
4943 while (*p++) p += lstrlenW(p) + 1;
4944 return p - porg + 1;
4948getenvblocksize(
void)
4958check_envsize(
size_t n)
4964 WCHAR* p = GetEnvironmentStringsW();
4967 FreeEnvironmentStringsW(p);
4968 if (
n >= getenvblocksize()) {
4976#if defined(_WIN32) || \
4977 (defined(__sun) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV)))
4979NORETURN(
static void invalid_envname(
const char *
name));
4982invalid_envname(
const char *
name)
4988check_envname(
const char *
name)
4991 invalid_envname(
name);
5001# if defined(MINGW_HAS_SECURE_API) || RUBY_MSVCRT_VERSION >= 80
5002# define HAVE__WPUTENV_S 1
5009 check_envname(
name);
5010 len = MultiByteToWideChar(CP_UTF8, 0,
name, -1,
NULL, 0);
5013 len2 = MultiByteToWideChar(CP_UTF8, 0, value, -1,
NULL, 0);
5014 if (check_envsize((
size_t)
len + len2)) {
5018 wvalue = wname +
len;
5019 MultiByteToWideChar(CP_UTF8, 0,
name, -1, wname,
len);
5020 MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, len2);
5021#ifndef HAVE__WPUTENV_S
5022 wname[
len-1] =
L'=';
5027 MultiByteToWideChar(CP_UTF8, 0,
name, -1, wname,
len);
5028 wvalue = wname +
len;
5030#ifndef HAVE__WPUTENV_S
5031 wname[
len-1] =
L'=';
5034#ifndef HAVE__WPUTENV_S
5035 failed = _wputenv(wname);
5037 failed = _wputenv_s(wname, wvalue);
5042 if (!value || !*value) {
5044 if (!SetEnvironmentVariable(
name, value) &&
5045 GetLastError() != ERROR_ENVVAR_NOT_FOUND)
goto fail;
5049 invalid_envname(
name);
5051#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
5069 size_t len, mem_size;
5070 char **env_ptr, *
str, *mem_ptr;
5072 check_envname(
name);
5076 mem_ptr =
malloc(mem_size);
5077 if (mem_ptr ==
NULL)
5084 while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
5105 for (max =
i;
environ[max]; max++) ;
5106 tmpenv =
ALLOC_N(
char*, max+2);
5107 for (j=0; j<max; j++)
5113 char **envp = origenviron;
5114 while (*envp && *envp !=
environ[
i]) envp++;
5189 return env_aset(nm, val);
5292env_each_key(
VALUE ehash)
5341 return env_values();
5362env_each_value(
VALUE ehash)
5368 values = env_values();
5394env_each_pair(
VALUE ehash)
5449env_reject_bang(
VALUE ehash)
5468 if (del == 0)
return Qnil;
5482env_delete_if(
VALUE ehash)
5485 env_reject_bang(ehash);
5523env_select(
VALUE ehash)
5558env_select_bang(
VALUE ehash)
5577 if (del == 0)
return Qnil;
5591env_keep_if(
VALUE ehash)
5594 env_select_bang(ehash);
5619 value = rb_f_getenv(
Qnil,
key);
5728 env_str_new2(s+1)));
5966 return env_key(dmy, value);
6000 return env_to_hash();
6043env_freeze(
VALUE self)
6096 return rb_hash_invert(env_to_hash());
6103 const char *keyptr, *eptr;
6108 if (elen != keylen)
continue;
6109 if (!
ENVNMATCH(keyptr, eptr, elen))
continue;
6169 if (!
NIL_P(oldval)) {
6194 env_update_block_i : env_update_i;
6316#define rb_intern(str) rb_intern_const(str)
6320 id_flatten_bang =
rb_intern(
"flatten!");
rb_encoding * rb_utf8_encoding(void)
rb_encoding * rb_filesystem_encoding(void)
rb_encoding * rb_default_internal_encoding(void)
rb_encoding * rb_enc_get(VALUE obj)
int rb_ascii8bit_encindex(void)
void rb_enc_copy(VALUE obj1, VALUE obj2)
int rb_locale_encindex(void)
rb_encoding * rb_locale_encoding(void)
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
#define ECONV_UNDEF_REPLACE
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
#define ECONV_INVALID_REPLACE
#define rb_enc_asciicompat(enc)
int rb_enc_str_asciionly_p(VALUE)
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *)
char str[HTML_ESCAPE_MAX_LEN+1]
void rb_include_module(VALUE, VALUE)
void rb_extend_object(VALUE, VALUE)
Extend the object with the module.
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
int rb_class_has_methods(VALUE c)
void rb_define_alias(VALUE, const char *, const char *)
Defines an alias of a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
VALUE rb_cObject
Object class.
void rb_raise(VALUE exc, const char *fmt,...)
void rb_bug(const char *fmt,...)
void rb_syserr_fail_str(int e, VALUE mesg)
void rb_sys_fail_str(VALUE mesg)
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
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(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
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)
Equivalent to Object#class in Ruby.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
VALUE rb_obj_hash(VALUE obj)
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
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)
MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size)
VALUE rb_hash_rassoc(VALUE hash, VALUE obj)
MJIT_FUNC_EXPORTED struct st_table * rb_hash_tbl_raw(VALUE hash)
VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
MJIT_FUNC_EXPORTED VALUE rb_hash_resurrect(VALUE hash)
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)
NOINLINE(static int ar_equal(VALUE x, VALUE y))
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)
VALUE rb_ident_hash_new(void)
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
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)
VALUE rb_hash_select_bang(VALUE hash)
#define RHASH_AR_CLEARED_HINT
MJIT_FUNC_EXPORTED VALUE rb_hash_has_key(VALUE hash, VALUE key)
#define get_env_ptr(var, val)
void rb_hash_transient_heap_evacuate(VALUE hash, int promote)
VALUE rb_hash_fetch(VALUE hash, VALUE key)
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_keep_if(VALUE hash)
MJIT_FUNC_EXPORTED VALUE rb_hash_compare_by_id_p(VALUE hash)
VALUE rb_hash_reject(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)
MJIT_FUNC_EXPORTED int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
MJIT_FUNC_EXPORTED VALUE rb_hash_keys(VALUE hash)
int rb_hash_ar_table_p(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)
NORETURN(static void no_new_key(void))
int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg)
VALUE rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
#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)
VALUE rb_hash_clear(VALUE hash)
const struct st_hash_type rb_hashtype_ident
size_t rb_hash_size_num(VALUE hash)
VALUE rb_hash_select(VALUE hash)
#define HASH_ASSERT(expr)
#define SET_DEFAULT(hash, ifnone)
st_table * rb_init_identtable(void)
void st_foreach_safe(st_table *table, st_foreach_func *func, st_data_t a)
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)
VALUE type(ANYARGS)
ANYARGS-ed function type.
double rb_float_value(VALUE v)
rb_atomic_t cnt[RUBY_NSIG]
void st_free_table(st_table *tab)
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
st_index_t st_keys(st_table *tab, st_data_t *keys, st_index_t size)
int st_shift(st_table *tab, st_data_t *key, st_data_t *value)
void st_add_direct(st_table *tab, st_data_t key, st_data_t value)
int st_insert(st_table *tab, st_data_t key, st_data_t value)
st_index_t st_values(st_table *tab, st_data_t *values, st_index_t size)
void st_clear(st_table *tab)
st_index_t st_hash(const void *ptr, size_t len, st_index_t h)
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
st_table * st_init_table(const struct st_hash_type *type)
int st_foreach_with_replace(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
int st_foreach_check(st_table *tab, st_foreach_check_callback_func *func, st_data_t arg, st_data_t never ATTRIBUTE_UNUSED)
st_table * st_copy(st_table *old_tab)
st_table * st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc)
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
ar_table_pair pairs[RHASH_AR_TABLE_MAX_SIZE]
st_foreach_callback_func * func
const struct st_hash_type * orighash
st_index_t(* hash)(st_data_t)
int(* compare)(st_data_t, st_data_t)
const struct st_hash_type * type
rb_hash_update_func * func
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
int rb_transient_heap_managed_ptr_p(const void *ptr)
char * ruby_strdup(const char *)
char * rb_w32_getenv(const char *)
char * rb_w32_ugetenv(const char *)