00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ruby/ruby.h"
00015 #include "ruby/st.h"
00016 #include "ruby/util.h"
00017 #include "ruby/encoding.h"
00018 #include "internal.h"
00019 #include <errno.h>
00020 #include "probes.h"
00021
00022 #ifdef __APPLE__
00023 # ifdef HAVE_CRT_EXTERNS_H
00024 # include <crt_externs.h>
00025 # else
00026 # include "missing/crt_externs.h"
00027 # endif
00028 #endif
00029
00030 #define HAS_EXTRA_STATES(hash, klass) ( \
00031 ((klass = has_extra_methods(rb_obj_class(hash))) != 0) || \
00032 FL_TEST((hash), FL_EXIVAR|FL_TAINT|HASH_PROC_DEFAULT) || \
00033 !NIL_P(RHASH_IFNONE(hash)))
00034 #define HASH_REJECT_COPY_EXTRA_STATES 1
00035
00036 static VALUE
00037 has_extra_methods(VALUE klass)
00038 {
00039 const VALUE base = rb_cHash;
00040 VALUE c = klass;
00041 while (c != base) {
00042 st_table *mtbl = RCLASS_M_TBL(c);
00043 if (mtbl && mtbl->num_entries) return klass;
00044 c = RCLASS_SUPER(c);
00045 }
00046 return 0;
00047 }
00048
00049 static VALUE rb_hash_s_try_convert(VALUE, VALUE);
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 VALUE
00062 rb_hash_freeze(VALUE hash)
00063 {
00064 return rb_obj_freeze(hash);
00065 }
00066
00067 VALUE rb_cHash;
00068
00069 static VALUE envtbl;
00070 static ID id_hash, id_yield, id_default, id_flatten_bang;
00071
00072 VALUE
00073 rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
00074 {
00075 RB_OBJ_WRITE(hash, (&RHASH(hash)->ifnone), ifnone);
00076 return hash;
00077 }
00078
00079 static int
00080 rb_any_cmp(VALUE a, VALUE b)
00081 {
00082 if (a == b) return 0;
00083 if (FIXNUM_P(a) && FIXNUM_P(b)) {
00084 return a != b;
00085 }
00086 if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString &&
00087 RB_TYPE_P(b, T_STRING) && RBASIC(b)->klass == rb_cString) {
00088 return rb_str_hash_cmp(a, b);
00089 }
00090 if (a == Qundef || b == Qundef) return -1;
00091 if (SYMBOL_P(a) && SYMBOL_P(b)) {
00092 return a != b;
00093 }
00094
00095 return !rb_eql(a, b);
00096 }
00097
00098 static VALUE
00099 hash_recursive(VALUE obj, VALUE arg, int recurse)
00100 {
00101 if (recurse) return INT2FIX(0);
00102 return rb_funcallv(obj, id_hash, 0, 0);
00103 }
00104
00105 VALUE
00106 rb_hash(VALUE obj)
00107 {
00108 VALUE hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
00109
00110 while (!FIXNUM_P(hval)) {
00111 if (RB_TYPE_P(hval, T_BIGNUM)) {
00112 int sign;
00113 unsigned long ul;
00114 sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0,
00115 INTEGER_PACK_NATIVE_BYTE_ORDER);
00116 ul &= (1UL << (sizeof(long)*CHAR_BIT-1)) - 1;
00117 if (sign < 0)
00118 return LONG2FIX(-(long)ul);
00119 return LONG2FIX((long)ul);
00120 }
00121 hval = rb_to_int(hval);
00122 }
00123 return hval;
00124 }
00125
00126 long rb_objid_hash(st_index_t index);
00127
00128 static st_index_t
00129 rb_any_hash(VALUE a)
00130 {
00131 VALUE hval;
00132 st_index_t hnum;
00133
00134 if (SPECIAL_CONST_P(a)) {
00135 if (a == Qundef) return 0;
00136 if (FLONUM_P(a)) {
00137
00138 goto flt;
00139 }
00140 hnum = rb_objid_hash((st_index_t)a);
00141 }
00142 else if (BUILTIN_TYPE(a) == T_STRING) {
00143 hnum = rb_str_hash(a);
00144 }
00145 else if (BUILTIN_TYPE(a) == T_FLOAT) {
00146 flt:
00147 hval = rb_dbl_hash(rb_float_value(a));
00148 hnum = FIX2LONG(hval);
00149 }
00150 else {
00151 hval = rb_hash(a);
00152 hnum = FIX2LONG(hval);
00153 }
00154 hnum <<= 1;
00155 return (st_index_t)RSHIFT(hnum, 1);
00156 }
00157
00158 long
00159 rb_objid_hash(st_index_t index)
00160 {
00161 st_index_t hnum = rb_hash_start(index);
00162 hnum = rb_hash_uint(hnum, (st_index_t)rb_any_hash);
00163 hnum = rb_hash_end(hnum);
00164 return hnum;
00165 }
00166
00167 static const struct st_hash_type objhash = {
00168 rb_any_cmp,
00169 rb_any_hash,
00170 };
00171
00172 extern const struct st_hash_type st_hashtype_num;
00173 #define identhash st_hashtype_num
00174
00175 typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
00176
00177 struct foreach_safe_arg {
00178 st_table *tbl;
00179 st_foreach_func *func;
00180 st_data_t arg;
00181 };
00182
00183 static int
00184 foreach_safe_i(st_data_t key, st_data_t value, st_data_t args, int error)
00185 {
00186 int status;
00187 struct foreach_safe_arg *arg = (void *)args;
00188
00189 if (error) return ST_STOP;
00190 status = (*arg->func)(key, value, arg->arg);
00191 if (status == ST_CONTINUE) {
00192 return ST_CHECK;
00193 }
00194 return status;
00195 }
00196
00197 void
00198 st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a)
00199 {
00200 struct foreach_safe_arg arg;
00201
00202 arg.tbl = table;
00203 arg.func = (st_foreach_func *)func;
00204 arg.arg = a;
00205 if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) {
00206 rb_raise(rb_eRuntimeError, "hash modified during iteration");
00207 }
00208 }
00209
00210 typedef int rb_foreach_func(VALUE, VALUE, VALUE);
00211
00212 struct hash_foreach_arg {
00213 VALUE hash;
00214 rb_foreach_func *func;
00215 VALUE arg;
00216 };
00217
00218 static int
00219 hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
00220 {
00221 struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp;
00222 int status;
00223 st_table *tbl;
00224
00225 if (error) return ST_STOP;
00226 tbl = RHASH(arg->hash)->ntbl;
00227 status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
00228 if (RHASH(arg->hash)->ntbl != tbl) {
00229 rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
00230 }
00231 switch (status) {
00232 case ST_DELETE:
00233 FL_SET(arg->hash, HASH_DELETED);
00234 return ST_DELETE;
00235 case ST_CONTINUE:
00236 break;
00237 case ST_STOP:
00238 return ST_STOP;
00239 }
00240 return ST_CHECK;
00241 }
00242
00243 static VALUE
00244 hash_foreach_ensure_rollback(VALUE hash)
00245 {
00246 RHASH_ITER_LEV(hash)++;
00247 return 0;
00248 }
00249
00250 static VALUE
00251 hash_foreach_ensure(VALUE hash)
00252 {
00253 if (--RHASH_ITER_LEV(hash) == 0) {
00254 if (FL_TEST(hash, HASH_DELETED)) {
00255 st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef);
00256 FL_UNSET(hash, HASH_DELETED);
00257 }
00258 }
00259 return 0;
00260 }
00261
00262 static VALUE
00263 hash_foreach_call(VALUE arg)
00264 {
00265 VALUE hash = ((struct hash_foreach_arg *)arg)->hash;
00266 if (st_foreach_check(RHASH(hash)->ntbl, hash_foreach_iter, (st_data_t)arg, (st_data_t)Qundef)) {
00267 rb_raise(rb_eRuntimeError, "hash modified during iteration");
00268 }
00269 return Qnil;
00270 }
00271
00272 void
00273 rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
00274 {
00275 struct hash_foreach_arg arg;
00276
00277 if (!RHASH(hash)->ntbl)
00278 return;
00279 RHASH_ITER_LEV(hash)++;
00280 arg.hash = hash;
00281 arg.func = (rb_foreach_func *)func;
00282 arg.arg = farg;
00283 rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
00284 }
00285
00286 static VALUE
00287 hash_alloc(VALUE klass)
00288 {
00289 NEWOBJ_OF(hash, struct RHash, klass, T_HASH | (RGENGC_WB_PROTECTED_HASH ? FL_WB_PROTECTED : 0));
00290
00291 RHASH_SET_IFNONE((VALUE)hash, Qnil);
00292
00293 return (VALUE)hash;
00294 }
00295
00296 static VALUE
00297 empty_hash_alloc(VALUE klass)
00298 {
00299 if (RUBY_DTRACE_HASH_CREATE_ENABLED()) {
00300 RUBY_DTRACE_HASH_CREATE(0, rb_sourcefile(), rb_sourceline());
00301 }
00302
00303 return hash_alloc(klass);
00304 }
00305
00306 VALUE
00307 rb_hash_new(void)
00308 {
00309 return hash_alloc(rb_cHash);
00310 }
00311
00312 static VALUE
00313 rb_hash_dup_empty(VALUE hash)
00314 {
00315 NEWOBJ_OF(ret, struct RHash,
00316 rb_obj_class(hash),
00317 (RBASIC(hash)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT));
00318 if (FL_TEST((hash), FL_EXIVAR))
00319 rb_copy_generic_ivar((VALUE)(ret),(VALUE)(hash));
00320
00321 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00322 FL_SET(ret, HASH_PROC_DEFAULT);
00323 }
00324 RHASH_SET_IFNONE(ret, RHASH_IFNONE(hash));
00325 return (VALUE)ret;
00326 }
00327
00328 VALUE
00329 rb_hash_dup(VALUE hash)
00330 {
00331 VALUE ret = rb_hash_dup_empty(hash);
00332 if (!RHASH_EMPTY_P(hash))
00333 RHASH(ret)->ntbl = st_copy(RHASH(hash)->ntbl);
00334 return ret;
00335 }
00336
00337 static void
00338 rb_hash_modify_check(VALUE hash)
00339 {
00340 rb_check_frozen(hash);
00341 }
00342
00343 static struct st_table *
00344 hash_tbl(VALUE hash)
00345 {
00346 if (!RHASH(hash)->ntbl) {
00347 RHASH(hash)->ntbl = st_init_table(&objhash);
00348 }
00349 return RHASH(hash)->ntbl;
00350 }
00351
00352 struct st_table *
00353 rb_hash_tbl(VALUE hash)
00354 {
00355 OBJ_WB_UNPROTECT(hash);
00356 return hash_tbl(hash);
00357 }
00358
00359 struct st_table *
00360 rb_hash_tbl_raw(VALUE hash)
00361 {
00362 return hash_tbl(hash);
00363 }
00364
00365 static void
00366 rb_hash_modify(VALUE hash)
00367 {
00368 rb_hash_modify_check(hash);
00369 hash_tbl(hash);
00370 }
00371
00372 NORETURN(static void no_new_key(void));
00373 static void
00374 no_new_key(void)
00375 {
00376 rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
00377 }
00378
00379 struct update_callback_arg {
00380 VALUE hash;
00381 st_data_t arg;
00382 };
00383
00384 #define NOINSERT_UPDATE_CALLBACK(func) \
00385 static int \
00386 func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
00387 { \
00388 if (!existing) no_new_key(); \
00389 return func(key, val, (struct update_arg *)arg, existing); \
00390 } \
00391 \
00392 static int \
00393 func##_insert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
00394 { \
00395 return func(key, val, (struct update_arg *)arg, existing); \
00396 }
00397
00398 struct update_arg {
00399 st_data_t arg;
00400 VALUE hash;
00401 VALUE new_key;
00402 VALUE old_key;
00403 VALUE new_value;
00404 VALUE old_value;
00405 };
00406
00407 static int
00408 tbl_update(VALUE hash, VALUE key, int (*func)(st_data_t *key, st_data_t *val, st_data_t arg, int existing), st_data_t optional_arg)
00409 {
00410 struct update_arg arg;
00411 int result;
00412
00413 arg.arg = optional_arg;
00414 arg.hash = hash;
00415 arg.new_key = 0;
00416 arg.old_key = Qundef;
00417 arg.new_value = 0;
00418 arg.old_value = Qundef;
00419
00420 result = st_update(RHASH(hash)->ntbl, (st_data_t)key, func, (st_data_t)&arg);
00421
00422
00423 if (arg.new_key) RB_OBJ_WRITTEN(hash, arg.old_key, arg.new_key);
00424 if (arg.new_value) RB_OBJ_WRITTEN(hash, arg.old_value, arg.new_value);
00425
00426 return result;
00427 }
00428
00429 #define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func##_insert)
00430
00431 #define RHASH_UPDATE_ITER(h, iter_lev, key, func, a) do { \
00432 tbl_update((h), (key), UPDATE_CALLBACK((iter_lev), func), (st_data_t)(a)); \
00433 } while (0)
00434
00435 #define RHASH_UPDATE(hash, key, func, arg) \
00436 RHASH_UPDATE_ITER(hash, RHASH_ITER_LEV(hash), key, func, arg)
00437
00438 static void
00439 default_proc_arity_check(VALUE proc)
00440 {
00441 int n = rb_proc_arity(proc);
00442
00443 if (rb_proc_lambda_p(proc) && n != 2 && (n >= 0 || n < -3)) {
00444 if (n < 0) n = -n-1;
00445 rb_raise(rb_eTypeError, "default_proc takes two arguments (2 for %d)", n);
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 static VALUE
00485 rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
00486 {
00487 VALUE ifnone;
00488
00489 rb_hash_modify(hash);
00490 if (rb_block_given_p()) {
00491 rb_check_arity(argc, 0, 0);
00492 ifnone = rb_block_proc();
00493 default_proc_arity_check(ifnone);
00494 RHASH_SET_IFNONE(hash, ifnone);
00495 FL_SET(hash, HASH_PROC_DEFAULT);
00496 }
00497 else {
00498 rb_scan_args(argc, argv, "01", &ifnone);
00499 RHASH_SET_IFNONE(hash, ifnone);
00500 }
00501
00502 return hash;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 static VALUE
00526 rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
00527 {
00528 VALUE hash, tmp;
00529 int i;
00530
00531 if (argc == 1) {
00532 tmp = rb_hash_s_try_convert(Qnil, argv[0]);
00533 if (!NIL_P(tmp)) {
00534 hash = hash_alloc(klass);
00535 if (RHASH(tmp)->ntbl) {
00536 RHASH(hash)->ntbl = st_copy(RHASH(tmp)->ntbl);
00537 }
00538 return hash;
00539 }
00540
00541 tmp = rb_check_array_type(argv[0]);
00542 if (!NIL_P(tmp)) {
00543 long i;
00544
00545 hash = hash_alloc(klass);
00546 for (i = 0; i < RARRAY_LEN(tmp); ++i) {
00547 VALUE e = RARRAY_AREF(tmp, i);
00548 VALUE v = rb_check_array_type(e);
00549 VALUE key, val = Qnil;
00550
00551 if (NIL_P(v)) {
00552 #if 0
00553 rb_raise(rb_eArgError, "wrong element type %s at %ld (expected array)",
00554 rb_builtin_class_name(e), i);
00555
00556 #else
00557 rb_warn("wrong element type %s at %ld (expected array)",
00558 rb_builtin_class_name(e), i);
00559 rb_warn("ignoring wrong elements is deprecated, remove them explicitly");
00560 rb_warn("this causes ArgumentError in the next release");
00561 continue;
00562 #endif
00563 }
00564 switch (RARRAY_LEN(v)) {
00565 default:
00566 rb_raise(rb_eArgError, "invalid number of elements (%ld for 1..2)",
00567 RARRAY_LEN(v));
00568 case 2:
00569 val = RARRAY_AREF(v, 1);
00570 case 1:
00571 key = RARRAY_AREF(v, 0);
00572 rb_hash_aset(hash, key, val);
00573 }
00574 }
00575 return hash;
00576 }
00577 }
00578 if (argc % 2 != 0) {
00579 rb_raise(rb_eArgError, "odd number of arguments for Hash");
00580 }
00581
00582 hash = hash_alloc(klass);
00583 for (i=0; i<argc; i+=2) {
00584 rb_hash_aset(hash, argv[i], argv[i + 1]);
00585 }
00586
00587 return hash;
00588 }
00589
00590 static VALUE
00591 to_hash(VALUE hash)
00592 {
00593 return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
00594 }
00595
00596 VALUE
00597 rb_check_hash_type(VALUE hash)
00598 {
00599 return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 static VALUE
00614 rb_hash_s_try_convert(VALUE dummy, VALUE hash)
00615 {
00616 return rb_check_hash_type(hash);
00617 }
00618
00619 struct rehash_arg {
00620 VALUE hash;
00621 st_table *tbl;
00622 };
00623
00624 static int
00625 rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
00626 {
00627 st_table *tbl = (st_table *)arg;
00628
00629 st_insert(tbl, (st_data_t)key, (st_data_t)value);
00630 return ST_CONTINUE;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 static VALUE
00654 rb_hash_rehash(VALUE hash)
00655 {
00656 VALUE tmp;
00657 st_table *tbl;
00658
00659 if (RHASH_ITER_LEV(hash) > 0) {
00660 rb_raise(rb_eRuntimeError, "rehash during iteration");
00661 }
00662 rb_hash_modify_check(hash);
00663 if (!RHASH(hash)->ntbl)
00664 return hash;
00665 tmp = hash_alloc(0);
00666 tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries);
00667 RHASH(tmp)->ntbl = tbl;
00668
00669 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl);
00670 st_free_table(RHASH(hash)->ntbl);
00671 RHASH(hash)->ntbl = tbl;
00672 RHASH(tmp)->ntbl = 0;
00673
00674 return hash;
00675 }
00676
00677 static VALUE
00678 hash_default_value(VALUE hash, VALUE key)
00679 {
00680 if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) {
00681 VALUE ifnone = RHASH_IFNONE(hash);
00682 if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone;
00683 if (key == Qundef) return Qnil;
00684 return rb_funcall(ifnone, id_yield, 2, hash, key);
00685 }
00686 else {
00687 return rb_funcall(hash, id_default, 1, key);
00688 }
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 VALUE
00706 rb_hash_aref(VALUE hash, VALUE key)
00707 {
00708 st_data_t val;
00709
00710 if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
00711 return hash_default_value(hash, key);
00712 }
00713 return (VALUE)val;
00714 }
00715
00716 VALUE
00717 rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
00718 {
00719 st_data_t val;
00720
00721 if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
00722 return def;
00723 }
00724 return (VALUE)val;
00725 }
00726
00727 VALUE
00728 rb_hash_lookup(VALUE hash, VALUE key)
00729 {
00730 return rb_hash_lookup2(hash, key, Qnil);
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 static VALUE
00763 rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
00764 {
00765 VALUE key, if_none;
00766 st_data_t val;
00767 long block_given;
00768
00769 rb_scan_args(argc, argv, "11", &key, &if_none);
00770
00771 block_given = rb_block_given_p();
00772 if (block_given && argc == 2) {
00773 rb_warn("block supersedes default value argument");
00774 }
00775 if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
00776 if (block_given) return rb_yield(key);
00777 if (argc == 1) {
00778 volatile VALUE desc = rb_protect(rb_inspect, key, 0);
00779 if (NIL_P(desc)) {
00780 desc = rb_any_to_s(key);
00781 }
00782 desc = rb_str_ellipsize(desc, 65);
00783 rb_raise(rb_eKeyError, "key not found: %"PRIsVALUE, desc);
00784 }
00785 return if_none;
00786 }
00787 return (VALUE)val;
00788 }
00789
00790 VALUE
00791 rb_hash_fetch(VALUE hash, VALUE key)
00792 {
00793 return rb_hash_fetch_m(1, &key, hash);
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 static VALUE
00818 rb_hash_default(int argc, VALUE *argv, VALUE hash)
00819 {
00820 VALUE key, ifnone;
00821
00822 rb_scan_args(argc, argv, "01", &key);
00823 ifnone = RHASH_IFNONE(hash);
00824 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00825 if (argc == 0) return Qnil;
00826 return rb_funcall(ifnone, id_yield, 2, hash, key);
00827 }
00828 return ifnone;
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 static VALUE
00852 rb_hash_set_default(VALUE hash, VALUE ifnone)
00853 {
00854 rb_hash_modify_check(hash);
00855 RHASH_SET_IFNONE(hash, ifnone);
00856 FL_UNSET(hash, HASH_PROC_DEFAULT);
00857 return ifnone;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 static VALUE
00876 rb_hash_default_proc(VALUE hash)
00877 {
00878 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00879 return RHASH_IFNONE(hash);
00880 }
00881 return Qnil;
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 static VALUE
00898 rb_hash_set_default_proc(VALUE hash, VALUE proc)
00899 {
00900 VALUE b;
00901
00902 rb_hash_modify_check(hash);
00903 if (NIL_P(proc)) {
00904 FL_UNSET(hash, HASH_PROC_DEFAULT);
00905 RHASH_SET_IFNONE(hash, proc);
00906 return proc;
00907 }
00908 b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
00909 if (NIL_P(b) || !rb_obj_is_proc(b)) {
00910 rb_raise(rb_eTypeError,
00911 "wrong default_proc type %s (expected Proc)",
00912 rb_obj_classname(proc));
00913 }
00914 proc = b;
00915 default_proc_arity_check(proc);
00916 RHASH_SET_IFNONE(hash, proc);
00917 FL_SET(hash, HASH_PROC_DEFAULT);
00918 return proc;
00919 }
00920
00921 static int
00922 key_i(VALUE key, VALUE value, VALUE arg)
00923 {
00924 VALUE *args = (VALUE *)arg;
00925
00926 if (rb_equal(value, args[0])) {
00927 args[1] = key;
00928 return ST_STOP;
00929 }
00930 return ST_CONTINUE;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 static VALUE
00948 rb_hash_key(VALUE hash, VALUE value)
00949 {
00950 VALUE args[2];
00951
00952 args[0] = value;
00953 args[1] = Qnil;
00954
00955 rb_hash_foreach(hash, key_i, (VALUE)args);
00956
00957 return args[1];
00958 }
00959
00960
00961 static VALUE
00962 rb_hash_index(VALUE hash, VALUE value)
00963 {
00964 rb_warn("Hash#index is deprecated; use Hash#key");
00965 return rb_hash_key(hash, value);
00966 }
00967
00968 static VALUE
00969 rb_hash_delete_key(VALUE hash, VALUE key)
00970 {
00971 st_data_t ktmp = (st_data_t)key, val;
00972
00973 if (!RHASH(hash)->ntbl)
00974 return Qundef;
00975 if (RHASH_ITER_LEV(hash) > 0) {
00976 if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, (st_data_t)Qundef)) {
00977 FL_SET(hash, HASH_DELETED);
00978 return (VALUE)val;
00979 }
00980 }
00981 else if (st_delete(RHASH(hash)->ntbl, &ktmp, &val))
00982 return (VALUE)val;
00983 return Qundef;
00984 }
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 VALUE
01005 rb_hash_delete(VALUE hash, VALUE key)
01006 {
01007 VALUE val;
01008
01009 rb_hash_modify_check(hash);
01010 val = rb_hash_delete_key(hash, key);
01011 if (val != Qundef) return val;
01012 if (rb_block_given_p()) {
01013 return rb_yield(key);
01014 }
01015 return Qnil;
01016 }
01017
01018 struct shift_var {
01019 VALUE key;
01020 VALUE val;
01021 };
01022
01023 static int
01024 shift_i_safe(VALUE key, VALUE value, VALUE arg)
01025 {
01026 struct shift_var *var = (struct shift_var *)arg;
01027
01028 var->key = key;
01029 var->val = value;
01030 return ST_STOP;
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046 static VALUE
01047 rb_hash_shift(VALUE hash)
01048 {
01049 struct shift_var var;
01050
01051 rb_hash_modify_check(hash);
01052 if (RHASH(hash)->ntbl) {
01053 var.key = Qundef;
01054 if (RHASH_ITER_LEV(hash) == 0) {
01055 if (st_shift(RHASH(hash)->ntbl, &var.key, &var.val)) {
01056 return rb_assoc_new(var.key, var.val);
01057 }
01058 }
01059 else {
01060 rb_hash_foreach(hash, shift_i_safe, (VALUE)&var);
01061 if (var.key != Qundef) {
01062 rb_hash_delete_key(hash, var.key);
01063 return rb_assoc_new(var.key, var.val);
01064 }
01065 }
01066 }
01067 return hash_default_value(hash, Qnil);
01068 }
01069
01070 static int
01071 delete_if_i(VALUE key, VALUE value, VALUE hash)
01072 {
01073 if (RTEST(rb_yield_values(2, key, value))) {
01074 return ST_DELETE;
01075 }
01076 return ST_CONTINUE;
01077 }
01078
01079 static VALUE rb_hash_size(VALUE hash);
01080
01081 static VALUE
01082 hash_enum_size(VALUE hash, VALUE args, VALUE eobj)
01083 {
01084 return rb_hash_size(hash);
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 VALUE
01103 rb_hash_delete_if(VALUE hash)
01104 {
01105 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01106 rb_hash_modify_check(hash);
01107 if (RHASH(hash)->ntbl)
01108 rb_hash_foreach(hash, delete_if_i, hash);
01109 return hash;
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 VALUE
01122 rb_hash_reject_bang(VALUE hash)
01123 {
01124 st_index_t n;
01125
01126 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01127 rb_hash_modify(hash);
01128 n = RHASH_SIZE(hash);
01129 if (!n) return Qnil;
01130 rb_hash_foreach(hash, delete_if_i, hash);
01131 if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
01132 return hash;
01133 }
01134
01135 static int
01136 reject_i(VALUE key, VALUE value, VALUE result)
01137 {
01138 if (!RTEST(rb_yield_values(2, key, value))) {
01139 rb_hash_aset(result, key, value);
01140 }
01141 return ST_CONTINUE;
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 VALUE
01159 rb_hash_reject(VALUE hash)
01160 {
01161 VALUE result;
01162
01163 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01164 if (RTEST(ruby_verbose)) {
01165 VALUE klass;
01166 if (HAS_EXTRA_STATES(hash, klass)) {
01167 #if HASH_REJECT_COPY_EXTRA_STATES
01168 rb_warn("copying extra states: %+"PRIsVALUE, hash);
01169 rb_warn("following states will not be copied in the future version:");
01170 if (klass) {
01171 rb_warn(" subclass: %+"PRIsVALUE, klass);
01172 }
01173 if (FL_TEST(hash, FL_EXIVAR)) {
01174 rb_warn(" instance variables: %+"PRIsVALUE,
01175 rb_obj_instance_variables(hash));
01176 }
01177 if (FL_TEST(hash, FL_TAINT)) {
01178 rb_warn(" taintedness");
01179 }
01180 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
01181 rb_warn(" default proc: %+"PRIsVALUE, RHASH_IFNONE(hash));
01182 }
01183 else if (!NIL_P(RHASH_IFNONE(hash)))
01184 rb_warn(" default value: %+"PRIsVALUE, RHASH_IFNONE(hash));
01185 #else
01186 rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash);
01187 #endif
01188 }
01189 }
01190 #if HASH_REJECT_COPY_EXTRA_STATES
01191 result = rb_hash_dup_empty(hash);
01192 #else
01193 result = rb_hash_new();
01194 #endif
01195 if (!RHASH_EMPTY_P(hash)) {
01196 rb_hash_foreach(hash, reject_i, result);
01197 }
01198 return result;
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 VALUE
01213 rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
01214 {
01215 VALUE result = rb_ary_new2(argc);
01216 long i;
01217
01218 for (i=0; i<argc; i++) {
01219 rb_ary_push(result, rb_hash_aref(hash, argv[i]));
01220 }
01221 return result;
01222 }
01223
01224 static int
01225 select_i(VALUE key, VALUE value, VALUE result)
01226 {
01227 if (RTEST(rb_yield_values(2, key, value))) {
01228 rb_hash_aset(result, key, value);
01229 }
01230 return ST_CONTINUE;
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247 VALUE
01248 rb_hash_select(VALUE hash)
01249 {
01250 VALUE result;
01251
01252 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01253 result = rb_hash_new();
01254 if (!RHASH_EMPTY_P(hash)) {
01255 rb_hash_foreach(hash, select_i, result);
01256 }
01257 return result;
01258 }
01259
01260 static int
01261 keep_if_i(VALUE key, VALUE value, VALUE hash)
01262 {
01263 if (!RTEST(rb_yield_values(2, key, value))) {
01264 return ST_DELETE;
01265 }
01266 return ST_CONTINUE;
01267 }
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278 VALUE
01279 rb_hash_select_bang(VALUE hash)
01280 {
01281 st_index_t n;
01282
01283 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01284 rb_hash_modify_check(hash);
01285 if (!RHASH(hash)->ntbl)
01286 return Qnil;
01287 n = RHASH(hash)->ntbl->num_entries;
01288 rb_hash_foreach(hash, keep_if_i, hash);
01289 if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
01290 return hash;
01291 }
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 VALUE
01306 rb_hash_keep_if(VALUE hash)
01307 {
01308 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01309 rb_hash_modify_check(hash);
01310 if (RHASH(hash)->ntbl)
01311 rb_hash_foreach(hash, keep_if_i, hash);
01312 return hash;
01313 }
01314
01315 static int
01316 clear_i(VALUE key, VALUE value, VALUE dummy)
01317 {
01318 return ST_DELETE;
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 VALUE
01333 rb_hash_clear(VALUE hash)
01334 {
01335 rb_hash_modify_check(hash);
01336 if (!RHASH(hash)->ntbl)
01337 return hash;
01338 if (RHASH(hash)->ntbl->num_entries > 0) {
01339 if (RHASH_ITER_LEV(hash) > 0)
01340 rb_hash_foreach(hash, clear_i, 0);
01341 else
01342 st_clear(RHASH(hash)->ntbl);
01343 }
01344
01345 return hash;
01346 }
01347
01348 static int
01349 hash_aset(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
01350 {
01351 if (existing) {
01352 arg->new_value = arg->arg;
01353 arg->old_value = *val;
01354 }
01355 else {
01356 arg->new_key = *key;
01357 arg->new_value = arg->arg;
01358 }
01359 *val = arg->arg;
01360 return ST_CONTINUE;
01361 }
01362
01363 static int
01364 hash_aset_str(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
01365 {
01366 if (!existing) {
01367 *key = rb_str_new_frozen(*key);
01368 }
01369 return hash_aset(key, val, arg, existing);
01370 }
01371
01372 NOINSERT_UPDATE_CALLBACK(hash_aset);
01373 NOINSERT_UPDATE_CALLBACK(hash_aset_str);
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401 VALUE
01402 rb_hash_aset(VALUE hash, VALUE key, VALUE val)
01403 {
01404 int iter_lev = RHASH_ITER_LEV(hash);
01405 st_table *tbl = RHASH(hash)->ntbl;
01406
01407 rb_hash_modify(hash);
01408 if (!tbl) {
01409 if (iter_lev > 0) no_new_key();
01410 tbl = hash_tbl(hash);
01411 }
01412 if (tbl->type == &identhash || rb_obj_class(key) != rb_cString) {
01413 RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
01414 }
01415 else {
01416 RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val);
01417 }
01418 return val;
01419 }
01420
01421 static int
01422 replace_i(VALUE key, VALUE val, VALUE hash)
01423 {
01424 rb_hash_aset(hash, key, val);
01425
01426 return ST_CONTINUE;
01427 }
01428
01429
01430 static VALUE
01431 rb_hash_initialize_copy(VALUE hash, VALUE hash2)
01432 {
01433 st_table *ntbl;
01434
01435 rb_hash_modify_check(hash);
01436 hash2 = to_hash(hash2);
01437
01438 Check_Type(hash2, T_HASH);
01439
01440 if (hash == hash2) return hash;
01441
01442 ntbl = RHASH(hash)->ntbl;
01443 if (RHASH(hash2)->ntbl) {
01444 if (ntbl) st_free_table(ntbl);
01445 RHASH(hash)->ntbl = st_copy(RHASH(hash2)->ntbl);
01446 if (RHASH(hash)->ntbl->num_entries)
01447 rb_hash_rehash(hash);
01448 }
01449 else if (ntbl) {
01450 st_clear(ntbl);
01451 }
01452
01453 if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
01454 FL_SET(hash, HASH_PROC_DEFAULT);
01455 }
01456 else {
01457 FL_UNSET(hash, HASH_PROC_DEFAULT);
01458 }
01459 RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
01460
01461 return hash;
01462 }
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476 static VALUE
01477 rb_hash_replace(VALUE hash, VALUE hash2)
01478 {
01479 st_table *table2;
01480
01481 rb_hash_modify_check(hash);
01482 if (hash == hash2) return hash;
01483 hash2 = to_hash(hash2);
01484
01485 RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
01486 if (FL_TEST(hash2, HASH_PROC_DEFAULT))
01487 FL_SET(hash, HASH_PROC_DEFAULT);
01488 else
01489 FL_UNSET(hash, HASH_PROC_DEFAULT);
01490
01491 table2 = RHASH(hash2)->ntbl;
01492
01493 rb_hash_clear(hash);
01494 if (table2) hash_tbl(hash)->type = table2->type;
01495 rb_hash_foreach(hash2, replace_i, hash);
01496
01497 return hash;
01498 }
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 static VALUE
01514 rb_hash_size(VALUE hash)
01515 {
01516 return INT2FIX(RHASH_SIZE(hash));
01517 }
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530 static VALUE
01531 rb_hash_empty_p(VALUE hash)
01532 {
01533 return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
01534 }
01535
01536 static int
01537 each_value_i(VALUE key, VALUE value)
01538 {
01539 rb_yield(value);
01540 return ST_CONTINUE;
01541 }
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 static VALUE
01563 rb_hash_each_value(VALUE hash)
01564 {
01565 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01566 rb_hash_foreach(hash, each_value_i, 0);
01567 return hash;
01568 }
01569
01570 static int
01571 each_key_i(VALUE key, VALUE value)
01572 {
01573 rb_yield(key);
01574 return ST_CONTINUE;
01575 }
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595 static VALUE
01596 rb_hash_each_key(VALUE hash)
01597 {
01598 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01599 rb_hash_foreach(hash, each_key_i, 0);
01600 return hash;
01601 }
01602
01603 static int
01604 each_pair_i(VALUE key, VALUE value)
01605 {
01606 rb_yield(rb_assoc_new(key, value));
01607 return ST_CONTINUE;
01608 }
01609
01610 static int
01611 each_pair_i_fast(VALUE key, VALUE value)
01612 {
01613 rb_yield_values(2, key, value);
01614 return ST_CONTINUE;
01615 }
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639 static VALUE
01640 rb_hash_each_pair(VALUE hash)
01641 {
01642 RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
01643 if (rb_block_arity() > 1)
01644 rb_hash_foreach(hash, each_pair_i_fast, 0);
01645 else
01646 rb_hash_foreach(hash, each_pair_i, 0);
01647 return hash;
01648 }
01649
01650 static int
01651 to_a_i(VALUE key, VALUE value, VALUE ary)
01652 {
01653 rb_ary_push(ary, rb_assoc_new(key, value));
01654 return ST_CONTINUE;
01655 }
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668 static VALUE
01669 rb_hash_to_a(VALUE hash)
01670 {
01671 VALUE ary;
01672
01673 ary = rb_ary_new_capa(RHASH_SIZE(hash));
01674 rb_hash_foreach(hash, to_a_i, ary);
01675 OBJ_INFECT(ary, hash);
01676
01677 return ary;
01678 }
01679
01680 static int
01681 inspect_i(VALUE key, VALUE value, VALUE str)
01682 {
01683 VALUE str2;
01684
01685 str2 = rb_inspect(key);
01686 if (RSTRING_LEN(str) > 1) {
01687 rb_str_buf_cat_ascii(str, ", ");
01688 }
01689 else {
01690 rb_enc_copy(str, str2);
01691 }
01692 rb_str_buf_append(str, str2);
01693 OBJ_INFECT(str, str2);
01694 rb_str_buf_cat_ascii(str, "=>");
01695 str2 = rb_inspect(value);
01696 rb_str_buf_append(str, str2);
01697 OBJ_INFECT(str, str2);
01698
01699 return ST_CONTINUE;
01700 }
01701
01702 static VALUE
01703 inspect_hash(VALUE hash, VALUE dummy, int recur)
01704 {
01705 VALUE str;
01706
01707 if (recur) return rb_usascii_str_new2("{...}");
01708 str = rb_str_buf_new2("{");
01709 rb_hash_foreach(hash, inspect_i, str);
01710 rb_str_buf_cat2(str, "}");
01711 OBJ_INFECT(str, hash);
01712
01713 return str;
01714 }
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727 static VALUE
01728 rb_hash_inspect(VALUE hash)
01729 {
01730 if (RHASH_EMPTY_P(hash))
01731 return rb_usascii_str_new2("{}");
01732 return rb_exec_recursive(inspect_hash, hash, 0);
01733 }
01734
01735
01736
01737
01738
01739
01740
01741
01742 static VALUE
01743 rb_hash_to_hash(VALUE hash)
01744 {
01745 return hash;
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756 static VALUE
01757 rb_hash_to_h(VALUE hash)
01758 {
01759 if (rb_obj_class(hash) != rb_cHash) {
01760 VALUE ret = rb_hash_new();
01761 if (!RHASH_EMPTY_P(hash))
01762 RHASH(ret)->ntbl = st_copy(RHASH(hash)->ntbl);
01763 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
01764 FL_SET(ret, HASH_PROC_DEFAULT);
01765 }
01766 RHASH_SET_IFNONE(ret, RHASH_IFNONE(hash));
01767 return ret;
01768 }
01769 return hash;
01770 }
01771
01772 static int
01773 keys_i(VALUE key, VALUE value, VALUE ary)
01774 {
01775 rb_ary_push(ary, key);
01776 return ST_CONTINUE;
01777 }
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791 VALUE
01792 rb_hash_keys(VALUE hash)
01793 {
01794 VALUE keys;
01795 st_index_t size = RHASH_SIZE(hash);
01796
01797 keys = rb_ary_new_capa(size);
01798 if (size == 0) return keys;
01799
01800 if (ST_DATA_COMPATIBLE_P(VALUE)) {
01801 st_table *table = RHASH(hash)->ntbl;
01802
01803 if (OBJ_PROMOTED(keys)) rb_gc_writebarrier_remember_promoted(keys);
01804 RARRAY_PTR_USE(keys, ptr, {
01805 size = st_keys_check(table, ptr, size, Qundef);
01806 });
01807 rb_ary_set_len(keys, size);
01808 }
01809 else {
01810 rb_hash_foreach(hash, keys_i, keys);
01811 }
01812
01813 return keys;
01814 }
01815
01816 static int
01817 values_i(VALUE key, VALUE value, VALUE ary)
01818 {
01819 rb_ary_push(ary, value);
01820 return ST_CONTINUE;
01821 }
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835 VALUE
01836 rb_hash_values(VALUE hash)
01837 {
01838 VALUE values;
01839 st_index_t size = RHASH_SIZE(hash);
01840
01841 values = rb_ary_new_capa(size);
01842 if (size == 0) return values;
01843
01844 if (ST_DATA_COMPATIBLE_P(VALUE)) {
01845 st_table *table = RHASH(hash)->ntbl;
01846
01847 if (OBJ_PROMOTED(values)) rb_gc_writebarrier_remember_promoted(values);
01848 RARRAY_PTR_USE(values, ptr, {
01849 size = st_values_check(table, ptr, size, Qundef);
01850 });
01851 rb_ary_set_len(values, size);
01852 }
01853 else {
01854 rb_hash_foreach(hash, values_i, values);
01855 }
01856
01857 return values;
01858 }
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875 static VALUE
01876 rb_hash_has_key(VALUE hash, VALUE key)
01877 {
01878 if (!RHASH(hash)->ntbl)
01879 return Qfalse;
01880 if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
01881 return Qtrue;
01882 }
01883 return Qfalse;
01884 }
01885
01886 static int
01887 rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
01888 {
01889 VALUE *data = (VALUE *)arg;
01890
01891 if (rb_equal(value, data[1])) {
01892 data[0] = Qtrue;
01893 return ST_STOP;
01894 }
01895 return ST_CONTINUE;
01896 }
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 static VALUE
01912 rb_hash_has_value(VALUE hash, VALUE val)
01913 {
01914 VALUE data[2];
01915
01916 data[0] = Qfalse;
01917 data[1] = val;
01918 rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
01919 return data[0];
01920 }
01921
01922 struct equal_data {
01923 VALUE result;
01924 st_table *tbl;
01925 int eql;
01926 };
01927
01928 static int
01929 eql_i(VALUE key, VALUE val1, VALUE arg)
01930 {
01931 struct equal_data *data = (struct equal_data *)arg;
01932 st_data_t val2;
01933
01934 if (!st_lookup(data->tbl, key, &val2)) {
01935 data->result = Qfalse;
01936 return ST_STOP;
01937 }
01938 if (!(data->eql ? rb_eql(val1, (VALUE)val2) : (int)rb_equal(val1, (VALUE)val2))) {
01939 data->result = Qfalse;
01940 return ST_STOP;
01941 }
01942 return ST_CONTINUE;
01943 }
01944
01945 static VALUE
01946 recursive_eql(VALUE hash, VALUE dt, int recur)
01947 {
01948 struct equal_data *data;
01949
01950 if (recur) return Qtrue;
01951 data = (struct equal_data*)dt;
01952 data->result = Qtrue;
01953 rb_hash_foreach(hash, eql_i, dt);
01954
01955 return data->result;
01956 }
01957
01958 static VALUE
01959 hash_equal(VALUE hash1, VALUE hash2, int eql)
01960 {
01961 struct equal_data data;
01962
01963 if (hash1 == hash2) return Qtrue;
01964 if (!RB_TYPE_P(hash2, T_HASH)) {
01965 if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
01966 return Qfalse;
01967 }
01968 if (eql)
01969 return rb_eql(hash2, hash1);
01970 else
01971 return rb_equal(hash2, hash1);
01972 }
01973 if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
01974 return Qfalse;
01975 if (!RHASH(hash1)->ntbl || !RHASH(hash2)->ntbl)
01976 return Qtrue;
01977 if (RHASH(hash1)->ntbl->type != RHASH(hash2)->ntbl->type)
01978 return Qfalse;
01979 #if 0
01980 if (!(rb_equal(RHASH_IFNONE(hash1), RHASH_IFNONE(hash2)) &&
01981 FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
01982 return Qfalse;
01983 #endif
01984
01985 data.tbl = RHASH(hash2)->ntbl;
01986 data.eql = eql;
01987 return rb_exec_recursive_paired(recursive_eql, hash1, hash2, (VALUE)&data);
01988 }
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009 static VALUE
02010 rb_hash_equal(VALUE hash1, VALUE hash2)
02011 {
02012 return hash_equal(hash1, hash2, FALSE);
02013 }
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023 static VALUE
02024 rb_hash_eql(VALUE hash1, VALUE hash2)
02025 {
02026 return hash_equal(hash1, hash2, TRUE);
02027 }
02028
02029 static int
02030 hash_i(VALUE key, VALUE val, VALUE arg)
02031 {
02032 st_index_t *hval = (st_index_t *)arg;
02033 st_index_t hdata[2];
02034
02035 hdata[0] = rb_hash(key);
02036 hdata[1] = rb_hash(val);
02037 *hval ^= st_hash(hdata, sizeof(hdata), 0);
02038 return ST_CONTINUE;
02039 }
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049 static VALUE
02050 rb_hash_hash(VALUE hash)
02051 {
02052 st_index_t size = RHASH_SIZE(hash);
02053 st_index_t hval = rb_hash_start(size);
02054 hval = rb_hash_uint(hval, (st_index_t)rb_hash_hash);
02055 if (size) {
02056 rb_hash_foreach(hash, hash_i, (VALUE)&hval);
02057 }
02058 hval = rb_hash_end(hval);
02059 return INT2FIX(hval);
02060 }
02061
02062 static int
02063 rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
02064 {
02065 rb_hash_aset(hash, value, key);
02066 return ST_CONTINUE;
02067 }
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081 static VALUE
02082 rb_hash_invert(VALUE hash)
02083 {
02084 VALUE h = rb_hash_new();
02085
02086 rb_hash_foreach(hash, rb_hash_invert_i, h);
02087 return h;
02088 }
02089
02090 static int
02091 rb_hash_update_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
02092 {
02093 if (existing) {
02094 arg->old_value = *value;
02095 arg->new_value = arg->arg;
02096 }
02097 else {
02098 arg->new_key = *key;
02099 arg->new_value = arg->arg;
02100 }
02101 *value = arg->arg;
02102 return ST_CONTINUE;
02103 }
02104
02105 NOINSERT_UPDATE_CALLBACK(rb_hash_update_callback);
02106
02107 static int
02108 rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
02109 {
02110 RHASH_UPDATE(hash, key, rb_hash_update_callback, value);
02111 return ST_CONTINUE;
02112 }
02113
02114 static int
02115 rb_hash_update_block_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
02116 {
02117 VALUE newvalue = (VALUE)arg->arg;
02118
02119 if (existing) {
02120 newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue);
02121 arg->old_value = *value;
02122 arg->new_value = newvalue;
02123 }
02124 else {
02125 arg->new_key = *key;
02126 arg->new_value = newvalue;
02127 }
02128 *value = newvalue;
02129 return ST_CONTINUE;
02130 }
02131
02132 NOINSERT_UPDATE_CALLBACK(rb_hash_update_block_callback);
02133
02134 static int
02135 rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
02136 {
02137 RHASH_UPDATE(hash, key, rb_hash_update_block_callback, value);
02138 return ST_CONTINUE;
02139 }
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164 static VALUE
02165 rb_hash_update(VALUE hash1, VALUE hash2)
02166 {
02167 rb_hash_modify(hash1);
02168 hash2 = to_hash(hash2);
02169 if (rb_block_given_p()) {
02170 rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
02171 }
02172 else {
02173 rb_hash_foreach(hash2, rb_hash_update_i, hash1);
02174 }
02175 return hash1;
02176 }
02177
02178 struct update_func_arg {
02179 VALUE hash;
02180 VALUE value;
02181 rb_hash_update_func *func;
02182 };
02183
02184 static int
02185 rb_hash_update_func_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
02186 {
02187 struct update_func_arg *uf_arg = (struct update_func_arg *)arg->arg;
02188 VALUE newvalue = uf_arg->value;
02189
02190 if (existing) {
02191 newvalue = (*uf_arg->func)((VALUE)*key, (VALUE)*value, newvalue);
02192 arg->old_value = *value;
02193 arg->new_value = newvalue;
02194 }
02195 else {
02196 arg->new_key = *key;
02197 arg->new_value = newvalue;
02198 }
02199 *value = newvalue;
02200 return ST_CONTINUE;
02201 }
02202
02203 NOINSERT_UPDATE_CALLBACK(rb_hash_update_func_callback);
02204
02205 static int
02206 rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0)
02207 {
02208 struct update_func_arg *arg = (struct update_func_arg *)arg0;
02209 VALUE hash = arg->hash;
02210
02211 arg->value = value;
02212 RHASH_UPDATE(hash, key, rb_hash_update_func_callback, (VALUE)arg);
02213 return ST_CONTINUE;
02214 }
02215
02216 VALUE
02217 rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
02218 {
02219 rb_hash_modify(hash1);
02220 hash2 = to_hash(hash2);
02221 if (func) {
02222 struct update_func_arg arg;
02223 arg.hash = hash1;
02224 arg.func = func;
02225 rb_hash_foreach(hash2, rb_hash_update_func_i, (VALUE)&arg);
02226 }
02227 else {
02228 rb_hash_foreach(hash2, rb_hash_update_i, hash1);
02229 }
02230 return hash1;
02231 }
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253 static VALUE
02254 rb_hash_merge(VALUE hash1, VALUE hash2)
02255 {
02256 return rb_hash_update(rb_obj_dup(hash1), hash2);
02257 }
02258
02259 static int
02260 assoc_cmp(VALUE a, VALUE b)
02261 {
02262 return !RTEST(rb_equal(a, b));
02263 }
02264
02265 static VALUE
02266 lookup2_call(VALUE arg)
02267 {
02268 VALUE *args = (VALUE *)arg;
02269 return rb_hash_lookup2(args[0], args[1], Qundef);
02270 }
02271
02272 struct reset_hash_type_arg {
02273 VALUE hash;
02274 const struct st_hash_type *orighash;
02275 };
02276
02277 static VALUE
02278 reset_hash_type(VALUE arg)
02279 {
02280 struct reset_hash_type_arg *p = (struct reset_hash_type_arg *)arg;
02281 RHASH(p->hash)->ntbl->type = p->orighash;
02282 return Qundef;
02283 }
02284
02285 static int
02286 assoc_i(VALUE key, VALUE val, VALUE arg)
02287 {
02288 VALUE *args = (VALUE *)arg;
02289
02290 if (RTEST(rb_equal(args[0], key))) {
02291 args[1] = rb_assoc_new(key, val);
02292 return ST_STOP;
02293 }
02294 return ST_CONTINUE;
02295 }
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311 VALUE
02312 rb_hash_assoc(VALUE hash, VALUE key)
02313 {
02314 st_table *table;
02315 const struct st_hash_type *orighash;
02316 VALUE args[2];
02317
02318 if (RHASH_EMPTY_P(hash)) return Qnil;
02319 table = RHASH(hash)->ntbl;
02320 orighash = table->type;
02321
02322 if (orighash != &identhash) {
02323 VALUE value;
02324 struct reset_hash_type_arg ensure_arg;
02325 struct st_hash_type assochash;
02326
02327 assochash.compare = assoc_cmp;
02328 assochash.hash = orighash->hash;
02329 table->type = &assochash;
02330 args[0] = hash;
02331 args[1] = key;
02332 ensure_arg.hash = hash;
02333 ensure_arg.orighash = orighash;
02334 value = rb_ensure(lookup2_call, (VALUE)&args, reset_hash_type, (VALUE)&ensure_arg);
02335 if (value != Qundef) return rb_assoc_new(key, value);
02336 }
02337
02338 args[0] = key;
02339 args[1] = Qnil;
02340 rb_hash_foreach(hash, assoc_i, (VALUE)args);
02341 return args[1];
02342 }
02343
02344 static int
02345 rassoc_i(VALUE key, VALUE val, VALUE arg)
02346 {
02347 VALUE *args = (VALUE *)arg;
02348
02349 if (RTEST(rb_equal(args[0], val))) {
02350 args[1] = rb_assoc_new(key, val);
02351 return ST_STOP;
02352 }
02353 return ST_CONTINUE;
02354 }
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369 VALUE
02370 rb_hash_rassoc(VALUE hash, VALUE obj)
02371 {
02372 VALUE args[2];
02373
02374 args[0] = obj;
02375 args[1] = Qnil;
02376 rb_hash_foreach(hash, rassoc_i, (VALUE)args);
02377 return args[1];
02378 }
02379
02380 static int
02381 flatten_i(VALUE key, VALUE val, VALUE ary)
02382 {
02383 VALUE pair[2];
02384
02385 pair[0] = key;
02386 pair[1] = val;
02387 rb_ary_cat(ary, pair, 2);
02388
02389 return ST_CONTINUE;
02390 }
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408 static VALUE
02409 rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
02410 {
02411 VALUE ary;
02412
02413 if (argc) {
02414 int level = NUM2INT(*argv);
02415 if (level == 0) return rb_hash_to_a(hash);
02416
02417 ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
02418 rb_hash_foreach(hash, flatten_i, ary);
02419 if (level - 1 > 0) {
02420 *argv = INT2FIX(level - 1);
02421 rb_funcall2(ary, id_flatten_bang, argc, argv);
02422 }
02423 else if (level < 0) {
02424 rb_funcall2(ary, id_flatten_bang, 0, 0);
02425 }
02426 }
02427 else {
02428 ary = rb_ary_new_capa(RHASH_SIZE(hash) * 2);
02429 rb_hash_foreach(hash, flatten_i, ary);
02430 }
02431
02432 return ary;
02433 }
02434
02435 static VALUE rb_hash_compare_by_id_p(VALUE hash);
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453 static VALUE
02454 rb_hash_compare_by_id(VALUE hash)
02455 {
02456 if (rb_hash_compare_by_id_p(hash)) return hash;
02457 rb_hash_modify(hash);
02458 RHASH(hash)->ntbl->type = &identhash;
02459 rb_hash_rehash(hash);
02460 return hash;
02461 }
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472 static VALUE
02473 rb_hash_compare_by_id_p(VALUE hash)
02474 {
02475 if (!RHASH(hash)->ntbl)
02476 return Qfalse;
02477 if (RHASH(hash)->ntbl->type == &identhash) {
02478 return Qtrue;
02479 }
02480 return Qfalse;
02481 }
02482
02483 static int path_tainted = -1;
02484
02485 static char **origenviron;
02486 #ifdef _WIN32
02487 #define GET_ENVIRON(e) ((e) = rb_w32_get_environ())
02488 #define FREE_ENVIRON(e) rb_w32_free_environ(e)
02489 static char **my_environ;
02490 #undef environ
02491 #define environ my_environ
02492 #undef getenv
02493 static inline char *
02494 w32_getenv(const char *name)
02495 {
02496 static int binary = -1;
02497 static int locale = -1;
02498 if (binary < 0) {
02499 binary = rb_ascii8bit_encindex();
02500 locale = rb_locale_encindex();
02501 }
02502 return locale == binary ? rb_w32_getenv(name) : rb_w32_ugetenv(name);
02503 }
02504 #define getenv(n) w32_getenv(n)
02505 #elif defined(__APPLE__)
02506 #undef environ
02507 #define environ (*_NSGetEnviron())
02508 #define GET_ENVIRON(e) (e)
02509 #define FREE_ENVIRON(e)
02510 #else
02511 extern char **environ;
02512 #define GET_ENVIRON(e) (e)
02513 #define FREE_ENVIRON(e)
02514 #endif
02515 #ifdef ENV_IGNORECASE
02516 #define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
02517 #define ENVNMATCH(s1, s2, n) (STRNCASECMP((s1), (s2), (n)) == 0)
02518 #else
02519 #define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
02520 #define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
02521 #endif
02522
02523 static VALUE
02524 env_str_new(const char *ptr, long len)
02525 {
02526 #ifdef _WIN32
02527 VALUE str = rb_str_conv_enc(rb_str_new(ptr, len), rb_utf8_encoding(), rb_locale_encoding());
02528 #else
02529 VALUE str = rb_locale_str_new(ptr, len);
02530 #endif
02531
02532 rb_obj_freeze(str);
02533 return str;
02534 }
02535
02536 static VALUE
02537 env_str_new2(const char *ptr)
02538 {
02539 if (!ptr) return Qnil;
02540 return env_str_new(ptr, strlen(ptr));
02541 }
02542
02543 static VALUE
02544 env_delete(VALUE obj, VALUE name)
02545 {
02546 char *nam, *val;
02547
02548 SafeStringValue(name);
02549 nam = RSTRING_PTR(name);
02550 if (memchr(nam, '\0', RSTRING_LEN(name))) {
02551 rb_raise(rb_eArgError, "bad environment variable name");
02552 }
02553 val = getenv(nam);
02554 if (val) {
02555 VALUE value = env_str_new2(val);
02556
02557 ruby_setenv(nam, 0);
02558 if (ENVMATCH(nam, PATH_ENV)) {
02559 path_tainted = 0;
02560 }
02561 return value;
02562 }
02563 return Qnil;
02564 }
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575 static VALUE
02576 env_delete_m(VALUE obj, VALUE name)
02577 {
02578 VALUE val;
02579
02580 val = env_delete(obj, name);
02581 if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
02582 return val;
02583 }
02584
02585 static int env_path_tainted(const char *);
02586
02587
02588
02589
02590
02591
02592
02593
02594 static VALUE
02595 rb_f_getenv(VALUE obj, VALUE name)
02596 {
02597 char *nam, *env;
02598
02599 SafeStringValue(name);
02600 nam = RSTRING_PTR(name);
02601 if (memchr(nam, '\0', RSTRING_LEN(name))) {
02602 rb_raise(rb_eArgError, "bad environment variable name");
02603 }
02604 env = getenv(nam);
02605 if (env) {
02606 if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env)) {
02607 #ifdef _WIN32
02608 VALUE str = rb_str_conv_enc(rb_str_new(env, strlen(env)), rb_utf8_encoding(), rb_filesystem_encoding());
02609 #else
02610 VALUE str = rb_filesystem_str_new_cstr(env);
02611 #endif
02612
02613 rb_obj_freeze(str);
02614 return str;
02615 }
02616 return env_str_new2(env);
02617 }
02618 return Qnil;
02619 }
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635 static VALUE
02636 env_fetch(int argc, VALUE *argv)
02637 {
02638 VALUE key, if_none;
02639 long block_given;
02640 char *nam, *env;
02641
02642 rb_scan_args(argc, argv, "11", &key, &if_none);
02643 block_given = rb_block_given_p();
02644 if (block_given && argc == 2) {
02645 rb_warn("block supersedes default value argument");
02646 }
02647 SafeStringValue(key);
02648 nam = RSTRING_PTR(key);
02649 if (memchr(nam, '\0', RSTRING_LEN(key))) {
02650 rb_raise(rb_eArgError, "bad environment variable name");
02651 }
02652 env = getenv(nam);
02653 if (!env) {
02654 if (block_given) return rb_yield(key);
02655 if (argc == 1) {
02656 rb_raise(rb_eKeyError, "key not found: \"%"PRIsVALUE"\"", key);
02657 }
02658 return if_none;
02659 }
02660 if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env))
02661 #ifdef _WIN32
02662 return rb_str_conv_enc(rb_str_new(env, strlen(env)), rb_utf8_encoding(), rb_filesystem_encoding());
02663 #else
02664 return rb_filesystem_str_new_cstr(env);
02665 #endif
02666 return env_str_new2(env);
02667 }
02668
02669 static void
02670 path_tainted_p(const char *path)
02671 {
02672 path_tainted = rb_path_check(path)?0:1;
02673 }
02674
02675 static int
02676 env_path_tainted(const char *path)
02677 {
02678 if (path_tainted < 0) {
02679 path_tainted_p(path);
02680 }
02681 return path_tainted;
02682 }
02683
02684 int
02685 rb_env_path_tainted(void)
02686 {
02687 if (path_tainted < 0) {
02688 path_tainted_p(getenv(PATH_ENV));
02689 }
02690 return path_tainted;
02691 }
02692
02693 #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
02694 #elif defined __sun
02695 static int
02696 in_origenv(const char *str)
02697 {
02698 char **env;
02699 for (env = origenviron; *env; ++env) {
02700 if (*env == str) return 1;
02701 }
02702 return 0;
02703 }
02704 #else
02705 static int
02706 envix(const char *nam)
02707 {
02708 register int i, len = strlen(nam);
02709 char **env;
02710
02711 env = GET_ENVIRON(environ);
02712 for (i = 0; env[i]; i++) {
02713 if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
02714 break;
02715 }
02716 FREE_ENVIRON(environ);
02717 return i;
02718 }
02719 #endif
02720
02721 #if defined(_WIN32)
02722 static size_t
02723 getenvsize(const char* p)
02724 {
02725 const char* porg = p;
02726 while (*p++) p += strlen(p) + 1;
02727 return p - porg + 1;
02728 }
02729 static size_t
02730 getenvblocksize()
02731 {
02732 return (rb_w32_osver() >= 5) ? 32767 : 5120;
02733 }
02734 #endif
02735
02736 #if !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV)
02737 NORETURN(static void invalid_envname(const char *name));
02738
02739 static void
02740 invalid_envname(const char *name)
02741 {
02742 rb_syserr_fail_str(EINVAL, rb_sprintf("ruby_setenv(%s)", name));
02743 }
02744
02745 static const char *
02746 check_envname(const char *name)
02747 {
02748 if (strchr(name, '=')) {
02749 invalid_envname(name);
02750 }
02751 return name;
02752 }
02753 #endif
02754
02755 void
02756 ruby_setenv(const char *name, const char *value)
02757 {
02758 #if defined(_WIN32)
02759 VALUE buf;
02760 int failed = 0;
02761 check_envname(name);
02762 if (value) {
02763 char* p = GetEnvironmentStringsA();
02764 size_t n;
02765 if (!p) goto fail;
02766 n = strlen(name) + 2 + strlen(value) + getenvsize(p);
02767 FreeEnvironmentStringsA(p);
02768 if (n >= getenvblocksize()) {
02769 goto fail;
02770 }
02771 buf = rb_sprintf("%s=%s", name, value);
02772 }
02773 else {
02774 buf = rb_sprintf("%s=", name);
02775 }
02776 failed = putenv(RSTRING_PTR(buf));
02777
02778
02779 rb_str_resize(buf, 0);
02780 if (!value || !*value) {
02781
02782 if (!SetEnvironmentVariable(name, value) &&
02783 GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail;
02784 }
02785 if (failed) {
02786 fail:
02787 invalid_envname(name);
02788 }
02789 #elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
02790 #undef setenv
02791 #undef unsetenv
02792 if (value) {
02793 if (setenv(name, value, 1))
02794 rb_sys_fail_str(rb_sprintf("setenv(%s)", name));
02795 }
02796 else {
02797 #ifdef VOID_UNSETENV
02798 unsetenv(name);
02799 #else
02800 if (unsetenv(name))
02801 rb_sys_fail_str(rb_sprintf("unsetenv(%s)", name));
02802 #endif
02803 }
02804 #elif defined __sun
02805 size_t len;
02806 char **env_ptr, *str;
02807
02808 len = strlen(name);
02809 for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) {
02810 if (!strncmp(str, name, len) && str[len] == '=') {
02811 if (!in_origenv(str)) free(str);
02812 while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
02813 break;
02814 }
02815 }
02816 if (value) {
02817 str = malloc(len += strlen(value) + 2);
02818 snprintf(str, len, "%s=%s", name, value);
02819 if (putenv(str))
02820 rb_sys_fail_str(rb_sprintf("putenv(%s)", name));
02821 }
02822 #else
02823 size_t len;
02824 int i;
02825
02826 i=envix(name);
02827
02828 if (environ == origenviron) {
02829 int j;
02830 int max;
02831 char **tmpenv;
02832
02833 for (max = i; environ[max]; max++) ;
02834 tmpenv = ALLOC_N(char*, max+2);
02835 for (j=0; j<max; j++)
02836 tmpenv[j] = ruby_strdup(environ[j]);
02837 tmpenv[max] = 0;
02838 environ = tmpenv;
02839 }
02840 if (environ[i]) {
02841 char **envp = origenviron;
02842 while (*envp && *envp != environ[i]) envp++;
02843 if (!*envp)
02844 xfree(environ[i]);
02845 if (!value) {
02846 while (environ[i]) {
02847 environ[i] = environ[i+1];
02848 i++;
02849 }
02850 return;
02851 }
02852 }
02853 else {
02854 if (!value) return;
02855 REALLOC_N(environ, char*, i+2);
02856 environ[i+1] = 0;
02857 }
02858 len = strlen(name) + strlen(value) + 2;
02859 environ[i] = ALLOC_N(char, len);
02860 snprintf(environ[i],len,"%s=%s",name,value);
02861 #endif
02862 }
02863
02864 void
02865 ruby_unsetenv(const char *name)
02866 {
02867 ruby_setenv(name, 0);
02868 }
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879 static VALUE
02880 env_aset(VALUE obj, VALUE nm, VALUE val)
02881 {
02882 char *name, *value;
02883
02884 if (NIL_P(val)) {
02885 env_delete(obj, nm);
02886 return Qnil;
02887 }
02888 SafeStringValue(nm);
02889 SafeStringValue(val);
02890 name = RSTRING_PTR(nm);
02891 value = RSTRING_PTR(val);
02892 if (memchr(name, '\0', RSTRING_LEN(nm)))
02893 rb_raise(rb_eArgError, "bad environment variable name");
02894 if (memchr(value, '\0', RSTRING_LEN(val)))
02895 rb_raise(rb_eArgError, "bad environment variable value");
02896
02897 ruby_setenv(name, value);
02898 if (ENVMATCH(name, PATH_ENV)) {
02899 if (OBJ_TAINTED(val)) {
02900
02901 path_tainted = 1;
02902 return val;
02903 }
02904 else {
02905 path_tainted_p(value);
02906 }
02907 }
02908 return val;
02909 }
02910
02911
02912
02913
02914
02915
02916
02917 static VALUE
02918 env_keys(void)
02919 {
02920 char **env;
02921 VALUE ary;
02922
02923 ary = rb_ary_new();
02924 env = GET_ENVIRON(environ);
02925 while (*env) {
02926 char *s = strchr(*env, '=');
02927 if (s) {
02928 rb_ary_push(ary, env_str_new(*env, s-*env));
02929 }
02930 env++;
02931 }
02932 FREE_ENVIRON(environ);
02933 return ary;
02934 }
02935
02936 static VALUE
02937 rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
02938 {
02939 char **env;
02940 long cnt = 0;
02941
02942 env = GET_ENVIRON(environ);
02943 for (; *env ; ++env) {
02944 if (strchr(*env, '=')) {
02945 cnt++;
02946 }
02947 }
02948 FREE_ENVIRON(environ);
02949 return LONG2FIX(cnt);
02950 }
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961 static VALUE
02962 env_each_key(VALUE ehash)
02963 {
02964 VALUE keys;
02965 long i;
02966
02967 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
02968 keys = env_keys();
02969 for (i=0; i<RARRAY_LEN(keys); i++) {
02970 rb_yield(RARRAY_AREF(keys, i));
02971 }
02972 return ehash;
02973 }
02974
02975
02976
02977
02978
02979
02980
02981 static VALUE
02982 env_values(void)
02983 {
02984 VALUE ary;
02985 char **env;
02986
02987 ary = rb_ary_new();
02988 env = GET_ENVIRON(environ);
02989 while (*env) {
02990 char *s = strchr(*env, '=');
02991 if (s) {
02992 rb_ary_push(ary, env_str_new2(s+1));
02993 }
02994 env++;
02995 }
02996 FREE_ENVIRON(environ);
02997 return ary;
02998 }
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009 static VALUE
03010 env_each_value(VALUE ehash)
03011 {
03012 VALUE values;
03013 long i;
03014
03015 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
03016 values = env_values();
03017 for (i=0; i<RARRAY_LEN(values); i++) {
03018 rb_yield(RARRAY_AREF(values, i));
03019 }
03020 return ehash;
03021 }
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034 static VALUE
03035 env_each_pair(VALUE ehash)
03036 {
03037 char **env;
03038 VALUE ary;
03039 long i;
03040
03041 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
03042
03043 ary = rb_ary_new();
03044 env = GET_ENVIRON(environ);
03045 while (*env) {
03046 char *s = strchr(*env, '=');
03047 if (s) {
03048 rb_ary_push(ary, env_str_new(*env, s-*env));
03049 rb_ary_push(ary, env_str_new2(s+1));
03050 }
03051 env++;
03052 }
03053 FREE_ENVIRON(environ);
03054
03055 if (rb_block_arity() > 1) {
03056 for (i=0; i<RARRAY_LEN(ary); i+=2) {
03057 rb_yield_values(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1));
03058 }
03059 }
03060 else {
03061 for (i=0; i<RARRAY_LEN(ary); i+=2) {
03062 rb_yield(rb_assoc_new(RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1)));
03063 }
03064 }
03065 return ehash;
03066 }
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077 static VALUE
03078 env_reject_bang(VALUE ehash)
03079 {
03080 volatile VALUE keys;
03081 long i;
03082 int del = 0;
03083
03084 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
03085 keys = env_keys();
03086 RBASIC_CLEAR_CLASS(keys);
03087 for (i=0; i<RARRAY_LEN(keys); i++) {
03088 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
03089 if (!NIL_P(val)) {
03090 if (RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
03091 FL_UNSET(RARRAY_AREF(keys, i), FL_TAINT);
03092 env_delete(Qnil, RARRAY_AREF(keys, i));
03093 del++;
03094 }
03095 }
03096 }
03097 if (del == 0) return Qnil;
03098 return envtbl;
03099 }
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110 static VALUE
03111 env_delete_if(VALUE ehash)
03112 {
03113 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
03114 env_reject_bang(ehash);
03115 return envtbl;
03116 }
03117
03118
03119
03120
03121
03122
03123
03124
03125 static VALUE
03126 env_values_at(int argc, VALUE *argv)
03127 {
03128 VALUE result;
03129 long i;
03130
03131 result = rb_ary_new();
03132 for (i=0; i<argc; i++) {
03133 rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
03134 }
03135 return result;
03136 }
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147 static VALUE
03148 env_select(VALUE ehash)
03149 {
03150 VALUE result;
03151 VALUE keys;
03152 long i;
03153
03154 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
03155 result = rb_hash_new();
03156 keys = env_keys();
03157 for (i = 0; i < RARRAY_LEN(keys); ++i) {
03158 VALUE key = RARRAY_AREF(keys, i);
03159 VALUE val = rb_f_getenv(Qnil, key);
03160 if (!NIL_P(val)) {
03161 if (RTEST(rb_yield_values(2, key, val))) {
03162 rb_hash_aset(result, key, val);
03163 }
03164 }
03165 }
03166
03167 return result;
03168 }
03169
03170
03171
03172
03173
03174
03175
03176
03177 static VALUE
03178 env_select_bang(VALUE ehash)
03179 {
03180 volatile VALUE keys;
03181 long i;
03182 int del = 0;
03183
03184 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
03185 keys = env_keys();
03186 RBASIC_CLEAR_CLASS(keys);
03187 for (i=0; i<RARRAY_LEN(keys); i++) {
03188 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
03189 if (!NIL_P(val)) {
03190 if (!RTEST(rb_yield_values(2, RARRAY_AREF(keys, i), val))) {
03191 FL_UNSET(RARRAY_AREF(keys, i), FL_TAINT);
03192 env_delete(Qnil, RARRAY_AREF(keys, i));
03193 del++;
03194 }
03195 }
03196 }
03197 if (del == 0) return Qnil;
03198 return envtbl;
03199 }
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210 static VALUE
03211 env_keep_if(VALUE ehash)
03212 {
03213 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
03214 env_select_bang(ehash);
03215 return envtbl;
03216 }
03217
03218
03219
03220
03221
03222
03223
03224 VALUE
03225 rb_env_clear(void)
03226 {
03227 volatile VALUE keys;
03228 long i;
03229
03230 keys = env_keys();
03231 for (i=0; i<RARRAY_LEN(keys); i++) {
03232 VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
03233 if (!NIL_P(val)) {
03234 env_delete(Qnil, RARRAY_AREF(keys, i));
03235 }
03236 }
03237 return envtbl;
03238 }
03239
03240
03241
03242
03243
03244
03245
03246 static VALUE
03247 env_to_s(void)
03248 {
03249 return rb_usascii_str_new2("ENV");
03250 }
03251
03252
03253
03254
03255
03256
03257
03258 static VALUE
03259 env_inspect(void)
03260 {
03261 char **env;
03262 VALUE str, i;
03263
03264 str = rb_str_buf_new2("{");
03265 env = GET_ENVIRON(environ);
03266 while (*env) {
03267 char *s = strchr(*env, '=');
03268
03269 if (env != environ) {
03270 rb_str_buf_cat2(str, ", ");
03271 }
03272 if (s) {
03273 rb_str_buf_cat2(str, "\"");
03274 rb_str_buf_cat(str, *env, s-*env);
03275 rb_str_buf_cat2(str, "\"=>");
03276 i = rb_inspect(rb_str_new2(s+1));
03277 rb_str_buf_append(str, i);
03278 }
03279 env++;
03280 }
03281 FREE_ENVIRON(environ);
03282 rb_str_buf_cat2(str, "}");
03283 OBJ_TAINT(str);
03284
03285 return str;
03286 }
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297 static VALUE
03298 env_to_a(void)
03299 {
03300 char **env;
03301 VALUE ary;
03302
03303 ary = rb_ary_new();
03304 env = GET_ENVIRON(environ);
03305 while (*env) {
03306 char *s = strchr(*env, '=');
03307 if (s) {
03308 rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
03309 env_str_new2(s+1)));
03310 }
03311 env++;
03312 }
03313 FREE_ENVIRON(environ);
03314 return ary;
03315 }
03316
03317
03318
03319
03320
03321
03322
03323
03324 static VALUE
03325 env_none(void)
03326 {
03327 return Qnil;
03328 }
03329
03330
03331
03332
03333
03334
03335
03336
03337 static VALUE
03338 env_size(void)
03339 {
03340 int i;
03341 char **env;
03342
03343 env = GET_ENVIRON(environ);
03344 for (i=0; env[i]; i++)
03345 ;
03346 FREE_ENVIRON(environ);
03347 return INT2FIX(i);
03348 }
03349
03350
03351
03352
03353
03354
03355
03356 static VALUE
03357 env_empty_p(void)
03358 {
03359 char **env;
03360
03361 env = GET_ENVIRON(environ);
03362 if (env[0] == 0) {
03363 FREE_ENVIRON(environ);
03364 return Qtrue;
03365 }
03366 FREE_ENVIRON(environ);
03367 return Qfalse;
03368 }
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379 static VALUE
03380 env_has_key(VALUE env, VALUE key)
03381 {
03382 char *s;
03383
03384 SafeStringValue(key);
03385 s = RSTRING_PTR(key);
03386 if (memchr(s, '\0', RSTRING_LEN(key)))
03387 rb_raise(rb_eArgError, "bad environment variable name");
03388 if (getenv(s)) return Qtrue;
03389 return Qfalse;
03390 }
03391
03392
03393
03394
03395
03396
03397
03398
03399 static VALUE
03400 env_assoc(VALUE env, VALUE key)
03401 {
03402 char *s, *e;
03403
03404 SafeStringValue(key);
03405 s = RSTRING_PTR(key);
03406 if (memchr(s, '\0', RSTRING_LEN(key)))
03407 rb_raise(rb_eArgError, "bad environment variable name");
03408 e = getenv(s);
03409 if (e) return rb_assoc_new(key, rb_tainted_str_new2(e));
03410 return Qnil;
03411 }
03412
03413
03414
03415
03416
03417
03418
03419
03420 static VALUE
03421 env_has_value(VALUE dmy, VALUE obj)
03422 {
03423 char **env;
03424
03425 obj = rb_check_string_type(obj);
03426 if (NIL_P(obj)) return Qnil;
03427 rb_check_safe_obj(obj);
03428 env = GET_ENVIRON(environ);
03429 while (*env) {
03430 char *s = strchr(*env, '=');
03431 if (s++) {
03432 long len = strlen(s);
03433 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
03434 FREE_ENVIRON(environ);
03435 return Qtrue;
03436 }
03437 }
03438 env++;
03439 }
03440 FREE_ENVIRON(environ);
03441 return Qfalse;
03442 }
03443
03444
03445
03446
03447
03448
03449
03450
03451 static VALUE
03452 env_rassoc(VALUE dmy, VALUE obj)
03453 {
03454 char **env;
03455
03456 obj = rb_check_string_type(obj);
03457 if (NIL_P(obj)) return Qnil;
03458 rb_check_safe_obj(obj);
03459 env = GET_ENVIRON(environ);
03460 while (*env) {
03461 char *s = strchr(*env, '=');
03462 if (s++) {
03463 long len = strlen(s);
03464 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
03465 VALUE result = rb_assoc_new(rb_tainted_str_new(*env, s-*env-1), obj);
03466 FREE_ENVIRON(environ);
03467 return result;
03468 }
03469 }
03470 env++;
03471 }
03472 FREE_ENVIRON(environ);
03473 return Qnil;
03474 }
03475
03476
03477
03478
03479
03480
03481
03482
03483 static VALUE
03484 env_key(VALUE dmy, VALUE value)
03485 {
03486 char **env;
03487 VALUE str;
03488
03489 SafeStringValue(value);
03490 env = GET_ENVIRON(environ);
03491 while (*env) {
03492 char *s = strchr(*env, '=');
03493 if (s++) {
03494 long len = strlen(s);
03495 if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
03496 str = env_str_new(*env, s-*env-1);
03497 FREE_ENVIRON(environ);
03498 return str;
03499 }
03500 }
03501 env++;
03502 }
03503 FREE_ENVIRON(environ);
03504 return Qnil;
03505 }
03506
03507
03508
03509
03510
03511
03512
03513 static VALUE
03514 env_index(VALUE dmy, VALUE value)
03515 {
03516 rb_warn("ENV.index is deprecated; use ENV.key");
03517 return env_key(dmy, value);
03518 }
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528 static VALUE
03529 env_to_hash(void)
03530 {
03531 char **env;
03532 VALUE hash;
03533
03534 hash = rb_hash_new();
03535 env = GET_ENVIRON(environ);
03536 while (*env) {
03537 char *s = strchr(*env, '=');
03538 if (s) {
03539 rb_hash_aset(hash, env_str_new(*env, s-*env),
03540 env_str_new2(s+1));
03541 }
03542 env++;
03543 }
03544 FREE_ENVIRON(environ);
03545 return hash;
03546 }
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556 static VALUE
03557 env_reject(void)
03558 {
03559 return rb_hash_delete_if(env_to_hash());
03560 }
03561
03562
03563
03564
03565
03566
03567
03568
03569 static VALUE
03570 env_shift(void)
03571 {
03572 char **env;
03573 VALUE result = Qnil;
03574
03575 env = GET_ENVIRON(environ);
03576 if (*env) {
03577 char *s = strchr(*env, '=');
03578 if (s) {
03579 VALUE key = env_str_new(*env, s-*env);
03580 VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
03581 env_delete(Qnil, key);
03582 result = rb_assoc_new(key, val);
03583 }
03584 }
03585 FREE_ENVIRON(environ);
03586 return result;
03587 }
03588
03589
03590
03591
03592
03593
03594
03595
03596 static VALUE
03597 env_invert(void)
03598 {
03599 return rb_hash_invert(env_to_hash());
03600 }
03601
03602 static int
03603 env_replace_i(VALUE key, VALUE val, VALUE keys)
03604 {
03605 env_aset(Qnil, key, val);
03606 if (rb_ary_includes(keys, key)) {
03607 rb_ary_delete(keys, key);
03608 }
03609 return ST_CONTINUE;
03610 }
03611
03612
03613
03614
03615
03616
03617
03618
03619 static VALUE
03620 env_replace(VALUE env, VALUE hash)
03621 {
03622 volatile VALUE keys;
03623 long i;
03624
03625 keys = env_keys();
03626 if (env == hash) return env;
03627 hash = to_hash(hash);
03628 rb_hash_foreach(hash, env_replace_i, keys);
03629
03630 for (i=0; i<RARRAY_LEN(keys); i++) {
03631 env_delete(env, RARRAY_AREF(keys, i));
03632 }
03633 return env;
03634 }
03635
03636 static int
03637 env_update_i(VALUE key, VALUE val)
03638 {
03639 if (rb_block_given_p()) {
03640 val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val);
03641 }
03642 env_aset(Qnil, key, val);
03643 return ST_CONTINUE;
03644 }
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656 static VALUE
03657 env_update(VALUE env, VALUE hash)
03658 {
03659 if (env == hash) return env;
03660 hash = to_hash(hash);
03661 rb_hash_foreach(hash, env_update_i, 0);
03662 return env;
03663 }
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778 void
03779 Init_Hash(void)
03780 {
03781 #undef rb_intern
03782 #define rb_intern(str) rb_intern_const(str)
03783
03784 id_hash = rb_intern("hash");
03785 id_yield = rb_intern("yield");
03786 id_default = rb_intern("default");
03787 id_flatten_bang = rb_intern("flatten!");
03788
03789 rb_cHash = rb_define_class("Hash", rb_cObject);
03790
03791 rb_include_module(rb_cHash, rb_mEnumerable);
03792
03793 rb_define_alloc_func(rb_cHash, empty_hash_alloc);
03794 rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
03795 rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
03796 rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
03797 rb_define_method(rb_cHash,"initialize_copy", rb_hash_initialize_copy, 1);
03798 rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0);
03799
03800 rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0);
03801 rb_define_method(rb_cHash,"to_h", rb_hash_to_h, 0);
03802 rb_define_method(rb_cHash,"to_a", rb_hash_to_a, 0);
03803 rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0);
03804 rb_define_alias(rb_cHash, "to_s", "inspect");
03805
03806 rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
03807 rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
03808 rb_define_method(rb_cHash,"hash", rb_hash_hash, 0);
03809 rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
03810 rb_define_method(rb_cHash,"fetch", rb_hash_fetch_m, -1);
03811 rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
03812 rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
03813 rb_define_method(rb_cHash,"default", rb_hash_default, -1);
03814 rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
03815 rb_define_method(rb_cHash,"default_proc", rb_hash_default_proc, 0);
03816 rb_define_method(rb_cHash,"default_proc=", rb_hash_set_default_proc, 1);
03817 rb_define_method(rb_cHash,"key", rb_hash_key, 1);
03818 rb_define_method(rb_cHash,"index", rb_hash_index, 1);
03819 rb_define_method(rb_cHash,"size", rb_hash_size, 0);
03820 rb_define_method(rb_cHash,"length", rb_hash_size, 0);
03821 rb_define_method(rb_cHash,"empty?", rb_hash_empty_p, 0);
03822
03823 rb_define_method(rb_cHash,"each_value", rb_hash_each_value, 0);
03824 rb_define_method(rb_cHash,"each_key", rb_hash_each_key, 0);
03825 rb_define_method(rb_cHash,"each_pair", rb_hash_each_pair, 0);
03826 rb_define_method(rb_cHash,"each", rb_hash_each_pair, 0);
03827
03828 rb_define_method(rb_cHash,"keys", rb_hash_keys, 0);
03829 rb_define_method(rb_cHash,"values", rb_hash_values, 0);
03830 rb_define_method(rb_cHash,"values_at", rb_hash_values_at, -1);
03831
03832 rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
03833 rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
03834 rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
03835 rb_define_method(rb_cHash,"keep_if", rb_hash_keep_if, 0);
03836 rb_define_method(rb_cHash,"select", rb_hash_select, 0);
03837 rb_define_method(rb_cHash,"select!", rb_hash_select_bang, 0);
03838 rb_define_method(rb_cHash,"reject", rb_hash_reject, 0);
03839 rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0);
03840 rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
03841 rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
03842 rb_define_method(rb_cHash,"update", rb_hash_update, 1);
03843 rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
03844 rb_define_method(rb_cHash,"merge!", rb_hash_update, 1);
03845 rb_define_method(rb_cHash,"merge", rb_hash_merge, 1);
03846 rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
03847 rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
03848 rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);
03849
03850 rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
03851 rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
03852 rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1);
03853 rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1);
03854 rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1);
03855 rb_define_method(rb_cHash,"value?", rb_hash_has_value, 1);
03856
03857 rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0);
03858 rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869 origenviron = environ;
03870 envtbl = rb_obj_alloc(rb_cObject);
03871 rb_extend_object(envtbl, rb_mEnumerable);
03872
03873 rb_define_singleton_method(envtbl,"[]", rb_f_getenv, 1);
03874 rb_define_singleton_method(envtbl,"fetch", env_fetch, -1);
03875 rb_define_singleton_method(envtbl,"[]=", env_aset, 2);
03876 rb_define_singleton_method(envtbl,"store", env_aset, 2);
03877 rb_define_singleton_method(envtbl,"each", env_each_pair, 0);
03878 rb_define_singleton_method(envtbl,"each_pair", env_each_pair, 0);
03879 rb_define_singleton_method(envtbl,"each_key", env_each_key, 0);
03880 rb_define_singleton_method(envtbl,"each_value", env_each_value, 0);
03881 rb_define_singleton_method(envtbl,"delete", env_delete_m, 1);
03882 rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0);
03883 rb_define_singleton_method(envtbl,"keep_if", env_keep_if, 0);
03884 rb_define_singleton_method(envtbl,"clear", rb_env_clear, 0);
03885 rb_define_singleton_method(envtbl,"reject", env_reject, 0);
03886 rb_define_singleton_method(envtbl,"reject!", env_reject_bang, 0);
03887 rb_define_singleton_method(envtbl,"select", env_select, 0);
03888 rb_define_singleton_method(envtbl,"select!", env_select_bang, 0);
03889 rb_define_singleton_method(envtbl,"shift", env_shift, 0);
03890 rb_define_singleton_method(envtbl,"invert", env_invert, 0);
03891 rb_define_singleton_method(envtbl,"replace", env_replace, 1);
03892 rb_define_singleton_method(envtbl,"update", env_update, 1);
03893 rb_define_singleton_method(envtbl,"inspect", env_inspect, 0);
03894 rb_define_singleton_method(envtbl,"rehash", env_none, 0);
03895 rb_define_singleton_method(envtbl,"to_a", env_to_a, 0);
03896 rb_define_singleton_method(envtbl,"to_s", env_to_s, 0);
03897 rb_define_singleton_method(envtbl,"key", env_key, 1);
03898 rb_define_singleton_method(envtbl,"index", env_index, 1);
03899 rb_define_singleton_method(envtbl,"size", env_size, 0);
03900 rb_define_singleton_method(envtbl,"length", env_size, 0);
03901 rb_define_singleton_method(envtbl,"empty?", env_empty_p, 0);
03902 rb_define_singleton_method(envtbl,"keys", env_keys, 0);
03903 rb_define_singleton_method(envtbl,"values", env_values, 0);
03904 rb_define_singleton_method(envtbl,"values_at", env_values_at, -1);
03905 rb_define_singleton_method(envtbl,"include?", env_has_key, 1);
03906 rb_define_singleton_method(envtbl,"member?", env_has_key, 1);
03907 rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1);
03908 rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1);
03909 rb_define_singleton_method(envtbl,"key?", env_has_key, 1);
03910 rb_define_singleton_method(envtbl,"value?", env_has_value, 1);
03911 rb_define_singleton_method(envtbl,"to_hash", env_to_hash, 0);
03912 rb_define_singleton_method(envtbl,"to_h", env_to_hash, 0);
03913 rb_define_singleton_method(envtbl,"assoc", env_assoc, 1);
03914 rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1);
03915
03916
03917
03918
03919
03920
03921 rb_define_global_const("ENV", envtbl);
03922
03923
03924 ruby_register_rollback_func_for_ensure(hash_foreach_ensure, hash_foreach_ensure_rollback);
03925 }
03926