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