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