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