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