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