设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 910|回复: 2
打印 上一主题 下一主题

[已经过期] 关于hash自动排列问题

[复制链接]

Lv1.梦旅人

梦石
0
星屑
66
在线时间
91 小时
注册时间
2012-8-15
帖子
57
跳转到指定楼层
1
发表于 2012-11-10 16:38:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
在$game_party里,道具都用到hash,而添加新的道具,会自动进行排列,造成新增的道具自动排到前面。
不知道谁有hash原代码。

Lv1.梦旅人

梦石
0
星屑
55
在线时间
323 小时
注册时间
2010-8-21
帖子
666
2
发表于 2012-11-10 17:52:48 | 只看该作者
无序的话用hash_obj.keys查看吧..
这里是1.9.3的hash.c
  1. /**********************************************************************

  2.   hash.c -

  3.   $Author: nobu $
  4.   created at: Mon Nov 22 18:51:18 JST 1993

  5.   Copyright (C) 1993-2007 Yukihiro Matsumoto
  6.   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
  7.   Copyright (C) 2000  Information-technology Promotion Agency, Japan

  8. **********************************************************************/

  9. #include "ruby/ruby.h"
  10. #include "ruby/st.h"
  11. #include "ruby/util.h"
  12. #include "ruby/encoding.h"
  13. #include <errno.h>

  14. #ifdef __APPLE__
  15. #include <crt_externs.h>
  16. #endif

  17. static VALUE rb_hash_s_try_convert(VALUE, VALUE);

  18. #define HASH_DELETED  FL_USER1
  19. #define HASH_PROC_DEFAULT FL_USER2

  20. VALUE
  21. rb_hash_freeze(VALUE hash)
  22. {
  23.   return rb_obj_freeze(hash);
  24. }

  25. VALUE rb_cHash;

  26. static VALUE envtbl;
  27. static ID id_hash, id_yield, id_default;

  28. static int
  29. rb_any_cmp(VALUE a, VALUE b)
  30. {
  31.   if (a == b) return 0;
  32.   if (FIXNUM_P(a) && FIXNUM_P(b))
  33.   {
  34.     return a != b;
  35.   }
  36.   if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
  37.       TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString)
  38.   {
  39.     return rb_str_hash_cmp(a, b);
  40.   }
  41.   if (a == Qundef || b == Qundef) return -1;
  42.   if (SYMBOL_P(a) && SYMBOL_P(b))
  43.   {
  44.     return a != b;
  45.   }

  46.   return !rb_eql(a, b);
  47. }

  48. VALUE
  49. rb_hash(VALUE obj)
  50. {
  51.   VALUE hval = rb_funcall(obj, id_hash, 0);
  52. retry:
  53.   switch (TYPE(hval))
  54.   {
  55.     case T_FIXNUM:
  56.       return hval;

  57.     case T_BIGNUM:
  58.       return LONG2FIX(((long*)(RBIGNUM_DIGITS(hval)))[0]);

  59.     default:
  60.       hval = rb_to_int(hval);
  61.       goto retry;
  62.   }
  63. }

  64. static st_index_t
  65. rb_any_hash(VALUE a)
  66. {
  67.   VALUE hval;
  68.   st_index_t hnum;

  69.   switch (TYPE(a))
  70.   {
  71.     case T_FIXNUM:
  72.     case T_SYMBOL:
  73.     case T_NIL:
  74.     case T_FALSE:
  75.     case T_TRUE:
  76.       hnum = rb_hash_end(rb_hash_start((unsigned int)a));
  77.       break;

  78.     case T_STRING:
  79.       hnum = rb_str_hash(a);
  80.       break;

  81.     default:
  82.       hval = rb_hash(a);
  83.       hnum = FIX2LONG(hval);
  84.   }
  85.   hnum <<= 1;
  86.   return (st_index_t)RSHIFT(hnum, 1);
  87. }

  88. static const struct st_hash_type objhash =
  89. {
  90.   rb_any_cmp,
  91.   rb_any_hash,
  92. };

  93. static const struct st_hash_type identhash =
  94. {
  95.   st_numcmp,
  96.   st_numhash,
  97. };

  98. typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);

  99. struct foreach_safe_arg
  100. {
  101.   st_table *tbl;
  102.   st_foreach_func *func;
  103.   st_data_t arg;
  104. };

  105. static int
  106. foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg)
  107. {
  108.   int status;

  109.   if (key == Qundef) return ST_CONTINUE;
  110.   status = (*arg->func)(key, value, arg->arg);
  111.   if (status == ST_CONTINUE)
  112.   {
  113.     return ST_CHECK;
  114.   }
  115.   return status;
  116. }

  117. void
  118. st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a)
  119. {
  120.   struct foreach_safe_arg arg;

  121.   arg.tbl = table;
  122.   arg.func = (st_foreach_func *)func;
  123.   arg.arg = a;
  124.   if (st_foreach(table, foreach_safe_i, (st_data_t)&arg))
  125.   {
  126.     rb_raise(rb_eRuntimeError, "hash modified during iteration");
  127.   }
  128. }

  129. typedef int rb_foreach_func(VALUE, VALUE, VALUE);

  130. struct hash_foreach_arg
  131. {
  132.   VALUE hash;
  133.   rb_foreach_func *func;
  134.   VALUE arg;
  135. };

  136. static int
  137. hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg)
  138. {
  139.   int status;
  140.   st_table *tbl;

  141.   tbl = RHASH(arg->hash)->ntbl;
  142.   if ((VALUE)key == Qundef) return ST_CONTINUE;
  143.   status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
  144.   if (RHASH(arg->hash)->ntbl != tbl)
  145.   {
  146.     rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
  147.   }
  148.   switch (status)
  149.   {
  150.     case ST_DELETE:
  151.       st_delete_safe(tbl, &key, 0, Qundef);
  152.       FL_SET(arg->hash, HASH_DELETED);
  153.     case ST_CONTINUE:
  154.       break;
  155.     case ST_STOP:
  156.       return ST_STOP;
  157.   }
  158.   return ST_CHECK;
  159. }

  160. static VALUE
  161. hash_foreach_ensure(VALUE hash)
  162. {
  163.   RHASH(hash)->iter_lev--;

  164.   if (RHASH(hash)->iter_lev == 0)
  165.   {
  166.     if (FL_TEST(hash, HASH_DELETED))
  167.     {
  168.       st_cleanup_safe(RHASH(hash)->ntbl, Qundef);
  169.       FL_UNSET(hash, HASH_DELETED);
  170.     }
  171.   }
  172.   return 0;
  173. }

  174. static VALUE
  175. hash_foreach_call(struct hash_foreach_arg *arg)
  176. {
  177.   if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg))
  178.   {
  179.     rb_raise(rb_eRuntimeError, "hash modified during iteration");
  180.   }
  181.   return Qnil;
  182. }

  183. void
  184. rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
  185. {
  186.   struct hash_foreach_arg arg;

  187.   if (!RHASH(hash)->ntbl)
  188.     return;
  189.   RHASH(hash)->iter_lev++;
  190.   arg.hash = hash;
  191.   arg.func = (rb_foreach_func *)func;
  192.   arg.arg  = farg;
  193.   rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
  194. }

  195. static VALUE
  196. hash_alloc(VALUE klass)
  197. {
  198.   NEWOBJ(hash, struct RHash);
  199.   OBJSETUP(hash, klass, T_HASH);

  200.   RHASH_IFNONE(hash) = Qnil;

  201.   return (VALUE)hash;
  202. }

  203. VALUE
  204. rb_hash_new(void)
  205. {
  206.   return hash_alloc(rb_cHash);
  207. }

  208. VALUE
  209. rb_hash_dup(VALUE hash)
  210. {
  211.   NEWOBJ(ret, struct RHash);
  212.   DUPSETUP(ret, hash);

  213.   if (!RHASH_EMPTY_P(hash))
  214.     ret->ntbl = st_copy(RHASH(hash)->ntbl);
  215.   if (FL_TEST(hash, HASH_PROC_DEFAULT))
  216.   {
  217.     FL_SET(ret, HASH_PROC_DEFAULT);
  218.   }
  219.   RHASH_IFNONE(ret) = RHASH_IFNONE(hash);
  220.   return (VALUE)ret;
  221. }

  222. static void
  223. rb_hash_modify_check(VALUE hash)
  224. {
  225.   rb_check_frozen(hash);
  226.   if (!OBJ_UNTRUSTED(hash) && rb_safe_level() >= 4)
  227.     rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
  228. }

  229. struct st_table *
  230.       rb_hash_tbl(VALUE hash)
  231. {
  232.   if (!RHASH(hash)->ntbl)
  233.   {
  234.     RHASH(hash)->ntbl = st_init_table(&objhash);
  235.   }
  236.   return RHASH(hash)->ntbl;
  237. }

  238. static void
  239. rb_hash_modify(VALUE hash)
  240. {
  241.   rb_hash_modify_check(hash);
  242.   rb_hash_tbl(hash);
  243. }

  244. static void
  245. hash_update(VALUE hash, VALUE key)
  246. {
  247.   if (RHASH(hash)->iter_lev > 0 && !st_lookup(RHASH(hash)->ntbl, key, 0))
  248.   {
  249.     rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
  250.   }
  251. }

  252. static void
  253. default_proc_arity_check(VALUE proc)
  254. {
  255.   int n = rb_proc_arity(proc);

  256.   if (rb_proc_lambda_p(proc) && n != 2 && (n >= 0 || n < -3))
  257.   {
  258.     if (n < 0) n = -n - 1;
  259.     rb_raise(rb_eTypeError, "default_proc takes two arguments (2 for %d)", n);
  260.   }
  261. }

  262. /*
  263. *  call-seq:
  264. *     Hash.new                          -> new_hash
  265. *     Hash.new(obj)                     -> new_hash
  266. *     Hash.new {|hash, key| block }     -> new_hash
  267. *
  268. *  Returns a new, empty hash. If this hash is subsequently accessed by
  269. *  a key that doesn't correspond to a hash entry, the value returned
  270. *  depends on the style of <code>new</code> used to create the hash. In
  271. *  the first form, the access returns <code>nil</code>. If
  272. *  <i>obj</i> is specified, this single object will be used for
  273. *  all <em>default values</em>. If a block is specified, it will be
  274. *  called with the hash object and the key, and should return the
  275. *  default value. It is the block's responsibility to store the value
  276. *  in the hash if required.
  277. *
  278. *     h = Hash.new("Go Fish")
  279. *     h["a"] = 100
  280. *     h["b"] = 200
  281. *     h["a"]           #=> 100
  282. *     h["c"]           #=> "Go Fish"
  283. *     # The following alters the single default object
  284. *     h["c"].upcase!   #=> "GO FISH"
  285. *     h["d"]           #=> "GO FISH"
  286. *     h.keys           #=> ["a", "b"]
  287. *
  288. *     # While this creates a new default object each time
  289. *     h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
  290. *     h["c"]           #=> "Go Fish: c"
  291. *     h["c"].upcase!   #=> "GO FISH: C"
  292. *     h["d"]           #=> "Go Fish: d"
  293. *     h.keys           #=> ["c", "d"]
  294. *
  295. */

  296. static VALUE
  297. rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
  298. {
  299.   VALUE ifnone;

  300.   rb_hash_modify(hash);
  301.   if (rb_block_given_p())
  302.   {
  303.     if (argc > 0)
  304.     {
  305.       rb_raise(rb_eArgError, "wrong number of arguments");
  306.     }
  307.     ifnone = rb_block_proc();
  308.     default_proc_arity_check(ifnone);
  309.     RHASH_IFNONE(hash) = ifnone;
  310.     FL_SET(hash, HASH_PROC_DEFAULT);
  311.   }
  312.   else
  313.   {
  314.     rb_scan_args(argc, argv, "01", &ifnone);
  315.     RHASH_IFNONE(hash) = ifnone;
  316.   }

  317.   return hash;
  318. }

  319. /*
  320. *  call-seq:
  321. *     Hash[ key, value, ... ]         -> new_hash
  322. *     Hash[ [ [key, value], ... ] ]   -> new_hash
  323. *     Hash[ object ]                  -> new_hash
  324. *
  325. *  Creates a new hash populated with the given objects. Equivalent to
  326. *  the literal <code>{ <i>key</i> => <i>value</i>, ... }</code>. In the first
  327. *  form, keys and values occur in pairs, so there must be an even number of arguments.
  328. *  The second and third form take a single argument which is either
  329. *  an array of key-value pairs or an object convertible to a hash.
  330. *
  331. *     Hash["a", 100, "b", 200]             #=> {"a"=>100, "b"=>200}
  332. *     Hash[ [ ["a", 100], ["b", 200] ] ]   #=> {"a"=>100, "b"=>200}
  333. *     Hash["a" => 100, "b" => 200]         #=> {"a"=>100, "b"=>200}
  334. */

  335. static VALUE
  336. rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
  337. {
  338.   VALUE hash, tmp;
  339.   int i;

  340.   if (argc == 1)
  341.   {
  342.     tmp = rb_hash_s_try_convert(Qnil, argv[0]);
  343.     if (!NIL_P(tmp))
  344.     {
  345.       hash = hash_alloc(klass);
  346.       if (RHASH(tmp)->ntbl)
  347.       {
  348.         RHASH(hash)->ntbl = st_copy(RHASH(tmp)->ntbl);
  349.       }
  350.       return hash;
  351.     }

  352.     tmp = rb_check_array_type(argv[0]);
  353.     if (!NIL_P(tmp))
  354.     {
  355.       long i;

  356.       hash = hash_alloc(klass);
  357.       for (i = 0; i < RARRAY_LEN(tmp); ++i)
  358.       {
  359.         VALUE v = rb_check_array_type(RARRAY_PTR(tmp)[i]);
  360.         VALUE key, val = Qnil;

  361.         if (NIL_P(v)) continue;
  362.         switch (RARRAY_LEN(v))
  363.         {
  364.           case 2:
  365.             val = RARRAY_PTR(v)[1];
  366.           case 1:
  367.             key = RARRAY_PTR(v)[0];
  368.             rb_hash_aset(hash, key, val);
  369.         }
  370.       }
  371.       return hash;
  372.     }
  373.   }
  374.   if (argc % 2 != 0)
  375.   {
  376.     rb_raise(rb_eArgError, "odd number of arguments for Hash");
  377.   }

  378.   hash = hash_alloc(klass);
  379.   for (i = 0; i < argc; i += 2)
  380.   {
  381.     rb_hash_aset(hash, argv[i], argv[i + 1]);
  382.   }

  383.   return hash;
  384. }

  385. static VALUE
  386. to_hash(VALUE hash)
  387. {
  388.   return rb_convert_type(hash, T_HASH, "Hash", "to_hash");
  389. }

  390. VALUE
  391. rb_check_hash_type(VALUE hash)
  392. {
  393.   return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
  394. }

  395. /*
  396. *  call-seq:
  397. *     Hash.try_convert(obj) -> hash or nil
  398. *
  399. *  Try to convert <i>obj</i> into a hash, using to_hash method.
  400. *  Returns converted hash or nil if <i>obj</i> cannot be converted
  401. *  for any reason.
  402. *
  403. *     Hash.try_convert({1=>2})   # => {1=>2}
  404. *     Hash.try_convert("1=>2")   # => nil
  405. */
  406. static VALUE
  407. rb_hash_s_try_convert(VALUE dummy, VALUE hash)
  408. {
  409.   return rb_check_hash_type(hash);
  410. }

  411. static int
  412. rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
  413. {
  414.   st_table *tbl = (st_table *)arg;

  415.   if (key != Qundef) st_insert(tbl, key, value);
  416.   return ST_CONTINUE;
  417. }

  418. /*
  419. *  call-seq:
  420. *     hsh.rehash -> hsh
  421. *
  422. *  Rebuilds the hash based on the current hash values for each key. If
  423. *  values of key objects have changed since they were inserted, this
  424. *  method will reindex <i>hsh</i>. If <code>Hash#rehash</code> is
  425. *  called while an iterator is traversing the hash, an
  426. *  <code>RuntimeError</code> will be raised in the iterator.
  427. *
  428. *     a = [ "a", "b" ]
  429. *     c = [ "c", "d" ]
  430. *     h = { a => 100, c => 300 }
  431. *     h[a]       #=> 100
  432. *     a[0] = "z"
  433. *     h[a]       #=> nil
  434. *     h.rehash   #=> {["z", "b"]=>100, ["c", "d"]=>300}
  435. *     h[a]       #=> 100
  436. */

  437. static VALUE
  438. rb_hash_rehash(VALUE hash)
  439. {
  440.   st_table *tbl;

  441.   if (RHASH(hash)->iter_lev > 0)
  442.   {
  443.     rb_raise(rb_eRuntimeError, "rehash during iteration");
  444.   }
  445.   rb_hash_modify_check(hash);
  446.   if (!RHASH(hash)->ntbl)
  447.     return hash;
  448.   tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries);
  449.   rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl);
  450.   st_free_table(RHASH(hash)->ntbl);
  451.   RHASH(hash)->ntbl = tbl;

  452.   return hash;
  453. }

  454. /*
  455. *  call-seq:
  456. *     hsh[key]    ->  value
  457. *
  458. *  Element Reference---Retrieves the <i>value</i> object corresponding
  459. *  to the <i>key</i> object. If not found, returns the default value (see
  460. *  <code>Hash::new</code> for details).
  461. *
  462. *     h = { "a" => 100, "b" => 200 }
  463. *     h["a"]   #=> 100
  464. *     h["c"]   #=> nil
  465. *
  466. */

  467. VALUE
  468. rb_hash_aref(VALUE hash, VALUE key)
  469. {
  470.   st_data_t val;

  471.   if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val))
  472.   {
  473.     if (!FL_TEST(hash, HASH_PROC_DEFAULT) &&
  474.         rb_method_basic_definition_p(CLASS_OF(hash), id_default))
  475.     {
  476.       return RHASH_IFNONE(hash);
  477.     }
  478.     else
  479.     {
  480.       return rb_funcall(hash, id_default, 1, key);
  481.     }
  482.   }
  483.   return (VALUE)val;
  484. }

  485. VALUE
  486. rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
  487. {
  488.   st_data_t val;

  489.   if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val))
  490.   {
  491.     return def; /* without Hash#default */
  492.   }
  493.   return (VALUE)val;
  494. }

  495. VALUE
  496. rb_hash_lookup(VALUE hash, VALUE key)
  497. {
  498.   return rb_hash_lookup2(hash, key, Qnil);
  499. }

  500. /*
  501. *  call-seq:
  502. *     hsh.fetch(key [, default] )       -> obj
  503. *     hsh.fetch(key) {| key | block }   -> obj
  504. *
  505. *  Returns a value from the hash for the given key. If the key can't be
  506. *  found, there are several options: With no other arguments, it will
  507. *  raise an <code>KeyError</code> exception; if <i>default</i> is
  508. *  given, then that will be returned; if the optional code block is
  509. *  specified, then that will be run and its result returned.
  510. *
  511. *     h = { "a" => 100, "b" => 200 }
  512. *     h.fetch("a")                            #=> 100
  513. *     h.fetch("z", "go fish")                 #=> "go fish"
  514. *     h.fetch("z") { |el| "go fish, #{el}"}   #=> "go fish, z"
  515. *
  516. *  The following example shows that an exception is raised if the key
  517. *  is not found and a default value is not supplied.
  518. *
  519. *     h = { "a" => 100, "b" => 200 }
  520. *     h.fetch("z")
  521. *
  522. *  <em>produces:</em>
  523. *
  524. *     prog.rb:2:in `fetch': key not found (KeyError)
  525. *      from prog.rb:2
  526. *
  527. */

  528. static VALUE
  529. rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
  530. {
  531.   VALUE key, if_none;
  532.   st_data_t val;
  533.   long block_given;

  534.   rb_scan_args(argc, argv, "11", &key, &if_none);

  535.   block_given = rb_block_given_p();
  536.   if (block_given && argc == 2)
  537.   {
  538.     rb_warn("block supersedes default value argument");
  539.   }
  540.   if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val))
  541.   {
  542.     if (block_given) return rb_yield(key);
  543.     if (argc == 1)
  544.     {
  545.       volatile VALUE desc = rb_protect(rb_inspect, key, 0);
  546.       if (NIL_P(desc))
  547.       {
  548.         desc = rb_any_to_s(key);
  549.       }
  550.       desc = rb_str_ellipsize(desc, 65);
  551.       rb_raise(rb_eKeyError, "key not found: %s", RSTRING_PTR(desc));
  552.     }
  553.     return if_none;
  554.   }
  555.   return (VALUE)val;
  556. }

  557. VALUE
  558. rb_hash_fetch(VALUE hash, VALUE key)
  559. {
  560.   return rb_hash_fetch_m(1, &key, hash);
  561. }

  562. /*
  563. *  call-seq:
  564. *     hsh.default(key=nil)   -> obj
  565. *
  566. *  Returns the default value, the value that would be returned by
  567. *  <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
  568. *  See also <code>Hash::new</code> and <code>Hash#default=</code>.
  569. *
  570. *     h = Hash.new                            #=> {}
  571. *     h.default                               #=> nil
  572. *     h.default(2)                            #=> nil
  573. *
  574. *     h = Hash.new("cat")                     #=> {}
  575. *     h.default                               #=> "cat"
  576. *     h.default(2)                            #=> "cat"
  577. *
  578. *     h = Hash.new {|h,k| h[k] = k.to_i*10}   #=> {}
  579. *     h.default                               #=> nil
  580. *     h.default(2)                            #=> 20
  581. */

  582. static VALUE
  583. rb_hash_default(int argc, VALUE *argv, VALUE hash)
  584. {
  585.   VALUE key, ifnone;

  586.   rb_scan_args(argc, argv, "01", &key);
  587.   ifnone = RHASH_IFNONE(hash);
  588.   if (FL_TEST(hash, HASH_PROC_DEFAULT))
  589.   {
  590.     if (argc == 0) return Qnil;
  591.     return rb_funcall(ifnone, id_yield, 2, hash, key);
  592.   }
  593.   return ifnone;
  594. }

  595. /*
  596. *  call-seq:
  597. *     hsh.default = obj     -> obj
  598. *
  599. *  Sets the default value, the value returned for a key that does not
  600. *  exist in the hash. It is not possible to set the default to a
  601. *  <code>Proc</code> that will be executed on each key lookup.
  602. *
  603. *     h = { "a" => 100, "b" => 200 }
  604. *     h.default = "Go fish"
  605. *     h["a"]     #=> 100
  606. *     h["z"]     #=> "Go fish"
  607. *     # This doesn't do what you might hope...
  608. *     h.default = proc do |hash, key|
  609. *       hash[key] = key + key
  610. *     end
  611. *     h[2]       #=> #<Proc:0x401b3948@-:6>
  612. *     h["cat"]   #=> #<Proc:0x401b3948@-:6>
  613. */

  614. static VALUE
  615. rb_hash_set_default(VALUE hash, VALUE ifnone)
  616. {
  617.   rb_hash_modify(hash);
  618.   RHASH_IFNONE(hash) = ifnone;
  619.   FL_UNSET(hash, HASH_PROC_DEFAULT);
  620.   return ifnone;
  621. }

  622. /*
  623. *  call-seq:
  624. *     hsh.default_proc -> anObject
  625. *
  626. *  If <code>Hash::new</code> was invoked with a block, return that
  627. *  block, otherwise return <code>nil</code>.
  628. *
  629. *     h = Hash.new {|h,k| h[k] = k*k }   #=> {}
  630. *     p = h.default_proc                 #=> #<Proc:0x401b3d08@-:1>
  631. *     a = []                             #=> []
  632. *     p.call(a, 2)
  633. *     a                                  #=> [nil, nil, 4]
  634. */


  635. static VALUE
  636. rb_hash_default_proc(VALUE hash)
  637. {
  638.   if (FL_TEST(hash, HASH_PROC_DEFAULT))
  639.   {
  640.     return RHASH_IFNONE(hash);
  641.   }
  642.   return Qnil;
  643. }

  644. /*
  645. *  call-seq:
  646. *     hsh.default_proc = proc_obj     -> proc_obj
  647. *
  648. *  Sets the default proc to be executed on each key lookup.
  649. *
  650. *     h.default_proc = proc do |hash, key|
  651. *       hash[key] = key + key
  652. *     end
  653. *     h[2]       #=> 4
  654. *     h["cat"]   #=> "catcat"
  655. */

  656. static VALUE
  657. rb_hash_set_default_proc(VALUE hash, VALUE proc)
  658. {
  659.   VALUE b;

  660.   rb_hash_modify(hash);
  661.   b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
  662.   if (NIL_P(b) || !rb_obj_is_proc(b))
  663.   {
  664.     rb_raise(rb_eTypeError,
  665.              "wrong default_proc type %s (expected Proc)",
  666.              rb_obj_classname(proc));
  667.   }
  668.   proc = b;
  669.   default_proc_arity_check(proc);
  670.   RHASH_IFNONE(hash) = proc;
  671.   FL_SET(hash, HASH_PROC_DEFAULT);
  672.   return proc;
  673. }

  674. static int
  675. key_i(VALUE key, VALUE value, VALUE arg)
  676. {
  677.   VALUE *args = (VALUE *)arg;

  678.   if (rb_equal(value, args[0]))
  679.   {
  680.     args[1] = key;
  681.     return ST_STOP;
  682.   }
  683.   return ST_CONTINUE;
  684. }

  685. /*
  686. *  call-seq:
  687. *     hsh.key(value)    -> key
  688. *
  689. *  Returns the key of an occurrence of a given value. If the value is
  690. *  not found, returns <code>nil</code>.
  691. *
  692. *     h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
  693. *     h.key(200)   #=> "b"
  694. *     h.key(300)   #=> "c"
  695. *     h.key(999)   #=> nil
  696. *
  697. */

  698. static VALUE
  699. rb_hash_key(VALUE hash, VALUE value)
  700. {
  701.   VALUE args[2];

  702.   args[0] = value;
  703.   args[1] = Qnil;

  704.   rb_hash_foreach(hash, key_i, (VALUE)args);

  705.   return args[1];
  706. }

  707. /* :nodoc: */
  708. static VALUE
  709. rb_hash_index(VALUE hash, VALUE value)
  710. {
  711.   rb_warn("Hash#index is deprecated; use Hash#key");
  712.   return rb_hash_key(hash, value);
  713. }

  714. static VALUE
  715. rb_hash_delete_key(VALUE hash, VALUE key)
  716. {
  717.   st_data_t ktmp = (st_data_t)key, val;

  718.   if (!RHASH(hash)->ntbl)
  719.     return Qundef;
  720.   if (RHASH(hash)->iter_lev > 0)
  721.   {
  722.     if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef))
  723.     {
  724.       FL_SET(hash, HASH_DELETED);
  725.       return (VALUE)val;
  726.     }
  727.   }
  728.   else if (st_delete(RHASH(hash)->ntbl, &ktmp, &val))
  729.     return (VALUE)val;
  730.   return Qundef;
  731. }

  732. /*
  733. *  call-seq:
  734. *     hsh.delete(key)                   -> value
  735. *     hsh.delete(key) {| key | block }  -> value
  736. *
  737. *  Deletes and returns a key-value pair from <i>hsh</i> whose key is
  738. *  equal to <i>key</i>. If the key is not found, returns the
  739. *  <em>default value</em>. If the optional code block is given and the
  740. *  key is not found, pass in the key and return the result of
  741. *  <i>block</i>.
  742. *
  743. *     h = { "a" => 100, "b" => 200 }
  744. *     h.delete("a")                              #=> 100
  745. *     h.delete("z")                              #=> nil
  746. *     h.delete("z") { |el| "#{el} not found" }   #=> "z not found"
  747. *
  748. */

  749. VALUE
  750. rb_hash_delete(VALUE hash, VALUE key)
  751. {
  752.   VALUE val;

  753.   rb_hash_modify(hash);
  754.   val = rb_hash_delete_key(hash, key);
  755.   if (val != Qundef) return val;
  756.   if (rb_block_given_p())
  757.   {
  758.     return rb_yield(key);
  759.   }
  760.   return Qnil;
  761. }

  762. struct shift_var
  763. {
  764.   VALUE key;
  765.   VALUE val;
  766. };

  767. static int
  768. shift_i(VALUE key, VALUE value, VALUE arg)
  769. {
  770.   struct shift_var *var = (struct shift_var *)arg;

  771.   if (key == Qundef) return ST_CONTINUE;
  772.   if (var->key != Qundef) return ST_STOP;
  773.   var->key = key;
  774.   var->val = value;
  775.   return ST_DELETE;
  776. }

  777. static int
  778. shift_i_safe(VALUE key, VALUE value, VALUE arg)
  779. {
  780.   struct shift_var *var = (struct shift_var *)arg;

  781.   if (key == Qundef) return ST_CONTINUE;
  782.   var->key = key;
  783.   var->val = value;
  784.   return ST_STOP;
  785. }

  786. /*
  787. *  call-seq:
  788. *     hsh.shift -> anArray or obj
  789. *
  790. *  Removes a key-value pair from <i>hsh</i> and returns it as the
  791. *  two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
  792. *  the hash's default value if the hash is empty.
  793. *
  794. *     h = { 1 => "a", 2 => "b", 3 => "c" }
  795. *     h.shift   #=> [1, "a"]
  796. *     h         #=> {2=>"b", 3=>"c"}
  797. */

  798. static VALUE
  799. rb_hash_shift(VALUE hash)
  800. {
  801.   struct shift_var var;

  802.   rb_hash_modify(hash);
  803.   var.key = Qundef;
  804.   rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i,
  805.                   (VALUE)&var);

  806.   if (var.key != Qundef)
  807.   {
  808.     if (RHASH(hash)->iter_lev > 0)
  809.     {
  810.       rb_hash_delete_key(hash, var.key);
  811.     }
  812.     return rb_assoc_new(var.key, var.val);
  813.   }
  814.   else if (FL_TEST(hash, HASH_PROC_DEFAULT))
  815.   {
  816.     return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil);
  817.   }
  818.   else
  819.   {
  820.     return RHASH_IFNONE(hash);
  821.   }
  822. }

  823. static int
  824. delete_if_i(VALUE key, VALUE value, VALUE hash)
  825. {
  826.   if (key == Qundef) return ST_CONTINUE;
  827.   if (RTEST(rb_yield_values(2, key, value)))
  828.   {
  829.     rb_hash_delete_key(hash, key);
  830.   }
  831.   return ST_CONTINUE;
  832. }

  833. /*
  834. *  call-seq:
  835. *     hsh.delete_if {| key, value | block }  -> hsh
  836. *     hsh.delete_if                          -> an_enumerator
  837. *
  838. *  Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
  839. *  evaluates to <code>true</code>.
  840. *
  841. *  If no block is given, an enumerator is returned instead.
  842. *
  843. *     h = { "a" => 100, "b" => 200, "c" => 300 }
  844. *     h.delete_if {|key, value| key >= "b" }   #=> {"a"=>100}
  845. *
  846. */

  847. VALUE
  848. rb_hash_delete_if(VALUE hash)
  849. {
  850.   RETURN_ENUMERATOR(hash, 0, 0);
  851.   rb_hash_modify(hash);
  852.   rb_hash_foreach(hash, delete_if_i, hash);
  853.   return hash;
  854. }

  855. /*
  856. *  call-seq:
  857. *     hsh.reject! {| key, value | block }  -> hsh or nil
  858. *     hsh.reject!                          -> an_enumerator
  859. *
  860. *  Equivalent to <code>Hash#delete_if</code>, but returns
  861. *  <code>nil</code> if no changes were made.
  862. */

  863. VALUE
  864. rb_hash_reject_bang(VALUE hash)
  865. {
  866.   st_index_t n;

  867.   RETURN_ENUMERATOR(hash, 0, 0);
  868.   rb_hash_modify(hash);
  869.   if (!RHASH(hash)->ntbl)
  870.     return Qnil;
  871.   n = RHASH(hash)->ntbl->num_entries;
  872.   rb_hash_foreach(hash, delete_if_i, hash);
  873.   if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
  874.   return hash;
  875. }

  876. /*
  877. *  call-seq:
  878. *     hsh.reject {| key, value | block }  -> a_hash
  879. *     hsh.reject                          -> an_enumerator
  880. *
  881. *  Same as <code>Hash#delete_if</code>, but works on (and returns) a
  882. *  copy of the <i>hsh</i>. Equivalent to
  883. *  <code><i>hsh</i>.dup.delete_if</code>.
  884. *
  885. */

  886. static VALUE
  887. rb_hash_reject(VALUE hash)
  888. {
  889.   return rb_hash_delete_if(rb_obj_dup(hash));
  890. }

  891. /*
  892. * call-seq:
  893. *   hsh.values_at(key, ...)   -> array
  894. *
  895. * Return an array containing the values associated with the given keys.
  896. * Also see <code>Hash.select</code>.
  897. *
  898. *   h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
  899. *   h.values_at("cow", "cat")  #=> ["bovine", "feline"]
  900. */

  901. VALUE
  902. rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
  903. {
  904.   VALUE result = rb_ary_new2(argc);
  905.   long i;

  906.   for (i = 0; i < argc; i++)
  907.   {
  908.     rb_ary_push(result, rb_hash_aref(hash, argv[i]));
  909.   }
  910.   return result;
  911. }

  912. static int
  913. select_i(VALUE key, VALUE value, VALUE result)
  914. {
  915.   if (key == Qundef) return ST_CONTINUE;
  916.   if (RTEST(rb_yield_values(2, key, value)))
  917.     rb_hash_aset(result, key, value);
  918.   return ST_CONTINUE;
  919. }

  920. /*
  921. *  call-seq:
  922. *     hsh.select {|key, value| block}   -> a_hash
  923. *     hsh.select                        -> an_enumerator
  924. *
  925. *  Returns a new hash consisting of entries for which the block returns true.
  926. *
  927. *  If no block is given, an enumerator is returned instead.
  928. *
  929. *     h = { "a" => 100, "b" => 200, "c" => 300 }
  930. *     h.select {|k,v| k > "a"}  #=> {"b" => 200, "c" => 300}
  931. *     h.select {|k,v| v < 200}  #=> {"a" => 100}
  932. */

  933. VALUE
  934. rb_hash_select(VALUE hash)
  935. {
  936.   VALUE result;

  937.   RETURN_ENUMERATOR(hash, 0, 0);
  938.   result = rb_hash_new();
  939.   rb_hash_foreach(hash, select_i, result);
  940.   return result;
  941. }

  942. static int
  943. keep_if_i(VALUE key, VALUE value, VALUE hash)
  944. {
  945.   if (key == Qundef) return ST_CONTINUE;
  946.   if (!RTEST(rb_yield_values(2, key, value)))
  947.   {
  948.     return ST_DELETE;
  949.   }
  950.   return ST_CONTINUE;
  951. }

  952. /*
  953. *  call-seq:
  954. *     hsh.select! {| key, value | block }  -> hsh or nil
  955. *     hsh.select!                          -> an_enumerator
  956. *
  957. *  Equivalent to <code>Hash#keep_if</code>, but returns
  958. *  <code>nil</code> if no changes were made.
  959. */

  960. VALUE
  961. rb_hash_select_bang(VALUE hash)
  962. {
  963.   st_index_t n;

  964.   RETURN_ENUMERATOR(hash, 0, 0);
  965.   rb_hash_modify(hash);
  966.   if (!RHASH(hash)->ntbl)
  967.     return Qnil;
  968.   n = RHASH(hash)->ntbl->num_entries;
  969.   rb_hash_foreach(hash, keep_if_i, hash);
  970.   if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
  971.   return hash;
  972. }

  973. /*
  974. *  call-seq:
  975. *     hsh.keep_if {| key, value | block }  -> hsh
  976. *     hsh.keep_if                          -> an_enumerator
  977. *
  978. *  Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
  979. *  evaluates to false.
  980. *
  981. *  If no block is given, an enumerator is returned instead.
  982. *
  983. */

  984. VALUE
  985. rb_hash_keep_if(VALUE hash)
  986. {
  987.   RETURN_ENUMERATOR(hash, 0, 0);
  988.   rb_hash_modify(hash);
  989.   rb_hash_foreach(hash, keep_if_i, hash);
  990.   return hash;
  991. }

  992. static int
  993. clear_i(VALUE key, VALUE value, VALUE dummy)
  994. {
  995.   return ST_DELETE;
  996. }

  997. /*
  998. *  call-seq:
  999. *     hsh.clear -> hsh
  1000. *
  1001. *  Removes all key-value pairs from <i>hsh</i>.
  1002. *
  1003. *     h = { "a" => 100, "b" => 200 }   #=> {"a"=>100, "b"=>200}
  1004. *     h.clear                          #=> {}
  1005. *
  1006. */

  1007. static VALUE
  1008. rb_hash_clear(VALUE hash)
  1009. {
  1010.   rb_hash_modify_check(hash);
  1011.   if (!RHASH(hash)->ntbl)
  1012.     return hash;
  1013.   if (RHASH(hash)->ntbl->num_entries > 0)
  1014.   {
  1015.     if (RHASH(hash)->iter_lev > 0)
  1016.       rb_hash_foreach(hash, clear_i, 0);
  1017.     else
  1018.       st_clear(RHASH(hash)->ntbl);
  1019.   }

  1020.   return hash;
  1021. }

  1022. static st_data_t
  1023. copy_str_key(st_data_t str)
  1024. {
  1025.   return (st_data_t)rb_str_new4((VALUE)str);
  1026. }

  1027. /*
  1028. *  call-seq:
  1029. *     hsh[key] = value        -> value
  1030. *     hsh.store(key, value)   -> value
  1031. *
  1032. *  Element Assignment---Associates the value given by
  1033. *  <i>value</i> with the key given by <i>key</i>.
  1034. *  <i>key</i> should not have its value changed while it is in
  1035. *  use as a key (a <code>String</code> passed as a key will be
  1036. *  duplicated and frozen).
  1037. *
  1038. *     h = { "a" => 100, "b" => 200 }
  1039. *     h["a"] = 9
  1040. *     h["c"] = 4
  1041. *     h   #=> {"a"=>9, "b"=>200, "c"=>4}
  1042. *
  1043. */

  1044. VALUE
  1045. rb_hash_aset(VALUE hash, VALUE key, VALUE val)
  1046. {
  1047.   rb_hash_modify(hash);
  1048.   hash_update(hash, key);
  1049.   if (RHASH(hash)->ntbl->type == &identhash || rb_obj_class(key) != rb_cString)
  1050.   {
  1051.     st_insert(RHASH(hash)->ntbl, key, val);
  1052.   }
  1053.   else
  1054.   {
  1055.     st_insert2(RHASH(hash)->ntbl, key, val, copy_str_key);
  1056.   }
  1057.   return val;
  1058. }

  1059. static int
  1060. replace_i(VALUE key, VALUE val, VALUE hash)
  1061. {
  1062.   if (key != Qundef)
  1063.   {
  1064.     rb_hash_aset(hash, key, val);
  1065.   }

  1066.   return ST_CONTINUE;
  1067. }

  1068. /*
  1069. *  call-seq:
  1070. *     hsh.replace(other_hash) -> hsh
  1071. *
  1072. *  Replaces the contents of <i>hsh</i> with the contents of
  1073. *  <i>other_hash</i>.
  1074. *
  1075. *     h = { "a" => 100, "b" => 200 }
  1076. *     h.replace({ "c" => 300, "d" => 400 })   #=> {"c"=>300, "d"=>400}
  1077. *
  1078. */

  1079. static VALUE
  1080. rb_hash_replace(VALUE hash, VALUE hash2)
  1081. {
  1082.   rb_hash_modify_check(hash);
  1083.   hash2 = to_hash(hash2);
  1084.   if (hash == hash2) return hash;
  1085.   rb_hash_clear(hash);
  1086.   if (RHASH(hash2)->ntbl)
  1087.   {
  1088.     rb_hash_tbl(hash);
  1089.     RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type;
  1090.   }
  1091.   rb_hash_foreach(hash2, replace_i, hash);
  1092.   RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);
  1093.   if (FL_TEST(hash2, HASH_PROC_DEFAULT))
  1094.   {
  1095.     FL_SET(hash, HASH_PROC_DEFAULT);
  1096.   }
  1097.   else
  1098.   {
  1099.     FL_UNSET(hash, HASH_PROC_DEFAULT);
  1100.   }

  1101.   return hash;
  1102. }

  1103. /*
  1104. *  call-seq:
  1105. *     hsh.length    ->  fixnum
  1106. *     hsh.size      ->  fixnum
  1107. *
  1108. *  Returns the number of key-value pairs in the hash.
  1109. *
  1110. *     h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
  1111. *     h.length        #=> 4
  1112. *     h.delete("a")   #=> 200
  1113. *     h.length        #=> 3
  1114. */

  1115. static VALUE
  1116. rb_hash_size(VALUE hash)
  1117. {
  1118.   if (!RHASH(hash)->ntbl)
  1119.     return INT2FIX(0);
  1120.   return INT2FIX(RHASH(hash)->ntbl->num_entries);
  1121. }


  1122. /*
  1123. *  call-seq:
  1124. *     hsh.empty?    -> true or false
  1125. *
  1126. *  Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
  1127. *
  1128. *     {}.empty?   #=> true
  1129. *
  1130. */

  1131. static VALUE
  1132. rb_hash_empty_p(VALUE hash)
  1133. {
  1134.   return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
  1135. }

  1136. static int
  1137. each_value_i(VALUE key, VALUE value)
  1138. {
  1139.   if (key == Qundef) return ST_CONTINUE;
  1140.   rb_yield(value);
  1141.   return ST_CONTINUE;
  1142. }

  1143. /*
  1144. *  call-seq:
  1145. *     hsh.each_value {| value | block } -> hsh
  1146. *     hsh.each_value                    -> an_enumerator
  1147. *
  1148. *  Calls <i>block</i> once for each key in <i>hsh</i>, passing the
  1149. *  value as a parameter.
  1150. *
  1151. *  If no block is given, an enumerator is returned instead.
  1152. *
  1153. *     h = { "a" => 100, "b" => 200 }
  1154. *     h.each_value {|value| puts value }
  1155. *
  1156. *  <em>produces:</em>
  1157. *
  1158. *     100
  1159. *     200
  1160. */

  1161. static VALUE
  1162. rb_hash_each_value(VALUE hash)
  1163. {
  1164.   RETURN_ENUMERATOR(hash, 0, 0);
  1165.   rb_hash_foreach(hash, each_value_i, 0);
  1166.   return hash;
  1167. }

  1168. static int
  1169. each_key_i(VALUE key, VALUE value)
  1170. {
  1171.   if (key == Qundef) return ST_CONTINUE;
  1172.   rb_yield(key);
  1173.   return ST_CONTINUE;
  1174. }

  1175. /*
  1176. *  call-seq:
  1177. *     hsh.each_key {| key | block } -> hsh
  1178. *     hsh.each_key                  -> an_enumerator
  1179. *
  1180. *  Calls <i>block</i> once for each key in <i>hsh</i>, passing the key
  1181. *  as a parameter.
  1182. *
  1183. *  If no block is given, an enumerator is returned instead.
  1184. *
  1185. *     h = { "a" => 100, "b" => 200 }
  1186. *     h.each_key {|key| puts key }
  1187. *
  1188. *  <em>produces:</em>
  1189. *
  1190. *     a
  1191. *     b
  1192. */
  1193. static VALUE
  1194. rb_hash_each_key(VALUE hash)
  1195. {
  1196.   RETURN_ENUMERATOR(hash, 0, 0);
  1197.   rb_hash_foreach(hash, each_key_i, 0);
  1198.   return hash;
  1199. }

  1200. static int
  1201. each_pair_i(VALUE key, VALUE value)
  1202. {
  1203.   if (key == Qundef) return ST_CONTINUE;
  1204.   rb_yield(rb_assoc_new(key, value));
  1205.   return ST_CONTINUE;
  1206. }

  1207. /*
  1208. *  call-seq:
  1209. *     hsh.each      {| key, value | block } -> hsh
  1210. *     hsh.each_pair {| key, value | block } -> hsh
  1211. *     hsh.each                              -> an_enumerator
  1212. *     hsh.each_pair                         -> an_enumerator
  1213. *
  1214. *  Calls <i>block</i> once for each key in <i>hsh</i>, passing the key-value
  1215. *  pair as parameters.
  1216. *
  1217. *  If no block is given, an enumerator is returned instead.
  1218. *
  1219. *     h = { "a" => 100, "b" => 200 }
  1220. *     h.each {|key, value| puts "#{key} is #{value}" }
  1221. *
  1222. *  <em>produces:</em>
  1223. *
  1224. *     a is 100
  1225. *     b is 200
  1226. *
  1227. */

  1228. static VALUE
  1229. rb_hash_each_pair(VALUE hash)
  1230. {
  1231.   RETURN_ENUMERATOR(hash, 0, 0);
  1232.   rb_hash_foreach(hash, each_pair_i, 0);
  1233.   return hash;
  1234. }

  1235. static int
  1236. to_a_i(VALUE key, VALUE value, VALUE ary)
  1237. {
  1238.   if (key == Qundef) return ST_CONTINUE;
  1239.   rb_ary_push(ary, rb_assoc_new(key, value));
  1240.   return ST_CONTINUE;
  1241. }

  1242. /*
  1243. *  call-seq:
  1244. *     hsh.to_a -> array
  1245. *
  1246. *  Converts <i>hsh</i> to a nested array of <code>[</code> <i>key,
  1247. *  value</i> <code>]</code> arrays.
  1248. *
  1249. *     h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
  1250. *     h.to_a   #=> [["c", 300], ["a", 100], ["d", 400]]
  1251. */

  1252. static VALUE
  1253. rb_hash_to_a(VALUE hash)
  1254. {
  1255.   VALUE ary;

  1256.   ary = rb_ary_new();
  1257.   rb_hash_foreach(hash, to_a_i, ary);
  1258.   OBJ_INFECT(ary, hash);

  1259.   return ary;
  1260. }

  1261. static int
  1262. inspect_i(VALUE key, VALUE value, VALUE str)
  1263. {
  1264.   VALUE str2;

  1265.   if (key == Qundef) return ST_CONTINUE;
  1266.   str2 = rb_inspect(key);
  1267.   if (RSTRING_LEN(str) > 1)
  1268.   {
  1269.     rb_str_cat2(str, ", ");
  1270.   }
  1271.   else
  1272.   {
  1273.     rb_enc_copy(str, str2);
  1274.   }
  1275.   rb_str_buf_append(str, str2);
  1276.   OBJ_INFECT(str, str2);
  1277.   rb_str_buf_cat2(str, "=>");
  1278.   str2 = rb_inspect(value);
  1279.   rb_str_buf_append(str, str2);
  1280.   OBJ_INFECT(str, str2);

  1281.   return ST_CONTINUE;
  1282. }

  1283. static VALUE
  1284. inspect_hash(VALUE hash, VALUE dummy, int recur)
  1285. {
  1286.   VALUE str;

  1287.   if (recur) return rb_usascii_str_new2("{...}");
  1288.   str = rb_str_buf_new2("{");
  1289.   rb_hash_foreach(hash, inspect_i, str);
  1290.   rb_str_buf_cat2(str, "}");
  1291.   OBJ_INFECT(str, hash);

  1292.   return str;
  1293. }

  1294. /*
  1295. * call-seq:
  1296. *   hsh.to_s     -> string
  1297. *   hsh.inspect  -> string
  1298. *
  1299. * Return the contents of this hash as a string.
  1300. *
  1301. *     h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300  }
  1302. *     h.to_s   #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}"
  1303. */

  1304. static VALUE
  1305. rb_hash_inspect(VALUE hash)
  1306. {
  1307.   if (RHASH_EMPTY_P(hash))
  1308.     return rb_usascii_str_new2("{}");
  1309.   return rb_exec_recursive(inspect_hash, hash, 0);
  1310. }

  1311. /*
  1312. * call-seq:
  1313. *    hsh.to_hash   => hsh
  1314. *
  1315. * Returns +self+.
  1316. */

  1317. static VALUE
  1318. rb_hash_to_hash(VALUE hash)
  1319. {
  1320.   return hash;
  1321. }

  1322. static int
  1323. keys_i(VALUE key, VALUE value, VALUE ary)
  1324. {
  1325.   if (key == Qundef) return ST_CONTINUE;
  1326.   rb_ary_push(ary, key);
  1327.   return ST_CONTINUE;
  1328. }

  1329. /*
  1330. *  call-seq:
  1331. *     hsh.keys    -> array
  1332. *
  1333. *  Returns a new array populated with the keys from this hash. See also
  1334. *  <code>Hash#values</code>.
  1335. *
  1336. *     h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
  1337. *     h.keys   #=> ["a", "b", "c", "d"]
  1338. *
  1339. */

  1340. static VALUE
  1341. rb_hash_keys(VALUE hash)
  1342. {
  1343.   VALUE ary;

  1344.   ary = rb_ary_new();
  1345.   rb_hash_foreach(hash, keys_i, ary);

  1346.   return ary;
  1347. }

  1348. static int
  1349. values_i(VALUE key, VALUE value, VALUE ary)
  1350. {
  1351.   if (key == Qundef) return ST_CONTINUE;
  1352.   rb_ary_push(ary, value);
  1353.   return ST_CONTINUE;
  1354. }

  1355. /*
  1356. *  call-seq:
  1357. *     hsh.values    -> array
  1358. *
  1359. *  Returns a new array populated with the values from <i>hsh</i>. See
  1360. *  also <code>Hash#keys</code>.
  1361. *
  1362. *     h = { "a" => 100, "b" => 200, "c" => 300 }
  1363. *     h.values   #=> [100, 200, 300]
  1364. *
  1365. */

  1366. static VALUE
  1367. rb_hash_values(VALUE hash)
  1368. {
  1369.   VALUE ary;

  1370.   ary = rb_ary_new();
  1371.   rb_hash_foreach(hash, values_i, ary);

  1372.   return ary;
  1373. }

  1374. /*
  1375. *  call-seq:
  1376. *     hsh.has_key?(key)    -> true or false
  1377. *     hsh.include?(key)    -> true or false
  1378. *     hsh.key?(key)        -> true or false
  1379. *     hsh.member?(key)     -> true or false
  1380. *
  1381. *  Returns <code>true</code> if the given key is present in <i>hsh</i>.
  1382. *
  1383. *     h = { "a" => 100, "b" => 200 }
  1384. *     h.has_key?("a")   #=> true
  1385. *     h.has_key?("z")   #=> false
  1386. *
  1387. */

  1388. static VALUE
  1389. rb_hash_has_key(VALUE hash, VALUE key)
  1390. {
  1391.   if (!RHASH(hash)->ntbl)
  1392.     return Qfalse;
  1393.   if (st_lookup(RHASH(hash)->ntbl, key, 0))
  1394.   {
  1395.     return Qtrue;
  1396.   }
  1397.   return Qfalse;
  1398. }

  1399. static int
  1400. rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
  1401. {
  1402.   VALUE *data = (VALUE *)arg;

  1403.   if (key == Qundef) return ST_CONTINUE;
  1404.   if (rb_equal(value, data[1]))
  1405.   {
  1406.     data[0] = Qtrue;
  1407.     return ST_STOP;
  1408.   }
  1409.   return ST_CONTINUE;
  1410. }

  1411. /*
  1412. *  call-seq:
  1413. *     hsh.has_value?(value)    -> true or false
  1414. *     hsh.value?(value)        -> true or false
  1415. *
  1416. *  Returns <code>true</code> if the given value is present for some key
  1417. *  in <i>hsh</i>.
  1418. *
  1419. *     h = { "a" => 100, "b" => 200 }
  1420. *     h.has_value?(100)   #=> true
  1421. *     h.has_value?(999)   #=> false
  1422. */

  1423. static VALUE
  1424. rb_hash_has_value(VALUE hash, VALUE val)
  1425. {
  1426.   VALUE data[2];

  1427.   data[0] = Qfalse;
  1428.   data[1] = val;
  1429.   rb_hash_foreach(hash, rb_hash_search_value, (VALUE)data);
  1430.   return data[0];
  1431. }

  1432. struct equal_data
  1433. {
  1434.   VALUE result;
  1435.   st_table *tbl;
  1436.   int eql;
  1437. };

  1438. static int
  1439. eql_i(VALUE key, VALUE val1, VALUE arg)
  1440. {
  1441.   struct equal_data *data = (struct equal_data *)arg;
  1442.   st_data_t val2;

  1443.   if (key == Qundef) return ST_CONTINUE;
  1444.   if (!st_lookup(data->tbl, key, &val2))
  1445.   {
  1446.     data->result = Qfalse;
  1447.     return ST_STOP;
  1448.   }
  1449.   if (!(data->eql ? rb_eql(val1, (VALUE)val2) : (int)rb_equal(val1, (VALUE)val2)))
  1450.   {
  1451.     data->result = Qfalse;
  1452.     return ST_STOP;
  1453.   }
  1454.   return ST_CONTINUE;
  1455. }

  1456. static VALUE
  1457. recursive_eql(VALUE hash, VALUE dt, int recur)
  1458. {
  1459.   struct equal_data *data;

  1460.   if (recur) return Qtrue;        /* Subtle! */
  1461.   data = (struct equal_data*)dt;
  1462.   data->result = Qtrue;
  1463.   rb_hash_foreach(hash, eql_i, dt);

  1464.   return data->result;
  1465. }

  1466. static VALUE
  1467. hash_equal(VALUE hash1, VALUE hash2, int eql)
  1468. {
  1469.   struct equal_data data;

  1470.   if (hash1 == hash2) return Qtrue;
  1471.   if (TYPE(hash2) != T_HASH)
  1472.   {
  1473.     if (!rb_respond_to(hash2, rb_intern("to_hash")))
  1474.     {
  1475.       return Qfalse;
  1476.     }
  1477.     if (eql)
  1478.       return rb_eql(hash2, hash1);
  1479.     else
  1480.       return rb_equal(hash2, hash1);
  1481.   }
  1482.   if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
  1483.     return Qfalse;
  1484.   if (!RHASH(hash1)->ntbl || !RHASH(hash2)->ntbl)
  1485.     return Qtrue;
  1486.   if (RHASH(hash1)->ntbl->type != RHASH(hash2)->ntbl->type)
  1487.     return Qfalse;
  1488. #if 0
  1489.   if (!(rb_equal(RHASH_IFNONE(hash1), RHASH_IFNONE(hash2)) &&
  1490.         FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
  1491.     return Qfalse;
  1492. #endif

  1493.   data.tbl = RHASH(hash2)->ntbl;
  1494.   data.eql = eql;
  1495.   return rb_exec_recursive_paired(recursive_eql, hash1, hash2, (VALUE)&data);
  1496. }

  1497. /*
  1498. *  call-seq:
  1499. *     hsh == other_hash    -> true or false
  1500. *
  1501. *  Equality---Two hashes are equal if they each contain the same number
  1502. *  of keys and if each key-value pair is equal to (according to
  1503. *  <code>Object#==</code>) the corresponding elements in the other
  1504. *  hash.
  1505. *
  1506. *     h1 = { "a" => 1, "c" => 2 }
  1507. *     h2 = { 7 => 35, "c" => 2, "a" => 1 }
  1508. *     h3 = { "a" => 1, "c" => 2, 7 => 35 }
  1509. *     h4 = { "a" => 1, "d" => 2, "f" => 35 }
  1510. *     h1 == h2   #=> false
  1511. *     h2 == h3   #=> true
  1512. *     h3 == h4   #=> false
  1513. *
  1514. */

  1515. static VALUE
  1516. rb_hash_equal(VALUE hash1, VALUE hash2)
  1517. {
  1518.   return hash_equal(hash1, hash2, FALSE);
  1519. }

  1520. /*
  1521. *  call-seq:
  1522. *     hash.eql?(other)  -> true or false
  1523. *
  1524. *  Returns <code>true</code> if <i>hash</i> and <i>other</i> are
  1525. *  both hashes with the same content.
  1526. */

  1527. static VALUE
  1528. rb_hash_eql(VALUE hash1, VALUE hash2)
  1529. {
  1530.   return hash_equal(hash1, hash2, TRUE);
  1531. }

  1532. static int
  1533. hash_i(VALUE key, VALUE val, VALUE arg)
  1534. {
  1535.   st_index_t *hval = (st_index_t *)arg;
  1536.   st_index_t hdata[2];

  1537.   if (key == Qundef) return ST_CONTINUE;
  1538.   hdata[0] = rb_hash(key);
  1539.   hdata[1] = rb_hash(val);
  1540.   *hval ^= st_hash(hdata, sizeof(hdata), 0);
  1541.   return ST_CONTINUE;
  1542. }

  1543. static VALUE
  1544. recursive_hash(VALUE hash, VALUE dummy, int recur)
  1545. {
  1546.   st_index_t hval;

  1547.   if (!RHASH(hash)->ntbl)
  1548.     return LONG2FIX(0);
  1549.   hval = RHASH(hash)->ntbl->num_entries;
  1550.   if (!hval) return LONG2FIX(0);
  1551.   if (recur)
  1552.     hval = rb_hash_uint(rb_hash_start(rb_hash(rb_cHash)), hval);
  1553.   else
  1554.     rb_hash_foreach(hash, hash_i, (VALUE)&hval);
  1555.   hval = rb_hash_end(hval);
  1556.   return INT2FIX(hval);
  1557. }

  1558. /*
  1559. *  call-seq:
  1560. *     hsh.hash   -> fixnum
  1561. *
  1562. *  Compute a hash-code for this hash. Two hashes with the same content
  1563. *  will have the same hash code (and will compare using <code>eql?</code>).
  1564. */

  1565. static VALUE
  1566. rb_hash_hash(VALUE hash)
  1567. {
  1568.   return rb_exec_recursive_outer(recursive_hash, hash, 0);
  1569. }

  1570. static int
  1571. rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
  1572. {
  1573.   if (key == Qundef) return ST_CONTINUE;
  1574.   rb_hash_aset(hash, value, key);
  1575.   return ST_CONTINUE;
  1576. }

  1577. /*
  1578. *  call-seq:
  1579. *     hsh.invert -> new_hash
  1580. *
  1581. *  Returns a new hash created by using <i>hsh</i>'s values as keys, and
  1582. *  the keys as values.
  1583. *
  1584. *     h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
  1585. *     h.invert   #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
  1586. *
  1587. */

  1588. static VALUE
  1589. rb_hash_invert(VALUE hash)
  1590. {
  1591.   VALUE h = rb_hash_new();

  1592.   rb_hash_foreach(hash, rb_hash_invert_i, h);
  1593.   return h;
  1594. }

  1595. static int
  1596. rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
  1597. {
  1598.   if (key == Qundef) return ST_CONTINUE;
  1599.   hash_update(hash, key);
  1600.   st_insert(RHASH(hash)->ntbl, key, value);
  1601.   return ST_CONTINUE;
  1602. }

  1603. static int
  1604. rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
  1605. {
  1606.   if (key == Qundef) return ST_CONTINUE;
  1607.   if (rb_hash_has_key(hash, key))
  1608.   {
  1609.     value = rb_yield_values(3, key, rb_hash_aref(hash, key), value);
  1610.   }
  1611.   hash_update(hash, key);
  1612.   st_insert(RHASH(hash)->ntbl, key, value);
  1613.   return ST_CONTINUE;
  1614. }

  1615. /*
  1616. *  call-seq:
  1617. *     hsh.merge!(other_hash)                                 -> hsh
  1618. *     hsh.update(other_hash)                                 -> hsh
  1619. *     hsh.merge!(other_hash){|key, oldval, newval| block}    -> hsh
  1620. *     hsh.update(other_hash){|key, oldval, newval| block}    -> hsh
  1621. *
  1622. *  Adds the contents of <i>other_hash</i> to <i>hsh</i>.  If no
  1623. *  block is specified, entries with duplicate keys are overwritten
  1624. *  with the values from <i>other_hash</i>, otherwise the value
  1625. *  of each duplicate key is determined by calling the block with
  1626. *  the key, its value in <i>hsh</i> and its value in <i>other_hash</i>.
  1627. *
  1628. *     h1 = { "a" => 100, "b" => 200 }
  1629. *     h2 = { "b" => 254, "c" => 300 }
  1630. *     h1.merge!(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}
  1631. *
  1632. *     h1 = { "a" => 100, "b" => 200 }
  1633. *     h2 = { "b" => 254, "c" => 300 }
  1634. *     h1.merge!(h2) { |key, v1, v2| v1 }
  1635. *                     #=> {"a"=>100, "b"=>200, "c"=>300}
  1636. */

  1637. static VALUE
  1638. rb_hash_update(VALUE hash1, VALUE hash2)
  1639. {
  1640.   rb_hash_modify(hash1);
  1641.   hash2 = to_hash(hash2);
  1642.   if (rb_block_given_p())
  1643.   {
  1644.     rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
  1645.   }
  1646.   else
  1647.   {
  1648.     rb_hash_foreach(hash2, rb_hash_update_i, hash1);
  1649.   }
  1650.   return hash1;
  1651. }

  1652. struct update_arg
  1653. {
  1654.   VALUE hash;
  1655.   rb_hash_update_func *func;
  1656. };

  1657. static int
  1658. rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0)
  1659. {
  1660.   struct update_arg *arg = (struct update_arg *)arg0;
  1661.   VALUE hash = arg->hash;

  1662.   if (key == Qundef) return ST_CONTINUE;
  1663.   if (rb_hash_has_key(hash, key))
  1664.   {
  1665.     value = (*arg->func)(key, rb_hash_aref(hash, key), value);
  1666.   }
  1667.   hash_update(hash, key);
  1668.   st_insert(RHASH(hash)->ntbl, key, value);
  1669.   return ST_CONTINUE;
  1670. }

  1671. VALUE
  1672. rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
  1673. {
  1674.   rb_hash_modify(hash1);
  1675.   hash2 = to_hash(hash2);
  1676.   if (func)
  1677.   {
  1678.     struct update_arg arg;
  1679.     arg.hash = hash1;
  1680.     arg.func = func;
  1681.     rb_hash_foreach(hash2, rb_hash_update_func_i, (VALUE)&arg);
  1682.   }
  1683.   else
  1684.   {
  1685.     rb_hash_foreach(hash2, rb_hash_update_i, hash1);
  1686.   }
  1687.   return hash1;
  1688. }

  1689. /*
  1690. *  call-seq:
  1691. *     hsh.merge(other_hash)                              -> new_hash
  1692. *     hsh.merge(other_hash){|key, oldval, newval| block} -> new_hash
  1693. *
  1694. *  Returns a new hash containing the contents of <i>other_hash</i> and
  1695. *  the contents of <i>hsh</i>. If no block is specified, the value for
  1696. *  entries with duplicate keys will be that of <i>other_hash</i>. Otherwise
  1697. *  the value for each duplicate key is determined by calling the block
  1698. *  with the key, its value in <i>hsh</i> and its value in <i>other_hash</i>.
  1699. *
  1700. *     h1 = { "a" => 100, "b" => 200 }
  1701. *     h2 = { "b" => 254, "c" => 300 }
  1702. *     h1.merge(h2)   #=> {"a"=>100, "b"=>254, "c"=>300}
  1703. *     h1.merge(h2){|key, oldval, newval| newval - oldval}
  1704. *                    #=> {"a"=>100, "b"=>54,  "c"=>300}
  1705. *     h1             #=> {"a"=>100, "b"=>200}
  1706. *
  1707. */

  1708. static VALUE
  1709. rb_hash_merge(VALUE hash1, VALUE hash2)
  1710. {
  1711.   return rb_hash_update(rb_obj_dup(hash1), hash2);
  1712. }

  1713. static int
  1714. assoc_i(VALUE key, VALUE val, VALUE arg)
  1715. {
  1716.   VALUE *args = (VALUE *)arg;

  1717.   if (key == Qundef) return ST_CONTINUE;
  1718.   if (RTEST(rb_equal(args[0], key)))
  1719.   {
  1720.     args[1] = rb_assoc_new(key, val);
  1721.     return ST_STOP;
  1722.   }
  1723.   return ST_CONTINUE;
  1724. }

  1725. /*
  1726. *  call-seq:
  1727. *     hash.assoc(obj)   ->  an_array  or  nil
  1728. *
  1729. *  Searches through the hash comparing _obj_ with the key using <code>==</code>.
  1730. *  Returns the key-value pair (two elements array) or +nil+
  1731. *  if no match is found.  See <code>Array#assoc</code>.
  1732. *
  1733. *     h = {"colors"  => ["red", "blue", "green"],
  1734. *          "letters" => ["a", "b", "c" ]}
  1735. *     h.assoc("letters")  #=> ["letters", ["a", "b", "c"]]
  1736. *     h.assoc("foo")      #=> nil
  1737. */

  1738. VALUE
  1739. rb_hash_assoc(VALUE hash, VALUE obj)
  1740. {
  1741.   VALUE args[2];

  1742.   args[0] = obj;
  1743.   args[1] = Qnil;
  1744.   rb_hash_foreach(hash, assoc_i, (VALUE)args);
  1745.   return args[1];
  1746. }

  1747. static int
  1748. rassoc_i(VALUE key, VALUE val, VALUE arg)
  1749. {
  1750.   VALUE *args = (VALUE *)arg;

  1751.   if (key == Qundef) return ST_CONTINUE;
  1752.   if (RTEST(rb_equal(args[0], val)))
  1753.   {
  1754.     args[1] = rb_assoc_new(key, val);
  1755.     return ST_STOP;
  1756.   }
  1757.   return ST_CONTINUE;
  1758. }

  1759. /*
  1760. *  call-seq:
  1761. *     hash.rassoc(obj) -> an_array or nil
  1762. *
  1763. *  Searches through the hash comparing _obj_ with the value using <code>==</code>.
  1764. *  Returns the first key-value pair (two-element array) that matches. See
  1765. *  also <code>Array#rassoc</code>.
  1766. *
  1767. *     a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
  1768. *     a.rassoc("two")    #=> [2, "two"]
  1769. *     a.rassoc("four")   #=> nil
  1770. */

  1771. VALUE
  1772. rb_hash_rassoc(VALUE hash, VALUE obj)
  1773. {
  1774.   VALUE args[2];

  1775.   args[0] = obj;
  1776.   args[1] = Qnil;
  1777.   rb_hash_foreach(hash, rassoc_i, (VALUE)args);
  1778.   return args[1];
  1779. }

  1780. /*
  1781. *  call-seq:
  1782. *     hash.flatten -> an_array
  1783. *     hash.flatten(level) -> an_array
  1784. *
  1785. *  Returns a new array that is a one-dimensional flattening of this
  1786. *  hash. That is, for every key or value that is an array, extract
  1787. *  its elements into the new array.  Unlike Array#flatten, this
  1788. *  method does not flatten recursively by default.  The optional
  1789. *  <i>level</i> argument determines the level of recursion to flatten.
  1790. *
  1791. *     a =  {1=> "one", 2 => [2,"two"], 3 => "three"}
  1792. *     a.flatten    # => [1, "one", 2, [2, "two"], 3, "three"]
  1793. *     a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
  1794. */

  1795. static VALUE
  1796. rb_hash_flatten(int argc, VALUE *argv, VALUE hash)
  1797. {
  1798.   VALUE ary, tmp;

  1799.   ary = rb_hash_to_a(hash);
  1800.   if (argc == 0)
  1801.   {
  1802.     argc = 1;
  1803.     tmp = INT2FIX(1);
  1804.     argv = &tmp;
  1805.   }
  1806.   rb_funcall2(ary, rb_intern("flatten!"), argc, argv);
  1807.   return ary;
  1808. }

  1809. /*
  1810. *  call-seq:
  1811. *     hsh.compare_by_identity -> hsh
  1812. *
  1813. *  Makes <i>hsh</i> compare its keys by their identity, i.e. it
  1814. *  will consider exact same objects as same keys.
  1815. *
  1816. *     h1 = { "a" => 100, "b" => 200, :c => "c" }
  1817. *     h1["a"]        #=> 100
  1818. *     h1.compare_by_identity
  1819. *     h1.compare_by_identity? #=> true
  1820. *     h1["a"]        #=> nil  # different objects.
  1821. *     h1[:c]         #=> "c"  # same symbols are all same.
  1822. *
  1823. */

  1824. static VALUE
  1825. rb_hash_compare_by_id(VALUE hash)
  1826. {
  1827.   rb_hash_modify(hash);
  1828.   RHASH(hash)->ntbl->type = &identhash;
  1829.   rb_hash_rehash(hash);
  1830.   return hash;
  1831. }

  1832. /*
  1833. *  call-seq:
  1834. *     hsh.compare_by_identity? -> true or false
  1835. *
  1836. *  Returns <code>true</code> if <i>hsh</i> will compare its keys by
  1837. *  their identity.  Also see <code>Hash#compare_by_identity</code>.
  1838. *
  1839. */

  1840. static VALUE
  1841. rb_hash_compare_by_id_p(VALUE hash)
  1842. {
  1843.   if (!RHASH(hash)->ntbl)
  1844.     return Qfalse;
  1845.   if (RHASH(hash)->ntbl->type == &identhash)
  1846.   {
  1847.     return Qtrue;
  1848.   }
  1849.   return Qfalse;
  1850. }

  1851. static int path_tainted = -1;

  1852. static char **origenviron;
  1853. #ifdef _WIN32
  1854. #define GET_ENVIRON(e) ((e) = rb_w32_get_environ())
  1855. #define FREE_ENVIRON(e) rb_w32_free_environ(e)
  1856. static char **my_environ;
  1857. #undef environ
  1858. #define environ my_environ
  1859. #elif defined(__APPLE__)
  1860. #undef environ
  1861. #define environ (*_NSGetEnviron())
  1862. #define GET_ENVIRON(e) (e)
  1863. #define FREE_ENVIRON(e)
  1864. #else
  1865. extern char **environ;
  1866. #define GET_ENVIRON(e) (e)
  1867. #define FREE_ENVIRON(e)
  1868. #endif
  1869. #ifdef ENV_IGNORECASE
  1870. #define ENVMATCH(s1, s2) (STRCASECMP((s1), (s2)) == 0)
  1871. #define ENVNMATCH(s1, s2, n) (STRNCASECMP((s1), (s2), (n)) == 0)
  1872. #else
  1873. #define ENVMATCH(n1, n2) (strcmp((n1), (n2)) == 0)
  1874. #define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
  1875. #endif

  1876. static VALUE
  1877. env_str_new(const char *ptr, long len)
  1878. {
  1879.   VALUE str = rb_locale_str_new(ptr, len);

  1880.   rb_obj_freeze(str);
  1881.   return str;
  1882. }

  1883. static VALUE
  1884. env_str_new2(const char *ptr)
  1885. {
  1886.   if (!ptr) return Qnil;
  1887.   return env_str_new(ptr, strlen(ptr));
  1888. }

  1889. static VALUE
  1890. env_delete(VALUE obj, VALUE name)
  1891. {
  1892.   char *nam, *val;

  1893.   rb_secure(4);
  1894.   SafeStringValue(name);
  1895.   nam = RSTRING_PTR(name);
  1896.   if (memchr(nam, '\0', RSTRING_LEN(name)))
  1897.   {
  1898.     rb_raise(rb_eArgError, "bad environment variable name");
  1899.   }
  1900.   val = getenv(nam);
  1901.   if (val)
  1902.   {
  1903.     VALUE value = env_str_new2(val);

  1904.     ruby_setenv(nam, 0);
  1905.     if (ENVMATCH(nam, PATH_ENV))
  1906.     {
  1907.       path_tainted = 0;
  1908.     }
  1909.     return value;
  1910.   }
  1911.   return Qnil;
  1912. }

  1913. /*
  1914. * call-seq:
  1915. *   ENV.delete(name)            -> value
  1916. *   ENV.delete(name) { |name| } -> value
  1917. *
  1918. * Deletes the environment variable with +name+ and returns the value of the
  1919. * variable.  If a block is given it will be called when the named environment
  1920. * does not exist.
  1921. */
  1922. static VALUE
  1923. env_delete_m(VALUE obj, VALUE name)
  1924. {
  1925.   VALUE val;

  1926.   val = env_delete(obj, name);
  1927.   if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
  1928.   return val;
  1929. }

  1930. static int env_path_tainted(const char *);

  1931. /*
  1932. * call-seq:
  1933. *   ENV[name] -> value
  1934. *
  1935. * Retrieves the +value+ for environment variable +name+ as a String.  Returns
  1936. * +nil+ if the named variable does not exist.
  1937. */
  1938. static VALUE
  1939. rb_f_getenv(VALUE obj, VALUE name)
  1940. {
  1941.   char *nam, *env;

  1942.   rb_secure(4);
  1943.   SafeStringValue(name);
  1944.   nam = RSTRING_PTR(name);
  1945.   if (memchr(nam, '\0', RSTRING_LEN(name)))
  1946.   {
  1947.     rb_raise(rb_eArgError, "bad environment variable name");
  1948.   }
  1949.   env = getenv(nam);
  1950.   if (env)
  1951.   {
  1952.     if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env))
  1953.     {
  1954.       VALUE str = rb_filesystem_str_new_cstr(env);

  1955.       rb_obj_freeze(str);
  1956.       return str;
  1957.     }
  1958.     return env_str_new2(env);
  1959.   }
  1960.   return Qnil;
  1961. }

  1962. /*
  1963. * :yield: missing_name
  1964. * call-seq:
  1965. *   ENV.fetch(name)                        -> value
  1966. *   ENV.fetch(name, default)               -> value
  1967. *   ENV.fetch(name) { |missing_name| ... } -> value
  1968. *
  1969. * Retrieves the environment variable +name+.
  1970. *
  1971. * If the given name does not exist and neither +default+ nor a block a
  1972. * provided an IndexError is raised.  If a block is given it is called with
  1973. * the missing name to provide a value.  If a default value is given it will
  1974. * be returned when no block is given.
  1975. */
  1976. static VALUE
  1977. env_fetch(int argc, VALUE *argv)
  1978. {
  1979.   VALUE key, if_none;
  1980.   long block_given;
  1981.   char *nam, *env;

  1982.   rb_secure(4);
  1983.   rb_scan_args(argc, argv, "11", &key, &if_none);
  1984.   block_given = rb_block_given_p();
  1985.   if (block_given && argc == 2)
  1986.   {
  1987.     rb_warn("block supersedes default value argument");
  1988.   }
  1989.   SafeStringValue(key);
  1990.   nam = RSTRING_PTR(key);
  1991.   if (memchr(nam, '\0', RSTRING_LEN(key)))
  1992.   {
  1993.     rb_raise(rb_eArgError, "bad environment variable name");
  1994.   }
  1995.   env = getenv(nam);
  1996.   if (!env)
  1997.   {
  1998.     if (block_given) return rb_yield(key);
  1999.     if (argc == 1)
  2000.     {
  2001.       rb_raise(rb_eKeyError, "key not found");
  2002.     }
  2003.     return if_none;
  2004.   }
  2005.   if (ENVMATCH(nam, PATH_ENV) && !env_path_tainted(env))
  2006.     return rb_filesystem_str_new_cstr(env);
  2007.   return env_str_new2(env);
  2008. }

  2009. static void
  2010. path_tainted_p(const char *path)
  2011. {
  2012.   path_tainted = rb_path_check(path) ? 0 : 1;
  2013. }

  2014. static int
  2015. env_path_tainted(const char *path)
  2016. {
  2017.   if (path_tainted < 0)
  2018.   {
  2019.     path_tainted_p(path);
  2020.   }
  2021.   return path_tainted;
  2022. }

  2023. int
  2024. rb_env_path_tainted(void)
  2025. {
  2026.   if (path_tainted < 0)
  2027.   {
  2028.     path_tainted_p(getenv(PATH_ENV));
  2029.   }
  2030.   return path_tainted;
  2031. }

  2032. #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
  2033. #elif defined __sun__
  2034. static int
  2035. in_origenv(const char *str)
  2036. {
  2037.   char **env;
  2038.   for (env = origenviron; *env; ++env)
  2039.   {
  2040.     if (*env == str) return 1;
  2041.   }
  2042.   return 0;
  2043. }
  2044. #else
  2045. static int
  2046. envix(const char *nam)
  2047. {
  2048.   register int i, len = strlen(nam);
  2049.   char **env;

  2050.   env = GET_ENVIRON(environ);
  2051.   for (i = 0; env[i]; i++)
  2052.   {
  2053.     if (ENVNMATCH(env[i], nam, len) && env[i][len] == '=')
  2054.       break;                        /* memcmp must come first to avoid */
  2055.   }                                        /* potential SEGV's */
  2056.   FREE_ENVIRON(environ);
  2057.   return i;
  2058. }
  2059. #endif

  2060. #if defined(_WIN32)
  2061. static size_t
  2062. getenvsize(const char* p)
  2063. {
  2064.   const char* porg = p;
  2065.   while (*p++) p += strlen(p) + 1;
  2066.   return p - porg + 1;
  2067. }
  2068. static size_t
  2069. getenvblocksize()
  2070. {
  2071.   return (rb_w32_osver() >= 5) ? 32767 : 5120;
  2072. }
  2073. #endif

  2074. void
  2075. ruby_setenv(const char *name, const char *value)
  2076. {
  2077. #if defined(_WIN32)
  2078.   VALUE buf;
  2079.   int failed = 0;
  2080.   if (strchr(name, '='))
  2081.   {
  2082. fail:
  2083.     errno = EINVAL;
  2084.     rb_sys_fail("ruby_setenv");
  2085.   }
  2086.   if (value)
  2087.   {
  2088.     const char* p = GetEnvironmentStringsA();
  2089.     if (!p) goto fail; /* never happen */
  2090.     if (strlen(name) + 2 + strlen(value) + getenvsize(p) >= getenvblocksize())
  2091.     {
  2092.       goto fail;  /* 2 for '=' & '\0' */
  2093.     }
  2094.     buf = rb_sprintf("%s=%s", name, value);
  2095.   }
  2096.   else
  2097.   {
  2098.     buf = rb_sprintf("%s=", name);
  2099.   }
  2100.   failed = putenv(RSTRING_PTR(buf));
  2101.   /* even if putenv() failed, clean up and try to delete the
  2102.    * variable from the system area. */
  2103.   rb_str_resize(buf, 0);
  2104.   if (!value || !*value)
  2105.   {
  2106.     /* putenv() doesn't handle empty value */
  2107.     if (!SetEnvironmentVariable(name, value) &&
  2108.         GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail;
  2109.   }
  2110.   if (failed) goto fail;
  2111. #elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
  2112. #undef setenv
  2113. #undef unsetenv
  2114.   if (value)
  2115.   {
  2116.     if (setenv(name, value, 1))
  2117.       rb_sys_fail("setenv");
  2118.   }
  2119.   else
  2120.   {
  2121. #ifdef VOID_UNSETENV
  2122.     unsetenv(name);
  2123. #else
  2124.     if (unsetenv(name))
  2125.       rb_sys_fail("unsetenv");
  2126. #endif
  2127.   }
  2128. #elif defined __sun__
  2129.   size_t len;
  2130.   char **env_ptr, *str;
  2131.   if (strchr(name, '='))
  2132.   {
  2133.     errno = EINVAL;
  2134.     rb_sys_fail("ruby_setenv");
  2135.   }
  2136.   len = strlen(name);
  2137.   for (env_ptr = GET_ENVIRON(environ); (str = *env_ptr) != 0; ++env_ptr)
  2138.   {
  2139.     if (!strncmp(str, name, len) && str[len] == '=')
  2140.     {
  2141.       if (!in_origenv(str)) free(str);
  2142.       while ((env_ptr[0] = env_ptr[1]) != 0) env_ptr++;
  2143.       break;
  2144.     }
  2145.   }
  2146.   if (value)
  2147.   {
  2148.     str = malloc(len += strlen(value) + 2);
  2149.     snprintf(str, len, "%s=%s", name, value);
  2150.     if (putenv(str))
  2151.       rb_sys_fail("putenv");
  2152.   }
  2153. #else  /* WIN32 */
  2154.   size_t len;
  2155.   int i;
  2156.   if (strchr(name, '='))
  2157.   {
  2158.     errno = EINVAL;
  2159.     rb_sys_fail("ruby_setenv");
  2160.   }
  2161.   i = envix(name);                      /* where does it go? */

  2162.   if (environ == origenviron)          /* need we copy environment? */
  2163.   {
  2164.     int j;
  2165.     int max;
  2166.     char **tmpenv;

  2167.     for (max = i; environ[max]; max++) ;
  2168.     tmpenv = ALLOC_N(char*, max + 2);
  2169.     for (j = 0; j < max; j++)                /* copy environment */
  2170.       tmpenv[j] = ruby_strdup(environ[j]);
  2171.     tmpenv[max] = 0;
  2172.     environ = tmpenv;                /* tell exec where it is now */
  2173.   }
  2174.   if (environ[i])
  2175.   {
  2176.     char **envp = origenviron;
  2177.     while (*envp && *envp != environ[i]) envp++;
  2178.     if (!*envp)
  2179.       xfree(environ[i]);
  2180.     if (!value)
  2181.     {
  2182.       while (environ[i])
  2183.       {
  2184.         environ[i] = environ[i+1];
  2185.         i++;
  2186.       }
  2187.       return;
  2188.     }
  2189.   }
  2190.   else                          /* does not exist yet */
  2191.   {
  2192.     if (!value) return;
  2193.     REALLOC_N(environ, char*, i + 2);        /* just expand it a bit */
  2194.     environ[i+1] = 0;        /* make sure it's null terminated */
  2195.   }
  2196.   len = strlen(name) + strlen(value) + 2;
  2197.   environ[i] = ALLOC_N(char, len);
  2198.   snprintf(environ[i], len, "%s=%s", name, value); /* all that work just for this */
  2199. #endif /* WIN32 */
  2200. }

  2201. void
  2202. ruby_unsetenv(const char *name)
  2203. {
  2204.   ruby_setenv(name, 0);
  2205. }

  2206. /*
  2207. * call-seq:
  2208. *   ENV[name] = value
  2209. *   ENV.store(name, value) -> value
  2210. *
  2211. * Sets the environment variable +name+ to +value+.  If the value given is
  2212. * +nil+ the environment variable is deleted.
  2213. *
  2214. */
  2215. static VALUE
  2216. env_aset(VALUE obj, VALUE nm, VALUE val)
  2217. {
  2218.   char *name, *value;

  2219.   if (rb_safe_level() >= 4)
  2220.   {
  2221.     rb_raise(rb_eSecurityError, "can't change environment variable");
  2222.   }

  2223.   if (NIL_P(val))
  2224.   {
  2225.     env_delete(obj, nm);
  2226.     return Qnil;
  2227.   }
  2228.   StringValue(nm);
  2229.   StringValue(val);
  2230.   name = RSTRING_PTR(nm);
  2231.   value = RSTRING_PTR(val);
  2232.   if (memchr(name, '\0', RSTRING_LEN(nm)))
  2233.     rb_raise(rb_eArgError, "bad environment variable name");
  2234.   if (memchr(value, '\0', RSTRING_LEN(val)))
  2235.     rb_raise(rb_eArgError, "bad environment variable value");

  2236.   ruby_setenv(name, value);
  2237.   if (ENVMATCH(name, PATH_ENV))
  2238.   {
  2239.     if (OBJ_TAINTED(val))
  2240.     {
  2241.       /* already tainted, no check */
  2242.       path_tainted = 1;
  2243.       return val;
  2244.     }
  2245.     else
  2246.     {
  2247.       path_tainted_p(value);
  2248.     }
  2249.   }
  2250.   return val;
  2251. }

  2252. /*
  2253. * call-seq:
  2254. *   ENV.keys -> Array
  2255. *
  2256. * Returns every environment variable name in an Array
  2257. */
  2258. static VALUE
  2259. env_keys(void)
  2260. {
  2261.   char **env;
  2262.   VALUE ary;

  2263.   rb_secure(4);
  2264.   ary = rb_ary_new();
  2265.   env = GET_ENVIRON(environ);
  2266.   while (*env)
  2267.   {
  2268.     char *s = strchr(*env, '=');
  2269.     if (s)
  2270.     {
  2271.       rb_ary_push(ary, env_str_new(*env, s - *env));
  2272.     }
  2273.     env++;
  2274.   }
  2275.   FREE_ENVIRON(environ);
  2276.   return ary;
  2277. }

  2278. /*
  2279. * call-seq:
  2280. *   ENV.each_key { |name| } -> Hash
  2281. *   ENV.each_key            -> Enumerator
  2282. *
  2283. * Yields each environment variable name.
  2284. *
  2285. * An Enumerator is returned if no block is given.
  2286. */
  2287. static VALUE
  2288. env_each_key(VALUE ehash)
  2289. {
  2290.   VALUE keys;
  2291.   long i;

  2292.   RETURN_ENUMERATOR(ehash, 0, 0);
  2293.   keys = env_keys();        /* rb_secure(4); */
  2294.   for (i = 0; i < RARRAY_LEN(keys); i++)
  2295.   {
  2296.     rb_yield(RARRAY_PTR(keys)[i]);
  2297.   }
  2298.   return ehash;
  2299. }

  2300. /*
  2301. * call-seq:
  2302. *   ENV.values -> Array
  2303. *
  2304. * Returns every environment variable value as an Array
  2305. */
  2306. static VALUE
  2307. env_values(void)
  2308. {
  2309.   VALUE ary;
  2310.   char **env;

  2311.   rb_secure(4);
  2312.   ary = rb_ary_new();
  2313.   env = GET_ENVIRON(environ);
  2314.   while (*env)
  2315.   {
  2316.     char *s = strchr(*env, '=');
  2317.     if (s)
  2318.     {
  2319.       rb_ary_push(ary, env_str_new2(s + 1));
  2320.     }
  2321.     env++;
  2322.   }
  2323.   FREE_ENVIRON(environ);
  2324.   return ary;
  2325. }

  2326. /*
  2327. * call-seq:
  2328. *   ENV.each_value { |value| } -> Hash
  2329. *   ENV.each_value             -> Enumerator
  2330. *
  2331. * Yields each environment variable +value+.
  2332. *
  2333. * An Enumerator is returned if no block was given.
  2334. */
  2335. static VALUE
  2336. env_each_value(VALUE ehash)
  2337. {
  2338.   VALUE values;
  2339.   long i;

  2340.   RETURN_ENUMERATOR(ehash, 0, 0);
  2341.   values = env_values();        /* rb_secure(4); */
  2342.   for (i = 0; i < RARRAY_LEN(values); i++)
  2343.   {
  2344.     rb_yield(RARRAY_PTR(values)[i]);
  2345.   }
  2346.   return ehash;
  2347. }

  2348. /*
  2349. * call-seq:
  2350. *   ENV.each      { |name, value| } -> Hash
  2351. *   ENV.each                        -> Enumerator
  2352. *   ENV.each_pair { |name, value| } -> Hash
  2353. *   ENV.each_pair                   -> Enumerator
  2354. *
  2355. * Yields each environment variable +name+ and +value+.
  2356. *
  2357. * If no block is given an Enumerator is returned.
  2358. */
  2359. static VALUE
  2360. env_each_pair(VALUE ehash)
  2361. {
  2362.   char **env;
  2363.   VALUE ary;
  2364.   long i;

  2365.   RETURN_ENUMERATOR(ehash, 0, 0);

  2366.   rb_secure(4);
  2367.   ary = rb_ary_new();
  2368.   env = GET_ENVIRON(environ);
  2369.   while (*env)
  2370.   {
  2371.     char *s = strchr(*env, '=');
  2372.     if (s)
  2373.     {
  2374.       rb_ary_push(ary, env_str_new(*env, s - *env));
  2375.       rb_ary_push(ary, env_str_new2(s + 1));
  2376.     }
  2377.     env++;
  2378.   }
  2379.   FREE_ENVIRON(environ);

  2380.   for (i = 0; i < RARRAY_LEN(ary); i += 2)
  2381.   {
  2382.     rb_yield(rb_assoc_new(RARRAY_PTR(ary)[i], RARRAY_PTR(ary)[i+1]));
  2383.   }
  2384.   return ehash;
  2385. }

  2386. /*
  2387. * call-seq:
  2388. *   ENV.reject! { |name, value| } -> Hash or nil
  2389. *   ENV.reject!                   -> Enumerator
  2390. *
  2391. * Equivalent to ENV#delete_if but returns +nil+ if no changes were made.
  2392. *
  2393. * Returns an Enumerator if no block was given.
  2394. */
  2395. static VALUE
  2396. env_reject_bang(VALUE ehash)
  2397. {
  2398.   volatile VALUE keys;
  2399.   long i;
  2400.   int del = 0;

  2401.   RETURN_ENUMERATOR(ehash, 0, 0);
  2402.   keys = env_keys();        /* rb_secure(4); */
  2403.   for (i = 0; i < RARRAY_LEN(keys); i++)
  2404.   {
  2405.     VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
  2406.     if (!NIL_P(val))
  2407.     {
  2408.       if (RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val)))
  2409.       {
  2410.         FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT);
  2411.         env_delete(Qnil, RARRAY_PTR(keys)[i]);
  2412.         del++;
  2413.       }
  2414.     }
  2415.   }
  2416.   if (del == 0) return Qnil;
  2417.   return envtbl;
  2418. }

  2419. /*
  2420. * call-seq:
  2421. *   ENV.delete_if { |name, value| } -> Hash
  2422. *   ENV.delete_if                   -> Enumerator
  2423. *
  2424. * Deletes every environment variable for which the block evaluates to +true+.
  2425. *
  2426. * If no block is given an enumerator is returned instead.
  2427. */
  2428. static VALUE
  2429. env_delete_if(VALUE ehash)
  2430. {
  2431.   RETURN_ENUMERATOR(ehash, 0, 0);
  2432.   env_reject_bang(ehash);
  2433.   return envtbl;
  2434. }

  2435. /*
  2436. * call-seq:
  2437. *   ENV.values_at(name, ...) -> Array
  2438. *
  2439. * Returns an array containing the environment variable values associated with
  2440. * the given names.  See also ENV.select.
  2441. */
  2442. static VALUE
  2443. env_values_at(int argc, VALUE *argv)
  2444. {
  2445.   VALUE result;
  2446.   long i;

  2447.   rb_secure(4);
  2448.   result = rb_ary_new();
  2449.   for (i = 0; i < argc; i++)
  2450.   {
  2451.     rb_ary_push(result, rb_f_getenv(Qnil, argv[i]));
  2452.   }
  2453.   return result;
  2454. }

  2455. /*
  2456. * call-seq:
  2457. *   ENV.select { |name, value| } -> Hash
  2458. *   ENV.select                   -> Enumerator
  2459. *
  2460. * Returns a copy of the environment for entries where the block returns true.
  2461. *
  2462. * Returns an Enumerator if no block was given.
  2463. */
  2464. static VALUE
  2465. env_select(VALUE ehash)
  2466. {
  2467.   VALUE result;
  2468.   char **env;

  2469.   RETURN_ENUMERATOR(ehash, 0, 0);
  2470.   rb_secure(4);
  2471.   result = rb_hash_new();
  2472.   env = GET_ENVIRON(environ);
  2473.   while (*env)
  2474.   {
  2475.     char *s = strchr(*env, '=');
  2476.     if (s)
  2477.     {
  2478.       VALUE k = env_str_new(*env, s - *env);
  2479.       VALUE v = env_str_new2(s + 1);
  2480.       if (RTEST(rb_yield_values(2, k, v)))
  2481.       {
  2482.         rb_hash_aset(result, k, v);
  2483.       }
  2484.     }
  2485.     env++;
  2486.   }
  2487.   FREE_ENVIRON(environ);

  2488.   return result;
  2489. }

  2490. /*
  2491. * call-seq:
  2492. *   ENV.select! { |name, value| } -> ENV or nil
  2493. *   ENV.select!                   -> Enumerator
  2494. *
  2495. * Equivalent to ENV#keep_if but returns +nil+ if no changes were made.
  2496. */
  2497. static VALUE
  2498. env_select_bang(VALUE ehash)
  2499. {
  2500.   volatile VALUE keys;
  2501.   long i;
  2502.   int del = 0;

  2503.   RETURN_ENUMERATOR(ehash, 0, 0);
  2504.   keys = env_keys();        /* rb_secure(4); */
  2505.   for (i = 0; i < RARRAY_LEN(keys); i++)
  2506.   {
  2507.     VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
  2508.     if (!NIL_P(val))
  2509.     {
  2510.       if (!RTEST(rb_yield_values(2, RARRAY_PTR(keys)[i], val)))
  2511.       {
  2512.         FL_UNSET(RARRAY_PTR(keys)[i], FL_TAINT);
  2513.         env_delete(Qnil, RARRAY_PTR(keys)[i]);
  2514.         del++;
  2515.       }
  2516.     }
  2517.   }
  2518.   if (del == 0) return Qnil;
  2519.   return envtbl;
  2520. }

  2521. /*
  2522. * call-seq:
  2523. *   ENV.keep_if { |name, value| } -> Hash
  2524. *   ENV.keep_if                   -> Enumerator
  2525. *
  2526. * Deletes every environment variable where the block evaluates to +false+.
  2527. *
  2528. * Returns an enumerator if no block was given.
  2529. */
  2530. static VALUE
  2531. env_keep_if(VALUE ehash)
  2532. {
  2533.   RETURN_ENUMERATOR(ehash, 0, 0);
  2534.   env_select_bang(ehash);
  2535.   return envtbl;
  2536. }

  2537. /*
  2538. * call-seq:
  2539. *   ENV.clear
  2540. *
  2541. * Removes every environment variable.
  2542. */
  2543. VALUE
  2544. rb_env_clear(void)
  2545. {
  2546.   volatile VALUE keys;
  2547.   long i;

  2548.   keys = env_keys();        /* rb_secure(4); */
  2549.   for (i = 0; i < RARRAY_LEN(keys); i++)
  2550.   {
  2551.     VALUE val = rb_f_getenv(Qnil, RARRAY_PTR(keys)[i]);
  2552.     if (!NIL_P(val))
  2553.     {
  2554.       env_delete(Qnil, RARRAY_PTR(keys)[i]);
  2555.     }
  2556.   }
  2557.   return envtbl;
  2558. }

  2559. /*
  2560. * call-seq:
  2561. *   ENV.to_s -> "ENV"
  2562. *
  2563. * Returns "ENV"
  2564. */
  2565. static VALUE
  2566. env_to_s(void)
  2567. {
  2568.   return rb_usascii_str_new2("ENV");
  2569. }

  2570. /*
  2571. * call-seq:
  2572. *   ENV.inspect -> string
  2573. *
  2574. * Returns the contents of the environment as a String.
  2575. */
  2576. static VALUE
  2577. env_inspect(void)
  2578. {
  2579.   char **env;
  2580.   VALUE str, i;

  2581.   rb_secure(4);
  2582.   str = rb_str_buf_new2("{");
  2583.   env = GET_ENVIRON(environ);
  2584.   while (*env)
  2585.   {
  2586.     char *s = strchr(*env, '=');

  2587.     if (env != environ)
  2588.     {
  2589.       rb_str_buf_cat2(str, ", ");
  2590.     }
  2591.     if (s)
  2592.     {
  2593.       rb_str_buf_cat2(str, "\"");
  2594.       rb_str_buf_cat(str, *env, s - *env);
  2595.       rb_str_buf_cat2(str, "\"=>");
  2596.       i = rb_inspect(rb_str_new2(s + 1));
  2597.       rb_str_buf_append(str, i);
  2598.     }
  2599.     env++;
  2600.   }
  2601.   FREE_ENVIRON(environ);
  2602.   rb_str_buf_cat2(str, "}");
  2603.   OBJ_TAINT(str);

  2604.   return str;
  2605. }

  2606. /*
  2607. * call-seq:
  2608. *   ENV.to_a -> Array
  2609. *
  2610. * Converts the environment variables into an array of names and value arrays.
  2611. *
  2612. *   ENV.to_a # => [["TERM" => "xterm-color"], ["SHELL" => "/bin/bash"], ...]
  2613. *
  2614. */
  2615. static VALUE
  2616. env_to_a(void)
  2617. {
  2618.   char **env;
  2619.   VALUE ary;

  2620.   rb_secure(4);
  2621.   ary = rb_ary_new();
  2622.   env = GET_ENVIRON(environ);
  2623.   while (*env)
  2624.   {
  2625.     char *s = strchr(*env, '=');
  2626.     if (s)
  2627.     {
  2628.       rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s - *env),
  2629.                                     env_str_new2(s + 1)));
  2630.     }
  2631.     env++;
  2632.   }
  2633.   FREE_ENVIRON(environ);
  2634.   return ary;
  2635. }

  2636. /*
  2637. * call-seq:
  2638. *   ENV.rehash
  2639. *
  2640. * Re-hashing the environment variables does nothing.  It is provided for
  2641. * compatibility with Hash.
  2642. */
  2643. static VALUE
  2644. env_none(void)
  2645. {
  2646.   return Qnil;
  2647. }

  2648. /*
  2649. * call-seq:
  2650. *   ENV.length
  2651. *   ENV.size
  2652. *
  2653. * Returns the number of environment variables.
  2654. */
  2655. static VALUE
  2656. env_size(void)
  2657. {
  2658.   int i;
  2659.   char **env;

  2660.   rb_secure(4);
  2661.   env = GET_ENVIRON(environ);
  2662.   for (i = 0; env[i]; i++)
  2663.     ;
  2664.   FREE_ENVIRON(environ);
  2665.   return INT2FIX(i);
  2666. }

  2667. /*
  2668. * call-seq:
  2669. *   ENV.empty? -> true or false
  2670. *
  2671. * Returns true when there are no environment variables
  2672. */
  2673. static VALUE
  2674. env_empty_p(void)
  2675. {
  2676.   char **env;

  2677.   rb_secure(4);
  2678.   env = GET_ENVIRON(environ);
  2679.   if (env[0] == 0)
  2680.   {
  2681.     FREE_ENVIRON(environ);
  2682.     return Qtrue;
  2683.   }
  2684.   FREE_ENVIRON(environ);
  2685.   return Qfalse;
  2686. }

  2687. /*
  2688. * call-seq:
  2689. *   ENV.key?(name)     -> true or false
  2690. *   ENV.include?(name) -> true or false
  2691. *   ENV.has_key?(name) -> true or false
  2692. *   ENV.member?(name)  -> true or false
  2693. *
  2694. * Returns +true+ if there is an environment variable with the given +name+.
  2695. */
  2696. static VALUE
  2697. env_has_key(VALUE env, VALUE key)
  2698. {
  2699.   char *s;

  2700.   rb_secure(4);
  2701.   s = StringValuePtr(key);
  2702.   if (memchr(s, '\0', RSTRING_LEN(key)))
  2703.     rb_raise(rb_eArgError, "bad environment variable name");
  2704.   if (getenv(s)) return Qtrue;
  2705.   return Qfalse;
  2706. }

  2707. /*
  2708. * call-seq:
  2709. *   ENV.assoc(name) -> Array or nil
  2710. *
  2711. * Returns an Array of the name and value of the environment variable with
  2712. * +name+ or +nil+ if the name cannot be found.
  2713. */
  2714. static VALUE
  2715. env_assoc(VALUE env, VALUE key)
  2716. {
  2717.   char *s, *e;

  2718.   rb_secure(4);
  2719.   s = StringValuePtr(key);
  2720.   if (memchr(s, '\0', RSTRING_LEN(key)))
  2721.     rb_raise(rb_eArgError, "bad environment variable name");
  2722.   e = getenv(s);
  2723.   if (e) return rb_assoc_new(key, rb_tainted_str_new2(e));
  2724.   return Qnil;
  2725. }

  2726. /*
  2727. * call-seq:
  2728. *   ENV.value?(value) -> true or false
  2729. *   ENV.has_value?(value) -> true or false
  2730. *
  2731. * Returns +true+ if there is an environment variable with the given +value+.
  2732. */
  2733. static VALUE
  2734. env_has_value(VALUE dmy, VALUE obj)
  2735. {
  2736.   char **env;

  2737.   rb_secure(4);
  2738.   obj = rb_check_string_type(obj);
  2739.   if (NIL_P(obj)) return Qnil;
  2740.   env = GET_ENVIRON(environ);
  2741.   while (*env)
  2742.   {
  2743.     char *s = strchr(*env, '=');
  2744.     if (s++)
  2745.     {
  2746.       long len = strlen(s);
  2747.       if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0)
  2748.       {
  2749.         FREE_ENVIRON(environ);
  2750.         return Qtrue;
  2751.       }
  2752.     }
  2753.     env++;
  2754.   }
  2755.   FREE_ENVIRON(environ);
  2756.   return Qfalse;
  2757. }

  2758. /*
  2759. * call-seq:
  2760. *   ENV.rassoc(value)
  2761. *
  2762. * Returns an Array of the name and value of the environment variable with
  2763. * +value+ or +nil+ if the value cannot be found.
  2764. */
  2765. static VALUE
  2766. env_rassoc(VALUE dmy, VALUE obj)
  2767. {
  2768.   char **env;

  2769.   rb_secure(4);
  2770.   obj = rb_check_string_type(obj);
  2771.   if (NIL_P(obj)) return Qnil;
  2772.   env = GET_ENVIRON(environ);
  2773.   while (*env)
  2774.   {
  2775.     char *s = strchr(*env, '=');
  2776.     if (s++)
  2777.     {
  2778.       long len = strlen(s);
  2779.       if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0)
  2780.       {
  2781.         VALUE result = rb_assoc_new(rb_tainted_str_new(*env, s - *env - 1), obj);
  2782.         FREE_ENVIRON(environ);
  2783.         return result;
  2784.       }
  2785.     }
  2786.     env++;
  2787.   }
  2788.   FREE_ENVIRON(environ);
  2789.   return Qnil;
  2790. }

  2791. /*
  2792. * call-seq:
  2793. *   ENV.key(value) -> name
  2794. *
  2795. * Returns the name of the environment variable with +value+.  If the value is
  2796. * not found +nil+ is returned.
  2797. */
  2798. static VALUE
  2799. env_key(VALUE dmy, VALUE value)
  2800. {
  2801.   char **env;
  2802.   VALUE str;

  2803.   rb_secure(4);
  2804.   StringValue(value);
  2805.   env = GET_ENVIRON(environ);
  2806.   while (*env)
  2807.   {
  2808.     char *s = strchr(*env, '=');
  2809.     if (s++)
  2810.     {
  2811.       long len = strlen(s);
  2812.       if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0)
  2813.       {
  2814.         str = env_str_new(*env, s - *env - 1);
  2815.         FREE_ENVIRON(environ);
  2816.         return str;
  2817.       }
  2818.     }
  2819.     env++;
  2820.   }
  2821.   FREE_ENVIRON(environ);
  2822.   return Qnil;
  2823. }

  2824. /*
  2825. * call-seq:
  2826. *   ENV.index(value) -> key
  2827. *
  2828. * Deprecated method that is equivalent to ENV.key
  2829. */
  2830. static VALUE
  2831. env_index(VALUE dmy, VALUE value)
  2832. {
  2833.   rb_warn("ENV.index is deprecated; use ENV.key");
  2834.   return env_key(dmy, value);
  2835. }

  2836. /*
  2837. * call-seq:
  2838. *   ENV.to_hash -> Hash
  2839. *
  2840. * Creates a hash with a copy of the environment variables.
  2841. *
  2842. */
  2843. static VALUE
  2844. env_to_hash(void)
  2845. {
  2846.   char **env;
  2847.   VALUE hash;

  2848.   rb_secure(4);
  2849.   hash = rb_hash_new();
  2850.   env = GET_ENVIRON(environ);
  2851.   while (*env)
  2852.   {
  2853.     char *s = strchr(*env, '=');
  2854.     if (s)
  2855.     {
  2856.       rb_hash_aset(hash, env_str_new(*env, s - *env),
  2857.                    env_str_new2(s + 1));
  2858.     }
  2859.     env++;
  2860.   }
  2861.   FREE_ENVIRON(environ);
  2862.   return hash;
  2863. }

  2864. /*
  2865. * call-seq:
  2866. *   ENV.reject { |name, value| } -> Hash
  2867. *   ENV.reject                   -> Enumerator
  2868. *
  2869. * Same as ENV#delete_if, but works on (and returns) a copy of the
  2870. * environment.
  2871. */
  2872. static VALUE
  2873. env_reject(void)
  2874. {
  2875.   return rb_hash_delete_if(env_to_hash());
  2876. }

  2877. /*
  2878. * call-seq:
  2879. *   ENV.shift -> Array or nil
  2880. *
  2881. * Removes an environment variable name-value pair from ENV and returns it as
  2882. * an Array.  Returns +nil+ if when the environment is empty.
  2883. */
  2884. static VALUE
  2885. env_shift(void)
  2886. {
  2887.   char **env;

  2888.   rb_secure(4);
  2889.   env = GET_ENVIRON(environ);
  2890.   if (*env)
  2891.   {
  2892.     char *s = strchr(*env, '=');
  2893.     if (s)
  2894.     {
  2895.       VALUE key = env_str_new(*env, s - *env);
  2896.       VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
  2897.       env_delete(Qnil, key);
  2898.       return rb_assoc_new(key, val);
  2899.     }
  2900.   }
  2901.   FREE_ENVIRON(environ);
  2902.   return Qnil;
  2903. }

  2904. /*
  2905. * call-seq:
  2906. *   ENV.invert -> Hash
  2907. *
  2908. * Returns a new hash created by using environment variable names as values
  2909. * and values as names.
  2910. */
  2911. static VALUE
  2912. env_invert(void)
  2913. {
  2914.   return rb_hash_invert(env_to_hash());
  2915. }

  2916. static int
  2917. env_replace_i(VALUE key, VALUE val, VALUE keys)
  2918. {
  2919.   if (key != Qundef)
  2920.   {
  2921.     env_aset(Qnil, key, val);
  2922.     if (rb_ary_includes(keys, key))
  2923.     {
  2924.       rb_ary_delete(keys, key);
  2925.     }
  2926.   }
  2927.   return ST_CONTINUE;
  2928. }

  2929. /*
  2930. * call-seq:
  2931. *   ENV.replace(hash) -> env
  2932. *
  2933. * Replaces the contents of the environment variables with the contents of
  2934. * +hash+.
  2935. */
  2936. static VALUE
  2937. env_replace(VALUE env, VALUE hash)
  2938. {
  2939.   volatile VALUE keys;
  2940.   long i;

  2941.   keys = env_keys();        /* rb_secure(4); */
  2942.   if (env == hash) return env;
  2943.   hash = to_hash(hash);
  2944.   rb_hash_foreach(hash, env_replace_i, keys);

  2945.   for (i = 0; i < RARRAY_LEN(keys); i++)
  2946.   {
  2947.     env_delete(env, RARRAY_PTR(keys)[i]);
  2948.   }
  2949.   return env;
  2950. }

  2951. static int
  2952. env_update_i(VALUE key, VALUE val)
  2953. {
  2954.   if (key != Qundef)
  2955.   {
  2956.     if (rb_block_given_p())
  2957.     {
  2958.       val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val);
  2959.     }
  2960.     env_aset(Qnil, key, val);
  2961.   }
  2962.   return ST_CONTINUE;
  2963. }

  2964. /*
  2965. * call-seq:
  2966. *   ENV.update(hash)                                  -> Hash
  2967. *   ENV.update(hash) { |name, old_value, new_value| } -> Hash
  2968. *
  2969. * Adds the contents of +hash+ to the environment variables.  If no block is
  2970. * specified entries with duplicate keys are overwritten, otherwise the value
  2971. * of each duplicate name is determined by calling the block with the key, its
  2972. * value from the environment and its value from the hash.
  2973. */
  2974. static VALUE
  2975. env_update(VALUE env, VALUE hash)
  2976. {
  2977.   rb_secure(4);
  2978.   if (env == hash) return env;
  2979.   hash = to_hash(hash);
  2980.   rb_hash_foreach(hash, env_update_i, 0);
  2981.   return env;
  2982. }

  2983. /*
  2984. *  A <code>Hash</code> is a collection of key-value pairs. It is
  2985. *  similar to an <code>Array</code>, except that indexing is done via
  2986. *  arbitrary keys of any object type, not an integer index. Hashes enumerate
  2987. *  their values in the order that the corresponding keys were inserted.
  2988. *
  2989. *  Hashes have a <em>default value</em> that is returned when accessing
  2990. *  keys that do not exist in the hash. By default, that value is
  2991. *  <code>nil</code>.
  2992. *
  2993. */

  2994. void
  2995. Init_Hash(void)
  2996. {
  2997. #undef rb_intern
  2998. #define rb_intern(str) rb_intern_const(str)

  2999.   id_hash = rb_intern("hash");
  3000.   id_yield = rb_intern("yield");
  3001.   id_default = rb_intern("default");

  3002.   rb_cHash = rb_define_class("Hash", rb_cObject);

  3003.   rb_include_module(rb_cHash, rb_mEnumerable);

  3004.   rb_define_alloc_func(rb_cHash, hash_alloc);
  3005.   rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
  3006.   rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
  3007.   rb_define_method(rb_cHash, "initialize", rb_hash_initialize, -1);
  3008.   rb_define_method(rb_cHash, "initialize_copy", rb_hash_replace, 1);
  3009.   rb_define_method(rb_cHash, "rehash", rb_hash_rehash, 0);

  3010.   rb_define_method(rb_cHash, "to_hash", rb_hash_to_hash, 0);
  3011.   rb_define_method(rb_cHash, "to_a", rb_hash_to_a, 0);
  3012.   rb_define_method(rb_cHash, "inspect", rb_hash_inspect, 0);
  3013.   rb_define_alias(rb_cHash, "to_s", "inspect");

  3014.   rb_define_method(rb_cHash, "==", rb_hash_equal, 1);
  3015.   rb_define_method(rb_cHash, "[]", rb_hash_aref, 1);
  3016.   rb_define_method(rb_cHash, "hash", rb_hash_hash, 0);
  3017.   rb_define_method(rb_cHash, "eql?", rb_hash_eql, 1);
  3018.   rb_define_method(rb_cHash, "fetch", rb_hash_fetch_m, -1);
  3019.   rb_define_method(rb_cHash, "[]=", rb_hash_aset, 2);
  3020.   rb_define_method(rb_cHash, "store", rb_hash_aset, 2);
  3021.   rb_define_method(rb_cHash, "default", rb_hash_default, -1);
  3022.   rb_define_method(rb_cHash, "default=", rb_hash_set_default, 1);
  3023.   rb_define_method(rb_cHash, "default_proc", rb_hash_default_proc, 0);
  3024.   rb_define_method(rb_cHash, "default_proc=", rb_hash_set_default_proc, 1);
  3025.   rb_define_method(rb_cHash, "key", rb_hash_key, 1);
  3026.   rb_define_method(rb_cHash, "index", rb_hash_index, 1);
  3027.   rb_define_method(rb_cHash, "size", rb_hash_size, 0);
  3028.   rb_define_method(rb_cHash, "length", rb_hash_size, 0);
  3029.   rb_define_method(rb_cHash, "empty?", rb_hash_empty_p, 0);

  3030.   rb_define_method(rb_cHash, "each_value", rb_hash_each_value, 0);
  3031.   rb_define_method(rb_cHash, "each_key", rb_hash_each_key, 0);
  3032.   rb_define_method(rb_cHash, "each_pair", rb_hash_each_pair, 0);
  3033.   rb_define_method(rb_cHash, "each", rb_hash_each_pair, 0);

  3034.   rb_define_method(rb_cHash, "keys", rb_hash_keys, 0);
  3035.   rb_define_method(rb_cHash, "values", rb_hash_values, 0);
  3036.   rb_define_method(rb_cHash, "values_at", rb_hash_values_at, -1);

  3037.   rb_define_method(rb_cHash, "shift", rb_hash_shift, 0);
  3038.   rb_define_method(rb_cHash, "delete", rb_hash_delete, 1);
  3039.   rb_define_method(rb_cHash, "delete_if", rb_hash_delete_if, 0);
  3040.   rb_define_method(rb_cHash, "keep_if", rb_hash_keep_if, 0);
  3041.   rb_define_method(rb_cHash, "select", rb_hash_select, 0);
  3042.   rb_define_method(rb_cHash, "select!", rb_hash_select_bang, 0);
  3043.   rb_define_method(rb_cHash, "reject", rb_hash_reject, 0);
  3044.   rb_define_method(rb_cHash, "reject!", rb_hash_reject_bang, 0);
  3045.   rb_define_method(rb_cHash, "clear", rb_hash_clear, 0);
  3046.   rb_define_method(rb_cHash, "invert", rb_hash_invert, 0);
  3047.   rb_define_method(rb_cHash, "update", rb_hash_update, 1);
  3048.   rb_define_method(rb_cHash, "replace", rb_hash_replace, 1);
  3049.   rb_define_method(rb_cHash, "merge!", rb_hash_update, 1);
  3050.   rb_define_method(rb_cHash, "merge", rb_hash_merge, 1);
  3051.   rb_define_method(rb_cHash, "assoc", rb_hash_assoc, 1);
  3052.   rb_define_method(rb_cHash, "rassoc", rb_hash_rassoc, 1);
  3053.   rb_define_method(rb_cHash, "flatten", rb_hash_flatten, -1);

  3054.   rb_define_method(rb_cHash, "include?", rb_hash_has_key, 1);
  3055.   rb_define_method(rb_cHash, "member?", rb_hash_has_key, 1);
  3056.   rb_define_method(rb_cHash, "has_key?", rb_hash_has_key, 1);
  3057.   rb_define_method(rb_cHash, "has_value?", rb_hash_has_value, 1);
  3058.   rb_define_method(rb_cHash, "key?", rb_hash_has_key, 1);
  3059.   rb_define_method(rb_cHash, "value?", rb_hash_has_value, 1);

  3060.   rb_define_method(rb_cHash, "compare_by_identity", rb_hash_compare_by_id, 0);
  3061.   rb_define_method(rb_cHash, "compare_by_identity?", rb_hash_compare_by_id_p, 0);

  3062.   /* Document-class: ENV
  3063.    *
  3064.    * ENV is a hash-like accessor for environment variables.
  3065.    */

  3066.   /*
  3067.    * Hack to get RDoc to regard ENV as a class:
  3068.    * envtbl = rb_define_class("ENV", rb_cObject);
  3069.    */
  3070.   origenviron = environ;
  3071.   envtbl = rb_obj_alloc(rb_cObject);
  3072.   rb_extend_object(envtbl, rb_mEnumerable);

  3073.   rb_define_singleton_method(envtbl, "[]", rb_f_getenv, 1);
  3074.   rb_define_singleton_method(envtbl, "fetch", env_fetch, -1);
  3075.   rb_define_singleton_method(envtbl, "[]=", env_aset, 2);
  3076.   rb_define_singleton_method(envtbl, "store", env_aset, 2);
  3077.   rb_define_singleton_method(envtbl, "each", env_each_pair, 0);
  3078.   rb_define_singleton_method(envtbl, "each_pair", env_each_pair, 0);
  3079.   rb_define_singleton_method(envtbl, "each_key", env_each_key, 0);
  3080.   rb_define_singleton_method(envtbl, "each_value", env_each_value, 0);
  3081.   rb_define_singleton_method(envtbl, "delete", env_delete_m, 1);
  3082.   rb_define_singleton_method(envtbl, "delete_if", env_delete_if, 0);
  3083.   rb_define_singleton_method(envtbl, "keep_if", env_keep_if, 0);
  3084.   rb_define_singleton_method(envtbl, "clear", rb_env_clear, 0);
  3085.   rb_define_singleton_method(envtbl, "reject", env_reject, 0);
  3086.   rb_define_singleton_method(envtbl, "reject!", env_reject_bang, 0);
  3087.   rb_define_singleton_method(envtbl, "select", env_select, 0);
  3088.   rb_define_singleton_method(envtbl, "select!", env_select_bang, 0);
  3089.   rb_define_singleton_method(envtbl, "shift", env_shift, 0);
  3090.   rb_define_singleton_method(envtbl, "invert", env_invert, 0);
  3091.   rb_define_singleton_method(envtbl, "replace", env_replace, 1);
  3092.   rb_define_singleton_method(envtbl, "update", env_update, 1);
  3093.   rb_define_singleton_method(envtbl, "inspect", env_inspect, 0);
  3094.   rb_define_singleton_method(envtbl, "rehash", env_none, 0);
  3095.   rb_define_singleton_method(envtbl, "to_a", env_to_a, 0);
  3096.   rb_define_singleton_method(envtbl, "to_s", env_to_s, 0);
  3097.   rb_define_singleton_method(envtbl, "key", env_key, 1);
  3098.   rb_define_singleton_method(envtbl, "index", env_index, 1);
  3099.   rb_define_singleton_method(envtbl, "size", env_size, 0);
  3100.   rb_define_singleton_method(envtbl, "length", env_size, 0);
  3101.   rb_define_singleton_method(envtbl, "empty?", env_empty_p, 0);
  3102.   rb_define_singleton_method(envtbl, "keys", env_keys, 0);
  3103.   rb_define_singleton_method(envtbl, "values", env_values, 0);
  3104.   rb_define_singleton_method(envtbl, "values_at", env_values_at, -1);
  3105.   rb_define_singleton_method(envtbl, "include?", env_has_key, 1);
  3106.   rb_define_singleton_method(envtbl, "member?", env_has_key, 1);
  3107.   rb_define_singleton_method(envtbl, "has_key?", env_has_key, 1);
  3108.   rb_define_singleton_method(envtbl, "has_value?", env_has_value, 1);
  3109.   rb_define_singleton_method(envtbl, "key?", env_has_key, 1);
  3110.   rb_define_singleton_method(envtbl, "value?", env_has_value, 1);
  3111.   rb_define_singleton_method(envtbl, "to_hash", env_to_hash, 0);
  3112.   rb_define_singleton_method(envtbl, "assoc", env_assoc, 1);
  3113.   rb_define_singleton_method(envtbl, "rassoc", env_rassoc, 1);

  3114.   /*
  3115.    * ENV is a Hash-like accessor for environment variables.
  3116.    *
  3117.    * See ENV (the class) for more details.
  3118.    */
  3119.   rb_define_global_const("ENV", envtbl);
  3120. }
复制代码

评分

参与人数 1星屑 +66 收起 理由
hcm + 66 感谢回答

查看全部评分

>>猛戳>>MetalSagaR游戏主页<<这里<<
欢迎提供您的意见
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
66
在线时间
91 小时
注册时间
2012-8-15
帖子
57
3
 楼主| 发表于 2012-11-10 18:42:49 | 只看该作者
有没有ruby版的?
觉得只要修改sort就行。
实在不行,用数组代替了

点评

ruby是C语言编写的,hash自然也是.....  发表于 2012-11-10 18:55
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2025-1-10 16:40

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表