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 <errno.h>
00018
00019 #ifdef __APPLE__
00020 #include <crt_externs.h>
00021 #endif
00022
00023 static VALUE rb_hash_s_try_convert(VALUE, VALUE);
00024
00025 #define HASH_DELETED FL_USER1
00026 #define HASH_PROC_DEFAULT FL_USER2
00027
00028 VALUE
00029 rb_hash_freeze(VALUE hash)
00030 {
00031 return rb_obj_freeze(hash);
00032 }
00033
00034 VALUE rb_cHash;
00035
00036 static VALUE envtbl;
00037 static ID id_hash, id_yield, id_default;
00038
00039 static int
00040 rb_any_cmp(VALUE a, VALUE b)
00041 {
00042 if (a == b) return 0;
00043 if (FIXNUM_P(a) && FIXNUM_P(b)) {
00044 return a != b;
00045 }
00046 if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
00047 TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
00048 return rb_str_hash_cmp(a, b);
00049 }
00050 if (a == Qundef || b == Qundef) return -1;
00051 if (SYMBOL_P(a) && SYMBOL_P(b)) {
00052 return a != b;
00053 }
00054
00055 return !rb_eql(a, b);
00056 }
00057
00058 VALUE
00059 rb_hash(VALUE obj)
00060 {
00061 VALUE hval = rb_funcall(obj, id_hash, 0);
00062 retry:
00063 switch (TYPE(hval)) {
00064 case T_FIXNUM:
00065 return hval;
00066
00067 case T_BIGNUM:
00068 return LONG2FIX(((long*)(RBIGNUM_DIGITS(hval)))[0]);
00069
00070 default:
00071 hval = rb_to_int(hval);
00072 goto retry;
00073 }
00074 }
00075
00076 static st_index_t
00077 rb_any_hash(VALUE a)
00078 {
00079 VALUE hval;
00080 st_index_t hnum;
00081
00082 switch (TYPE(a)) {
00083 case T_FIXNUM:
00084 case T_SYMBOL:
00085 case T_NIL:
00086 case T_FALSE:
00087 case T_TRUE:
00088 hnum = rb_hash_end(rb_hash_start((unsigned int)a));
00089 break;
00090
00091 case T_STRING:
00092 hnum = rb_str_hash(a);
00093 break;
00094
00095 default:
00096 hval = rb_hash(a);
00097 hnum = FIX2LONG(hval);
00098 }
00099 hnum <<= 1;
00100 return (st_index_t)RSHIFT(hnum, 1);
00101 }
00102
00103 static const struct st_hash_type objhash = {
00104 rb_any_cmp,
00105 rb_any_hash,
00106 };
00107
00108 static const struct st_hash_type identhash = {
00109 st_numcmp,
00110 st_numhash,
00111 };
00112
00113 typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
00114
00115 struct foreach_safe_arg {
00116 st_table *tbl;
00117 st_foreach_func *func;
00118 st_data_t arg;
00119 };
00120
00121 static int
00122 foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg)
00123 {
00124 int status;
00125
00126 if (key == Qundef) return ST_CONTINUE;
00127 status = (*arg->func)(key, value, arg->arg);
00128 if (status == ST_CONTINUE) {
00129 return ST_CHECK;
00130 }
00131 return status;
00132 }
00133
00134 void
00135 st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a)
00136 {
00137 struct foreach_safe_arg arg;
00138
00139 arg.tbl = table;
00140 arg.func = (st_foreach_func *)func;
00141 arg.arg = a;
00142 if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) {
00143 rb_raise(rb_eRuntimeError, "hash modified during iteration");
00144 }
00145 }
00146
00147 typedef int rb_foreach_func(VALUE, VALUE, VALUE);
00148
00149 struct hash_foreach_arg {
00150 VALUE hash;
00151 rb_foreach_func *func;
00152 VALUE arg;
00153 };
00154
00155 static int
00156 hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg)
00157 {
00158 int status;
00159 st_table *tbl;
00160
00161 tbl = RHASH(arg->hash)->ntbl;
00162 if ((VALUE)key == Qundef) return ST_CONTINUE;
00163 status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
00164 if (RHASH(arg->hash)->ntbl != tbl) {
00165 rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
00166 }
00167 switch (status) {
00168 case ST_DELETE:
00169 st_delete_safe(tbl, &key, 0, Qundef);
00170 FL_SET(arg->hash, HASH_DELETED);
00171 case ST_CONTINUE:
00172 break;
00173 case ST_STOP:
00174 return ST_STOP;
00175 }
00176 return ST_CHECK;
00177 }
00178
00179 static VALUE
00180 hash_foreach_ensure(VALUE hash)
00181 {
00182 RHASH(hash)->iter_lev--;
00183
00184 if (RHASH(hash)->iter_lev == 0) {
00185 if (FL_TEST(hash, HASH_DELETED)) {
00186 st_cleanup_safe(RHASH(hash)->ntbl, Qundef);
00187 FL_UNSET(hash, HASH_DELETED);
00188 }
00189 }
00190 return 0;
00191 }
00192
00193 static VALUE
00194 hash_foreach_call(struct hash_foreach_arg *arg)
00195 {
00196 if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) {
00197 rb_raise(rb_eRuntimeError, "hash modified during iteration");
00198 }
00199 return Qnil;
00200 }
00201
00202 void
00203 rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
00204 {
00205 struct hash_foreach_arg arg;
00206
00207 if (!RHASH(hash)->ntbl)
00208 return;
00209 RHASH(hash)->iter_lev++;
00210 arg.hash = hash;
00211 arg.func = (rb_foreach_func *)func;
00212 arg.arg = farg;
00213 rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
00214 }
00215
00216 static VALUE
00217 hash_alloc(VALUE klass)
00218 {
00219 NEWOBJ(hash, struct RHash);
00220 OBJSETUP(hash, klass, T_HASH);
00221
00222 RHASH_IFNONE(hash) = Qnil;
00223
00224 return (VALUE)hash;
00225 }
00226
00227 VALUE
00228 rb_hash_new(void)
00229 {
00230 return hash_alloc(rb_cHash);
00231 }
00232
00233 VALUE
00234 rb_hash_dup(VALUE hash)
00235 {
00236 NEWOBJ(ret, struct RHash);
00237 DUPSETUP(ret, hash);
00238
00239 if (!RHASH_EMPTY_P(hash))
00240 ret->ntbl = st_copy(RHASH(hash)->ntbl);
00241 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00242 FL_SET(ret, HASH_PROC_DEFAULT);
00243 }
00244 RHASH_IFNONE(ret) = RHASH_IFNONE(hash);
00245 return (VALUE)ret;
00246 }
00247
00248 static void
00249 rb_hash_modify_check(VALUE hash)
00250 {
00251 if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
00252 if (!OBJ_UNTRUSTED(hash) && rb_safe_level() >= 4)
00253 rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
00254 }
00255
00256 struct st_table *
00257 rb_hash_tbl(VALUE hash)
00258 {
00259 if (!RHASH(hash)->ntbl) {
00260 RHASH(hash)->ntbl = st_init_table(&objhash);
00261 }
00262 return RHASH(hash)->ntbl;
00263 }
00264
00265 static void
00266 rb_hash_modify(VALUE hash)
00267 {
00268 rb_hash_modify_check(hash);
00269 rb_hash_tbl(hash);
00270 }
00271
00272 static void
00273 hash_update(VALUE hash, VALUE key)
00274 {
00275 if (RHASH(hash)->iter_lev > 0 && !st_lookup(RHASH(hash)->ntbl, key, 0)) {
00276 rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
00277 }
00278 }
00279
00280 static void
00281 default_proc_arity_check(VALUE proc)
00282 {
00283 int n = rb_proc_arity(proc);
00284
00285 if (rb_proc_lambda_p(proc) && n != 2 && (n >= 0 || n < -3)) {
00286 if (n < 0) n = -n-1;
00287 rb_raise(rb_eTypeError, "default_proc takes two arguments (2 for %d)", n);
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 static VALUE
00327 rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
00328 {
00329 VALUE ifnone;
00330
00331 rb_hash_modify(hash);
00332 if (rb_block_given_p()) {
00333 if (argc > 0) {
00334 rb_raise(rb_eArgError, "wrong number of arguments");
00335 }
00336 ifnone = rb_block_proc();
00337 default_proc_arity_check(ifnone);
00338 RHASH_IFNONE(hash) = ifnone;
00339 FL_SET(hash, HASH_PROC_DEFAULT);
00340 }
00341 else {
00342 rb_scan_args(argc, argv, "01", &ifnone);
00343 RHASH_IFNONE(hash) = ifnone;
00344 }
00345
00346 return hash;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 static VALUE
00367 rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
00368 {
00369 VALUE hash, tmp;
00370 int i;
00371
00372 if (argc == 1) {
00373 tmp = rb_hash_s_try_convert(Qnil, argv[0]);
00374 if (!NIL_P(tmp)) {
00375 hash = hash_alloc(klass);
00376 if (RHASH(tmp)->ntbl) {
00377 RHASH(hash)->ntbl = st_copy(RHASH(tmp)->ntbl);
00378 }
00379 return hash;
00380 }
00381
00382 tmp = rb_check_array_type(argv[0]);
00383 if (!NIL_P(tmp)) {
00384 long i;
00385
00386 hash = hash_alloc(klass);
00387 for (i = 0; i < RARRAY_LEN(tmp); ++i) {
00388 VALUE v = rb_check_array_type(RARRAY_PTR(tmp)[i]);
00389 VALUE key, val = Qnil;
00390
00391 if (NIL_P(v)) continue;
00392 switch (RARRAY_LEN(v)) {
00393 case 2:
00394 val = RARRAY_PTR(v)[1];
00395 case 1:
00396 key = RARRAY_PTR(v)[0];
00397 rb_hash_aset(hash, key, val);
00398 }
00399 }
00400 return hash;
00401 }
00402 }
00403 if (argc % 2 != 0) {
00404 rb_raise(rb_eArgError, "odd number of arguments for Hash");
00405 }
00406
00407 hash = hash_alloc(klass);
00408 for (i=0; i<argc; i+=2) {
00409 rb_hash_aset(hash, argv[i], argv[i + 1]);
00410 }
00411
00412 return hash;
00413 }
00414
00415 static VALUE
00416 to_hash(VALUE hash)
00417 {
00418 return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 static VALUE
00433 rb_hash_s_try_convert(VALUE dummy, VALUE hash)
00434 {
00435 return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
00436 }
00437
00438 static int
00439 rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
00440 {
00441 st_table *tbl = (st_table *)arg;
00442
00443 if (key != Qundef) st_insert(tbl, key, value);
00444 return ST_CONTINUE;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 static VALUE
00468 rb_hash_rehash(VALUE hash)
00469 {
00470 st_table *tbl;
00471
00472 if (RHASH(hash)->iter_lev > 0) {
00473 rb_raise(rb_eRuntimeError, "rehash during iteration");
00474 }
00475 rb_hash_modify_check(hash);
00476 if (!RHASH(hash)->ntbl)
00477 return hash;
00478 tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries);
00479 rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl);
00480 st_free_table(RHASH(hash)->ntbl);
00481 RHASH(hash)->ntbl = tbl;
00482
00483 return hash;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 VALUE
00501 rb_hash_aref(VALUE hash, VALUE key)
00502 {
00503 VALUE val;
00504
00505 if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
00506 return rb_funcall(hash, id_default, 1, key);
00507 }
00508 return val;
00509 }
00510
00511 VALUE
00512 rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
00513 {
00514 VALUE val;
00515
00516 if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
00517 return def;
00518 }
00519 return val;
00520 }
00521
00522 VALUE
00523 rb_hash_lookup(VALUE hash, VALUE key)
00524 {
00525 return rb_hash_lookup2(hash, key, Qnil);
00526 }
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 static VALUE
00558 rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
00559 {
00560 VALUE key, if_none;
00561 VALUE val;
00562 long block_given;
00563
00564 rb_scan_args(argc, argv, "11", &key, &if_none);
00565
00566 block_given = rb_block_given_p();
00567 if (block_given && argc == 2) {
00568 rb_warn("block supersedes default value argument");
00569 }
00570 if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
00571 if (block_given) return rb_yield(key);
00572 if (argc == 1) {
00573 volatile VALUE desc = rb_protect(rb_inspect, key, 0);
00574 if (NIL_P(desc) || RSTRING_LEN(desc) > 65) {
00575 desc = rb_any_to_s(key);
00576 }
00577 rb_raise(rb_eKeyError, "key not found: %s", RSTRING_PTR(desc));
00578 }
00579 return if_none;
00580 }
00581 return val;
00582 }
00583
00584 VALUE
00585 rb_hash_fetch(VALUE hash, VALUE key)
00586 {
00587 return rb_hash_fetch_m(1, &key, hash);
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 static VALUE
00612 rb_hash_default(int argc, VALUE *argv, VALUE hash)
00613 {
00614 VALUE key, ifnone;
00615
00616 rb_scan_args(argc, argv, "01", &key);
00617 ifnone = RHASH_IFNONE(hash);
00618 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00619 if (argc == 0) return Qnil;
00620 return rb_funcall(ifnone, id_yield, 2, hash, key);
00621 }
00622 return ifnone;
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 static VALUE
00646 rb_hash_set_default(VALUE hash, VALUE ifnone)
00647 {
00648 rb_hash_modify(hash);
00649 RHASH_IFNONE(hash) = ifnone;
00650 FL_UNSET(hash, HASH_PROC_DEFAULT);
00651 return ifnone;
00652 }
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 static VALUE
00670 rb_hash_default_proc(VALUE hash)
00671 {
00672 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00673 return RHASH_IFNONE(hash);
00674 }
00675 return Qnil;
00676 }
00677
00678 VALUE rb_obj_is_proc(VALUE proc);
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 static VALUE
00694 rb_hash_set_default_proc(VALUE hash, VALUE proc)
00695 {
00696 VALUE b;
00697
00698 rb_hash_modify(hash);
00699 b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
00700 if (NIL_P(b) || !rb_obj_is_proc(b)) {
00701 rb_raise(rb_eTypeError,
00702 "wrong default_proc type %s (expected Proc)",
00703 rb_obj_classname(proc));
00704 }
00705 proc = b;
00706 default_proc_arity_check(proc);
00707 RHASH_IFNONE(hash) = proc;
00708 FL_SET(hash, HASH_PROC_DEFAULT);
00709 return proc;
00710 }
00711
00712 static int
00713 key_i(VALUE key, VALUE value, VALUE arg)
00714 {
00715 VALUE *args = (VALUE *)arg;
00716
00717 if (rb_equal(value, args[0])) {
00718 args[1] = key;
00719 return ST_STOP;
00720 }
00721 return ST_CONTINUE;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 static VALUE
00737 rb_hash_key(VALUE hash, VALUE value)
00738 {
00739 VALUE args[2];
00740
00741 args[0] = value;
00742 args[1] = Qnil;
00743
00744 rb_hash_foreach(hash, key_i, (VALUE)args);
00745
00746 return args[1];
00747 }
00748
00749
00750 static VALUE
00751 rb_hash_index(VALUE hash, VALUE value)
00752 {
00753 rb_warn("Hash#index is deprecated; use Hash#key");
00754 return rb_hash_key(hash, value);
00755 }
00756
00757 static VALUE
00758 rb_hash_delete_key(VALUE hash, VALUE key)
00759 {
00760 st_data_t ktmp = (st_data_t)key, val;
00761
00762 if (!RHASH(hash)->ntbl)
00763 return Qundef;
00764 if (RHASH(hash)->iter_lev > 0) {
00765 if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) {
00766 FL_SET(hash, HASH_DELETED);
00767 return (VALUE)val;
00768 }
00769 }
00770 else if (st_delete(RHASH(hash)->ntbl, &ktmp, &val))
00771 return (VALUE)val;
00772 return Qundef;
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 VALUE
00794 rb_hash_delete(VALUE hash, VALUE key)
00795 {
00796 VALUE val;
00797
00798 rb_hash_modify(hash);
00799 val = rb_hash_delete_key(hash, key);
00800 if (val != Qundef) return val;
00801 if (rb_block_given_p()) {
00802 return rb_yield(key);
00803 }
00804 return Qnil;
00805 }
00806
00807 struct shift_var {
00808 VALUE key;
00809 VALUE val;
00810 };
00811
00812 static int
00813 shift_i(VALUE key, VALUE value, VALUE arg)
00814 {
00815 struct shift_var *var = (struct shift_var *)arg;
00816
00817 if (key == Qundef) return ST_CONTINUE;
00818 if (var->key != Qundef) return ST_STOP;
00819 var->key = key;
00820 var->val = value;
00821 return ST_DELETE;
00822 }
00823
00824 static int
00825 shift_i_safe(VALUE key, VALUE value, VALUE arg)
00826 {
00827 struct shift_var *var = (struct shift_var *)arg;
00828
00829 if (key == Qundef) return ST_CONTINUE;
00830 var->key = key;
00831 var->val = value;
00832 return ST_STOP;
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 static VALUE
00849 rb_hash_shift(VALUE hash)
00850 {
00851 struct shift_var var;
00852
00853 rb_hash_modify(hash);
00854 var.key = Qundef;
00855 rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i,
00856 (VALUE)&var);
00857
00858 if (var.key != Qundef) {
00859 if (RHASH(hash)->iter_lev > 0) {
00860 rb_hash_delete_key(hash, var.key);
00861 }
00862 return rb_assoc_new(var.key, var.val);
00863 }
00864 else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00865 return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil);
00866 }
00867 else {
00868 return RHASH_IFNONE(hash);
00869 }
00870 }
00871
00872 static int
00873 delete_if_i(VALUE key, VALUE value, VALUE hash)
00874 {
00875 if (key == Qundef) return ST_CONTINUE;
00876 if (RTEST(rb_yield_values(2, key, value))) {
00877 rb_hash_delete_key(hash, key);
00878 }
00879 return ST_CONTINUE;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 VALUE
00898 rb_hash_delete_if(VALUE hash)
00899 {
00900 RETURN_ENUMERATOR(hash, 0, 0);
00901 rb_hash_modify(hash);
00902 rb_hash_foreach(hash, delete_if_i, hash);
00903 return hash;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915 VALUE
00916 rb_hash_reject_bang(VALUE hash)
00917 {
00918 st_index_t n;
00919
00920 RETURN_ENUMERATOR(hash, 0, 0);
00921 rb_hash_modify(hash);
00922 if (!RHASH(hash)->ntbl)
00923 return Qnil;
00924 n = RHASH(hash)->ntbl->num_entries;
00925 rb_hash_foreach(hash, delete_if_i, hash);
00926 if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
00927 return hash;
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 static VALUE
00941 rb_hash_reject(VALUE hash)
00942 {
00943 return rb_hash_delete_if(rb_obj_dup(hash));
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 VALUE
00958 rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
00959 {
00960 VALUE result = rb_ary_new2(argc);
00961 long i;
00962
00963 for (i=0; i<argc; i++) {
00964 rb_ary_push(result, rb_hash_aref(hash, argv[i]));
00965 }
00966 return result;
00967 }
00968
00969 static int
00970 select_i(VALUE key, VALUE value, VALUE result)
00971 {
00972 if (key == Qundef) return ST_CONTINUE;
00973 if (RTEST(rb_yield_values(2, key, value)))
00974 rb_hash_aset(result, key, value);
00975 return ST_CONTINUE;
00976 }
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 VALUE
00993 rb_hash_select(VALUE hash)
00994 {
00995 VALUE result;
00996
00997 RETURN_ENUMERATOR(hash, 0, 0);
00998 result = rb_hash_new();
00999 rb_hash_foreach(hash, select_i, result);
01000 return result;
01001 }
01002
01003 static int
01004 keep_if_i(VALUE key, VALUE value, VALUE hash)
01005 {
01006 if (key == Qundef) return ST_CONTINUE;
01007 if (!RTEST(rb_yield_values(2, key, value))) {
01008 return ST_DELETE;
01009 }
01010 return ST_CONTINUE;
01011 }
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 VALUE
01023 rb_hash_select_bang(VALUE hash)
01024 {
01025 st_index_t n;
01026
01027 RETURN_ENUMERATOR(hash, 0, 0);
01028 rb_hash_modify(hash);
01029 if (!RHASH(hash)->ntbl)
01030 return Qnil;
01031 n = RHASH(hash)->ntbl->num_entries;
01032 rb_hash_foreach(hash, keep_if_i, hash);
01033 if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
01034 return hash;
01035 }
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049 VALUE
01050 rb_hash_keep_if(VALUE hash)
01051 {
01052 RETURN_ENUMERATOR(hash, 0, 0);
01053 rb_hash_modify(hash);
01054 rb_hash_foreach(hash, keep_if_i, hash);
01055 return hash;
01056 }
01057
01058 static int
01059 clear_i(VALUE key, VALUE value, VALUE dummy)
01060 {
01061 return ST_DELETE;
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075 static VALUE
01076 rb_hash_clear(VALUE hash)
01077 {
01078 rb_hash_modify_check(hash);
01079 if (!RHASH(hash)->ntbl)
01080 return hash;
01081 if (RHASH(hash)->ntbl->num_entries > 0) {
01082 if (RHASH(hash)->iter_lev > 0)
01083 rb_hash_foreach(hash, clear_i, 0);
01084 else
01085 st_clear(RHASH(hash)->ntbl);
01086 }
01087
01088 return hash;
01089 }
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 VALUE
01110 rb_hash_aset(VALUE hash, VALUE key, VALUE val)
01111 {
01112 rb_hash_modify(hash);
01113 hash_update(hash, key);
01114 if (RHASH(hash)->ntbl->type == &identhash || rb_obj_class(key) != rb_cString) {
01115 st_insert(RHASH(hash)->ntbl, key, val);
01116 }
01117 else {
01118 st_insert2(RHASH(hash)->ntbl, key, val, rb_str_new4);
01119 }
01120 return val;
01121 }
01122
01123 static int
01124 replace_i(VALUE key, VALUE val, VALUE hash)
01125 {
01126 if (key != Qundef) {
01127 rb_hash_aset(hash, key, val);
01128 }
01129
01130 return ST_CONTINUE;
01131 }
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 static VALUE
01146 rb_hash_replace(VALUE hash, VALUE hash2)
01147 {
01148 rb_hash_modify_check(hash);
01149 hash2 = to_hash(hash2);
01150 if (hash == hash2) return hash;
01151 rb_hash_clear(hash);
01152 if (RHASH(hash2)->ntbl) {
01153 rb_hash_tbl(hash);
01154 RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type;
01155 }
01156 rb_hash_foreach(hash2, replace_i, hash);
01157 RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);
01158 if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
01159 FL_SET(hash, HASH_PROC_DEFAULT);
01160 }
01161 else {
01162 FL_UNSET(hash, HASH_PROC_DEFAULT);
01163 }
01164
01165 return hash;
01166 }
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 static VALUE
01182 rb_hash_size(VALUE hash)
01183 {
01184 if (!RHASH(hash)->ntbl)
01185 return INT2FIX(0);
01186 return INT2FIX(RHASH(hash)->ntbl->num_entries);
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200 static VALUE
01201 rb_hash_empty_p(VALUE hash)
01202 {
01203 return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
01204 }
01205
01206 static int
01207 each_value_i(VALUE key, VALUE value)
01208 {
01209 if (key == Qundef) return ST_CONTINUE;
01210 rb_yield(value);
01211 return ST_CONTINUE;
01212 }
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 static VALUE
01234 rb_hash_each_value(VALUE hash)
01235 {
01236 RETURN_ENUMERATOR(hash, 0, 0);
01237 rb_hash_foreach(hash, each_value_i, 0);
01238 return hash;
01239 }
01240
01241 static int
01242 each_key_i(VALUE key, VALUE value)
01243 {
01244 if (key == Qundef) return ST_CONTINUE;
01245 rb_yield(key);
01246 return ST_CONTINUE;
01247 }
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267 static VALUE
01268 rb_hash_each_key(VALUE hash)
01269 {
01270 RETURN_ENUMERATOR(hash, 0, 0);
01271 rb_hash_foreach(hash, each_key_i, 0);
01272 return hash;
01273 }
01274
01275 static int
01276 each_pair_i(VALUE key, VALUE value)
01277 {
01278 if (key == Qundef) return ST_CONTINUE;
01279 rb_yield(rb_assoc_new(key, value));
01280 return ST_CONTINUE;
01281 }
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 static VALUE
01306 rb_hash_each_pair(VALUE hash)
01307 {
01308 RETURN_ENUMERATOR(hash, 0, 0);
01309 rb_hash_foreach(hash, each_pair_i, 0);
01310 return hash;
01311 }
01312
01313 static int
01314 to_a_i(VALUE key, VALUE value, VALUE ary)
01315 {
01316 if (key == Qundef) return ST_CONTINUE;
01317 rb_ary_push(ary, rb_assoc_new(key, value));
01318 return ST_CONTINUE;
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 static VALUE
01333 rb_hash_to_a(VALUE hash)
01334 {
01335 VALUE ary;
01336
01337 ary = rb_ary_new();
01338 rb_hash_foreach(hash, to_a_i, ary);
01339 OBJ_INFECT(ary, hash);
01340
01341 return ary;
01342 }
01343
01344 static int
01345 inspect_i(VALUE key, VALUE value, VALUE str)
01346 {
01347 VALUE str2;
01348
01349 if (key == Qundef) return ST_CONTINUE;
01350 if (RSTRING_LEN(str) > 1) {
01351 rb_str_cat2(str, ", ");
01352 }
01353 str2 = rb_inspect(key);
01354 rb_str_buf_append(str, str2);
01355 OBJ_INFECT(str, str2);
01356 rb_str_buf_cat2(str, "=>");
01357 str2 = rb_inspect(value);
01358 rb_str_buf_append(str, str2);
01359 OBJ_INFECT(str, str2);
01360
01361 return ST_CONTINUE;
01362 }
01363
01364 static VALUE
01365 inspect_hash(VALUE hash, VALUE dummy, int recur)
01366 {
01367 VALUE str;
01368
01369 if (recur) return rb_usascii_str_new2("{...}");
01370 str = rb_str_buf_new2("{");
01371 rb_hash_foreach(hash, inspect_i, str);
01372 rb_str_buf_cat2(str, "}");
01373 OBJ_INFECT(str, hash);
01374
01375 return str;
01376 }
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 static VALUE
01390 rb_hash_inspect(VALUE hash)
01391 {
01392 if (RHASH_EMPTY_P(hash))
01393 return rb_usascii_str_new2("{}");
01394 return rb_exec_recursive(inspect_hash, hash, 0);
01395 }
01396
01397
01398
01399
01400
01401
01402
01403
01404 static VALUE
01405 rb_hash_to_hash(VALUE hash)
01406 {
01407 return hash;
01408 }
01409
01410 static int
01411 keys_i(VALUE key, VALUE value, VALUE ary)
01412 {
01413 if (key == Qundef) return ST_CONTINUE;
01414 rb_ary_push(ary, key);
01415 return ST_CONTINUE;
01416 }
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430 static VALUE
01431 rb_hash_keys(VALUE hash)
01432 {
01433 VALUE ary;
01434
01435 ary = rb_ary_new();
01436 rb_hash_foreach(hash, keys_i, ary);
01437
01438 return ary;
01439 }
01440
01441 static int
01442 values_i(VALUE key, VALUE value, VALUE ary)
01443 {
01444 if (key == Qundef) return ST_CONTINUE;
01445 rb_ary_push(ary, value);
01446 return ST_CONTINUE;
01447 }
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 static VALUE
01462 rb_hash_values(VALUE hash)
01463 {
01464 VALUE ary;
01465
01466 ary = rb_ary_new();
01467 rb_hash_foreach(hash, values_i, ary);
01468
01469 return ary;
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487 static VALUE
01488 rb_hash_has_key(VALUE hash, VALUE key)
01489 {
01490 if (!RHASH(hash)->ntbl)
01491 return Qfalse;
01492 if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
01493 return Qtrue;
01494 }
01495 return Qfalse;
01496 }
01497
01498 static int
01499 rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
01500 {
01501 VALUE *data = (VALUE *)arg;
01502
01503 if (key == Qundef) return ST_CONTINUE;
01504 if (rb_equal(value, data[1])) {
01505 data[0] = Qtrue;
01506 return ST_STOP;
01507 }
01508 return ST_CONTINUE;
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 static VALUE
01525 rb_hash_has_value(VALUE hash, VALUE val)
01526 {
01527 VALUE data[2];
01528
01529 data[0] = Qfalse;
01530 data[1] = val;
01531 rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
01532 return data[0];
01533 }
01534
01535 struct equal_data {
01536 VALUE result;
01537 st_table *tbl;
01538 int eql;
01539 };
01540
01541 static int
01542 eql_i(VALUE key, VALUE val1, VALUE arg)
01543 {
01544 struct equal_data *data = (struct equal_data *)arg;
01545 VALUE val2;
01546
01547 if (key == Qundef) return ST_CONTINUE;
01548 if (!st_lookup(data->tbl, key, &val2)) {
01549 data->result = Qfalse;
01550 return ST_STOP;
01551 }
01552 if (!(data->eql ? rb_eql(val1, val2) : (int)rb_equal(val1, val2))) {
01553 data->result = Qfalse;
01554 return ST_STOP;
01555 }
01556 return ST_CONTINUE;
01557 }
01558
01559 static VALUE
01560 recursive_eql(VALUE hash, VALUE dt, int recur)
01561 {
01562 struct equal_data *data;
01563
01564 if (recur) return Qtrue;
01565 data = (struct equal_data*)dt;
01566 data->result = Qtrue;
01567 rb_hash_foreach(hash, eql_i, dt);
01568
01569 return data->result;
01570 }
01571
01572 static VALUE
01573 hash_equal(VALUE hash1, VALUE hash2, int eql)
01574 {
01575 struct equal_data data;
01576
01577 if (hash1 == hash2) return Qtrue;
01578 if (TYPE(hash2) != T_HASH) {
01579 if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
01580 return Qfalse;
01581 }
01582 if (eql)
01583 return rb_eql(hash2, hash1);
01584 else
01585 return rb_equal(hash2, hash1);
01586 }
01587 if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
01588 return Qfalse;
01589 if (!RHASH(hash1)->ntbl || !RHASH(hash2)->ntbl)
01590 return Qtrue;
01591 if (RHASH(hash1)->ntbl->type != RHASH(hash2)->ntbl->type)
01592 return Qfalse;
01593 #if 0
01594 if (!(rb_equal(RHASH_IFNONE(hash1), RHASH_IFNONE(hash2)) &&
01595 FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
01596 return Qfalse;
01597 #endif
01598
01599 data.tbl = RHASH(hash2)->ntbl;
01600 data.eql = eql;
01601 return rb_exec_recursive_paired(recursive_eql, hash1, hash2, (VALUE)&data);
01602 }
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623 static VALUE
01624 rb_hash_equal(VALUE hash1, VALUE hash2)
01625 {
01626 return hash_equal(hash1, hash2, FALSE);
01627 }
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637 static VALUE
01638 rb_hash_eql(VALUE hash1, VALUE hash2)
01639 {
01640 return hash_equal(hash1, hash2, TRUE);
01641 }
01642
01643 static int
01644 hash_i(VALUE key, VALUE val, VALUE arg)
01645 {
01646 st_index_t *hval = (st_index_t *)arg;
01647
01648 if (key == Qundef) return ST_CONTINUE;
01649 *hval ^= rb_hash_end(rb_hash_uint(rb_hash_start(rb_hash(key)), rb_hash(val)));
01650 return ST_CONTINUE;
01651 }
01652
01653 static VALUE
01654 recursive_hash(VALUE hash, VALUE dummy, int recur)
01655 {
01656 st_index_t hval;
01657
01658 if (!RHASH(hash)->ntbl)
01659 return LONG2FIX(0);
01660 hval = RHASH(hash)->ntbl->num_entries;
01661 if (recur)
01662 hval = rb_hash_end(rb_hash_uint(rb_hash_start(rb_hash(rb_cHash)), hval));
01663 else
01664 rb_hash_foreach(hash, hash_i, (VALUE)&hval);
01665 return INT2FIX(hval);
01666 }
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676 static VALUE
01677 rb_hash_hash(VALUE hash)
01678 {
01679 return rb_exec_recursive_outer(recursive_hash, hash, 0);
01680 }
01681
01682 static int
01683 rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
01684 {
01685 if (key == Qundef) return ST_CONTINUE;
01686 rb_hash_aset(hash, value, key);
01687 return ST_CONTINUE;
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702 static VALUE
01703 rb_hash_invert(VALUE hash)
01704 {
01705 VALUE h = rb_hash_new();
01706
01707 rb_hash_foreach(hash, rb_hash_invert_i, h);
01708 return h;
01709 }
01710
01711 static int
01712 rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
01713 {
01714 if (key == Qundef) return ST_CONTINUE;
01715 hash_update(hash, key);
01716 st_insert(RHASH(hash)->ntbl, key, value);
01717 return ST_CONTINUE;
01718 }
01719
01720 static int
01721 rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
01722 {
01723 if (key == Qundef) return ST_CONTINUE;
01724 if (rb_hash_has_key(hash, key)) {
01725 value = rb_yield_values(3, key, rb_hash_aref(hash, key), value);
01726 }
01727 hash_update(hash, key);
01728 st_insert(RHASH(hash)->ntbl, key, value);
01729 return ST_CONTINUE;
01730 }
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755 static VALUE
01756 rb_hash_update(VALUE hash1, VALUE hash2)
01757 {
01758 rb_hash_modify(hash1);
01759 hash2 = to_hash(hash2);
01760 if (rb_block_given_p()) {
01761 rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
01762 }
01763 else {
01764 rb_hash_foreach(hash2, rb_hash_update_i, hash1);
01765 }
01766 return hash1;
01767 }
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789 static VALUE
01790 rb_hash_merge(VALUE hash1, VALUE hash2)
01791 {
01792 return rb_hash_update(rb_obj_dup(hash1), hash2);
01793 }
01794
01795 static int
01796 assoc_i(VALUE key, VALUE val, VALUE arg)
01797 {
01798 VALUE *args = (VALUE *)arg;
01799
01800 if (key == Qundef) return ST_CONTINUE;
01801 if (RTEST(rb_equal(args[0], key))) {
01802 args[1] = rb_assoc_new(key, val);
01803 return ST_STOP;
01804 }
01805 return ST_CONTINUE;
01806 }
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 VALUE
01823 rb_hash_assoc(VALUE hash, VALUE obj)
01824 {
01825 VALUE args[2];
01826
01827 args[0] = obj;
01828 args[1] = Qnil;
01829 rb_hash_foreach(hash, assoc_i, (VALUE)args);
01830 return args[1];
01831 }
01832
01833 static int
01834 rassoc_i(VALUE key, VALUE val, VALUE arg)
01835 {
01836 VALUE *args = (VALUE *)arg;
01837
01838 if (key == Qundef) return ST_CONTINUE;
01839 if (RTEST(rb_equal(args[0], val))) {
01840 args[1] = rb_assoc_new(key, val);
01841 return ST_STOP;
01842 }
01843 return ST_CONTINUE;
01844 }
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 VALUE
01860 rb_hash_rassoc(VALUE hash, VALUE obj)
01861 {
01862 VALUE args[2];
01863
01864 args[0] = obj;
01865 args[1] = Qnil;
01866 rb_hash_foreach(hash, rassoc_i, (VALUE)args);
01867 return args[1];
01868 }
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886 static VALUE
01887 rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
01888 {
01889 VALUE ary, tmp;
01890
01891 ary = rb_hash_to_a(hash);
01892 if (argc == 0) {
01893 argc = 1;
01894 tmp = INT2FIX(1);
01895 argv = &tmp;
01896 }
01897 rb_funcall2(ary, rb_intern("flatten!"), argc, argv);
01898 return ary;
01899 }
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 static VALUE
01918 rb_hash_compare_by_id(VALUE hash)
01919 {
01920 rb_hash_modify(hash);
01921 RHASH(hash)->ntbl->type = &identhash;
01922 rb_hash_rehash(hash);
01923 return hash;
01924 }
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 static VALUE
01936 rb_hash_compare_by_id_p(VALUE hash)
01937 {
01938 if (!RHASH(hash)->ntbl)
01939 return Qfalse;
01940 if (RHASH(hash)->ntbl->type == &identhash) {
01941 return Qtrue;
01942 }
01943 return Qfalse;
01944 }
01945
01946 static int path_tainted = -1;
01947
01948 static char **origenviron;
01949 #ifdef _WIN32
01950 #define GET_ENVIRON(e) (e = rb_w32_get_environ())
01951 #define FREE_ENVIRON(e) rb_w32_free_environ(e)
01952 static char **my_environ;
01953 #undef environ
01954 #define environ my_environ
01955 #elif defined(__APPLE__)
01956 #undef environ
01957 #define environ (*_NSGetEnviron())
01958 #define GET_ENVIRON(e) (e)
01959 #define FREE_ENVIRON(e)
01960 #else
01961 extern char **environ;
01962 #define GET_ENVIRON(e) (e)
01963 #define FREE_ENVIRON(e)
01964 #endif
01965 #ifdef ENV_IGNORECASE
01966 #define ENVMATCH(s1, s2) (STRCASECMP(s1, s2) == 0)
01967 #define ENVNMATCH(s1, s2, n) (STRNCASECMP(s1, s2, n) == 0)
01968 #else
01969 #define ENVMATCH(n1, n2) (strcmp(n1, n2) == 0)
01970 #define ENVNMATCH(s1, s2, n) (memcmp(s1, s2, n) == 0)
01971 #endif
01972
01973 static VALUE
01974 env_str_new(const char *ptr, long len)
01975 {
01976 VALUE str = rb_locale_str_new(ptr, len);
01977
01978 rb_obj_freeze(str);
01979 return str;
01980 }
01981
01982 static VALUE
01983 env_str_new2(const char *ptr)
01984 {
01985 if (!ptr) return Qnil;
01986 return env_str_new(ptr, strlen(ptr));
01987 }
01988
01989 static VALUE
01990 env_delete(VALUE obj, VALUE name)
01991 {
01992 char *nam, *val;
01993
01994 rb_secure(4);
01995 SafeStringValue(name);
01996 nam = RSTRING_PTR(name);
01997 if (memchr(nam, '\0', RSTRING_LEN(name))) {
01998 rb_raise(rb_eArgError, "bad environment variable name");
01999 }
02000 val = getenv(nam);
02001 if (val) {
02002 VALUE value = env_str_new2(val);
02003
02004 ruby_setenv(nam, 0);
02005 if (ENVMATCH(nam, PATH_ENV)) {
02006 path_tainted = 0;
02007 }
02008 return value;
02009 }
02010 return Qnil;
02011 }
02012
02013 static VALUE
02014 env_delete_m(VALUE obj, VALUE name)
02015 {
02016 VALUE val;
02017
02018 val = env_delete(obj, name);
02019 if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
02020 return val;
02021 }
02022
02023 static int env_path_tainted(const char *);
02024
02025 static VALUE
02026 rb_f_getenv(VALUE obj, VALUE name)
02027 {
02028 char *nam, *env;
02029
02030 rb_secure(4);
02031 SafeStringValue(name);
02032 nam = RSTRING_PTR(name);
02033 if (memchr(nam, '\0', RSTRING_LEN(name))) {
02034 rb_raise(rb_eArgError, "bad environment variable name");
02035 }
02036 env = getenv(nam);
02037 if (env) {
02038 if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env)) {
02039 VALUE str = rb_filesystem_str_new_cstr(env);
02040
02041 rb_obj_freeze(str);
02042 return str;
02043 }
02044 return env_str_new2(env);
02045 }
02046 return Qnil;
02047 }
02048
02049 static VALUE
02050 env_fetch(int argc, VALUE *argv)
02051 {
02052 VALUE key, if_none;
02053 long block_given;
02054 char *nam, *env;
02055
02056 rb_secure(4);
02057 rb_scan_args(argc, argv, "11", &key, &if_none);
02058 block_given = rb_block_given_p();
02059 if (block_given && argc == 2) {
02060 rb_warn("block supersedes default value argument");
02061 }
02062 SafeStringValue(key);
02063 nam = RSTRING_PTR(key);
02064 if (memchr(nam, '\0', RSTRING_LEN(key))) {
02065 rb_raise(rb_eArgError, "bad environment variable name");
02066 }
02067 env = getenv(nam);
02068 if (!env) {
02069 if (block_given) return rb_yield(key);
02070 if (argc == 1) {
02071 rb_raise(rb_eKeyError, "key not found");
02072 }
02073 return if_none;
02074 }
02075 if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env))
02076 return rb_filesystem_str_new_cstr(env);
02077 return env_str_new2(env);
02078 }
02079
02080 static void
02081 path_tainted_p(const char *path)
02082 {
02083 path_tainted = rb_path_check(path)?0:1;
02084 }
02085
02086 static int
02087 env_path_tainted(const char *path)
02088 {
02089 if (path_tainted < 0) {
02090 path_tainted_p(path);
02091 }
02092 return path_tainted;
02093 }
02094
02095 int
02096 rb_env_path_tainted(void)
02097 {
02098 if (path_tainted < 0) {
02099 path_tainted_p(getenv(PATH_ENV));
02100 }
02101 return path_tainted;
02102 }
02103
02104 #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
02105 #elif defined __sun__
02106 static int
02107 in_origenv(const char *str)
02108 {
02109 char **env;
02110 for (env = origenviron; *env; ++env) {
02111 if (*env == str) return 1;
02112 }
02113 return 0;
02114 }
02115 #else
02116 static int
02117 envix(const char *nam)
02118 {
02119 register int i, len = strlen(nam);
02120 char **env;
02121
02122 env = GET_ENVIRON(environ);
02123 for (i = 0; env[i]; i++) {
02124 if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
02125 break;
02126 }
02127 FREE_ENVIRON(environ);
02128 return i;
02129 }
02130 #endif
02131
02132 void
02133 ruby_setenv(const char *name, const char *value)
02134 {
02135 #if defined(_WIN32)
02136 int len;
02137 char *buf;
02138 int failed = 0;
02139 if (strchr(name, '=')) {
02140 errno = EINVAL;
02141 rb_sys_fail("ruby_setenv");
02142 }
02143 if (value) {
02144 len = strlen(name) + 1 + strlen(value) + 1;
02145 buf = ALLOCA_N(char, len);
02146 snprintf(buf, len, "%s=%s", name, value);
02147 failed = putenv(buf);
02148
02149
02150 if (!*value)
02151 failed = !SetEnvironmentVariable(name,value);
02152 }
02153 else {
02154 len = strlen(name) + 1 + 1;
02155 buf = ALLOCA_N(char, len);
02156 snprintf(buf, len, "%s=", name);
02157 putenv(buf);
02158 failed = !SetEnvironmentVariable(name, 0);
02159 }
02160 if (failed) {
02161 rb_warn("failed to set environment variable. Ruby 1.9.3 will raise SystemCallError in this case.");
02162 }
02163 #elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
02164 #undef setenv
02165 #undef unsetenv
02166 if (value) {
02167 if (setenv(name, value, 1))
02168 rb_sys_fail("setenv");
02169 } else {
02170 #ifdef VOID_UNSETENV
02171 unsetenv(name);
02172 #else
02173 if (unsetenv(name))
02174 rb_sys_fail("unsetenv");
02175 #endif
02176 }
02177 #elif defined __sun__
02178 size_t len;
02179 char **env_ptr, *str;
02180 if (strchr(name, '=')) {
02181 errno = EINVAL;
02182 rb_sys_fail("ruby_setenv");
02183 }
02184 len = strlen(name);
02185 for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) {
02186 if (!strncmp(str, name, len) && str[len] == '=') {
02187 if (!in_origenv(str)) free(str);
02188 while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
02189 break;
02190 }
02191 }
02192 if (value) {
02193 str = malloc(len += strlen(value) + 2);
02194 snprintf(str, len, "%s=%s", name, value);
02195 if (putenv(str))
02196 rb_sys_fail("putenv");
02197 }
02198 #else
02199 size_t len;
02200 int i;
02201 if (strchr(name, '=')) {
02202 errno = EINVAL;
02203 rb_sys_fail("ruby_setenv");
02204 }
02205 i=envix(name);
02206
02207 if (environ == origenviron) {
02208 int j;
02209 int max;
02210 char **tmpenv;
02211
02212 for (max = i; environ[max]; max++) ;
02213 tmpenv = ALLOC_N(char*, max+2);
02214 for (j=0; j<max; j++)
02215 tmpenv[j] = ruby_strdup(environ[j]);
02216 tmpenv[max] = 0;
02217 environ = tmpenv;
02218 }
02219 if (environ[i]) {
02220 char **envp = origenviron;
02221 while (*envp && *envp != environ[i]) envp++;
02222 if (!*envp)
02223 xfree(environ[i]);
02224 if (!value) {
02225 while (environ[i]) {
02226 environ[i] = environ[i+1];
02227 i++;
02228 }
02229 return;
02230 }
02231 }
02232 else {
02233 if (!value) return;
02234 REALLOC_N(environ, char*, i+2);
02235 environ[i+1] = 0;
02236 }
02237 len = strlen(name) + strlen(value) + 2;
02238 environ[i] = ALLOC_N(char, len);
02239 snprintf(environ[i],len,"%s=%s",name,value);
02240 #endif
02241 }
02242
02243 void
02244 ruby_unsetenv(const char *name)
02245 {
02246 ruby_setenv(name, 0);
02247 }
02248
02249 static VALUE
02250 env_aset(VALUE obj, VALUE nm, VALUE val)
02251 {
02252 char *name, *value;
02253
02254 if (rb_safe_level() >= 4) {
02255 rb_raise(rb_eSecurityError, "can't change environment variable");
02256 }
02257
02258 if (NIL_P(val)) {
02259 env_delete(obj, nm);
02260 return Qnil;
02261 }
02262 StringValue(nm);
02263 StringValue(val);
02264 name = RSTRING_PTR(nm);
02265 value = RSTRING_PTR(val);
02266 if (memchr(name, '\0', RSTRING_LEN(nm)))
02267 rb_raise(rb_eArgError, "bad environment variable name");
02268 if (memchr(value, '\0', RSTRING_LEN(val)))
02269 rb_raise(rb_eArgError, "bad environment variable value");
02270
02271 ruby_setenv(name, value);
02272 if (ENVMATCH(name, PATH_ENV)) {
02273 if (OBJ_TAINTED(val)) {
02274
02275 path_tainted = 1;
02276 return val;
02277 }
02278 else {
02279 path_tainted_p(value);
02280 }
02281 }
02282 return val;
02283 }
02284
02285 static VALUE
02286 env_keys(void)
02287 {
02288 char **env;
02289 VALUE ary;
02290
02291 rb_secure(4);
02292 ary = rb_ary_new();
02293 env = GET_ENVIRON(environ);
02294 while (*env) {
02295 char *s = strchr(*env, '=');
02296 if (s) {
02297 rb_ary_push(ary, env_str_new(*env, s-*env));
02298 }
02299 env++;
02300 }
02301 FREE_ENVIRON(environ);
02302 return ary;
02303 }
02304
02305 static VALUE
02306 env_each_key(VALUE ehash)
02307 {
02308 VALUE keys;
02309 long i;
02310
02311 RETURN_ENUMERATOR(ehash, 0, 0);
02312 keys = env_keys();
02313 for (i=0; i<RARRAY_LEN(keys); i++) {
02314 rb_yield(RARRAY_PTR(keys)[i]);
02315 }
02316 return ehash;
02317 }
02318
02319 static VALUE
02320 env_values(void)
02321 {
02322 VALUE ary;
02323 char **env;
02324
02325 rb_secure(4);
02326 ary = rb_ary_new();
02327 env = GET_ENVIRON(environ);
02328 while (*env) {
02329 char *s = strchr(*env, '=');
02330 if (s) {
02331 rb_ary_push(ary, env_str_new2(s+1));
02332 }
02333 env++;
02334 }
02335 FREE_ENVIRON(environ);
02336 return ary;
02337 }
02338
02339 static VALUE
02340 env_each_value(VALUE ehash)
02341 {
02342 VALUE values;
02343 long i;
02344
02345 RETURN_ENUMERATOR(ehash, 0, 0);
02346 values = env_values();
02347 for (i=0; i<RARRAY_LEN(values); i++) {
02348 rb_yield(RARRAY_PTR(values)[i]);
02349 }
02350 return ehash;
02351 }
02352
02353 static VALUE
02354 env_each_pair(VALUE ehash)
02355 {
02356 char **env;
02357 VALUE ary;
02358 long i;
02359
02360 RETURN_ENUMERATOR(ehash, 0, 0);
02361
02362 rb_secure(4);
02363 ary = rb_ary_new();
02364 env = GET_ENVIRON(environ);
02365 while (*env) {
02366 char *s = strchr(*env, '=');
02367 if (s) {
02368 rb_ary_push(ary, env_str_new(*env, s-*env));
02369 rb_ary_push(ary, env_str_new2(s+1));
02370 }
02371 env++;
02372 }
02373 FREE_ENVIRON(environ);
02374
02375 for (i=0; i<RARRAY_LEN(ary); i+=2) {
02376 rb_yield(rb_assoc_new(RARRAY_PTR(ary)[i], RARRAY_PTR(ary)[i+1]));
02377 }
02378 return ehash;
02379 }
02380
02381 static VALUE
02382 env_reject_bang(VALUE ehash)
02383 {
02384 volatile VALUE keys;
02385 long i;
02386 int del = 0;
02387
02388 RETURN_ENUMERATOR(ehash, 0, 0);
02389 keys = env_keys();
02390 for (i=0; i<RARRAY_LEN(keys); i++) {
02391 VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
02392 if (!NIL_P(val)) {
02393 if (RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val))) {
02394 FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT);
02395 env_delete(Qnil, RARRAY_PTR(keys)[i]);
02396 del++;
02397 }
02398 }
02399 }
02400 if (del == 0) return Qnil;
02401 return envtbl;
02402 }
02403
02404 static VALUE
02405 env_delete_if(VALUE ehash)
02406 {
02407 RETURN_ENUMERATOR(ehash, 0, 0);
02408 env_reject_bang(ehash);
02409 return envtbl;
02410 }
02411
02412 static VALUE
02413 env_values_at(int argc, VALUE *argv)
02414 {
02415 VALUE result;
02416 long i;
02417
02418 rb_secure(4);
02419 result = rb_ary_new();
02420 for (i=0; i<argc; i++) {
02421 rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
02422 }
02423 return result;
02424 }
02425
02426 static VALUE
02427 env_select(VALUE ehash)
02428 {
02429 VALUE result;
02430 char **env;
02431
02432 RETURN_ENUMERATOR(ehash, 0, 0);
02433 rb_secure(4);
02434 result = rb_hash_new();
02435 env = GET_ENVIRON(environ);
02436 while (*env) {
02437 char *s = strchr(*env, '=');
02438 if (s) {
02439 VALUE k = env_str_new(*env, s-*env);
02440 VALUE v = env_str_new2(s+1);
02441 if (RTEST(rb_yield_values(2, k, v))) {
02442 rb_hash_aset(result, k, v);
02443 }
02444 }
02445 env++;
02446 }
02447 FREE_ENVIRON(environ);
02448
02449 return result;
02450 }
02451
02452 static VALUE
02453 env_select_bang(VALUE ehash)
02454 {
02455 volatile VALUE keys;
02456 long i;
02457 int del = 0;
02458
02459 RETURN_ENUMERATOR(ehash, 0, 0);
02460 keys = env_keys();
02461 for (i=0; i<RARRAY_LEN(keys); i++) {
02462 VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
02463 if (!NIL_P(val)) {
02464 if (!RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val))) {
02465 FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT);
02466 env_delete(Qnil, RARRAY_PTR(keys)[i]);
02467 del++;
02468 }
02469 }
02470 }
02471 if (del == 0) return Qnil;
02472 return envtbl;
02473 }
02474
02475 static VALUE
02476 env_keep_if(VALUE ehash)
02477 {
02478 RETURN_ENUMERATOR(ehash, 0, 0);
02479 env_select_bang(ehash);
02480 return envtbl;
02481 }
02482
02483 VALUE
02484 rb_env_clear(void)
02485 {
02486 volatile VALUE keys;
02487 long i;
02488
02489 keys = env_keys();
02490 for (i=0; i<RARRAY_LEN(keys); i++) {
02491 VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
02492 if (!NIL_P(val)) {
02493 env_delete(Qnil, RARRAY_PTR(keys)[i]);
02494 }
02495 }
02496 return envtbl;
02497 }
02498
02499 static VALUE
02500 env_to_s(void)
02501 {
02502 return rb_usascii_str_new2("ENV");
02503 }
02504
02505 static VALUE
02506 env_inspect(void)
02507 {
02508 char **env;
02509 VALUE str, i;
02510
02511 rb_secure(4);
02512 str = rb_str_buf_new2("{");
02513 env = GET_ENVIRON(environ);
02514 while (*env) {
02515 char *s = strchr(*env, '=');
02516
02517 if (env != environ) {
02518 rb_str_buf_cat2(str, ", ");
02519 }
02520 if (s) {
02521 rb_str_buf_cat2(str, "\"");
02522 rb_str_buf_cat(str, *env, s-*env);
02523 rb_str_buf_cat2(str, "\"=>");
02524 i = rb_inspect(rb_str_new2(s+1));
02525 rb_str_buf_append(str, i);
02526 }
02527 env++;
02528 }
02529 FREE_ENVIRON(environ);
02530 rb_str_buf_cat2(str, "}");
02531 OBJ_TAINT(str);
02532
02533 return str;
02534 }
02535
02536 static VALUE
02537 env_to_a(void)
02538 {
02539 char **env;
02540 VALUE ary;
02541
02542 rb_secure(4);
02543 ary = rb_ary_new();
02544 env = GET_ENVIRON(environ);
02545 while (*env) {
02546 char *s = strchr(*env, '=');
02547 if (s) {
02548 rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
02549 env_str_new2(s+1)));
02550 }
02551 env++;
02552 }
02553 FREE_ENVIRON(environ);
02554 return ary;
02555 }
02556
02557 static VALUE
02558 env_none(void)
02559 {
02560 return Qnil;
02561 }
02562
02563 static VALUE
02564 env_size(void)
02565 {
02566 int i;
02567 char **env;
02568
02569 rb_secure(4);
02570 env = GET_ENVIRON(environ);
02571 for(i=0; env[i]; i++)
02572 ;
02573 FREE_ENVIRON(environ);
02574 return INT2FIX(i);
02575 }
02576
02577 static VALUE
02578 env_empty_p(void)
02579 {
02580 char **env;
02581
02582 rb_secure(4);
02583 env = GET_ENVIRON(environ);
02584 if (env[0] == 0) {
02585 FREE_ENVIRON(environ);
02586 return Qtrue;
02587 }
02588 FREE_ENVIRON(environ);
02589 return Qfalse;
02590 }
02591
02592 static VALUE
02593 env_has_key(VALUE env, VALUE key)
02594 {
02595 char *s;
02596
02597 rb_secure(4);
02598 s = StringValuePtr(key);
02599 if (memchr(s, '\0', RSTRING_LEN(key)))
02600 rb_raise(rb_eArgError, "bad environment variable name");
02601 if (getenv(s)) return Qtrue;
02602 return Qfalse;
02603 }
02604
02605 static VALUE
02606 env_assoc(VALUE env, VALUE key)
02607 {
02608 char *s, *e;
02609
02610 rb_secure(4);
02611 s = StringValuePtr(key);
02612 if (memchr(s, '\0', RSTRING_LEN(key)))
02613 rb_raise(rb_eArgError, "bad environment variable name");
02614 e = getenv(s);
02615 if (e) return rb_assoc_new(key, rb_tainted_str_new2(e));
02616 return Qnil;
02617 }
02618
02619 static VALUE
02620 env_has_value(VALUE dmy, VALUE obj)
02621 {
02622 char **env;
02623
02624 rb_secure(4);
02625 obj = rb_check_string_type(obj);
02626 if (NIL_P(obj)) return Qnil;
02627 env = GET_ENVIRON(environ);
02628 while (*env) {
02629 char *s = strchr(*env, '=');
02630 if (s++) {
02631 long len = strlen(s);
02632 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
02633 FREE_ENVIRON(environ);
02634 return Qtrue;
02635 }
02636 }
02637 env++;
02638 }
02639 FREE_ENVIRON(environ);
02640 return Qfalse;
02641 }
02642
02643 static VALUE
02644 env_rassoc(VALUE dmy, VALUE obj)
02645 {
02646 char **env;
02647
02648 rb_secure(4);
02649 obj = rb_check_string_type(obj);
02650 if (NIL_P(obj)) return Qnil;
02651 env = GET_ENVIRON(environ);
02652 while (*env) {
02653 char *s = strchr(*env, '=');
02654 if (s++) {
02655 long len = strlen(s);
02656 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
02657 VALUE result = rb_assoc_new(rb_tainted_str_new(*env, s-*env-1), obj);
02658 FREE_ENVIRON(environ);
02659 return result;
02660 }
02661 }
02662 env++;
02663 }
02664 FREE_ENVIRON(environ);
02665 return Qnil;
02666 }
02667
02668 static VALUE
02669 env_key(VALUE dmy, VALUE value)
02670 {
02671 char **env;
02672 VALUE str;
02673
02674 rb_secure(4);
02675 StringValue(value);
02676 env = GET_ENVIRON(environ);
02677 while (*env) {
02678 char *s = strchr(*env, '=');
02679 if (s++) {
02680 long len = strlen(s);
02681 if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
02682 str = env_str_new(*env, s-*env-1);
02683 FREE_ENVIRON(environ);
02684 return str;
02685 }
02686 }
02687 env++;
02688 }
02689 FREE_ENVIRON(environ);
02690 return Qnil;
02691 }
02692
02693 static VALUE
02694 env_index(VALUE dmy, VALUE value)
02695 {
02696 rb_warn("ENV.index is deprecated; use ENV.key");
02697 return env_key(dmy, value);
02698 }
02699
02700 static VALUE
02701 env_to_hash(void)
02702 {
02703 char **env;
02704 VALUE hash;
02705
02706 rb_secure(4);
02707 hash = rb_hash_new();
02708 env = GET_ENVIRON(environ);
02709 while (*env) {
02710 char *s = strchr(*env, '=');
02711 if (s) {
02712 rb_hash_aset(hash, env_str_new(*env, s-*env),
02713 env_str_new2(s+1));
02714 }
02715 env++;
02716 }
02717 FREE_ENVIRON(environ);
02718 return hash;
02719 }
02720
02721 static VALUE
02722 env_reject(void)
02723 {
02724 return rb_hash_delete_if(env_to_hash());
02725 }
02726
02727 static VALUE
02728 env_shift(void)
02729 {
02730 char **env;
02731
02732 rb_secure(4);
02733 env = GET_ENVIRON(environ);
02734 if (*env) {
02735 char *s = strchr(*env, '=');
02736 if (s) {
02737 VALUE key = env_str_new(*env, s-*env);
02738 VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
02739 env_delete(Qnil, key);
02740 return rb_assoc_new(key, val);
02741 }
02742 }
02743 FREE_ENVIRON(environ);
02744 return Qnil;
02745 }
02746
02747 static VALUE
02748 env_invert(void)
02749 {
02750 return rb_hash_invert(env_to_hash());
02751 }
02752
02753 static int
02754 env_replace_i(VALUE key, VALUE val, VALUE keys)
02755 {
02756 if (key != Qundef) {
02757 env_aset(Qnil, key, val);
02758 if (rb_ary_includes(keys, key)) {
02759 rb_ary_delete(keys, key);
02760 }
02761 }
02762 return ST_CONTINUE;
02763 }
02764
02765 static VALUE
02766 env_replace(VALUE env, VALUE hash)
02767 {
02768 volatile VALUE keys;
02769 long i;
02770
02771 keys = env_keys();
02772 if (env == hash) return env;
02773 hash = to_hash(hash);
02774 rb_hash_foreach(hash, env_replace_i, keys);
02775
02776 for (i=0; i<RARRAY_LEN(keys); i++) {
02777 env_delete(env, RARRAY_PTR(keys)[i]);
02778 }
02779 return env;
02780 }
02781
02782 static int
02783 env_update_i(VALUE key, VALUE val)
02784 {
02785 if (key != Qundef) {
02786 if (rb_block_given_p()) {
02787 val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val);
02788 }
02789 env_aset(Qnil, key, val);
02790 }
02791 return ST_CONTINUE;
02792 }
02793
02794 static VALUE
02795 env_update(VALUE env, VALUE hash)
02796 {
02797 rb_secure(4);
02798 if (env == hash) return env;
02799 hash = to_hash(hash);
02800 rb_hash_foreach(hash, env_update_i, 0);
02801 return env;
02802 }
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816 void
02817 Init_Hash(void)
02818 {
02819 #undef rb_intern
02820 #define rb_intern(str) rb_intern_const(str)
02821
02822 id_hash = rb_intern("hash");
02823 id_yield = rb_intern("yield");
02824 id_default = rb_intern("default");
02825
02826 rb_cHash = rb_define_class("Hash", rb_cObject);
02827
02828 rb_include_module(rb_cHash, rb_mEnumerable);
02829
02830 rb_define_alloc_func(rb_cHash, hash_alloc);
02831 rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
02832 rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
02833 rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
02834 rb_define_method(rb_cHash,"initialize_copy", rb_hash_replace, 1);
02835 rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0);
02836
02837 rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0);
02838 rb_define_method(rb_cHash,"to_a", rb_hash_to_a, 0);
02839 rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0);
02840 rb_define_alias(rb_cHash, "to_s", "inspect");
02841
02842 rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
02843 rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
02844 rb_define_method(rb_cHash,"hash", rb_hash_hash, 0);
02845 rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
02846 rb_define_method(rb_cHash,"fetch", rb_hash_fetch_m, -1);
02847 rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
02848 rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
02849 rb_define_method(rb_cHash,"default", rb_hash_default, -1);
02850 rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
02851 rb_define_method(rb_cHash,"default_proc", rb_hash_default_proc, 0);
02852 rb_define_method(rb_cHash,"default_proc=", rb_hash_set_default_proc, 1);
02853 rb_define_method(rb_cHash,"key", rb_hash_key, 1);
02854 rb_define_method(rb_cHash,"index", rb_hash_index, 1);
02855 rb_define_method(rb_cHash,"size", rb_hash_size, 0);
02856 rb_define_method(rb_cHash,"length", rb_hash_size, 0);
02857 rb_define_method(rb_cHash,"empty?", rb_hash_empty_p, 0);
02858
02859 rb_define_method(rb_cHash,"each_value", rb_hash_each_value, 0);
02860 rb_define_method(rb_cHash,"each_key", rb_hash_each_key, 0);
02861 rb_define_method(rb_cHash,"each_pair", rb_hash_each_pair, 0);
02862 rb_define_method(rb_cHash,"each", rb_hash_each_pair, 0);
02863
02864 rb_define_method(rb_cHash,"keys", rb_hash_keys, 0);
02865 rb_define_method(rb_cHash,"values", rb_hash_values, 0);
02866 rb_define_method(rb_cHash,"values_at", rb_hash_values_at, -1);
02867
02868 rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
02869 rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
02870 rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
02871 rb_define_method(rb_cHash,"keep_if", rb_hash_keep_if, 0);
02872 rb_define_method(rb_cHash,"select", rb_hash_select, 0);
02873 rb_define_method(rb_cHash,"select!", rb_hash_select_bang, 0);
02874 rb_define_method(rb_cHash,"reject", rb_hash_reject, 0);
02875 rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0);
02876 rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
02877 rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
02878 rb_define_method(rb_cHash,"update", rb_hash_update, 1);
02879 rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
02880 rb_define_method(rb_cHash,"merge!", rb_hash_update, 1);
02881 rb_define_method(rb_cHash,"merge", rb_hash_merge, 1);
02882 rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
02883 rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
02884 rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);
02885
02886 rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
02887 rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
02888 rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1);
02889 rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1);
02890 rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1);
02891 rb_define_method(rb_cHash,"value?", rb_hash_has_value, 1);
02892
02893 rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0);
02894 rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
02895
02896 origenviron = environ;
02897 envtbl = rb_obj_alloc(rb_cObject);
02898 rb_extend_object(envtbl, rb_mEnumerable);
02899
02900 rb_define_singleton_method(envtbl,"[]", rb_f_getenv, 1);
02901 rb_define_singleton_method(envtbl,"fetch", env_fetch, -1);
02902 rb_define_singleton_method(envtbl,"[]=", env_aset, 2);
02903 rb_define_singleton_method(envtbl,"store", env_aset, 2);
02904 rb_define_singleton_method(envtbl,"each", env_each_pair, 0);
02905 rb_define_singleton_method(envtbl,"each_pair", env_each_pair, 0);
02906 rb_define_singleton_method(envtbl,"each_key", env_each_key, 0);
02907 rb_define_singleton_method(envtbl,"each_value", env_each_value, 0);
02908 rb_define_singleton_method(envtbl,"delete", env_delete_m, 1);
02909 rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0);
02910 rb_define_singleton_method(envtbl,"keep_if", env_keep_if, 0);
02911 rb_define_singleton_method(envtbl,"clear", rb_env_clear, 0);
02912 rb_define_singleton_method(envtbl,"reject", env_reject, 0);
02913 rb_define_singleton_method(envtbl,"reject!", env_reject_bang, 0);
02914 rb_define_singleton_method(envtbl,"select", env_select, 0);
02915 rb_define_singleton_method(envtbl,"select!", env_select_bang, 0);
02916 rb_define_singleton_method(envtbl,"shift", env_shift, 0);
02917 rb_define_singleton_method(envtbl,"invert", env_invert, 0);
02918 rb_define_singleton_method(envtbl,"replace", env_replace, 1);
02919 rb_define_singleton_method(envtbl,"update", env_update, 1);
02920 rb_define_singleton_method(envtbl,"inspect", env_inspect, 0);
02921 rb_define_singleton_method(envtbl,"rehash", env_none, 0);
02922 rb_define_singleton_method(envtbl,"to_a", env_to_a, 0);
02923 rb_define_singleton_method(envtbl,"to_s", env_to_s, 0);
02924 rb_define_singleton_method(envtbl,"key", env_key, 1);
02925 rb_define_singleton_method(envtbl,"index", env_index, 1);
02926 rb_define_singleton_method(envtbl,"size", env_size, 0);
02927 rb_define_singleton_method(envtbl,"length", env_size, 0);
02928 rb_define_singleton_method(envtbl,"empty?", env_empty_p, 0);
02929 rb_define_singleton_method(envtbl,"keys", env_keys, 0);
02930 rb_define_singleton_method(envtbl,"values", env_values, 0);
02931 rb_define_singleton_method(envtbl,"values_at", env_values_at, -1);
02932 rb_define_singleton_method(envtbl,"include?", env_has_key, 1);
02933 rb_define_singleton_method(envtbl,"member?", env_has_key, 1);
02934 rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1);
02935 rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1);
02936 rb_define_singleton_method(envtbl,"key?", env_has_key, 1);
02937 rb_define_singleton_method(envtbl,"value?", env_has_value, 1);
02938 rb_define_singleton_method(envtbl,"to_hash", env_to_hash, 0);
02939 rb_define_singleton_method(envtbl,"assoc", env_assoc, 1);
02940 rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1);
02941
02942 rb_define_global_const("ENV", envtbl);
02943 }
02944