|
Ruby
2.0.0p353(2013-11-22revision43784)
|
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 01176 * 01177 * Associates the value given by +value+ with the key given by +key+. 01178 * 01179 * h = { "a" => 100, "b" => 200 } 01180 * h["a"] = 9 01181 * h["c"] = 4 01182 * h #=> {"a"=>9, "b"=>200, "c"=>4} 01183 * 01184 * +key+ should not have its value changed while it is in use as a key (an 01185 * <tt>unfrozen String</tt> passed as a key will be duplicated and frozen). 01186 * 01187 * a = "a" 01188 * b = "b".freeze 01189 * h = { a => 100, b => 200 } 01190 * h.key(100).equal? a #=> false 01191 * h.key(200).equal? b #=> true 01192 * 01193 */ 01194 01195 VALUE 01196 rb_hash_aset(VALUE hash, VALUE key, VALUE val) 01197 { 01198 int iter_lev = RHASH_ITER_LEV(hash); 01199 st_table *tbl = RHASH(hash)->ntbl; 01200 01201 rb_hash_modify(hash); 01202 if (!tbl) { 01203 if (iter_lev > 0) no_new_key(); 01204 tbl = RHASH_TBL(hash); 01205 } 01206 if (tbl->type == &identhash || rb_obj_class(key) != rb_cString) { 01207 RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val); 01208 } 01209 else { 01210 RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset_str, val); 01211 } 01212 return val; 01213 } 01214 01215 static int 01216 replace_i(VALUE key, VALUE val, VALUE hash) 01217 { 01218 rb_hash_aset(hash, key, val); 01219 01220 return ST_CONTINUE; 01221 } 01222 01223 static VALUE 01224 rb_hash_initialize_copy(VALUE hash, VALUE hash2) 01225 { 01226 rb_hash_modify_check(hash); 01227 hash2 = to_hash(hash2); 01228 01229 Check_Type(hash2, T_HASH); 01230 01231 if (!RHASH_EMPTY_P(hash2)) { 01232 RHASH(hash)->ntbl = st_copy(RHASH(hash2)->ntbl); 01233 rb_hash_rehash(hash); 01234 } 01235 01236 if (FL_TEST(hash2, HASH_PROC_DEFAULT)) { 01237 FL_SET(hash, HASH_PROC_DEFAULT); 01238 } 01239 else { 01240 FL_UNSET(hash, HASH_PROC_DEFAULT); 01241 } 01242 RHASH_IFNONE(hash) = RHASH_IFNONE(hash2); 01243 01244 return hash; 01245 } 01246 01247 /* 01248 * call-seq: 01249 * hsh.replace(other_hash) -> hsh 01250 * 01251 * Replaces the contents of <i>hsh</i> with the contents of 01252 * <i>other_hash</i>. 01253 * 01254 * h = { "a" => 100, "b" => 200 } 01255 * h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400} 01256 * 01257 */ 01258 01259 static VALUE 01260 rb_hash_replace(VALUE hash, VALUE hash2) 01261 { 01262 rb_hash_modify_check(hash); 01263 hash2 = to_hash(hash2); 01264 if (hash == hash2) return hash; 01265 rb_hash_clear(hash); 01266 if (RHASH(hash2)->ntbl) { 01267 rb_hash_tbl(hash); 01268 RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type; 01269 } 01270 rb_hash_foreach(hash2, replace_i, hash); 01271 RHASH_IFNONE(hash) = RHASH_IFNONE(hash2); 01272 if (FL_TEST(hash2, HASH_PROC_DEFAULT)) { 01273 FL_SET(hash, HASH_PROC_DEFAULT); 01274 } 01275 else { 01276 FL_UNSET(hash, HASH_PROC_DEFAULT); 01277 } 01278 01279 return hash; 01280 } 01281 01282 /* 01283 * call-seq: 01284 * hsh.length -> fixnum 01285 * hsh.size -> fixnum 01286 * 01287 * Returns the number of key-value pairs in the hash. 01288 * 01289 * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 } 01290 * h.length #=> 4 01291 * h.delete("a") #=> 200 01292 * h.length #=> 3 01293 */ 01294 01295 static VALUE 01296 rb_hash_size(VALUE hash) 01297 { 01298 if (!RHASH(hash)->ntbl) 01299 return INT2FIX(0); 01300 return INT2FIX(RHASH(hash)->ntbl->num_entries); 01301 } 01302 01303 01304 /* 01305 * call-seq: 01306 * hsh.empty? -> true or false 01307 * 01308 * Returns <code>true</code> if <i>hsh</i> contains no key-value pairs. 01309 * 01310 * {}.empty? #=> true 01311 * 01312 */ 01313 01314 static VALUE 01315 rb_hash_empty_p(VALUE hash) 01316 { 01317 return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse; 01318 } 01319 01320 static int 01321 each_value_i(VALUE key, VALUE value) 01322 { 01323 rb_yield(value); 01324 return ST_CONTINUE; 01325 } 01326 01327 /* 01328 * call-seq: 01329 * hsh.each_value {| value | block } -> hsh 01330 * hsh.each_value -> an_enumerator 01331 * 01332 * Calls <i>block</i> once for each key in <i>hsh</i>, passing the 01333 * value as a parameter. 01334 * 01335 * If no block is given, an enumerator is returned instead. 01336 * 01337 * h = { "a" => 100, "b" => 200 } 01338 * h.each_value {|value| puts value } 01339 * 01340 * <em>produces:</em> 01341 * 01342 * 100 01343 * 200 01344 */ 01345 01346 static VALUE 01347 rb_hash_each_value(VALUE hash) 01348 { 01349 RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size); 01350 rb_hash_foreach(hash, each_value_i, 0); 01351 return hash; 01352 } 01353 01354 static int 01355 each_key_i(VALUE key, VALUE value) 01356 { 01357 rb_yield(key); 01358 return ST_CONTINUE; 01359 } 01360 01361 /* 01362 * call-seq: 01363 * hsh.each_key {| key | block } -> hsh 01364 * hsh.each_key -> an_enumerator 01365 * 01366 * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key 01367 * as a parameter. 01368 * 01369 * If no block is given, an enumerator is returned instead. 01370 * 01371 * h = { "a" => 100, "b" => 200 } 01372 * h.each_key {|key| puts key } 01373 * 01374 * <em>produces:</em> 01375 * 01376 * a 01377 * b 01378 */ 01379 static VALUE 01380 rb_hash_each_key(VALUE hash) 01381 { 01382 RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size); 01383 rb_hash_foreach(hash, each_key_i, 0); 01384 return hash; 01385 } 01386 01387 static int 01388 each_pair_i(VALUE key, VALUE value) 01389 { 01390 rb_yield(rb_assoc_new(key, value)); 01391 return ST_CONTINUE; 01392 } 01393 01394 /* 01395 * call-seq: 01396 * hsh.each {| key, value | block } -> hsh 01397 * hsh.each_pair {| key, value | block } -> hsh 01398 * hsh.each -> an_enumerator 01399 * hsh.each_pair -> an_enumerator 01400 * 01401 * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key-value 01402 * pair as parameters. 01403 * 01404 * If no block is given, an enumerator is returned instead. 01405 * 01406 * h = { "a" => 100, "b" => 200 } 01407 * h.each {|key, value| puts "#{key} is #{value}" } 01408 * 01409 * <em>produces:</em> 01410 * 01411 * a is 100 01412 * b is 200 01413 * 01414 */ 01415 01416 static VALUE 01417 rb_hash_each_pair(VALUE hash) 01418 { 01419 RETURN_SIZED_ENUMERATOR(hash, 0, 0, rb_hash_size); 01420 rb_hash_foreach(hash, each_pair_i, 0); 01421 return hash; 01422 } 01423 01424 static int 01425 to_a_i(VALUE key, VALUE value, VALUE ary) 01426 { 01427 rb_ary_push(ary, rb_assoc_new(key, value)); 01428 return ST_CONTINUE; 01429 } 01430 01431 /* 01432 * call-seq: 01433 * hsh.to_a -> array 01434 * 01435 * Converts <i>hsh</i> to a nested array of <code>[</code> <i>key, 01436 * value</i> <code>]</code> arrays. 01437 * 01438 * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } 01439 * h.to_a #=> [["c", 300], ["a", 100], ["d", 400]] 01440 */ 01441 01442 static VALUE 01443 rb_hash_to_a(VALUE hash) 01444 { 01445 VALUE ary; 01446 01447 ary = rb_ary_new(); 01448 rb_hash_foreach(hash, to_a_i, ary); 01449 OBJ_INFECT(ary, hash); 01450 01451 return ary; 01452 } 01453 01454 static int 01455 inspect_i(VALUE key, VALUE value, VALUE str) 01456 { 01457 VALUE str2; 01458 01459 str2 = rb_inspect(key); 01460 if (RSTRING_LEN(str) > 1) { 01461 rb_str_buf_cat_ascii(str, ", "); 01462 } 01463 else { 01464 rb_enc_copy(str, str2); 01465 } 01466 rb_str_buf_append(str, str2); 01467 OBJ_INFECT(str, str2); 01468 rb_str_buf_cat_ascii(str, "=>"); 01469 str2 = rb_inspect(value); 01470 rb_str_buf_append(str, str2); 01471 OBJ_INFECT(str, str2); 01472 01473 return ST_CONTINUE; 01474 } 01475 01476 static VALUE 01477 inspect_hash(VALUE hash, VALUE dummy, int recur) 01478 { 01479 VALUE str; 01480 01481 if (recur) return rb_usascii_str_new2("{...}"); 01482 str = rb_str_buf_new2("{"); 01483 rb_hash_foreach(hash, inspect_i, str); 01484 rb_str_buf_cat2(str, "}"); 01485 OBJ_INFECT(str, hash); 01486 01487 return str; 01488 } 01489 01490 /* 01491 * call-seq: 01492 * hsh.to_s -> string 01493 * hsh.inspect -> string 01494 * 01495 * Return the contents of this hash as a string. 01496 * 01497 * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } 01498 * h.to_s #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}" 01499 */ 01500 01501 static VALUE 01502 rb_hash_inspect(VALUE hash) 01503 { 01504 if (RHASH_EMPTY_P(hash)) 01505 return rb_usascii_str_new2("{}"); 01506 return rb_exec_recursive(inspect_hash, hash, 0); 01507 } 01508 01509 /* 01510 * call-seq: 01511 * hsh.to_hash => hsh 01512 * 01513 * Returns +self+. 01514 */ 01515 01516 static VALUE 01517 rb_hash_to_hash(VALUE hash) 01518 { 01519 return hash; 01520 } 01521 01522 /* 01523 * call-seq: 01524 * hsh.to_h -> hsh or new_hash 01525 * 01526 * Returns +self+. If called on a subclass of Hash, converts 01527 * the receiver to a Hash object. 01528 */ 01529 01530 static VALUE 01531 rb_hash_to_h(VALUE hash) 01532 { 01533 if (rb_obj_class(hash) != rb_cHash) { 01534 VALUE ret = rb_hash_new(); 01535 if (!RHASH_EMPTY_P(hash)) 01536 RHASH(ret)->ntbl = st_copy(RHASH(hash)->ntbl); 01537 if (FL_TEST(hash, HASH_PROC_DEFAULT)) { 01538 FL_SET(ret, HASH_PROC_DEFAULT); 01539 } 01540 RHASH_IFNONE(ret) = RHASH_IFNONE(hash); 01541 return ret; 01542 } 01543 return hash; 01544 } 01545 01546 static int 01547 keys_i(VALUE key, VALUE value, VALUE ary) 01548 { 01549 rb_ary_push(ary, key); 01550 return ST_CONTINUE; 01551 } 01552 01553 /* 01554 * call-seq: 01555 * hsh.keys -> array 01556 * 01557 * Returns a new array populated with the keys from this hash. See also 01558 * <code>Hash#values</code>. 01559 * 01560 * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 } 01561 * h.keys #=> ["a", "b", "c", "d"] 01562 * 01563 */ 01564 01565 static VALUE 01566 rb_hash_keys(VALUE hash) 01567 { 01568 VALUE ary; 01569 01570 ary = rb_ary_new(); 01571 rb_hash_foreach(hash, keys_i, ary); 01572 01573 return ary; 01574 } 01575 01576 static int 01577 values_i(VALUE key, VALUE value, VALUE ary) 01578 { 01579 rb_ary_push(ary, value); 01580 return ST_CONTINUE; 01581 } 01582 01583 /* 01584 * call-seq: 01585 * hsh.values -> array 01586 * 01587 * Returns a new array populated with the values from <i>hsh</i>. See 01588 * also <code>Hash#keys</code>. 01589 * 01590 * h = { "a" => 100, "b" => 200, "c" => 300 } 01591 * h.values #=> [100, 200, 300] 01592 * 01593 */ 01594 01595 static VALUE 01596 rb_hash_values(VALUE hash) 01597 { 01598 VALUE ary; 01599 01600 ary = rb_ary_new(); 01601 rb_hash_foreach(hash, values_i, ary); 01602 01603 return ary; 01604 } 01605 01606 /* 01607 * call-seq: 01608 * hsh.has_key?(key) -> true or false 01609 * hsh.include?(key) -> true or false 01610 * hsh.key?(key) -> true or false 01611 * hsh.member?(key) -> true or false 01612 * 01613 * Returns <code>true</code> if the given key is present in <i>hsh</i>. 01614 * 01615 * h = { "a" => 100, "b" => 200 } 01616 * h.has_key?("a") #=> true 01617 * h.has_key?("z") #=> false 01618 * 01619 */ 01620 01621 static VALUE 01622 rb_hash_has_key(VALUE hash, VALUE key) 01623 { 01624 if (!RHASH(hash)->ntbl) 01625 return Qfalse; 01626 if (st_lookup(RHASH(hash)->ntbl, key, 0)) { 01627 return Qtrue; 01628 } 01629 return Qfalse; 01630 } 01631 01632 static int 01633 rb_hash_search_value(VALUE key, VALUE value, VALUE arg) 01634 { 01635 VALUE *data = (VALUE *)arg; 01636 01637 if (rb_equal(value, data[1])) { 01638 data[0] = Qtrue; 01639 return ST_STOP; 01640 } 01641 return ST_CONTINUE; 01642 } 01643 01644 /* 01645 * call-seq: 01646 * hsh.has_value?(value) -> true or false 01647 * hsh.value?(value) -> true or false 01648 * 01649 * Returns <code>true</code> if the given value is present for some key 01650 * in <i>hsh</i>. 01651 * 01652 * h = { "a" => 100, "b" => 200 } 01653 * h.has_value?(100) #=> true 01654 * h.has_value?(999) #=> false 01655 */ 01656 01657 static VALUE 01658 rb_hash_has_value(VALUE hash, VALUE val) 01659 { 01660 VALUE data[2]; 01661 01662 data[0] = Qfalse; 01663 data[1] = val; 01664 rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data); 01665 return data[0]; 01666 } 01667 01668 struct equal_data { 01669 VALUE result; 01670 st_table *tbl; 01671 int eql; 01672 }; 01673 01674 static int 01675 eql_i(VALUE key, VALUE val1, VALUE arg) 01676 { 01677 struct equal_data *data = (struct equal_data *)arg; 01678 st_data_t val2; 01679 01680 if (!st_lookup(data->tbl, key, &val2)) { 01681 data->result = Qfalse; 01682 return ST_STOP; 01683 } 01684 if (!(data->eql ? rb_eql(val1, (VALUE)val2) : (int)rb_equal(val1, (VALUE)val2))) { 01685 data->result = Qfalse; 01686 return ST_STOP; 01687 } 01688 return ST_CONTINUE; 01689 } 01690 01691 static VALUE 01692 recursive_eql(VALUE hash, VALUE dt, int recur) 01693 { 01694 struct equal_data *data; 01695 01696 if (recur) return Qtrue; /* Subtle! */ 01697 data = (struct equal_data*)dt; 01698 data->result = Qtrue; 01699 rb_hash_foreach(hash, eql_i, dt); 01700 01701 return data->result; 01702 } 01703 01704 static VALUE 01705 hash_equal(VALUE hash1, VALUE hash2, int eql) 01706 { 01707 struct equal_data data; 01708 01709 if (hash1 == hash2) return Qtrue; 01710 if (!RB_TYPE_P(hash2, T_HASH)) { 01711 if (!rb_respond_to(hash2, rb_intern("to_hash"))) { 01712 return Qfalse; 01713 } 01714 if (eql) 01715 return rb_eql(hash2, hash1); 01716 else 01717 return rb_equal(hash2, hash1); 01718 } 01719 if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2)) 01720 return Qfalse; 01721 if (!RHASH(hash1)->ntbl || !RHASH(hash2)->ntbl) 01722 return Qtrue; 01723 if (RHASH(hash1)->ntbl->type != RHASH(hash2)->ntbl->type) 01724 return Qfalse; 01725 #if 0 01726 if (!(rb_equal(RHASH_IFNONE(hash1), RHASH_IFNONE(hash2)) && 01727 FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT))) 01728 return Qfalse; 01729 #endif 01730 01731 data.tbl = RHASH(hash2)->ntbl; 01732 data.eql = eql; 01733 return rb_exec_recursive_paired(recursive_eql, hash1, hash2, (VALUE)&data); 01734 } 01735 01736 /* 01737 * call-seq: 01738 * hsh == other_hash -> true or false 01739 * 01740 * Equality---Two hashes are equal if they each contain the same number 01741 * of keys and if each key-value pair is equal to (according to 01742 * <code>Object#==</code>) the corresponding elements in the other 01743 * hash. 01744 * 01745 * h1 = { "a" => 1, "c" => 2 } 01746 * h2 = { 7 => 35, "c" => 2, "a" => 1 } 01747 * h3 = { "a" => 1, "c" => 2, 7 => 35 } 01748 * h4 = { "a" => 1, "d" => 2, "f" => 35 } 01749 * h1 == h2 #=> false 01750 * h2 == h3 #=> true 01751 * h3 == h4 #=> false 01752 * 01753 */ 01754 01755 static VALUE 01756 rb_hash_equal(VALUE hash1, VALUE hash2) 01757 { 01758 return hash_equal(hash1, hash2, FALSE); 01759 } 01760 01761 /* 01762 * call-seq: 01763 * hash.eql?(other) -> true or false 01764 * 01765 * Returns <code>true</code> if <i>hash</i> and <i>other</i> are 01766 * both hashes with the same content. 01767 */ 01768 01769 static VALUE 01770 rb_hash_eql(VALUE hash1, VALUE hash2) 01771 { 01772 return hash_equal(hash1, hash2, TRUE); 01773 } 01774 01775 static int 01776 hash_i(VALUE key, VALUE val, VALUE arg) 01777 { 01778 st_index_t *hval = (st_index_t *)arg; 01779 st_index_t hdata[2]; 01780 01781 hdata[0] = rb_hash(key); 01782 hdata[1] = rb_hash(val); 01783 *hval ^= st_hash(hdata, sizeof(hdata), 0); 01784 return ST_CONTINUE; 01785 } 01786 01787 static VALUE 01788 recursive_hash(VALUE hash, VALUE dummy, int recur) 01789 { 01790 st_index_t hval; 01791 01792 if (!RHASH(hash)->ntbl) 01793 return LONG2FIX(0); 01794 hval = RHASH(hash)->ntbl->num_entries; 01795 if (!hval) return LONG2FIX(0); 01796 if (recur) 01797 hval = rb_hash_uint(rb_hash_start(rb_hash(rb_cHash)), hval); 01798 else 01799 rb_hash_foreach(hash, hash_i, (VALUE)&hval); 01800 hval = rb_hash_end(hval); 01801 return INT2FIX(hval); 01802 } 01803 01804 /* 01805 * call-seq: 01806 * hsh.hash -> fixnum 01807 * 01808 * Compute a hash-code for this hash. Two hashes with the same content 01809 * will have the same hash code (and will compare using <code>eql?</code>). 01810 */ 01811 01812 static VALUE 01813 rb_hash_hash(VALUE hash) 01814 { 01815 return rb_exec_recursive_outer(recursive_hash, hash, 0); 01816 } 01817 01818 static int 01819 rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) 01820 { 01821 rb_hash_aset(hash, value, key); 01822 return ST_CONTINUE; 01823 } 01824 01825 /* 01826 * call-seq: 01827 * hsh.invert -> new_hash 01828 * 01829 * Returns a new hash created by using <i>hsh</i>'s values as keys, and 01830 * the keys as values. 01831 * 01832 * h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 } 01833 * h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"} 01834 * 01835 */ 01836 01837 static VALUE 01838 rb_hash_invert(VALUE hash) 01839 { 01840 VALUE h = rb_hash_new(); 01841 01842 rb_hash_foreach(hash, rb_hash_invert_i, h); 01843 return h; 01844 } 01845 01846 static int 01847 rb_hash_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing) 01848 { 01849 *value = arg; 01850 return ST_CONTINUE; 01851 } 01852 01853 static NOINSERT_UPDATE_CALLBACK(rb_hash_update_callback) 01854 01855 static int 01856 rb_hash_update_i(VALUE key, VALUE value, VALUE hash) 01857 { 01858 RHASH_UPDATE(hash, key, rb_hash_update_callback, value); 01859 return ST_CONTINUE; 01860 } 01861 01862 static int 01863 rb_hash_update_block_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing) 01864 { 01865 VALUE newvalue = (VALUE)arg; 01866 if (existing) { 01867 newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue); 01868 } 01869 *value = (st_data_t)newvalue; 01870 return ST_CONTINUE; 01871 } 01872 01873 static NOINSERT_UPDATE_CALLBACK(rb_hash_update_block_callback) 01874 01875 static int 01876 rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) 01877 { 01878 RHASH_UPDATE(hash, key, rb_hash_update_block_callback, value); 01879 return ST_CONTINUE; 01880 } 01881 01882 /* 01883 * call-seq: 01884 * hsh.merge!(other_hash) -> hsh 01885 * hsh.update(other_hash) -> hsh 01886 * hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh 01887 * hsh.update(other_hash){|key, oldval, newval| block} -> hsh 01888 * 01889 * Adds the contents of _other_hash_ to _hsh_. If no block is specified, 01890 * entries with duplicate keys are overwritten with the values from 01891 * _other_hash_, otherwise the value of each duplicate key is determined by 01892 * calling the block with the key, its value in _hsh_ and its value in 01893 * _other_hash_. 01894 * 01895 * h1 = { "a" => 100, "b" => 200 } 01896 * h2 = { "b" => 254, "c" => 300 } 01897 * h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300} 01898 * 01899 * h1 = { "a" => 100, "b" => 200 } 01900 * h2 = { "b" => 254, "c" => 300 } 01901 * h1.merge!(h2) { |key, v1, v2| v1 } 01902 * #=> {"a"=>100, "b"=>200, "c"=>300} 01903 */ 01904 01905 static VALUE 01906 rb_hash_update(VALUE hash1, VALUE hash2) 01907 { 01908 rb_hash_modify(hash1); 01909 hash2 = to_hash(hash2); 01910 if (rb_block_given_p()) { 01911 rb_hash_foreach(hash2, rb_hash_update_block_i, hash1); 01912 } 01913 else { 01914 rb_hash_foreach(hash2, rb_hash_update_i, hash1); 01915 } 01916 return hash1; 01917 } 01918 01919 struct update_arg { 01920 VALUE hash; 01921 VALUE value; 01922 rb_hash_update_func *func; 01923 }; 01924 01925 static int 01926 rb_hash_update_func_callback(st_data_t *key, st_data_t *value, st_data_t arg0, int existing) 01927 { 01928 struct update_arg *arg = (struct update_arg *)arg0; 01929 VALUE newvalue = arg->value; 01930 if (existing) { 01931 newvalue = (*arg->func)((VALUE)*key, (VALUE)*value, newvalue); 01932 } 01933 *value = (st_data_t)newvalue; 01934 return ST_CONTINUE; 01935 } 01936 01937 static NOINSERT_UPDATE_CALLBACK(rb_hash_update_func_callback) 01938 01939 static int 01940 rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0) 01941 { 01942 struct update_arg *arg = (struct update_arg *)arg0; 01943 VALUE hash = arg->hash; 01944 01945 arg->value = value; 01946 RHASH_UPDATE(hash, key, rb_hash_update_func_callback, arg); 01947 return ST_CONTINUE; 01948 } 01949 01950 VALUE 01951 rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func) 01952 { 01953 rb_hash_modify(hash1); 01954 hash2 = to_hash(hash2); 01955 if (func) { 01956 struct update_arg arg; 01957 arg.hash = hash1; 01958 arg.func = func; 01959 rb_hash_foreach(hash2, rb_hash_update_func_i, (VALUE)&arg); 01960 } 01961 else { 01962 rb_hash_foreach(hash2, rb_hash_update_i, hash1); 01963 } 01964 return hash1; 01965 } 01966 01967 /* 01968 * call-seq: 01969 * hsh.merge(other_hash) -> new_hash 01970 * hsh.merge(other_hash){|key, oldval, newval| block} -> new_hash 01971 * 01972 * Returns a new hash containing the contents of <i>other_hash</i> and 01973 * the contents of <i>hsh</i>. If no block is specified, the value for 01974 * entries with duplicate keys will be that of <i>other_hash</i>. Otherwise 01975 * the value for each duplicate key is determined by calling the block 01976 * with the key, its value in <i>hsh</i> and its value in <i>other_hash</i>. 01977 * 01978 * h1 = { "a" => 100, "b" => 200 } 01979 * h2 = { "b" => 254, "c" => 300 } 01980 * h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300} 01981 * h1.merge(h2){|key, oldval, newval| newval - oldval} 01982 * #=> {"a"=>100, "b"=>54, "c"=>300} 01983 * h1 #=> {"a"=>100, "b"=>200} 01984 * 01985 */ 01986 01987 static VALUE 01988 rb_hash_merge(VALUE hash1, VALUE hash2) 01989 { 01990 return rb_hash_update(rb_obj_dup(hash1), hash2); 01991 } 01992 01993 static int 01994 assoc_i(VALUE key, VALUE val, VALUE arg) 01995 { 01996 VALUE *args = (VALUE *)arg; 01997 01998 if (RTEST(rb_equal(args[0], key))) { 01999 args[1] = rb_assoc_new(key, val); 02000 return ST_STOP; 02001 } 02002 return ST_CONTINUE; 02003 } 02004 02005 /* 02006 * call-seq: 02007 * hash.assoc(obj) -> an_array or nil 02008 * 02009 * Searches through the hash comparing _obj_ with the key using <code>==</code>. 02010 * Returns the key-value pair (two elements array) or +nil+ 02011 * if no match is found. See <code>Array#assoc</code>. 02012 * 02013 * h = {"colors" => ["red", "blue", "green"], 02014 * "letters" => ["a", "b", "c" ]} 02015 * h.assoc("letters") #=> ["letters", ["a", "b", "c"]] 02016 * h.assoc("foo") #=> nil 02017 */ 02018 02019 VALUE 02020 rb_hash_assoc(VALUE hash, VALUE obj) 02021 { 02022 VALUE args[2]; 02023 02024 args[0] = obj; 02025 args[1] = Qnil; 02026 rb_hash_foreach(hash, assoc_i, (VALUE)args); 02027 return args[1]; 02028 } 02029 02030 static int 02031 rassoc_i(VALUE key, VALUE val, VALUE arg) 02032 { 02033 VALUE *args = (VALUE *)arg; 02034 02035 if (RTEST(rb_equal(args[0], val))) { 02036 args[1] = rb_assoc_new(key, val); 02037 return ST_STOP; 02038 } 02039 return ST_CONTINUE; 02040 } 02041 02042 /* 02043 * call-seq: 02044 * hash.rassoc(obj) -> an_array or nil 02045 * 02046 * Searches through the hash comparing _obj_ with the value using <code>==</code>. 02047 * Returns the first key-value pair (two-element array) that matches. See 02048 * also <code>Array#rassoc</code>. 02049 * 02050 * a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"} 02051 * a.rassoc("two") #=> [2, "two"] 02052 * a.rassoc("four") #=> nil 02053 */ 02054 02055 VALUE 02056 rb_hash_rassoc(VALUE hash, VALUE obj) 02057 { 02058 VALUE args[2]; 02059 02060 args[0] = obj; 02061 args[1] = Qnil; 02062 rb_hash_foreach(hash, rassoc_i, (VALUE)args); 02063 return args[1]; 02064 } 02065 02066 /* 02067 * call-seq: 02068 * hash.flatten -> an_array 02069 * hash.flatten(level) -> an_array 02070 * 02071 * Returns a new array that is a one-dimensional flattening of this 02072 * hash. That is, for every key or value that is an array, extract 02073 * its elements into the new array. Unlike Array#flatten, this 02074 * method does not flatten recursively by default. The optional 02075 * <i>level</i> argument determines the level of recursion to flatten. 02076 * 02077 * a = {1=> "one", 2 => [2,"two"], 3 => "three"} 02078 * a.flatten # => [1, "one", 2, [2, "two"], 3, "three"] 02079 * a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"] 02080 */ 02081 02082 static VALUE 02083 rb_hash_flatten(int argc, VALUE *argv, VALUE hash) 02084 { 02085 VALUE ary, tmp; 02086 02087 ary = rb_hash_to_a(hash); 02088 if (argc == 0) { 02089 argc = 1; 02090 tmp = INT2FIX(1); 02091 argv = &tmp; 02092 } 02093 rb_funcall2(ary, rb_intern("flatten!"), argc, argv); 02094 return ary; 02095 } 02096 02097 /* 02098 * call-seq: 02099 * hsh.compare_by_identity -> hsh 02100 * 02101 * Makes <i>hsh</i> compare its keys by their identity, i.e. it 02102 * will consider exact same objects as same keys. 02103 * 02104 * h1 = { "a" => 100, "b" => 200, :c => "c" } 02105 * h1["a"] #=> 100 02106 * h1.compare_by_identity 02107 * h1.compare_by_identity? #=> true 02108 * h1["a"] #=> nil # different objects. 02109 * h1[:c] #=> "c" # same symbols are all same. 02110 * 02111 */ 02112 02113 static VALUE 02114 rb_hash_compare_by_id(VALUE hash) 02115 { 02116 rb_hash_modify(hash); 02117 RHASH(hash)->ntbl->type = &identhash; 02118 rb_hash_rehash(hash); 02119 return hash; 02120 } 02121 02122 /* 02123 * call-seq: 02124 * hsh.compare_by_identity? -> true or false 02125 * 02126 * Returns <code>true</code> if <i>hsh</i> will compare its keys by 02127 * their identity. Also see <code>Hash#compare_by_identity</code>. 02128 * 02129 */ 02130 02131 static VALUE 02132 rb_hash_compare_by_id_p(VALUE hash) 02133 { 02134 if (!RHASH(hash)->ntbl) 02135 return Qfalse; 02136 if (RHASH(hash)->ntbl->type == &identhash) { 02137 return Qtrue; 02138 } 02139 return Qfalse; 02140 } 02141 02142 static int path_tainted = -1; 02143 02144 static char **origenviron; 02145 #ifdef _WIN32 02146 #define GET_ENVIRON(e) ((e) = rb_w32_get_environ()) 02147 #define FREE_ENVIRON(e) rb_w32_free_environ(e) 02148 static char **my_environ; 02149 #undef environ 02150 #define environ my_environ 02151 #undef getenv 02152 #define getenv(n) rb_w32_ugetenv(n) 02153 #elif defined(__APPLE__) 02154 #undef environ 02155 #define environ (*_NSGetEnviron()) 02156 #define GET_ENVIRON(e) (e) 02157 #define FREE_ENVIRON(e) 02158 #else 02159 extern char **environ; 02160 #define GET_ENVIRON(e) (e) 02161 #define FREE_ENVIRON(e) 02162 #endif 02163 #ifdef ENV_IGNORECASE 02164 #define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0) 02165 #define ENVNMATCH(s1, s2, n) (STRNCASECMP((s1), (s2), (n)) == 0) 02166 #else 02167 #define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0) 02168 #define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0) 02169 #endif 02170 02171 static VALUE 02172 env_str_new(const char *ptr, long len) 02173 { 02174 #ifdef _WIN32 02175 VALUE str = rb_str_conv_enc(rb_str_new(ptr, len), rb_utf8_encoding(), rb_locale_encoding()); 02176 #else 02177 VALUE str = rb_locale_str_new(ptr, len); 02178 #endif 02179 02180 rb_obj_freeze(str); 02181 return str; 02182 } 02183 02184 static VALUE 02185 env_str_new2(const char *ptr) 02186 { 02187 if (!ptr) return Qnil; 02188 return env_str_new(ptr, strlen(ptr)); 02189 } 02190 02191 static VALUE 02192 env_delete(VALUE obj, VALUE name) 02193 { 02194 char *nam, *val; 02195 02196 rb_secure(4); 02197 SafeStringValue(name); 02198 nam = RSTRING_PTR(name); 02199 if (memchr(nam, '\0', RSTRING_LEN(name))) { 02200 rb_raise(rb_eArgError, "bad environment variable name"); 02201 } 02202 val = getenv(nam); 02203 if (val) { 02204 VALUE value = env_str_new2(val); 02205 02206 ruby_setenv(nam, 0); 02207 if (ENVMATCH(nam, PATH_ENV)) { 02208 path_tainted = 0; 02209 } 02210 return value; 02211 } 02212 return Qnil; 02213 } 02214 02215 /* 02216 * call-seq: 02217 * ENV.delete(name) -> value 02218 * ENV.delete(name) { |name| } -> value 02219 * 02220 * Deletes the environment variable with +name+ and returns the value of the 02221 * variable. If a block is given it will be called when the named environment 02222 * does not exist. 02223 */ 02224 static VALUE 02225 env_delete_m(VALUE obj, VALUE name) 02226 { 02227 VALUE val; 02228 02229 val = env_delete(obj, name); 02230 if (NIL_P(val) && rb_block_given_p()) rb_yield(name); 02231 return val; 02232 } 02233 02234 static int env_path_tainted(const char *); 02235 02236 /* 02237 * call-seq: 02238 * ENV[name] -> value 02239 * 02240 * Retrieves the +value+ for environment variable +name+ as a String. Returns 02241 * +nil+ if the named variable does not exist. 02242 */ 02243 static VALUE 02244 rb_f_getenv(VALUE obj, VALUE name) 02245 { 02246 char *nam, *env; 02247 02248 rb_secure(4); 02249 SafeStringValue(name); 02250 nam = RSTRING_PTR(name); 02251 if (memchr(nam, '\0', RSTRING_LEN(name))) { 02252 rb_raise(rb_eArgError, "bad environment variable name"); 02253 } 02254 env = getenv(nam); 02255 if (env) { 02256 if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env)) { 02257 #ifdef _WIN32 02258 VALUE str = rb_str_conv_enc(rb_str_new(env, strlen(env)), rb_utf8_encoding(), rb_filesystem_encoding()); 02259 #else 02260 VALUE str = rb_filesystem_str_new_cstr(env); 02261 #endif 02262 02263 rb_obj_freeze(str); 02264 return str; 02265 } 02266 return env_str_new2(env); 02267 } 02268 return Qnil; 02269 } 02270 02271 /* 02272 * :yield: missing_name 02273 * call-seq: 02274 * ENV.fetch(name) -> value 02275 * ENV.fetch(name, default) -> value 02276 * ENV.fetch(name) { |missing_name| ... } -> value 02277 * 02278 * Retrieves the environment variable +name+. 02279 * 02280 * If the given name does not exist and neither +default+ nor a block a 02281 * provided an IndexError is raised. If a block is given it is called with 02282 * the missing name to provide a value. If a default value is given it will 02283 * be returned when no block is given. 02284 */ 02285 static VALUE 02286 env_fetch(int argc, VALUE *argv) 02287 { 02288 VALUE key, if_none; 02289 long block_given; 02290 char *nam, *env; 02291 02292 rb_secure(4); 02293 rb_scan_args(argc, argv, "11", &key, &if_none); 02294 block_given = rb_block_given_p(); 02295 if (block_given && argc == 2) { 02296 rb_warn("block supersedes default value argument"); 02297 } 02298 SafeStringValue(key); 02299 nam = RSTRING_PTR(key); 02300 if (memchr(nam, '\0', RSTRING_LEN(key))) { 02301 rb_raise(rb_eArgError, "bad environment variable name"); 02302 } 02303 env = getenv(nam); 02304 if (!env) { 02305 if (block_given) return rb_yield(key); 02306 if (argc == 1) { 02307 rb_raise(rb_eKeyError, "key not found"); 02308 } 02309 return if_none; 02310 } 02311 if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env)) 02312 #ifdef _WIN32 02313 return rb_str_conv_enc(rb_str_new(env, strlen(env)), rb_utf8_encoding(), rb_filesystem_encoding()); 02314 #else 02315 return rb_filesystem_str_new_cstr(env); 02316 #endif 02317 return env_str_new2(env); 02318 } 02319 02320 static void 02321 path_tainted_p(const char *path) 02322 { 02323 path_tainted = rb_path_check(path)?0:1; 02324 } 02325 02326 static int 02327 env_path_tainted(const char *path) 02328 { 02329 if (path_tainted < 0) { 02330 path_tainted_p(path); 02331 } 02332 return path_tainted; 02333 } 02334 02335 int 02336 rb_env_path_tainted(void) 02337 { 02338 if (path_tainted < 0) { 02339 path_tainted_p(getenv(PATH_ENV)); 02340 } 02341 return path_tainted; 02342 } 02343 02344 #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV)) 02345 #elif defined __sun 02346 static int 02347 in_origenv(const char *str) 02348 { 02349 char **env; 02350 for (env = origenviron; *env; ++env) { 02351 if (*env == str) return 1; 02352 } 02353 return 0; 02354 } 02355 #else 02356 static int 02357 envix(const char *nam) 02358 { 02359 register int i, len = strlen(nam); 02360 char **env; 02361 02362 env = GET_ENVIRON(environ); 02363 for (i = 0; env[i]; i++) { 02364 if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=') 02365 break; /* memcmp must come first to avoid */ 02366 } /* potential SEGV's */ 02367 FREE_ENVIRON(environ); 02368 return i; 02369 } 02370 #endif 02371 02372 #if defined(_WIN32) 02373 static size_t 02374 getenvsize(const char* p) 02375 { 02376 const char* porg = p; 02377 while (*p++) p += strlen(p) + 1; 02378 return p - porg + 1; 02379 } 02380 static size_t 02381 getenvblocksize() 02382 { 02383 return (rb_w32_osver() >= 5) ? 32767 : 5120; 02384 } 02385 #endif 02386 02387 void 02388 ruby_setenv(const char *name, const char *value) 02389 { 02390 #if defined(_WIN32) 02391 VALUE buf; 02392 int failed = 0; 02393 if (strchr(name, '=')) { 02394 fail: 02395 errno = EINVAL; 02396 rb_sys_fail("ruby_setenv"); 02397 } 02398 if (value) { 02399 const char* p = GetEnvironmentStringsA(); 02400 if (!p) goto fail; /* never happen */ 02401 if (strlen(name) + 2 + strlen(value) + getenvsize(p) >= getenvblocksize()) { 02402 goto fail; /* 2 for '=' & '\0' */ 02403 } 02404 buf = rb_sprintf("%s=%s", name, value); 02405 } 02406 else { 02407 buf = rb_sprintf("%s=", name); 02408 } 02409 failed = putenv(RSTRING_PTR(buf)); 02410 /* even if putenv() failed, clean up and try to delete the 02411 * variable from the system area. */ 02412 rb_str_resize(buf, 0); 02413 if (!value || !*value) { 02414 /* putenv() doesn't handle empty value */ 02415 if (!SetEnvironmentVariable(name, value) && 02416 GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail; 02417 } 02418 if (failed) goto fail; 02419 #elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV) 02420 #undef setenv 02421 #undef unsetenv 02422 if (value) { 02423 if (setenv(name, value, 1)) 02424 rb_sys_fail("setenv"); 02425 } else { 02426 #ifdef VOID_UNSETENV 02427 unsetenv(name); 02428 #else 02429 if (unsetenv(name)) 02430 rb_sys_fail("unsetenv"); 02431 #endif 02432 } 02433 #elif defined __sun 02434 size_t len; 02435 char **env_ptr, *str; 02436 if (strchr(name, '=')) { 02437 errno = EINVAL; 02438 rb_sys_fail("ruby_setenv"); 02439 } 02440 len = strlen(name); 02441 for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr) { 02442 if (!strncmp(str, name, len) && str[len] == '=') { 02443 if (!in_origenv(str)) free(str); 02444 while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++; 02445 break; 02446 } 02447 } 02448 if (value) { 02449 str = malloc(len += strlen(value) + 2); 02450 snprintf(str, len, "%s=%s", name, value); 02451 if (putenv(str)) 02452 rb_sys_fail("putenv"); 02453 } 02454 #else /* WIN32 */ 02455 size_t len; 02456 int i; 02457 if (strchr(name, '=')) { 02458 errno = EINVAL; 02459 rb_sys_fail("ruby_setenv"); 02460 } 02461 i=envix(name); /* where does it go? */ 02462 02463 if (environ == origenviron) { /* need we copy environment? */ 02464 int j; 02465 int max; 02466 char **tmpenv; 02467 02468 for (max = i; environ[max]; max++) ; 02469 tmpenv = ALLOC_N(char*, max+2); 02470 for (j=0; j<max; j++) /* copy environment */ 02471 tmpenv[j] = ruby_strdup(environ[j]); 02472 tmpenv[max] = 0; 02473 environ = tmpenv; /* tell exec where it is now */ 02474 } 02475 if (environ[i]) { 02476 char **envp = origenviron; 02477 while (*envp && *envp != environ[i]) envp++; 02478 if (!*envp) 02479 xfree(environ[i]); 02480 if (!value) { 02481 while (environ[i]) { 02482 environ[i] = environ[i+1]; 02483 i++; 02484 } 02485 return; 02486 } 02487 } 02488 else { /* does not exist yet */ 02489 if (!value) return; 02490 REALLOC_N(environ, char*, i+2); /* just expand it a bit */ 02491 environ[i+1] = 0; /* make sure it's null terminated */ 02492 } 02493 len = strlen(name) + strlen(value) + 2; 02494 environ[i] = ALLOC_N(char, len); 02495 snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */ 02496 #endif /* WIN32 */ 02497 } 02498 02499 void 02500 ruby_unsetenv(const char *name) 02501 { 02502 ruby_setenv(name, 0); 02503 } 02504 02505 /* 02506 * call-seq: 02507 * ENV[name] = value 02508 * ENV.store(name, value) -> value 02509 * 02510 * Sets the environment variable +name+ to +value+. If the value given is 02511 * +nil+ the environment variable is deleted. 02512 * 02513 */ 02514 static VALUE 02515 env_aset(VALUE obj, VALUE nm, VALUE val) 02516 { 02517 char *name, *value; 02518 02519 if (rb_safe_level() >= 4) { 02520 rb_raise(rb_eSecurityError, "can't change environment variable"); 02521 } 02522 02523 if (NIL_P(val)) { 02524 env_delete(obj, nm); 02525 return Qnil; 02526 } 02527 StringValue(nm); 02528 StringValue(val); 02529 name = RSTRING_PTR(nm); 02530 value = RSTRING_PTR(val); 02531 if (memchr(name, '\0', RSTRING_LEN(nm))) 02532 rb_raise(rb_eArgError, "bad environment variable name"); 02533 if (memchr(value, '\0', RSTRING_LEN(val))) 02534 rb_raise(rb_eArgError, "bad environment variable value"); 02535 02536 ruby_setenv(name, value); 02537 if (ENVMATCH(name, PATH_ENV)) { 02538 if (OBJ_TAINTED(val)) { 02539 /* already tainted, no check */ 02540 path_tainted = 1; 02541 return val; 02542 } 02543 else { 02544 path_tainted_p(value); 02545 } 02546 } 02547 return val; 02548 } 02549 02550 /* 02551 * call-seq: 02552 * ENV.keys -> Array 02553 * 02554 * Returns every environment variable name in an Array 02555 */ 02556 static VALUE 02557 env_keys(void) 02558 { 02559 char **env; 02560 VALUE ary; 02561 02562 rb_secure(4); 02563 ary = rb_ary_new(); 02564 env = GET_ENVIRON(environ); 02565 while (*env) { 02566 char *s = strchr(*env, '='); 02567 if (s) { 02568 rb_ary_push(ary, env_str_new(*env, s-*env)); 02569 } 02570 env++; 02571 } 02572 FREE_ENVIRON(environ); 02573 return ary; 02574 } 02575 02576 static VALUE 02577 rb_env_size(VALUE ehash) 02578 { 02579 char **env; 02580 long cnt = 0; 02581 02582 rb_secure(4); 02583 02584 env = GET_ENVIRON(environ); 02585 for (; *env ; ++env) { 02586 if (strchr(*env, '=')) { 02587 cnt++; 02588 } 02589 } 02590 FREE_ENVIRON(environ); 02591 return LONG2FIX(cnt); 02592 } 02593 02594 /* 02595 * call-seq: 02596 * ENV.each_key { |name| } -> Hash 02597 * ENV.each_key -> Enumerator 02598 * 02599 * Yields each environment variable name. 02600 * 02601 * An Enumerator is returned if no block is given. 02602 */ 02603 static VALUE 02604 env_each_key(VALUE ehash) 02605 { 02606 VALUE keys; 02607 long i; 02608 02609 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02610 keys = env_keys(); /* rb_secure(4); */ 02611 for (i=0; i<RARRAY_LEN(keys); i++) { 02612 rb_yield(RARRAY_PTR(keys)[i]); 02613 } 02614 return ehash; 02615 } 02616 02617 /* 02618 * call-seq: 02619 * ENV.values -> Array 02620 * 02621 * Returns every environment variable value as an Array 02622 */ 02623 static VALUE 02624 env_values(void) 02625 { 02626 VALUE ary; 02627 char **env; 02628 02629 rb_secure(4); 02630 ary = rb_ary_new(); 02631 env = GET_ENVIRON(environ); 02632 while (*env) { 02633 char *s = strchr(*env, '='); 02634 if (s) { 02635 rb_ary_push(ary, env_str_new2(s+1)); 02636 } 02637 env++; 02638 } 02639 FREE_ENVIRON(environ); 02640 return ary; 02641 } 02642 02643 /* 02644 * call-seq: 02645 * ENV.each_value { |value| } -> Hash 02646 * ENV.each_value -> Enumerator 02647 * 02648 * Yields each environment variable +value+. 02649 * 02650 * An Enumerator is returned if no block was given. 02651 */ 02652 static VALUE 02653 env_each_value(VALUE ehash) 02654 { 02655 VALUE values; 02656 long i; 02657 02658 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02659 values = env_values(); /* rb_secure(4); */ 02660 for (i=0; i<RARRAY_LEN(values); i++) { 02661 rb_yield(RARRAY_PTR(values)[i]); 02662 } 02663 return ehash; 02664 } 02665 02666 /* 02667 * call-seq: 02668 * ENV.each { |name, value| } -> Hash 02669 * ENV.each -> Enumerator 02670 * ENV.each_pair { |name, value| } -> Hash 02671 * ENV.each_pair -> Enumerator 02672 * 02673 * Yields each environment variable +name+ and +value+. 02674 * 02675 * If no block is given an Enumerator is returned. 02676 */ 02677 static VALUE 02678 env_each_pair(VALUE ehash) 02679 { 02680 char **env; 02681 VALUE ary; 02682 long i; 02683 02684 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02685 02686 rb_secure(4); 02687 ary = rb_ary_new(); 02688 env = GET_ENVIRON(environ); 02689 while (*env) { 02690 char *s = strchr(*env, '='); 02691 if (s) { 02692 rb_ary_push(ary, env_str_new(*env, s-*env)); 02693 rb_ary_push(ary, env_str_new2(s+1)); 02694 } 02695 env++; 02696 } 02697 FREE_ENVIRON(environ); 02698 02699 for (i=0; i<RARRAY_LEN(ary); i+=2) { 02700 rb_yield(rb_assoc_new(RARRAY_PTR(ary)[i], RARRAY_PTR(ary)[i+1])); 02701 } 02702 return ehash; 02703 } 02704 02705 /* 02706 * call-seq: 02707 * ENV.reject! { |name, value| } -> ENV or nil 02708 * ENV.reject! -> Enumerator 02709 * 02710 * Equivalent to ENV#delete_if but returns +nil+ if no changes were made. 02711 * 02712 * Returns an Enumerator if no block was given. 02713 */ 02714 static VALUE 02715 env_reject_bang(VALUE ehash) 02716 { 02717 volatile VALUE keys; 02718 long i; 02719 int del = 0; 02720 02721 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02722 keys = env_keys(); /* rb_secure(4); */ 02723 RBASIC(keys)->klass = 0; 02724 for (i=0; i<RARRAY_LEN(keys); i++) { 02725 VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]); 02726 if (!NIL_P(val)) { 02727 if (RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val))) { 02728 FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT); 02729 env_delete(Qnil, RARRAY_PTR(keys)[i]); 02730 del++; 02731 } 02732 } 02733 } 02734 if (del == 0) return Qnil; 02735 return envtbl; 02736 } 02737 02738 /* 02739 * call-seq: 02740 * ENV.delete_if { |name, value| } -> Hash 02741 * ENV.delete_if -> Enumerator 02742 * 02743 * Deletes every environment variable for which the block evaluates to +true+. 02744 * 02745 * If no block is given an enumerator is returned instead. 02746 */ 02747 static VALUE 02748 env_delete_if(VALUE ehash) 02749 { 02750 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02751 env_reject_bang(ehash); 02752 return envtbl; 02753 } 02754 02755 /* 02756 * call-seq: 02757 * ENV.values_at(name, ...) -> Array 02758 * 02759 * Returns an array containing the environment variable values associated with 02760 * the given names. See also ENV.select. 02761 */ 02762 static VALUE 02763 env_values_at(int argc, VALUE *argv) 02764 { 02765 VALUE result; 02766 long i; 02767 02768 rb_secure(4); 02769 result = rb_ary_new(); 02770 for (i=0; i<argc; i++) { 02771 rb_ary_push(result, rb_f_getenv(Qnil, argv[i])); 02772 } 02773 return result; 02774 } 02775 02776 /* 02777 * call-seq: 02778 * ENV.select { |name, value| } -> Hash 02779 * ENV.select -> Enumerator 02780 * 02781 * Returns a copy of the environment for entries where the block returns true. 02782 * 02783 * Returns an Enumerator if no block was given. 02784 */ 02785 static VALUE 02786 env_select(VALUE ehash) 02787 { 02788 VALUE result; 02789 char **env; 02790 02791 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02792 rb_secure(4); 02793 result = rb_hash_new(); 02794 env = GET_ENVIRON(environ); 02795 while (*env) { 02796 char *s = strchr(*env, '='); 02797 if (s) { 02798 VALUE k = env_str_new(*env, s-*env); 02799 VALUE v = env_str_new2(s+1); 02800 if (RTEST(rb_yield_values(2, k, v))) { 02801 rb_hash_aset(result, k, v); 02802 } 02803 } 02804 env++; 02805 } 02806 FREE_ENVIRON(environ); 02807 02808 return result; 02809 } 02810 02811 /* 02812 * call-seq: 02813 * ENV.select! { |name, value| } -> ENV or nil 02814 * ENV.select! -> Enumerator 02815 * 02816 * Equivalent to ENV#keep_if but returns +nil+ if no changes were made. 02817 */ 02818 static VALUE 02819 env_select_bang(VALUE ehash) 02820 { 02821 volatile VALUE keys; 02822 long i; 02823 int del = 0; 02824 02825 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02826 keys = env_keys(); /* rb_secure(4); */ 02827 RBASIC(keys)->klass = 0; 02828 for (i=0; i<RARRAY_LEN(keys); i++) { 02829 VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]); 02830 if (!NIL_P(val)) { 02831 if (!RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val))) { 02832 FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT); 02833 env_delete(Qnil, RARRAY_PTR(keys)[i]); 02834 del++; 02835 } 02836 } 02837 } 02838 if (del == 0) return Qnil; 02839 return envtbl; 02840 } 02841 02842 /* 02843 * call-seq: 02844 * ENV.keep_if { |name, value| } -> Hash 02845 * ENV.keep_if -> Enumerator 02846 * 02847 * Deletes every environment variable where the block evaluates to +false+. 02848 * 02849 * Returns an enumerator if no block was given. 02850 */ 02851 static VALUE 02852 env_keep_if(VALUE ehash) 02853 { 02854 RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size); 02855 env_select_bang(ehash); 02856 return envtbl; 02857 } 02858 02859 /* 02860 * call-seq: 02861 * ENV.clear 02862 * 02863 * Removes every environment variable. 02864 */ 02865 VALUE 02866 rb_env_clear(void) 02867 { 02868 volatile VALUE keys; 02869 long i; 02870 02871 keys = env_keys(); /* rb_secure(4); */ 02872 for (i=0; i<RARRAY_LEN(keys); i++) { 02873 VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]); 02874 if (!NIL_P(val)) { 02875 env_delete(Qnil, RARRAY_PTR(keys)[i]); 02876 } 02877 } 02878 return envtbl; 02879 } 02880 02881 /* 02882 * call-seq: 02883 * ENV.to_s -> "ENV" 02884 * 02885 * Returns "ENV" 02886 */ 02887 static VALUE 02888 env_to_s(void) 02889 { 02890 return rb_usascii_str_new2("ENV"); 02891 } 02892 02893 /* 02894 * call-seq: 02895 * ENV.inspect -> string 02896 * 02897 * Returns the contents of the environment as a String. 02898 */ 02899 static VALUE 02900 env_inspect(void) 02901 { 02902 char **env; 02903 VALUE str, i; 02904 02905 rb_secure(4); 02906 str = rb_str_buf_new2("{"); 02907 env = GET_ENVIRON(environ); 02908 while (*env) { 02909 char *s = strchr(*env, '='); 02910 02911 if (env != environ) { 02912 rb_str_buf_cat2(str, ", "); 02913 } 02914 if (s) { 02915 rb_str_buf_cat2(str, "\""); 02916 rb_str_buf_cat(str, *env, s-*env); 02917 rb_str_buf_cat2(str, "\"=>"); 02918 i = rb_inspect(rb_str_new2(s+1)); 02919 rb_str_buf_append(str, i); 02920 } 02921 env++; 02922 } 02923 FREE_ENVIRON(environ); 02924 rb_str_buf_cat2(str, "}"); 02925 OBJ_TAINT(str); 02926 02927 return str; 02928 } 02929 02930 /* 02931 * call-seq: 02932 * ENV.to_a -> Array 02933 * 02934 * Converts the environment variables into an array of names and value arrays. 02935 * 02936 * ENV.to_a # => [["TERM", "xterm-color"], ["SHELL", "/bin/bash"], ...] 02937 * 02938 */ 02939 static VALUE 02940 env_to_a(void) 02941 { 02942 char **env; 02943 VALUE ary; 02944 02945 rb_secure(4); 02946 ary = rb_ary_new(); 02947 env = GET_ENVIRON(environ); 02948 while (*env) { 02949 char *s = strchr(*env, '='); 02950 if (s) { 02951 rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env), 02952 env_str_new2(s+1))); 02953 } 02954 env++; 02955 } 02956 FREE_ENVIRON(environ); 02957 return ary; 02958 } 02959 02960 /* 02961 * call-seq: 02962 * ENV.rehash 02963 * 02964 * Re-hashing the environment variables does nothing. It is provided for 02965 * compatibility with Hash. 02966 */ 02967 static VALUE 02968 env_none(void) 02969 { 02970 return Qnil; 02971 } 02972 02973 /* 02974 * call-seq: 02975 * ENV.length 02976 * ENV.size 02977 * 02978 * Returns the number of environment variables. 02979 */ 02980 static VALUE 02981 env_size(void) 02982 { 02983 int i; 02984 char **env; 02985 02986 rb_secure(4); 02987 env = GET_ENVIRON(environ); 02988 for (i=0; env[i]; i++) 02989 ; 02990 FREE_ENVIRON(environ); 02991 return INT2FIX(i); 02992 } 02993 02994 /* 02995 * call-seq: 02996 * ENV.empty? -> true or false 02997 * 02998 * Returns true when there are no environment variables 02999 */ 03000 static VALUE 03001 env_empty_p(void) 03002 { 03003 char **env; 03004 03005 rb_secure(4); 03006 env = GET_ENVIRON(environ); 03007 if (env[0] == 0) { 03008 FREE_ENVIRON(environ); 03009 return Qtrue; 03010 } 03011 FREE_ENVIRON(environ); 03012 return Qfalse; 03013 } 03014 03015 /* 03016 * call-seq: 03017 * ENV.key?(name) -> true or false 03018 * ENV.include?(name) -> true or false 03019 * ENV.has_key?(name) -> true or false 03020 * ENV.member?(name) -> true or false 03021 * 03022 * Returns +true+ if there is an environment variable with the given +name+. 03023 */ 03024 static VALUE 03025 env_has_key(VALUE env, VALUE key) 03026 { 03027 char *s; 03028 03029 rb_secure(4); 03030 s = StringValuePtr(key); 03031 if (memchr(s, '\0', RSTRING_LEN(key))) 03032 rb_raise(rb_eArgError, "bad environment variable name"); 03033 if (getenv(s)) return Qtrue; 03034 return Qfalse; 03035 } 03036 03037 /* 03038 * call-seq: 03039 * ENV.assoc(name) -> Array or nil 03040 * 03041 * Returns an Array of the name and value of the environment variable with 03042 * +name+ or +nil+ if the name cannot be found. 03043 */ 03044 static VALUE 03045 env_assoc(VALUE env, VALUE key) 03046 { 03047 char *s, *e; 03048 03049 rb_secure(4); 03050 s = StringValuePtr(key); 03051 if (memchr(s, '\0', RSTRING_LEN(key))) 03052 rb_raise(rb_eArgError, "bad environment variable name"); 03053 e = getenv(s); 03054 if (e) return rb_assoc_new(key, rb_tainted_str_new2(e)); 03055 return Qnil; 03056 } 03057 03058 /* 03059 * call-seq: 03060 * ENV.value?(value) -> true or false 03061 * ENV.has_value?(value) -> true or false 03062 * 03063 * Returns +true+ if there is an environment variable with the given +value+. 03064 */ 03065 static VALUE 03066 env_has_value(VALUE dmy, VALUE obj) 03067 { 03068 char **env; 03069 03070 rb_secure(4); 03071 obj = rb_check_string_type(obj); 03072 if (NIL_P(obj)) return Qnil; 03073 env = GET_ENVIRON(environ); 03074 while (*env) { 03075 char *s = strchr(*env, '='); 03076 if (s++) { 03077 long len = strlen(s); 03078 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) { 03079 FREE_ENVIRON(environ); 03080 return Qtrue; 03081 } 03082 } 03083 env++; 03084 } 03085 FREE_ENVIRON(environ); 03086 return Qfalse; 03087 } 03088 03089 /* 03090 * call-seq: 03091 * ENV.rassoc(value) 03092 * 03093 * Returns an Array of the name and value of the environment variable with 03094 * +value+ or +nil+ if the value cannot be found. 03095 */ 03096 static VALUE 03097 env_rassoc(VALUE dmy, VALUE obj) 03098 { 03099 char **env; 03100 03101 rb_secure(4); 03102 obj = rb_check_string_type(obj); 03103 if (NIL_P(obj)) return Qnil; 03104 env = GET_ENVIRON(environ); 03105 while (*env) { 03106 char *s = strchr(*env, '='); 03107 if (s++) { 03108 long len = strlen(s); 03109 if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) { 03110 VALUE result = rb_assoc_new(rb_tainted_str_new(*env, s-*env-1), obj); 03111 FREE_ENVIRON(environ); 03112 return result; 03113 } 03114 } 03115 env++; 03116 } 03117 FREE_ENVIRON(environ); 03118 return Qnil; 03119 } 03120 03121 /* 03122 * call-seq: 03123 * ENV.key(value) -> name 03124 * 03125 * Returns the name of the environment variable with +value+. If the value is 03126 * not found +nil+ is returned. 03127 */ 03128 static VALUE 03129 env_key(VALUE dmy, VALUE value) 03130 { 03131 char **env; 03132 VALUE str; 03133 03134 rb_secure(4); 03135 StringValue(value); 03136 env = GET_ENVIRON(environ); 03137 while (*env) { 03138 char *s = strchr(*env, '='); 03139 if (s++) { 03140 long len = strlen(s); 03141 if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) { 03142 str = env_str_new(*env, s-*env-1); 03143 FREE_ENVIRON(environ); 03144 return str; 03145 } 03146 } 03147 env++; 03148 } 03149 FREE_ENVIRON(environ); 03150 return Qnil; 03151 } 03152 03153 /* 03154 * call-seq: 03155 * ENV.index(value) -> key 03156 * 03157 * Deprecated method that is equivalent to ENV.key 03158 */ 03159 static VALUE 03160 env_index(VALUE dmy, VALUE value) 03161 { 03162 rb_warn("ENV.index is deprecated; use ENV.key"); 03163 return env_key(dmy, value); 03164 } 03165 03166 /* 03167 * call-seq: 03168 * ENV.to_hash -> hash 03169 * ENV.to_h -> hash 03170 * 03171 * Creates a hash with a copy of the environment variables. 03172 * 03173 */ 03174 static VALUE 03175 env_to_hash(void) 03176 { 03177 char **env; 03178 VALUE hash; 03179 03180 rb_secure(4); 03181 hash = rb_hash_new(); 03182 env = GET_ENVIRON(environ); 03183 while (*env) { 03184 char *s = strchr(*env, '='); 03185 if (s) { 03186 rb_hash_aset(hash, env_str_new(*env, s-*env), 03187 env_str_new2(s+1)); 03188 } 03189 env++; 03190 } 03191 FREE_ENVIRON(environ); 03192 return hash; 03193 } 03194 03195 /* 03196 * call-seq: 03197 * ENV.reject { |name, value| } -> Hash 03198 * ENV.reject -> Enumerator 03199 * 03200 * Same as ENV#delete_if, but works on (and returns) a copy of the 03201 * environment. 03202 */ 03203 static VALUE 03204 env_reject(void) 03205 { 03206 return rb_hash_delete_if(env_to_hash()); 03207 } 03208 03209 /* 03210 * call-seq: 03211 * ENV.shift -> Array or nil 03212 * 03213 * Removes an environment variable name-value pair from ENV and returns it as 03214 * an Array. Returns +nil+ if when the environment is empty. 03215 */ 03216 static VALUE 03217 env_shift(void) 03218 { 03219 char **env; 03220 03221 rb_secure(4); 03222 env = GET_ENVIRON(environ); 03223 if (*env) { 03224 char *s = strchr(*env, '='); 03225 if (s) { 03226 VALUE key = env_str_new(*env, s-*env); 03227 VALUE val = env_str_new2(getenv(RSTRING_PTR(key))); 03228 env_delete(Qnil, key); 03229 return rb_assoc_new(key, val); 03230 } 03231 } 03232 FREE_ENVIRON(environ); 03233 return Qnil; 03234 } 03235 03236 /* 03237 * call-seq: 03238 * ENV.invert -> Hash 03239 * 03240 * Returns a new hash created by using environment variable names as values 03241 * and values as names. 03242 */ 03243 static VALUE 03244 env_invert(void) 03245 { 03246 return rb_hash_invert(env_to_hash()); 03247 } 03248 03249 static int 03250 env_replace_i(VALUE key, VALUE val, VALUE keys) 03251 { 03252 env_aset(Qnil, key, val); 03253 if (rb_ary_includes(keys, key)) { 03254 rb_ary_delete(keys, key); 03255 } 03256 return ST_CONTINUE; 03257 } 03258 03259 /* 03260 * call-seq: 03261 * ENV.replace(hash) -> env 03262 * 03263 * Replaces the contents of the environment variables with the contents of 03264 * +hash+. 03265 */ 03266 static VALUE 03267 env_replace(VALUE env, VALUE hash) 03268 { 03269 volatile VALUE keys; 03270 long i; 03271 03272 keys = env_keys(); /* rb_secure(4); */ 03273 if (env == hash) return env; 03274 hash = to_hash(hash); 03275 rb_hash_foreach(hash, env_replace_i, keys); 03276 03277 for (i=0; i<RARRAY_LEN(keys); i++) { 03278 env_delete(env, RARRAY_PTR(keys)[i]); 03279 } 03280 return env; 03281 } 03282 03283 static int 03284 env_update_i(VALUE key, VALUE val) 03285 { 03286 if (rb_block_given_p()) { 03287 val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); 03288 } 03289 env_aset(Qnil, key, val); 03290 return ST_CONTINUE; 03291 } 03292 03293 /* 03294 * call-seq: 03295 * ENV.update(hash) -> Hash 03296 * ENV.update(hash) { |name, old_value, new_value| } -> Hash 03297 * 03298 * Adds the contents of +hash+ to the environment variables. If no block is 03299 * specified entries with duplicate keys are overwritten, otherwise the value 03300 * of each duplicate name is determined by calling the block with the key, its 03301 * value from the environment and its value from the hash. 03302 */ 03303 static VALUE 03304 env_update(VALUE env, VALUE hash) 03305 { 03306 rb_secure(4); 03307 if (env == hash) return env; 03308 hash = to_hash(hash); 03309 rb_hash_foreach(hash, env_update_i, 0); 03310 return env; 03311 } 03312 03313 /* 03314 * A Hash is a dictionary-like collection of unique keys and their values. 03315 * Also called associative arrays, they are similar to Arrays, but where an 03316 * Array uses integers as its index, a Hash allows you to use any object 03317 * type. 03318 * 03319 * Hashes enumerate their values in the order that the corresponding keys 03320 * were inserted. 03321 * 03322 * A Hash can be easily created by using its implicit form: 03323 * 03324 * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } 03325 * 03326 * Hashes allow an alternate syntax form when your keys are always symbols. 03327 * Instead of 03328 * 03329 * options = { :font_size => 10, :font_family => "Arial" } 03330 * 03331 * You could write it as: 03332 * 03333 * options = { font_size: 10, font_family: "Arial" } 03334 * 03335 * Each named key is a symbol you can access in hash: 03336 * 03337 * options[:font_size] # => 10 03338 * 03339 * A Hash can also be created through its ::new method: 03340 * 03341 * grades = Hash.new 03342 * grades["Dorothy Doe"] = 9 03343 * 03344 * Hashes have a <em>default value</em> that is returned when accessing 03345 * keys that do not exist in the hash. If no default is set +nil+ is used. 03346 * You can set the default value by sending it as an argument to Hash.new: 03347 * 03348 * grades = Hash.new(0) 03349 * 03350 * Or by using the #default= method: 03351 * 03352 * grades = {"Timmy Doe" => 8} 03353 * grades.default = 0 03354 * 03355 * Accessing a value in a Hash requires using its key: 03356 * 03357 * puts grades["Jane Doe"] # => 10 03358 * 03359 * === Common Uses 03360 * 03361 * Hashes are an easy way to represent data structures, such as 03362 * 03363 * books = {} 03364 * books[:matz] = "The Ruby Language" 03365 * books[:black] = "The Well-Grounded Rubyist" 03366 * 03367 * Hashes are also commonly used as a way to have named parameters in 03368 * functions. Note that no brackets are used below. If a hash is the last 03369 * argument on a method call, no braces are needed, thus creating a really 03370 * clean interface: 03371 * 03372 * Person.create(name: "John Doe", age: 27) 03373 * 03374 * def self.create(params) 03375 * @name = params[:name] 03376 * @age = params[:age] 03377 * end 03378 * 03379 * === Hash Keys 03380 * 03381 * Two objects refer to the same hash key when their <code>hash</code> value 03382 * is identical and the two objects are <code>eql?</code> to each other. 03383 * 03384 * A user-defined class may be used as a hash key if the <code>hash</code> 03385 * and <code>eql?</code> methods are overridden to provide meaningful 03386 * behavior. By default, separate instances refer to separate hash keys. 03387 * 03388 * A typical implementation of <code>hash</code> is based on the 03389 * object's data while <code>eql?</code> is usually aliased to the overridden 03390 * <code>==</code> method: 03391 * 03392 * class Book 03393 * attr_reader :author, :title 03394 * 03395 * def initialize(author, title) 03396 * @author = author 03397 * @title = title 03398 * end 03399 * 03400 * def ==(other) 03401 * self.class === other and 03402 * other.author == @author and 03403 * other.title == @title 03404 * end 03405 * 03406 * alias eql? == 03407 * 03408 * def hash 03409 * @author.hash ^ @title.hash # XOR 03410 * end 03411 * end 03412 * 03413 * book1 = Book.new 'matz', 'Ruby in a Nutshell' 03414 * book2 = Book.new 'matz', 'Ruby in a Nutshell' 03415 * 03416 * reviews = {} 03417 * 03418 * reviews[book1] = 'Great reference!' 03419 * reviews[book2] = 'Nice and compact!' 03420 * 03421 * reviews.length #=> 1 03422 * 03423 * See also Object#hash and Object#eql? 03424 */ 03425 03426 void 03427 Init_Hash(void) 03428 { 03429 #undef rb_intern 03430 #define rb_intern(str) rb_intern_const(str) 03431 03432 id_hash = rb_intern("hash"); 03433 id_yield = rb_intern("yield"); 03434 id_default = rb_intern("default"); 03435 03436 rb_cHash = rb_define_class("Hash", rb_cObject); 03437 03438 rb_include_module(rb_cHash, rb_mEnumerable); 03439 03440 rb_define_alloc_func(rb_cHash, empty_hash_alloc); 03441 rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1); 03442 rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1); 03443 rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1); 03444 rb_define_method(rb_cHash,"initialize_copy", rb_hash_initialize_copy, 1); 03445 rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0); 03446 03447 rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0); 03448 rb_define_method(rb_cHash,"to_h", rb_hash_to_h, 0); 03449 rb_define_method(rb_cHash,"to_a", rb_hash_to_a, 0); 03450 rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0); 03451 rb_define_alias(rb_cHash, "to_s", "inspect"); 03452 03453 rb_define_method(rb_cHash,"==", rb_hash_equal, 1); 03454 rb_define_method(rb_cHash,"[]", rb_hash_aref, 1); 03455 rb_define_method(rb_cHash,"hash", rb_hash_hash, 0); 03456 rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1); 03457 rb_define_method(rb_cHash,"fetch", rb_hash_fetch_m, -1); 03458 rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2); 03459 rb_define_method(rb_cHash,"store", rb_hash_aset, 2); 03460 rb_define_method(rb_cHash,"default", rb_hash_default, -1); 03461 rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1); 03462 rb_define_method(rb_cHash,"default_proc", rb_hash_default_proc, 0); 03463 rb_define_method(rb_cHash,"default_proc=", rb_hash_set_default_proc, 1); 03464 rb_define_method(rb_cHash,"key", rb_hash_key, 1); 03465 rb_define_method(rb_cHash,"index", rb_hash_index, 1); 03466 rb_define_method(rb_cHash,"size", rb_hash_size, 0); 03467 rb_define_method(rb_cHash,"length", rb_hash_size, 0); 03468 rb_define_method(rb_cHash,"empty?", rb_hash_empty_p, 0); 03469 03470 rb_define_method(rb_cHash,"each_value", rb_hash_each_value, 0); 03471 rb_define_method(rb_cHash,"each_key", rb_hash_each_key, 0); 03472 rb_define_method(rb_cHash,"each_pair", rb_hash_each_pair, 0); 03473 rb_define_method(rb_cHash,"each", rb_hash_each_pair, 0); 03474 03475 rb_define_method(rb_cHash,"keys", rb_hash_keys, 0); 03476 rb_define_method(rb_cHash,"values", rb_hash_values, 0); 03477 rb_define_method(rb_cHash,"values_at", rb_hash_values_at, -1); 03478 03479 rb_define_method(rb_cHash,"shift", rb_hash_shift, 0); 03480 rb_define_method(rb_cHash,"delete", rb_hash_delete, 1); 03481 rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0); 03482 rb_define_method(rb_cHash,"keep_if", rb_hash_keep_if, 0); 03483 rb_define_method(rb_cHash,"select", rb_hash_select, 0); 03484 rb_define_method(rb_cHash,"select!", rb_hash_select_bang, 0); 03485 rb_define_method(rb_cHash,"reject", rb_hash_reject, 0); 03486 rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0); 03487 rb_define_method(rb_cHash,"clear", rb_hash_clear, 0); 03488 rb_define_method(rb_cHash,"invert", rb_hash_invert, 0); 03489 rb_define_method(rb_cHash,"update", rb_hash_update, 1); 03490 rb_define_method(rb_cHash,"replace", rb_hash_replace, 1); 03491 rb_define_method(rb_cHash,"merge!", rb_hash_update, 1); 03492 rb_define_method(rb_cHash,"merge", rb_hash_merge, 1); 03493 rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1); 03494 rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1); 03495 rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1); 03496 03497 rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1); 03498 rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1); 03499 rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1); 03500 rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1); 03501 rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1); 03502 rb_define_method(rb_cHash,"value?", rb_hash_has_value, 1); 03503 03504 rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0); 03505 rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0); 03506 03507 /* Document-class: ENV 03508 * 03509 * ENV is a hash-like accessor for environment variables. 03510 */ 03511 03512 /* 03513 * Hack to get RDoc to regard ENV as a class: 03514 * envtbl = rb_define_class("ENV", rb_cObject); 03515 */ 03516 origenviron = environ; 03517 envtbl = rb_obj_alloc(rb_cObject); 03518 rb_extend_object(envtbl, rb_mEnumerable); 03519 03520 rb_define_singleton_method(envtbl,"[]", rb_f_getenv, 1); 03521 rb_define_singleton_method(envtbl,"fetch", env_fetch, -1); 03522 rb_define_singleton_method(envtbl,"[]=", env_aset, 2); 03523 rb_define_singleton_method(envtbl,"store", env_aset, 2); 03524 rb_define_singleton_method(envtbl,"each", env_each_pair, 0); 03525 rb_define_singleton_method(envtbl,"each_pair", env_each_pair, 0); 03526 rb_define_singleton_method(envtbl,"each_key", env_each_key, 0); 03527 rb_define_singleton_method(envtbl,"each_value", env_each_value, 0); 03528 rb_define_singleton_method(envtbl,"delete", env_delete_m, 1); 03529 rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0); 03530 rb_define_singleton_method(envtbl,"keep_if", env_keep_if, 0); 03531 rb_define_singleton_method(envtbl,"clear", rb_env_clear, 0); 03532 rb_define_singleton_method(envtbl,"reject", env_reject, 0); 03533 rb_define_singleton_method(envtbl,"reject!", env_reject_bang, 0); 03534 rb_define_singleton_method(envtbl,"select", env_select, 0); 03535 rb_define_singleton_method(envtbl,"select!", env_select_bang, 0); 03536 rb_define_singleton_method(envtbl,"shift", env_shift, 0); 03537 rb_define_singleton_method(envtbl,"invert", env_invert, 0); 03538 rb_define_singleton_method(envtbl,"replace", env_replace, 1); 03539 rb_define_singleton_method(envtbl,"update", env_update, 1); 03540 rb_define_singleton_method(envtbl,"inspect", env_inspect, 0); 03541 rb_define_singleton_method(envtbl,"rehash", env_none, 0); 03542 rb_define_singleton_method(envtbl,"to_a", env_to_a, 0); 03543 rb_define_singleton_method(envtbl,"to_s", env_to_s, 0); 03544 rb_define_singleton_method(envtbl,"key", env_key, 1); 03545 rb_define_singleton_method(envtbl,"index", env_index, 1); 03546 rb_define_singleton_method(envtbl,"size", env_size, 0); 03547 rb_define_singleton_method(envtbl,"length", env_size, 0); 03548 rb_define_singleton_method(envtbl,"empty?", env_empty_p, 0); 03549 rb_define_singleton_method(envtbl,"keys", env_keys, 0); 03550 rb_define_singleton_method(envtbl,"values", env_values, 0); 03551 rb_define_singleton_method(envtbl,"values_at", env_values_at, -1); 03552 rb_define_singleton_method(envtbl,"include?", env_has_key, 1); 03553 rb_define_singleton_method(envtbl,"member?", env_has_key, 1); 03554 rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1); 03555 rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1); 03556 rb_define_singleton_method(envtbl,"key?", env_has_key, 1); 03557 rb_define_singleton_method(envtbl,"value?", env_has_value, 1); 03558 rb_define_singleton_method(envtbl,"to_hash", env_to_hash, 0); 03559 rb_define_singleton_method(envtbl,"to_h", env_to_hash, 0); 03560 rb_define_singleton_method(envtbl,"assoc", env_assoc, 1); 03561 rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1); 03562 03563 /* 03564 * ENV is a Hash-like accessor for environment variables. 03565 * 03566 * See ENV (the class) for more details. 03567 */ 03568 rb_define_global_const("ENV", envtbl); 03569 } 03570
1.7.6.1