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