00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ruby.h"
00016 #include "st.h"
00017 #include "util.h"
00018 #include "rubysig.h"
00019
00020 #ifdef __APPLE__
00021 #include <crt_externs.h>
00022 #endif
00023
00024 #define HASH_DELETED FL_USER1
00025 #define HASH_PROC_DEFAULT FL_USER2
00026
00027 static void
00028 rb_hash_modify(hash)
00029 VALUE hash;
00030 {
00031 if (!RHASH(hash)->tbl) rb_raise(rb_eTypeError, "uninitialized Hash");
00032 if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
00033 if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4)
00034 rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
00035 }
00036
00037 VALUE
00038 rb_hash_freeze(hash)
00039 VALUE hash;
00040 {
00041 return rb_obj_freeze(hash);
00042 }
00043
00044 VALUE rb_cHash;
00045
00046 static VALUE envtbl;
00047 static ID id_hash, id_call, id_default;
00048
00049 static VALUE
00050 eql(args)
00051 VALUE *args;
00052 {
00053 return (VALUE)rb_eql(args[0], args[1]);
00054 }
00055
00056 static int
00057 rb_any_cmp(a, b)
00058 VALUE a, b;
00059 {
00060 VALUE args[2];
00061
00062 if (a == b) return 0;
00063 if (FIXNUM_P(a) && FIXNUM_P(b)) {
00064 return a != b;
00065 }
00066 if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
00067 TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
00068 return rb_str_cmp(a, b);
00069 }
00070 if (a == Qundef || b == Qundef) return -1;
00071 if (SYMBOL_P(a) && SYMBOL_P(b)) {
00072 return a != b;
00073 }
00074
00075 args[0] = a;
00076 args[1] = b;
00077 return !rb_with_disable_interrupt(eql, (VALUE)args);
00078 }
00079
00080 VALUE
00081 rb_hash(obj)
00082 VALUE obj;
00083 {
00084 return rb_funcall(obj, id_hash, 0);
00085 }
00086
00087 static int
00088 rb_any_hash(a)
00089 VALUE a;
00090 {
00091 VALUE hval;
00092
00093 switch (TYPE(a)) {
00094 case T_FIXNUM:
00095 case T_SYMBOL:
00096 return (int)a;
00097 break;
00098
00099 case T_STRING:
00100 return rb_str_hash(a);
00101 break;
00102
00103 default:
00104 hval = rb_funcall(a, id_hash, 0);
00105 if (!FIXNUM_P(hval)) {
00106 hval = rb_funcall(hval, '%', 1, INT2FIX(536870923));
00107 }
00108 return (int)FIX2LONG(hval);
00109 }
00110 }
00111
00112 static struct st_hash_type objhash = {
00113 rb_any_cmp,
00114 rb_any_hash,
00115 };
00116
00117 struct foreach_safe_arg {
00118 st_table *tbl;
00119 int (*func)();
00120 st_data_t arg;
00121 };
00122
00123 static int
00124 foreach_safe_i(key, value, arg)
00125 st_data_t key, value;
00126 struct foreach_safe_arg *arg;
00127 {
00128 int status;
00129
00130 if (key == Qundef) return ST_CONTINUE;
00131 status = (*arg->func)(key, value, arg->arg);
00132 if (status == ST_CONTINUE) {
00133 return ST_CHECK;
00134 }
00135 return status;
00136 }
00137
00138 void
00139 st_foreach_safe(table, func, a)
00140 st_table *table;
00141 int (*func)();
00142 st_data_t a;
00143 {
00144 struct foreach_safe_arg arg;
00145
00146 arg.tbl = table;
00147 arg.func = func;
00148 arg.arg = a;
00149 if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) {
00150 rb_raise(rb_eRuntimeError, "hash modified during iteration");
00151 }
00152 }
00153
00154 struct hash_foreach_arg {
00155 VALUE hash;
00156 int (*func)();
00157 VALUE arg;
00158 };
00159
00160 static int
00161 hash_foreach_iter(key, value, arg)
00162 VALUE key, value;
00163 struct hash_foreach_arg *arg;
00164 {
00165 int status;
00166 st_table *tbl;
00167
00168 tbl = RHASH(arg->hash)->tbl;
00169 if (key == Qundef) return ST_CONTINUE;
00170 status = (*arg->func)(key, value, arg->arg);
00171 if (RHASH(arg->hash)->tbl != tbl) {
00172 rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
00173 }
00174 switch (status) {
00175 case ST_DELETE:
00176 st_delete_safe(tbl, (st_data_t*)&key, 0, Qundef);
00177 FL_SET(arg->hash, HASH_DELETED);
00178 case ST_CONTINUE:
00179 break;
00180 case ST_STOP:
00181 return ST_STOP;
00182 }
00183 return ST_CHECK;
00184 }
00185
00186 static VALUE
00187 hash_foreach_ensure(hash)
00188 VALUE hash;
00189 {
00190 RHASH(hash)->iter_lev--;
00191
00192 if (RHASH(hash)->iter_lev == 0) {
00193 if (FL_TEST(hash, HASH_DELETED)) {
00194 st_cleanup_safe(RHASH(hash)->tbl, Qundef);
00195 FL_UNSET(hash, HASH_DELETED);
00196 }
00197 }
00198 return 0;
00199 }
00200
00201 static VALUE
00202 hash_foreach_call(arg)
00203 struct hash_foreach_arg *arg;
00204 {
00205 if (st_foreach(RHASH(arg->hash)->tbl, hash_foreach_iter, (st_data_t)arg)) {
00206 rb_raise(rb_eRuntimeError, "hash modified during iteration");
00207 }
00208 return Qnil;
00209 }
00210
00211 void
00212 rb_hash_foreach(hash, func, farg)
00213 VALUE hash;
00214 int (*func)();
00215 VALUE farg;
00216 {
00217 struct hash_foreach_arg arg;
00218
00219 RHASH(hash)->iter_lev++;
00220 arg.hash = hash;
00221 arg.func = func;
00222 arg.arg = farg;
00223 rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
00224 }
00225
00226 static VALUE hash_alloc (VALUE);
00227 static VALUE
00228 hash_alloc(klass)
00229 VALUE klass;
00230 {
00231 NEWOBJ(hash, struct RHash);
00232 OBJSETUP(hash, klass, T_HASH);
00233
00234 hash->ifnone = Qnil;
00235 hash->tbl = st_init_table(&objhash);
00236
00237 return (VALUE)hash;
00238 }
00239
00240 VALUE
00241 rb_hash_new()
00242 {
00243 return hash_alloc(rb_cHash);
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 static VALUE
00282 rb_hash_initialize(argc, argv, hash)
00283 int argc;
00284 VALUE *argv;
00285 VALUE hash;
00286 {
00287 VALUE ifnone;
00288
00289 rb_hash_modify(hash);
00290 if (rb_block_given_p()) {
00291 if (argc > 0) {
00292 rb_raise(rb_eArgError, "wrong number of arguments");
00293 }
00294 RHASH(hash)->ifnone = rb_block_proc();
00295 FL_SET(hash, HASH_PROC_DEFAULT);
00296 }
00297 else {
00298 rb_scan_args(argc, argv, "01", &ifnone);
00299 RHASH(hash)->ifnone = ifnone;
00300 }
00301
00302 return hash;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 static VALUE
00319 rb_hash_s_create(argc, argv, klass)
00320 int argc;
00321 VALUE *argv;
00322 VALUE klass;
00323 {
00324 VALUE hash;
00325 int i;
00326
00327 if (argc == 1 && TYPE(argv[0]) == T_HASH) {
00328 hash = hash_alloc(klass);
00329
00330 RHASH(hash)->ifnone = Qnil;
00331 RHASH(hash)->tbl = st_copy(RHASH(argv[0])->tbl);
00332
00333 return hash;
00334 }
00335
00336 if (argc % 2 != 0) {
00337 rb_raise(rb_eArgError, "odd number of arguments for Hash");
00338 }
00339
00340 hash = hash_alloc(klass);
00341 for (i=0; i<argc; i+=2) {
00342 rb_hash_aset(hash, argv[i], argv[i + 1]);
00343 }
00344
00345 return hash;
00346 }
00347
00348 static VALUE
00349 to_hash(hash)
00350 VALUE hash;
00351 {
00352 return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
00353 }
00354
00355 static int
00356 rb_hash_rehash_i(key, value, tbl)
00357 VALUE key, value;
00358 st_table *tbl;
00359 {
00360 if (key != Qundef) st_insert(tbl, key, value);
00361 return ST_CONTINUE;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 static VALUE
00385 rb_hash_rehash(hash)
00386 VALUE hash;
00387 {
00388 st_table *tbl;
00389
00390 rb_hash_modify(hash);
00391 tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries);
00392 rb_hash_foreach(hash, rb_hash_rehash_i, (st_data_t)tbl);
00393 st_free_table(RHASH(hash)->tbl);
00394 RHASH(hash)->tbl = tbl;
00395
00396 return hash;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 VALUE
00414 rb_hash_aref(hash, key)
00415 VALUE hash, key;
00416 {
00417 VALUE val;
00418
00419 if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
00420 return rb_funcall(hash, id_default, 1, key);
00421 }
00422 return val;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 static VALUE
00455 rb_hash_fetch(argc, argv, hash)
00456 int argc;
00457 VALUE *argv;
00458 VALUE hash;
00459 {
00460 VALUE key, if_none;
00461 VALUE val;
00462 long block_given;
00463
00464 rb_scan_args(argc, argv, "11", &key, &if_none);
00465
00466 block_given = rb_block_given_p();
00467 if (block_given && argc == 2) {
00468 rb_warn("block supersedes default value argument");
00469 }
00470 if (!st_lookup(RHASH(hash)->tbl, key, &val)) {
00471 if (block_given) return rb_yield(key);
00472 if (argc == 1) {
00473 rb_raise(rb_eIndexError, "key not found");
00474 }
00475 return if_none;
00476 }
00477 return val;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 static VALUE
00502 rb_hash_default(argc, argv, hash)
00503 int argc;
00504 VALUE *argv;
00505 VALUE hash;
00506 {
00507 VALUE key;
00508
00509 rb_scan_args(argc, argv, "01", &key);
00510 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00511 return rb_funcall(RHASH(hash)->ifnone, id_call, 2, hash, key);
00512 }
00513 return RHASH(hash)->ifnone;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 static VALUE
00537 rb_hash_set_default(hash, ifnone)
00538 VALUE hash, ifnone;
00539 {
00540 rb_hash_modify(hash);
00541 RHASH(hash)->ifnone = ifnone;
00542 FL_UNSET(hash, HASH_PROC_DEFAULT);
00543 return ifnone;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 static VALUE
00562 rb_hash_default_proc(hash)
00563 VALUE hash;
00564 {
00565 if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00566 return RHASH(hash)->ifnone;
00567 }
00568 return Qnil;
00569 }
00570
00571 static int
00572 index_i(key, value, args)
00573 VALUE key, value;
00574 VALUE *args;
00575 {
00576 if (rb_equal(value, args[0])) {
00577 args[1] = key;
00578 return ST_STOP;
00579 }
00580 return ST_CONTINUE;
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 static VALUE
00596 rb_hash_index(hash, value)
00597 VALUE hash, value;
00598 {
00599 VALUE args[2];
00600
00601 args[0] = value;
00602 args[1] = Qnil;
00603
00604 rb_hash_foreach(hash, index_i, (st_data_t)args);
00605
00606 return args[1];
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 static VALUE
00619 rb_hash_indexes(argc, argv, hash)
00620 int argc;
00621 VALUE *argv;
00622 VALUE hash;
00623 {
00624 VALUE indexes;
00625 int i;
00626
00627 rb_warn("Hash#%s is deprecated; use Hash#values_at",
00628 rb_id2name(rb_frame_last_func()));
00629 indexes = rb_ary_new2(argc);
00630 for (i=0; i<argc; i++) {
00631 RARRAY(indexes)->ptr[i] = rb_hash_aref(hash, argv[i]);
00632 RARRAY(indexes)->len++;
00633 }
00634 return indexes;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 VALUE
00656 rb_hash_delete(hash, key)
00657 VALUE hash, key;
00658 {
00659 VALUE val;
00660
00661 rb_hash_modify(hash);
00662 if (RHASH(hash)->iter_lev > 0) {
00663 if (st_delete_safe(RHASH(hash)->tbl, (st_data_t*)&key, &val, Qundef)) {
00664 FL_SET(hash, HASH_DELETED);
00665 return val;
00666 }
00667 }
00668 else if (st_delete(RHASH(hash)->tbl, (st_data_t*)&key, &val))
00669 return val;
00670 if (rb_block_given_p()) {
00671 return rb_yield(key);
00672 }
00673 return Qnil;
00674 }
00675
00676 struct shift_var {
00677 int stop;
00678 VALUE key;
00679 VALUE val;
00680 };
00681
00682 static int
00683 shift_i(key, value, var)
00684 VALUE key, value;
00685 struct shift_var *var;
00686 {
00687 if (key == Qundef) return ST_CONTINUE;
00688 if (var->stop) return ST_STOP;
00689 var->stop = 1;
00690 var->key = key;
00691 var->val = value;
00692 return ST_DELETE;
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 static VALUE
00709 rb_hash_shift(hash)
00710 VALUE hash;
00711 {
00712 struct shift_var var;
00713
00714 rb_hash_modify(hash);
00715 var.stop = 0;
00716 rb_hash_foreach(hash, shift_i, (st_data_t)&var);
00717
00718 if (var.stop) {
00719 return rb_assoc_new(var.key, var.val);
00720 }
00721 else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
00722 return rb_funcall(RHASH(hash)->ifnone, id_call, 2, hash, Qnil);
00723 }
00724 else {
00725 return RHASH(hash)->ifnone;
00726 }
00727 }
00728
00729 static int
00730 delete_if_i(key, value, hash)
00731 VALUE key, value, hash;
00732 {
00733 if (key == Qundef) return ST_CONTINUE;
00734 if (RTEST(rb_yield_values(2, key, value))) {
00735 rb_hash_delete(hash, key);
00736 }
00737 return ST_CONTINUE;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 VALUE
00753 rb_hash_delete_if(hash)
00754 VALUE hash;
00755 {
00756 rb_hash_modify(hash);
00757 rb_hash_foreach(hash, delete_if_i, hash);
00758 return hash;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 VALUE
00770 rb_hash_reject_bang(hash)
00771 VALUE hash;
00772 {
00773 int n = RHASH(hash)->tbl->num_entries;
00774 rb_hash_delete_if(hash);
00775 if (n == RHASH(hash)->tbl->num_entries) return Qnil;
00776 return hash;
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 static VALUE
00790 rb_hash_reject(hash)
00791 VALUE hash;
00792 {
00793 return rb_hash_delete_if(rb_obj_dup(hash));
00794 }
00795
00796 static int
00797 select_i(key, value, result)
00798 VALUE key, value, result;
00799 {
00800 if (key == Qundef) return ST_CONTINUE;
00801 if (RTEST(rb_yield_values(2, key, value)))
00802 rb_ary_push(result, rb_assoc_new(key, value));
00803 return ST_CONTINUE;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 VALUE
00818 rb_hash_values_at(argc, argv, hash)
00819 int argc;
00820 VALUE *argv;
00821 VALUE hash;
00822 {
00823 VALUE result = rb_ary_new();
00824 long i;
00825
00826 for (i=0; i<argc; i++) {
00827 rb_ary_push(result, rb_hash_aref(hash, argv[i]));
00828 }
00829 return result;
00830 }
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 VALUE
00846 rb_hash_select(argc, argv, hash)
00847 int argc;
00848 VALUE *argv;
00849 VALUE hash;
00850 {
00851 VALUE result;
00852
00853 if (argc > 0) {
00854 rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
00855 }
00856 result = rb_ary_new();
00857 rb_hash_foreach(hash, select_i, result);
00858 return result;
00859 }
00860
00861 static int
00862 clear_i(key, value, dummy)
00863 VALUE key, value, dummy;
00864 {
00865 return ST_DELETE;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 static VALUE
00880 rb_hash_clear(hash)
00881 VALUE hash;
00882 {
00883 rb_hash_modify(hash);
00884 if (RHASH(hash)->tbl->num_entries > 0) {
00885 rb_hash_foreach(hash, clear_i, 0);
00886 }
00887
00888 return hash;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 VALUE
00910 rb_hash_aset(hash, key, val)
00911 VALUE hash, key, val;
00912 {
00913 rb_hash_modify(hash);
00914 if (TYPE(key) != T_STRING || st_lookup(RHASH(hash)->tbl, key, 0)) {
00915 st_insert(RHASH(hash)->tbl, key, val);
00916 }
00917 else {
00918 st_add_direct(RHASH(hash)->tbl, rb_str_new4(key), val);
00919 }
00920 return val;
00921 }
00922
00923 static int
00924 replace_i(key, val, hash)
00925 VALUE key, val, hash;
00926 {
00927 if (key != Qundef) {
00928 rb_hash_aset(hash, key, val);
00929 }
00930
00931 return ST_CONTINUE;
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 static VALUE
00947 rb_hash_replace(hash, hash2)
00948 VALUE hash, hash2;
00949 {
00950 hash2 = to_hash(hash2);
00951 if (hash == hash2) return hash;
00952 rb_hash_clear(hash);
00953 rb_hash_foreach(hash2, replace_i, hash);
00954 RHASH(hash)->ifnone = RHASH(hash2)->ifnone;
00955 if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
00956 FL_SET(hash, HASH_PROC_DEFAULT);
00957 }
00958 else {
00959 FL_UNSET(hash, HASH_PROC_DEFAULT);
00960 }
00961
00962 return hash;
00963 }
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 static VALUE
00979 rb_hash_size(hash)
00980 VALUE hash;
00981 {
00982 return INT2FIX(RHASH(hash)->tbl->num_entries);
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 static VALUE
00997 rb_hash_empty_p(hash)
00998 VALUE hash;
00999 {
01000 if (RHASH(hash)->tbl->num_entries == 0)
01001 return Qtrue;
01002 return Qfalse;
01003 }
01004
01005 static int
01006 each_value_i(key, value)
01007 VALUE key, value;
01008 {
01009 if (key == Qundef) return ST_CONTINUE;
01010 rb_yield(value);
01011 return ST_CONTINUE;
01012 }
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 static VALUE
01031 rb_hash_each_value(hash)
01032 VALUE hash;
01033 {
01034 rb_hash_foreach(hash, each_value_i, 0);
01035 return hash;
01036 }
01037
01038 static int
01039 each_key_i(key, value)
01040 VALUE key, value;
01041 {
01042 if (key == Qundef) return ST_CONTINUE;
01043 rb_yield(key);
01044 return ST_CONTINUE;
01045 }
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static VALUE
01063 rb_hash_each_key(hash)
01064 VALUE hash;
01065 {
01066 rb_hash_foreach(hash, each_key_i, 0);
01067 return hash;
01068 }
01069
01070 static int
01071 each_pair_i(key, value)
01072 VALUE key, value;
01073 {
01074 if (key == Qundef) return ST_CONTINUE;
01075 rb_yield_values(2, key, value);
01076 return ST_CONTINUE;
01077 }
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096 static VALUE
01097 rb_hash_each_pair(hash)
01098 VALUE hash;
01099 {
01100 rb_hash_foreach(hash, each_pair_i, 0);
01101 return hash;
01102 }
01103
01104 static int
01105 each_i(key, value)
01106 VALUE key, value;
01107 {
01108 if (key == Qundef) return ST_CONTINUE;
01109 rb_yield(rb_assoc_new(key, value));
01110 return ST_CONTINUE;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 static VALUE
01134 rb_hash_each(hash)
01135 VALUE hash;
01136 {
01137 rb_hash_foreach(hash, each_i, 0);
01138 return hash;
01139 }
01140
01141 static int
01142 to_a_i(key, value, ary)
01143 VALUE key, value, ary;
01144 {
01145 if (key == Qundef) return ST_CONTINUE;
01146 rb_ary_push(ary, rb_assoc_new(key, value));
01147 return ST_CONTINUE;
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 static VALUE
01162 rb_hash_to_a(hash)
01163 VALUE hash;
01164 {
01165 VALUE ary;
01166
01167 ary = rb_ary_new();
01168 rb_hash_foreach(hash, to_a_i, ary);
01169 if (OBJ_TAINTED(hash)) OBJ_TAINT(ary);
01170
01171 return ary;
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189 static VALUE
01190 rb_hash_sort(hash)
01191 VALUE hash;
01192 {
01193 VALUE entries = rb_hash_to_a(hash);
01194 rb_ary_sort_bang(entries);
01195 return entries;
01196 }
01197
01198 static int
01199 inspect_i(key, value, str)
01200 VALUE key, value, str;
01201 {
01202 VALUE str2;
01203
01204 if (key == Qundef) return ST_CONTINUE;
01205 if (RSTRING(str)->len > 1) {
01206 rb_str_cat2(str, ", ");
01207 }
01208 str2 = rb_inspect(key);
01209 rb_str_buf_append(str, str2);
01210 OBJ_INFECT(str, str2);
01211 rb_str_buf_cat2(str, "=>");
01212 str2 = rb_inspect(value);
01213 rb_str_buf_append(str, str2);
01214 OBJ_INFECT(str, str2);
01215
01216 return ST_CONTINUE;
01217 }
01218
01219 static VALUE
01220 inspect_hash(hash)
01221 VALUE hash;
01222 {
01223 VALUE str;
01224
01225 str = rb_str_buf_new2("{");
01226 rb_hash_foreach(hash, inspect_i, str);
01227 rb_str_buf_cat2(str, "}");
01228 OBJ_INFECT(str, hash);
01229
01230 return str;
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240 static VALUE
01241 rb_hash_inspect(hash)
01242 VALUE hash;
01243 {
01244 if (RHASH(hash)->tbl == 0 || RHASH(hash)->tbl->num_entries == 0)
01245 return rb_str_new2("{}");
01246 if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
01247 return rb_protect_inspect(inspect_hash, hash, 0);
01248 }
01249
01250 static VALUE
01251 to_s_hash(hash)
01252 VALUE hash;
01253 {
01254 return rb_ary_to_s(rb_hash_to_a(hash));
01255 }
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 static VALUE
01271 rb_hash_to_s(hash)
01272 VALUE hash;
01273 {
01274 if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
01275 return rb_protect_inspect(to_s_hash, hash, 0);
01276 }
01277
01278
01279
01280
01281
01282
01283
01284
01285 static VALUE
01286 rb_hash_to_hash(hash)
01287 VALUE hash;
01288 {
01289 return hash;
01290 }
01291
01292 static int
01293 keys_i(key, value, ary)
01294 VALUE key, value, ary;
01295 {
01296 if (key == Qundef) return ST_CONTINUE;
01297 rb_ary_push(ary, key);
01298 return ST_CONTINUE;
01299 }
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313 static VALUE
01314 rb_hash_keys(hash)
01315 VALUE hash;
01316 {
01317 VALUE ary;
01318
01319 ary = rb_ary_new();
01320 rb_hash_foreach(hash, keys_i, ary);
01321
01322 return ary;
01323 }
01324
01325 static int
01326 values_i(key, value, ary)
01327 VALUE key, value, ary;
01328 {
01329 if (key == Qundef) return ST_CONTINUE;
01330 rb_ary_push(ary, value);
01331 return ST_CONTINUE;
01332 }
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 static VALUE
01347 rb_hash_values(hash)
01348 VALUE hash;
01349 {
01350 VALUE ary;
01351
01352 ary = rb_ary_new();
01353 rb_hash_foreach(hash, values_i, ary);
01354
01355 return ary;
01356 }
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 static VALUE
01374 rb_hash_has_key(hash, key)
01375 VALUE hash;
01376 VALUE key;
01377 {
01378 if (st_lookup(RHASH(hash)->tbl, key, 0)) {
01379 return Qtrue;
01380 }
01381 return Qfalse;
01382 }
01383
01384 static int
01385 rb_hash_search_value(key, value, data)
01386 VALUE key, value, *data;
01387 {
01388 if (key == Qundef) return ST_CONTINUE;
01389 if (rb_equal(value, data[1])) {
01390 data[0] = Qtrue;
01391 return ST_STOP;
01392 }
01393 return ST_CONTINUE;
01394 }
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409 static VALUE
01410 rb_hash_has_value(hash, val)
01411 VALUE hash;
01412 VALUE val;
01413 {
01414 VALUE data[2];
01415
01416 data[0] = Qfalse;
01417 data[1] = val;
01418 rb_hash_foreach(hash, rb_hash_search_value, (st_data_t)data);
01419 return data[0];
01420 }
01421
01422 struct equal_data {
01423 int result;
01424 st_table *tbl;
01425 };
01426
01427 static int
01428 equal_i(key, val1, data)
01429 VALUE key, val1;
01430 struct equal_data *data;
01431 {
01432 VALUE val2;
01433
01434 if (key == Qundef) return ST_CONTINUE;
01435 if (!st_lookup(data->tbl, key, &val2)) {
01436 data->result = Qfalse;
01437 return ST_STOP;
01438 }
01439 if (!rb_equal(val1, val2)) {
01440 data->result = Qfalse;
01441 return ST_STOP;
01442 }
01443 return ST_CONTINUE;
01444 }
01445
01446 static VALUE
01447 hash_equal(hash1, hash2, eql)
01448 VALUE hash1, hash2;
01449 int eql;
01450 {
01451 struct equal_data data;
01452
01453 if (hash1 == hash2) return Qtrue;
01454 if (TYPE(hash2) != T_HASH) {
01455 if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
01456 return Qfalse;
01457 }
01458 return rb_equal(hash2, hash1);
01459 }
01460 if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries)
01461 return Qfalse;
01462 if (eql) {
01463 if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
01464 FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
01465 return Qfalse;
01466 }
01467
01468 data.tbl = RHASH(hash2)->tbl;
01469 data.result = Qtrue;
01470 rb_hash_foreach(hash1, equal_i, (st_data_t)&data);
01471
01472 return data.result;
01473 }
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494 static VALUE
01495 rb_hash_equal(hash1, hash2)
01496 VALUE hash1, hash2;
01497 {
01498 return hash_equal(hash1, hash2, Qfalse);
01499 }
01500
01501 static int
01502 rb_hash_invert_i(key, value, hash)
01503 VALUE key, value;
01504 VALUE hash;
01505 {
01506 if (key == Qundef) return ST_CONTINUE;
01507 rb_hash_aset(hash, value, key);
01508 return ST_CONTINUE;
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523 static VALUE
01524 rb_hash_invert(hash)
01525 VALUE hash;
01526 {
01527 VALUE h = rb_hash_new();
01528
01529 rb_hash_foreach(hash, rb_hash_invert_i, h);
01530 return h;
01531 }
01532
01533 static int
01534 rb_hash_update_i(key, value, hash)
01535 VALUE key, value;
01536 VALUE hash;
01537 {
01538 if (key == Qundef) return ST_CONTINUE;
01539 rb_hash_aset(hash, key, value);
01540 return ST_CONTINUE;
01541 }
01542
01543 static int
01544 rb_hash_update_block_i(key, value, hash)
01545 VALUE key, value;
01546 VALUE hash;
01547 {
01548 if (key == Qundef) return ST_CONTINUE;
01549 if (rb_hash_has_key(hash, key)) {
01550 value = rb_yield_values(3, key, rb_hash_aref(hash, key), value);
01551 }
01552 rb_hash_aset(hash, key, value);
01553 return ST_CONTINUE;
01554 }
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571 static VALUE
01572 rb_hash_update(hash1, hash2)
01573 VALUE hash1, hash2;
01574 {
01575 hash2 = to_hash(hash2);
01576 if (rb_block_given_p()) {
01577 rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
01578 }
01579 else {
01580 rb_hash_foreach(hash2, rb_hash_update_i, hash1);
01581 }
01582 return hash1;
01583 }
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601 static VALUE
01602 rb_hash_merge(hash1, hash2)
01603 VALUE hash1, hash2;
01604 {
01605 return rb_hash_update(rb_obj_dup(hash1), hash2);
01606 }
01607
01608 static int path_tainted = -1;
01609
01610 static char **origenviron;
01611 #ifdef _WIN32
01612 #define GET_ENVIRON(e) (e = rb_w32_get_environ())
01613 #define FREE_ENVIRON(e) rb_w32_free_environ(e)
01614 static char **my_environ;
01615 #undef environ
01616 #define environ my_environ
01617 #elif defined(__APPLE__)
01618 #undef environ
01619 #define environ (*_NSGetEnviron())
01620 #define GET_ENVIRON(e) (e)
01621 #define FREE_ENVIRON(e)
01622 #else
01623 extern char **environ;
01624 #define GET_ENVIRON(e) (e)
01625 #define FREE_ENVIRON(e)
01626 #endif
01627
01628 static VALUE
01629 env_str_new(ptr, len)
01630 const char *ptr;
01631 long len;
01632 {
01633 VALUE str = rb_tainted_str_new(ptr, len);
01634
01635 rb_obj_freeze(str);
01636 return str;
01637 }
01638
01639 static VALUE
01640 env_str_new2(ptr)
01641 const char *ptr;
01642 {
01643 if (!ptr) return Qnil;
01644 return env_str_new(ptr, strlen(ptr));
01645 }
01646
01647 static VALUE
01648 env_delete(obj, name)
01649 VALUE obj, name;
01650 {
01651 char *nam, *val;
01652
01653 rb_secure(4);
01654 SafeStringValue(name);
01655 nam = RSTRING(name)->ptr;
01656 if (strlen(nam) != RSTRING(name)->len) {
01657 rb_raise(rb_eArgError, "bad environment variable name");
01658 }
01659 val = getenv(nam);
01660 if (val) {
01661 VALUE value = env_str_new2(val);
01662
01663 ruby_setenv(nam, 0);
01664 #ifdef ENV_IGNORECASE
01665 if (strcasecmp(nam, PATH_ENV) == 0)
01666 #else
01667 if (strcmp(nam, PATH_ENV) == 0)
01668 #endif
01669 {
01670 path_tainted = 0;
01671 }
01672 return value;
01673 }
01674 return Qnil;
01675 }
01676
01677 static VALUE
01678 env_delete_m(obj, name)
01679 VALUE obj, name;
01680 {
01681 VALUE val;
01682
01683 val = env_delete(obj, name);
01684 if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
01685 return val;
01686 }
01687
01688 static VALUE
01689 rb_f_getenv(obj, name)
01690 VALUE obj, name;
01691 {
01692 char *nam, *env;
01693
01694 StringValue(name);
01695 nam = RSTRING(name)->ptr;
01696 if (strlen(nam) != RSTRING(name)->len) {
01697 rb_raise(rb_eArgError, "bad environment variable name");
01698 }
01699 env = getenv(nam);
01700 if (env) {
01701 #ifdef ENV_IGNORECASE
01702 if (strcasecmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
01703 #else
01704 if (strcmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
01705 #endif
01706 {
01707 VALUE str = rb_str_new2(env);
01708
01709 rb_obj_freeze(str);
01710 return str;
01711 }
01712 return env_str_new2(env);
01713 }
01714 return Qnil;
01715 }
01716
01717 static VALUE
01718 env_fetch(argc, argv)
01719 int argc;
01720 VALUE *argv;
01721 {
01722 VALUE key, if_none;
01723 long block_given;
01724 char *nam, *env;
01725
01726 rb_scan_args(argc, argv, "11", &key, &if_none);
01727 block_given = rb_block_given_p();
01728 if (block_given && argc == 2) {
01729 rb_warn("block supersedes default value argument");
01730 }
01731 StringValue(key);
01732 nam = RSTRING(key)->ptr;
01733 if (str