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