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