[#26463] New Features for the Array Module — Daniel Cohen <danielc2017@...>
To Whom it May Concern:
[#26488] Add Standard Deviation Function to Math Module — Daniel Cohen <danielc2017@...>
This patch adds a Standard Deviation function to the Math Module. It takes
Hi,
OK,
Hi,
Matz,
Hi,
On Tue, Nov 3, 2009 at 16:56, Yusuke ENDOH <mame@tsg.ne.jp> wrote:
On Nov 3, 2009, at 8:28 PM, Cameron McBride wrote:
2009/11/4 Yusuke ENDOH <mame@tsg.ne.jp>:
[#26492] HashWithIndifferentAccess to core — Urabe Shyouhei <shyouhei@...>
Hello,
Hi,
On Tue, Nov 3, 2009 at 6:48 AM, Yukihiro Matsumoto <matz@ruby-lang.org> wro=
Just a thought: What about implementing this with an option on Hash:new,
Hi,
Hi,
2009/11/6 Yukihiro Matsumoto <matz@ruby-lang.org>:
Hi,
Hi,
I'm not sure that it really makes sense to add any of this to core.
On Sat, Nov 7, 2009 at 10:21 AM, Rick DeNatale <rick.denatale@gmail.com> wrote:
On Nov 7, 2009, at 1:57 PM, Jeremy Kemper wrote:
On Sat, Nov 7, 2009 at 3:14 PM, James Edward Gray II
Hi,
[#26497] [Bug #2326] 1.8.7 Segmentation fault — Johan Holmberg <redmine@...>
Bug #2326: 1.8.7 Segmentation fault
Issue #2326 has been updated by Hongli Lai.
[#26523] [Bug #2330] Non systematic segmentation fault with autoload rubyspec — Marc-Andre Lafortune <redmine@...>
Bug #2330: Non systematic segmentation fault with autoload rubyspec
Issue #2330 has been updated by Marc-Andre Lafortune.
Hi,
Argh... I can't reproduce my minimal case scenario anymore. Maybe
1) The minimal test case
Hi,
[#26540] [Bug #2336] pathname compare fails in windows — Roger Pack <redmine@...>
Bug #2336: pathname compare fails in windows
[#26560] [Feature #2340] Removing YAML/Syck — Yui NARUSE <redmine@...>
Feature #2340: Removing YAML/Syck
Issue #2340 has been updated by Yui NARUSE.
On Nov 6, 2009, at 4:02 AM, Yui NARUSE wrote:
> > Issue #2340 has been updated by Yui NARUSE.
Jon wrote:
> > If you're looking at alternatives, does http://pyyaml.org/wiki/LibYAML
On Sat, Nov 07, 2009 at 12:59:25AM +0900, NARUSE, Yui wrote:
Aaron Patterson wrote:
On Sat, Nov 07, 2009 at 09:21:06PM +0900, NARUSE, Yui wrote:
On Sat, Nov 7, 2009 at 2:52 PM, Aaron Patterson
2009/11/12 5:47, Charles Oliver Nutter wrote:
On Fri, Nov 6, 2009 at 16:00, James Edward Gray II
On Nov 6, 2009, at 9:48 AM, Nikolai Weibull wrote:
James Edward Gray II wrote:
On Fri, Nov 6, 2009 at 18:38, Joel VanderWerf <vjoel@path.berkeley.edu> wro=
Issue #2340 has been updated by Yui NARUSE.
[#26563] [Bug #2343] Timeout.timeout doesn't raise Timeout::Error by default — Hongli Lai <redmine@...>
Bug #2343: Timeout.timeout doesn't raise Timeout::Error by default
[#26623] Re: [ruby-cvs:32896] Ruby:r25678 (trunk): * ext/dl/cptr.c (rb_dlptr_s_malloc, rb_dlptr_initialize): adding — Tanaka Akira <akr@...>
In article <200911062250.nA6Mo69d010341@ci.ruby-lang.org>,
In article <87y6mhb180.fsf@fsij.org>,
On Thu, Nov 12, 2009 at 11:54:49AM +0900, Tanaka Akira wrote:
[#26632] [Feature #2347] Math::INFINITY — Marc-Andre Lafortune <redmine@...>
Feature #2347: Math::INFINITY
2009/11/9 Marc-Andre Lafortune <redmine@ruby-lang.org>:
[#26635] [Feature #2348] RBTree Should be Added to the Standard Library — James Gray <redmine@...>
Feature #2348: RBTree Should be Added to the Standard Library
Issue #2348 has been updated by James Gray.
Hi,
Hi,
Hi,
Yusuke ENDOH wrote:
2010/3/22 Bill Kelly <billk@cts.com>:
[#26650] [Feature #2350] Unicode specific functionality on String in 1.9 — Manfred Stienstra <redmine@...>
Feature #2350: Unicode specific functionality on String in 1.9
Issue #2350 has been updated by Yusuke Endoh.
On Thu, Mar 25, 2010 at 14:45, Yusuke Endoh <redmine@ruby-lang.org> wrote:
(2010/03/26 0:02), Nikolai Weibull wrote:
On Thu, Mar 25, 2010 at 18:24, NARUSE, Yui <naruse@airemix.jp> wrote:
On Thu, Mar 25, 2010 at 19:33, Nikolai Weibull <now@bitwi.se> wrote:
The problem is that the definition of #upcase doesn't only depend on the
On Fri, Mar 18, 2011 at 11:53, Magnus Holm <judofyr@gmail.com> wrote:
[#26652] [Bug #2351] system() hardlinked to /bin/sh — Marcus Franke <redmine@...>
Bug #2351: system() hardlinked to /bin/sh
Issue #2351 has been updated by Motohiro KOSAKI.
[#26668] [Bug #2353] hash.c:setenv causes crashes in Solaris — Christian Höltje <redmine@...>
Bug #2353: hash.c:setenv causes crashes in Solaris
[#26704] Maintainer confirmation process done. — "Yugui (Yuki Sonoda)" <yugui@...>
I'm sorry for my closing the maintainer confirmation process so late.
On Thu, Nov 12, 2009 at 05:29:55PM +0900, Yugui (Yuki Sonoda) wrote:
Aaron Patterson wrote:
[#26722] [Bug #2362] undefined variable has value? — Vit Ondruch <redmine@...>
Bug #2362: undefined variable has value?
[#26735] warnings on build — Roger Pack <rogerdpack@...>
As an FYI, I get these at compile time:
[#26736] [Bug #2365] Matrix: poor handling of coercion errors [patch] — Marc-Andre Lafortune <redmine@...>
Bug #2365: Matrix: poor handling of coercion errors [patch]
Issue #2365 has been updated by Marc-Andre Lafortune.
Hi,
Hi,
[#26745] [Bug #2371] [BUG] thread_free: locking _mutex must be NULL — Chris Schlaeger <redmine@...>
Bug #2371: [BUG] thread_free: locking _mutex must be NULL
[#26753] (send #2) cgi.rb cleanup — Ryan Davis <ryand-ruby@...>
(not sure why my previous email about this got dropped)
Hi,
[#26767] [Bug #2376] Kernel.__method__ rubyspec failures for 1.8.* — Vladimir Sizikov <redmine@...>
Bug #2376: Kernel.__method__ rubyspec failures for 1.8.*
[#26771] [Bug #2377] update documentation for IO#eof? — Roger Pack <redmine@...>
Bug #2377: update documentation for IO#eof?
[#26772] [Bug #2378] Regression in ParseDate.parsedate('nn-nn') — Vladimir Sizikov <redmine@...>
Bug #2378: Regression in ParseDate.parsedate('nn-nn')
Issue #2378 has been updated by Hiro Asari.
[#26774] Ruby constant lookup — Yehuda Katz <wycats@...>
Over the past six months or so, I have been working with the new Ruby 1.9
Hi,
Shugo,
Hi,
On Tue, Nov 17, 2009 at 1:29 AM, Shugo Maeda <shugo@ruby-lang.org> wrote:
Hi,
On Sun, Nov 22, 2009 at 8:08 PM, Shugo Maeda <shugo@ruby-lang.org> wrote:
On Mon, Nov 23, 2009 at 8:08 AM, Rick DeNatale <rick.denatale@gmail.com> wr=
Hi,
Shugo,
[#26788] [Bug #2380] IO#eof? behavior different with 1.9.1p243-mingw32 than other platforms — Ian Dees <redmine@...>
Bug #2380: IO#eof? behavior different with 1.9.1p243-mingw32 than other platforms
Issue #2380 has been updated by Vit Ondruch.
[#26837] [Bug #2389] REXML rails to format parsed SVGs created with inkscape — Alexey Froloff <redmine@...>
Bug #2389: REXML rails to format parsed SVGs created with inkscape
[#26852] Internals: #to_s .vs. #to_str? — Kurt Stephens <ks@...>
Is there a description of the semantic differences between #to_s and
[#26868] [Bug #2392] "Date.valid_civil?" issue in p383 — Ozgun Koyun <redmine@...>
Bug #2392: "Date.valid_civil?" issue in p383
[#26869] Caching #to_s for immutables (and a possible future for constant-folding) — Kurt Stephens <ks@...>
I have a proof-of-concept patch to MRI that caches #to_s values for
> =A0It reduces the number of #to_s Strings created during the MRI test sui=
The attached patch add caching of #to_s results to the main immutable
> Yes. =A0The MRI test suite runs at 45 sec with these changes and at 53 se=
I just ran rubyspec against it; ~ 5% time improvement.
Attached is a new version of the patch.
Hi,
On Tue, Dec 1, 2009 at 18:19, Yusuke ENDOH <mame@tsg.ne.jp> wrote:
Nikolai Weibull wrote:
[#26877] [Bug #2394] [BUG] pthread_mutex_lock: 22 revisited — Roger Pack <redmine@...>
Bug #2394: [BUG] pthread_mutex_lock: 22 revisited
[#26889] email from redmine — danielcavanagh@...
hi
[#26931] Re: something broke ruby floats — Ryan Davis <ryand-ruby@...>
CC'ing ruby-core@
[#26939] Methods with default params not at the end and with rest params — Vladimir Sizikov <vsizikov@...>
Hi,
Hi,
Hi Matz,
[#26943] [Bug #2412] CSV regression after revision 25952 — Alexey Froloff <redmine@...>
Bug #2412: CSV regression after revision 25952
[ruby-core:26492] HashWithIndifferentAccess to core
Hello,
I got a pull request for a HashWithIndifferentAccess implementation to me=
rge
into core. I think it's almost OK to make it so (except few minor bugs t=
hat can
easily be handled). How about it? I'm also attaching a patch file for p=
eople who
are not used to git (mainly nobu).
-------- Original Message --------
Subject: [GitHub] methodmissing sent you a message
Date: Mon, 2 Nov 2009 12:40:24 -0800
From: GitHub <noreply@github.com>
To: shyouhei@ruby-lang.org
methodmissing wants you to pull from methodmissing/ruby at hwia
Body: Hi,
I've played extensively with a HashWithIndifferentAccess (hwia / Mash)
implementation as an extension to both ruby 1.9.x and ruby 1.8.7 (
http://github.com/methodmissing/hwia and
http://blog.methodmissing.com/2009/08/29/alternative-hashwithindifferenta=
ccess/)
before and recently took the leap to patch against 1.9.2 as a Hash subcla=
ss.
I've tried to conform to recommended code conventions, tried to not injec=
t this
into the critical path of common Hash use cases and abstracted to macros =
where
possible.
Wycats suggested to send the pull request - naming conventions at the mom=
ent is
dangling - StrHash, IndifferentHash etc. I'll make myself available with
whatever time is required to have this conform to current ruby-core
standards.I'm also open to moving the recursive conversion to an extensio=
n and
implement a thin API as per identhash on Hash instead.
It passes against today's (Nov 2) trunk with "make check" and related.Fee=
dback
much appreciated if and when there's a moment.
- Lourens
View repository: http://github.com/methodmissing/ruby/tree/hwia
-------- patch --------
% git diff --patch-with-stat origin/trunk..HEAD
hash.c | 185 +++++++++++++++++++++++++++++++--
include/ruby/intern.h | 1 +
string.c | 12 ++
test/ruby/test_hash.rb | 252 ++++++++++++++++++++++++++++++++++++++++=
++++++
test/ruby/test_symbol.rb | 7 ++
5 files changed, 445 insertions(+), 12 deletions(-)
diff --git a/hash.c b/hash.c
index ef8b9a8..332f89d 100644
--- a/hash.c
+++ b/hash.c
@@ -23,6 +23,27 @@ static VALUE rb_hash_s_try_convert(VALUE, VALUE);
=20
#define HASH_DELETED FL_USER1
#define HASH_PROC_DEFAULT FL_USER2
+#define STR_HASH FL_USER3
+
+static VALUE rb_hash_rehash(VALUE hash);
+static VALUE rb_hash_update(VALUE hash1, VALUE hash2);
+static VALUE rb_hash_strhash(VALUE hash);
+static void rb_strhash_convert(VALUE *value);
+
+#define NEW_STR_HASH(hash,other) do {\
+ FL_SET(RHASH(hash), STR_HASH); \
+ RHASH(hash)->ntbl->type =3D &strhash; \
+ RHASH(hash)->ifnone =3D RHASH(other)->ifnone; \
+ return rb_hash_rehash(rb_convert_type(hash, T_HASH, "StrHash", "to_ha=
sh")); \
+} while (0)
+
+#define STR_HASH_P(hash) (FL_TEST(RHASH(hash), STR_HASH) || RBASIC(hash)=
->klass =3D=3D rb_cStrHash)
+
+#define CONVERT_STR_HASH(hash,value) do {\
+ if STR_HASH_P(hash){ \
+ rb_strhash_convert(&value); \
+ } \
+} while (0)
=20
VALUE
rb_hash_freeze(VALUE hash)
@@ -31,6 +52,7 @@ rb_hash_freeze(VALUE hash)
}
=20
VALUE rb_cHash;
+VALUE rb_cStrHash;
=20
static VALUE envtbl;
static ID id_hash, id_yield, id_default;
@@ -54,6 +76,37 @@ rb_any_cmp(VALUE a, VALUE b)
return !rb_eql(a, b);
}
=20
+int
+strhash_cmp(VALUE *s1,VALUE *s2)
+{
+ int s1_hash =3D SYMBOL_P(*s1) ? rb_sym_hash(*s1) : rb_str_hash(*s1);=
+ int s2_hash =3D SYMBOL_P(*s2) ? rb_sym_hash(*s2) : rb_str_hash(*s2);=
+ if (s1_hash =3D=3D s2_hash) return 0;
+ if (s1_hash > s2_hash) return 1;
+ return -1;=09
+}
+
+static int
+rb_strhash_cmp(VALUE a, VALUE b)
+{
+ if (a =3D=3D b) return 0;
+ if (FIXNUM_P(a) && FIXNUM_P(b)) {
+ return a !=3D b;
+ }
+ if (a =3D=3D Qundef || b =3D=3D Qundef) return -1;
+ if (SYMBOL_P(a) && SYMBOL_P(b)) {
+ return a !=3D b;
+ }
+ if ((TYPE(a) =3D=3D T_STRING && RBASIC(a)->klass =3D=3D rb_cString &=
& SYMBOL_P(b)) || (TYPE(b) =3D=3D T_STRING && RBASIC(b)->klass =3D=3D rb_=
cString && SYMBOL_P(a))) {
+ return strhash_cmp(&a, &b);
+ }
+ if (TYPE(a) =3D=3D T_STRING && RBASIC(a)->klass =3D=3D rb_cString &&=
+ TYPE(b) =3D=3D T_STRING && RBASIC(b)->klass =3D=3D rb_cString) {
+ return rb_str_cmp(a, b);
+ }
+ return !rb_eql(a, b);
+}
+
VALUE
rb_hash(VALUE obj)
{
@@ -99,11 +152,44 @@ rb_any_hash(VALUE a)
return (st_index_t)RSHIFT(hnum, 1);
}
=20
+static st_index_t
+rb_strhash_hash(VALUE a)
+{
+ VALUE hval;
+ st_index_t hnum;
+
+ switch (TYPE(a)) {
+ case T_FIXNUM:
+ case T_NIL:
+ case T_FALSE:
+ case T_TRUE:
+ hnum =3D rb_hash_end(rb_hash_start((unsigned int)a));
+ break;
+ case T_SYMBOL:
+ hnum =3D rb_sym_hash(a); =20
+ break;
+ case T_STRING:
+ hnum =3D rb_str_hash(a);
+ break;
+
+ default:
+ hval =3D rb_hash(a);
+ hnum =3D FIX2LONG(hval);
+ }
+ hnum <<=3D 1;
+ return (st_index_t)RSHIFT(hnum, 1);
+}
+
static const struct st_hash_type objhash =3D {
rb_any_cmp,
rb_any_hash,
};
=20
+static const struct st_hash_type strhash =3D {
+ rb_strhash_cmp,
+ rb_strhash_hash,
+};
+
static const struct st_hash_type identhash =3D {
st_numcmp,
st_numhash,
@@ -219,7 +305,7 @@ hash_alloc(VALUE klass)
OBJSETUP(hash, klass, T_HASH);
=20
hash->ifnone =3D Qnil;
-
+ if (klass =3D=3D rb_cStrHash) FL_SET(hash, STR_HASH);
return (VALUE)hash;
}
=20
@@ -230,6 +316,12 @@ rb_hash_new(void)
}
=20
VALUE
+rb_strhash_new(void)
+{
+ return hash_alloc(rb_cStrHash);
+}
+
+VALUE
rb_hash_dup(VALUE hash)
{
NEWOBJ(ret, struct RHash);
@@ -240,8 +332,33 @@ rb_hash_dup(VALUE hash)
if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
FL_SET(ret, HASH_PROC_DEFAULT);
}
- ret->ifnone =3D RHASH(hash)->ifnone;
- return (VALUE)ret;
+ if STR_HASH_P(hash){
+ NEW_STR_HASH(ret,hash);
+ }else{=20
+ ret->ifnone =3D RHASH(hash)->ifnone;
+ return (VALUE)ret;
+ }
+}
+
+static void
+rb_strhash_convert(VALUE *val)
+{
+ int i;
+ VALUE values;
+
+ switch (TYPE(*val)) {
+ case T_HASH:
+ *val =3D rb_hash_strhash(*val);=20
+ break; =20
+ case T_ARRAY:
+ values =3D rb_ary_new2(RARRAY_LEN(*val));
+ for (i =3D 0; i < RARRAY_LEN(*val); i++) {
+ VALUE el =3D RARRAY_PTR(*val)[i];
+ rb_ary_push(values, (TYPE(el) =3D=3D T_HASH) ? rb_hash_st=
rhash(el) : el);
+ }=20
+ *val =3D values;
+ break;
+ }
}
=20
static void
@@ -256,7 +373,7 @@ struct st_table *
rb_hash_tbl(VALUE hash)
{
if (!RHASH(hash)->ntbl) {
- RHASH(hash)->ntbl =3D st_init_table(&objhash);
+ RHASH(hash)->ntbl =3D STR_HASH_P(hash) ? st_init_table(&strhash) : st_i=
nit_table(&objhash);
}
return RHASH(hash)->ntbl;
}
@@ -318,7 +435,9 @@ static VALUE
rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
{
VALUE ifnone;
-
+ VALUE constructor;
+ rb_scan_args(argc, argv, "01", &constructor);
+ if(TYPE(constructor) =3D=3D T_HASH) return rb_hash_update(hash,const=
ructor);
rb_hash_modify(hash);
if (rb_block_given_p()) {
if (argc > 0) {
@@ -333,7 +452,6 @@ rb_hash_initialize(int argc, VALUE *argv, VALUE hash)=
rb_scan_args(argc, argv, "01", &ifnone);
RHASH(hash)->ifnone =3D ifnone;
}
-
return hash;
}
=20
@@ -366,8 +484,11 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass)=
hash =3D hash_alloc(klass);
if (RHASH(tmp)->ntbl) {
RHASH(hash)->ntbl =3D st_copy(RHASH(tmp)->ntbl);
+ if (FL_TEST(RHASH(tmp), STR_HASH) || klass =3D=3D rb_cStrHash){
+ NEW_STR_HASH(hash,tmp);
+ }else
+ return hash;
}
- return hash;
}
=20
tmp =3D rb_check_array_type(argv[0]);
@@ -426,12 +547,21 @@ rb_hash_s_try_convert(VALUE dummy, VALUE hash)
return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
}
=20
+static VALUE
+rb_strhash_s_try_convert(VALUE dummy, VALUE hash)
+{
+ return rb_check_convert_type(hash, T_HASH, "StrHash", "to_hash");
+}
+
static int
rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
{
st_table *tbl =3D (st_table *)arg;
=20
- if (key !=3D Qundef) st_insert(tbl, key, value);
+ if (key !=3D Qundef){=20
+ if (tbl->type =3D=3D &strhash) rb_strhash_convert(&value);
+ st_insert(tbl, key, value);
+ }
return ST_CONTINUE;
}
=20
@@ -459,7 +589,6 @@ static VALUE
rb_hash_rehash(VALUE hash)
{
st_table *tbl;
-
if (RHASH(hash)->iter_lev > 0) {
rb_raise(rb_eRuntimeError, "rehash during iteration");
}
@@ -470,7 +599,6 @@ rb_hash_rehash(VALUE hash)
rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tbl);
st_free_table(RHASH(hash)->ntbl);
RHASH(hash)->ntbl =3D tbl;
-
return hash;
}
=20
@@ -974,7 +1102,7 @@ rb_hash_select(VALUE hash)
VALUE result;
=20
RETURN_ENUMERATOR(hash, 0, 0);
- result =3D rb_hash_new();
+ result =3D STR_HASH_P(hash) ? rb_strhash_new() : rb_hash_new();
rb_hash_foreach(hash, select_i, result);
return result;
}
@@ -1046,6 +1174,13 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val)
return val;
}
=20
+VALUE
+rb_strhash_aset(VALUE hash, VALUE key, VALUE val)
+{
+ CONVERT_STR_HASH(hash,val);
+ rb_hash_aset(hash, key, val);
+}
+
static int
replace_i(VALUE key, VALUE val, VALUE hash)
{
@@ -1617,7 +1752,7 @@ rb_hash_invert_i(VALUE key, VALUE value, VALUE hash=
)
static VALUE
rb_hash_invert(VALUE hash)
{
- VALUE h =3D rb_hash_new();
+ VALUE h =3D STR_HASH_P(hash) ? rb_strhash_new() : rb_hash_new();
=20
rb_hash_foreach(hash, rb_hash_invert_i, h);
return h;
@@ -1627,6 +1762,7 @@ static int
rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
{
if (key =3D=3D Qundef) return ST_CONTINUE;
+ CONVERT_STR_HASH(hash,value);
st_insert(RHASH(hash)->ntbl, key, value);
return ST_CONTINUE;
}
@@ -1637,6 +1773,7 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALU=
E hash)
if (key =3D=3D Qundef) return ST_CONTINUE;
if (rb_hash_has_key(hash, key)) {
value =3D rb_yield_values(3, key, rb_hash_aref(hash, key), value);
+ CONVERT_STR_HASH(hash,value);
}
st_insert(RHASH(hash)->ntbl, key, value);
return ST_CONTINUE;
@@ -1852,6 +1989,24 @@ rb_hash_compare_by_id_p(VALUE hash)
return Qfalse;
}
=20
+static VALUE
+rb_hash_strhash(VALUE hash)
+{
+ if STR_HASH_P(hash)
+ return hash;
+ VALUE args[1];
+ args[0] =3D hash;
+ return rb_hash_s_create(1, (VALUE *)args, rb_cStrHash);
+}
+
+static VALUE
+rb_strhash_to_hash(VALUE hash)
+{
+ VALUE args[1];
+ args[0] =3D hash;
+ return rb_hash_s_create(1, (VALUE *)args, rb_cHash);
+}
+
static int path_tainted =3D -1;
=20
static char **origenviron;
@@ -2649,6 +2804,8 @@ Init_Hash(void)
id_default =3D rb_intern("default");
=20
rb_cHash =3D rb_define_class("Hash", rb_cObject);
+ rb_cStrHash =3D rb_define_class("StrHash", rb_cHash);
+ rb_define_singleton_method(rb_cStrHash, "try_convert", rb_strhash_s_=
try_convert, 1);
=20
rb_include_module(rb_cHash, rb_mEnumerable);
=20
@@ -2715,6 +2872,10 @@ Init_Hash(void)
=20
rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_=
id, 0);
rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by=
_id_p, 0);
+ rb_define_method(rb_cHash, "strhash", rb_hash_strhash, 0);
+ rb_define_method(rb_cStrHash, "to_hash", rb_strhash_to_hash, 0);
+ rb_define_method(rb_cStrHash, "[]=3D", rb_strhash_aset, 2);
+ rb_define_method(rb_cStrHash, "store", rb_strhash_aset, 2);
=20
origenviron =3D environ;
envtbl =3D rb_obj_alloc(rb_cObject);
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index fd37eca..c97caef 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -660,6 +660,7 @@ void rb_str_associate(VALUE, VALUE);
VALUE rb_str_associated(VALUE);
void rb_str_setter(VALUE, ID, VALUE*);
VALUE rb_str_intern(VALUE);
+st_index_t rb_sym_hash(VALUE);
VALUE rb_sym_to_s(VALUE);
VALUE rb_str_length(VALUE);
long rb_str_offset(VALUE, long);
diff --git a/string.c b/string.c
index e7f7e86..cc4ff34 100644
--- a/string.c
+++ b/string.c
@@ -7025,6 +7025,17 @@ sym_equal(VALUE sym1, VALUE sym2)
return Qfalse;
}
=20
+st_index_t
+rb_sym_hash(VALUE sym){
+ ID id =3D SYM2ID(sym);
+ return rb_str_hash(rb_id2str(id)); =20
+}
+
+static VALUE
+rb_sym_hash_m(VALUE sym){
+ st_index_t hval =3D rb_sym_hash(sym);
+ return INT2FIX(hval);
+}
=20
static int
sym_printable(const char *s, const char *send, rb_encoding *enc)
@@ -7508,6 +7519,7 @@ Init_String(void)
rb_define_method(rb_cSymbol, "=3D=3D=3D", sym_equal, 1);
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
rb_define_method(rb_cSymbol, "to_s", rb_sym_to_s, 0);
+ rb_define_method(rb_cSymbol, "hash", rb_sym_hash_m, 0);
rb_define_method(rb_cSymbol, "id2name", rb_sym_to_s, 0);
rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0);
rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index c860b25..b3145e9 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -872,3 +872,255 @@ class TestHash < Test::Unit::TestCase
assert_equal({x=3D>1}.hash, {x=3D>1}.hash)
end
end
+
+class HashToStrHash < Test::Unit::TestCase
+ def test_strhash
+ hash =3D { 'a' =3D> 1, 'b' =3D> 2 }
+ assert_instance_of StrHash, hash.strhash
+ assert_equal %w(a b), hash.keys
+ assert_equal [1,2], hash.values
+ end =20
+end
+
+class TestStrHash < Test::Unit::TestCase
+ def setup
+ @strings =3D { 'a' =3D> 1, 'b' =3D> 2 }.strhash
+ @symbols =3D { :a =3D> 1, :b =3D> 2 }.strhash
+ @mixed =3D { :a =3D> 1, 'b' =3D> 2 }.strhash
+ @fixnums =3D { 0 =3D> 1, 1 =3D> 2 }.strhash
+ end
+
+ def test_inherits_hash
+ assert_equal Hash, StrHash.superclass
+ end
+
+ def test_strhash
+ assert_equal @strings.object_id, @strings.strhash.object_id
+ assert_instance_of StrHash, { 'a' =3D> 1, 'b' =3D> 2 }.strhash
+ end
+ =20
+ def test_initialize
+ strhash =3D StrHash.new({ 'a' =3D> 1, 'b' =3D> 2 })
+ assert_equal 1, strhash[:a]=20
+ strhash =3D StrHash.new
+ strhash[:a] =3D 'a'
+ assert_equal 'a', strhash[:a]
+ end
+
+ def test_set
+ array =3D [{ 'a' =3D> 1, 'b' =3D> 2 }, [:a,:b,:c]]
+ @strings[:array] =3D array
+ assert_instance_of StrHash, @strings[:array].shift
+ assert_instance_of Array, @strings[:array] =3D array =20
+ @strings[:hash] =3D { 'a' =3D> 1, 'b' =3D> 2 }
+ assert_instance_of StrHash, @strings[:hash]
+ end
+ =20
+ def test_dup
+ assert_equal @strings, @strings.dup
+ assert_equal @mixed, @mixed.dup
+ assert_not_equal @mixed.object_id, @mixed.dup.object_id
+ end
+
+ def test_keys
+ assert_equal ["a", "b"], @strings.keys
+ assert_equal [:a, :b], @symbols.keys
+ assert_equal [:a, "b"], @mixed.keys
+ assert_equal [0, 1], @fixnums.keys =20
+ end
+ =20
+ def test_values
+ assert_equal [1, 2], @strings.values
+ assert_equal [1, 2], @symbols.values
+ assert_equal [1, 2], @mixed.values
+ assert_equal [1, 2], @fixnums.values =20
+ end =20
+=20
+ def test_fetch
+ assert_equal 1, @strings.fetch('a')
+ assert_equal 1, @strings.fetch(:a.to_s)
+ assert_equal 1, @strings.fetch(:a)
+ end
+
+ def test_key?
+ assert @strings.key?(:a)
+ assert @strings.include?('a')
+ assert @mixed.has_key?('b')
+ end
+ =20
+ def test_delete
+ @strings.delete('a')
+ assert !@strings.key?(:a)
+ end
+
+ def test_assorted
+ hashes =3D { :@strings =3D> @strings, :@symbols =3D> @symbols, :@mix=
ed =3D> @mixed }
+ method_map =3D { :'[]' =3D> 1, :fetch =3D> 1, :values_at =3D> [1],
+ :has_key? =3D> true, :include? =3D> true, :key? =3D> true,
+ :member? =3D> true }
+
+ hashes.each do |name, hash|
+ method_map.sort_by { |m| m.to_s }.each do |meth, expected|
+ assert_equal(expected, hash.__send__(meth, 'a'),
+ "Calling #{name}.#{meth} 'a'")
+ assert_equal(expected, hash.__send__(meth, :a),
+ "Calling #{name}.#{meth} :a")
+ end
+ end
+
+ assert_equal [1, 2], @strings.values_at('a', 'b')
+ assert_equal [1, 2], @strings.values_at(:a, :b)
+ assert_equal [1, 2], @symbols.values_at('a', 'b')
+ assert_equal [1, 2], @symbols.values_at(:a, :b)
+ assert_equal [1, 2], @mixed.values_at('a', 'b')
+ assert_equal [1, 2], @mixed.values_at(:a, :b)
+ end
+ =20
+ def test_reading
+ hash =3D StrHash.new
+ hash["a"] =3D 1
+ hash["b"] =3D true
+ hash["c"] =3D false
+ hash["d"] =3D nil
+
+ assert_equal 1, hash[:a]
+ assert_equal true, hash[:b]
+ assert_equal false, hash[:c]
+ assert_equal nil, hash[:d]
+ assert_equal nil, hash[:e]
+ end =20
+
+ def test_reading_with_nonnil_default
+ hash =3D StrHash.new(1)
+ hash["a"] =3D 1
+ hash["b"] =3D true
+ hash["c"] =3D false
+ hash["d"] =3D nil
+
+ assert_equal 1, hash[:a]
+ assert_equal true, hash[:b]
+ assert_equal false, hash[:c]
+ assert_equal nil, hash[:d]
+ assert_equal 1, hash[:e]
+ end
+ =20
+ def test_writing
+ hash =3D StrHash.new
+ hash[:a] =3D 1
+ hash['b'] =3D 2
+ hash[3] =3D 3
+
+ assert_equal hash['a'], 1
+ assert_equal hash['b'], 2
+ assert_equal hash[:a], 1
+ assert_equal hash[:b], 2
+ assert_equal hash[3], 3
+ end =20
+
+ def test_update
+ hash =3D StrHash.new
+ hash[:a] =3D 'a'
+ hash['b'] =3D 'b'
+
+ updated_with_strings =3D hash.update(@strings)
+ updated_with_symbols =3D hash.update(@symbols)
+ updated_with_mixed =3D hash.update(@mixed)
+
+ assert_equal updated_with_strings[:a], 1
+ assert_equal updated_with_strings['a'], 1
+ assert_equal updated_with_strings['b'], 2
+
+ assert_equal updated_with_symbols[:a], 1
+ assert_equal updated_with_symbols['b'], 2
+ assert_equal updated_with_symbols[:b], 2
+
+ assert_equal updated_with_mixed[:a], 1
+ assert_equal updated_with_mixed['b'], 2
+
+ assert [updated_with_strings, updated_with_symbols, updated_with_mix=
ed].all? { |h| h.keys.size =3D=3D 2 }
+ end =20
+
+ def test_merging
+ hash =3D StrHash.new
+ hash[:a] =3D 'failure'
+ hash['b'] =3D 'failure'
+
+ other =3D { 'a' =3D> 1, :b =3D> 2 }
+
+ merged =3D hash.merge(other)
+
+ assert_equal StrHash, merged.class
+ assert_equal 1, merged[:a]
+ assert_equal 2, merged['b']
+
+ hash.update(other)
+
+ assert_equal 1, hash[:a]
+ assert_equal 2, hash['b']
+ end =20
+
+ def test_deleting
+ get_hash =3D proc{ StrHash[ :a =3D> 'foo' ] }
+ hash =3D get_hash.call
+ assert_equal hash.delete(:a), 'foo'
+ assert_equal hash.delete(:a), nil
+ hash =3D get_hash.call
+ assert_equal hash.delete('a'), 'foo'
+ assert_equal hash.delete('a'), nil
+ end =20
+
+ def test_to_hash
+ assert_instance_of Hash, @strings.to_hash
+ assert_equal %w(a b), @strings.to_hash.keys
+ # Should convert to a Hash with String keys.
+ assert_equal @strings, @mixed.strhash.to_hash
+
+ # Should preserve the default value.
+ mixed_with_default =3D @mixed.dup
+ mixed_with_default.default =3D '1234'
+ roundtrip =3D mixed_with_default.strhash.to_hash
+ assert_equal @strings, roundtrip
+ assert_equal '1234', roundtrip.default =20
+ end
+
+ def test_hash_with_array_of_hashes
+ hash =3D { "urls" =3D> { "url" =3D> [ { "address" =3D> "1" }, { "add=
ress" =3D> "2" } ] }}
+ strhash =3D StrHash[hash]
+ assert_equal "1", strhash[:urls][:url].first[:address]
+ end
+
+ def test_indifferent_subhashes
+ h =3D {'user' =3D> {'id' =3D> 5}}.strhash
+ ['user', :user].each {|user| [:id, 'id'].each {|id| assert_equal 5, =
h[user][id], "h[#{user.inspect}][#{id.inspect}] should be 5"}}
+
+ h =3D {:user =3D> {:id =3D> 5}}.strhash
+ ['user', :user].each {|user| [:id, 'id'].each {|id| assert_equal 5, =
h[user][id], "h[#{user.inspect}][#{id.inspect}] should be 5"}}
+ end =20
+
+ def test_assorted_keys_not_stringified
+ original =3D {Object.new =3D> 2, 1 =3D> 2, [] =3D> true}
+ indiff =3D original.strhash
+ assert(!indiff.keys.any? {|k| k.kind_of? String}, "A key was convert=
ed to a string!")
+ end
+
+ def test_should_use_default_value_for_unknown_key
+ strhash =3D StrHash.new(3)
+ assert_equal 3, strhash[:new_key]
+ end
+
+ def test_should_use_default_value_if_no_key_is_supplied
+ strhash =3D StrHash.new(3)
+ assert_equal 3, strhash.default
+ end
+
+ def test_should_nil_if_no_default_value_is_supplied
+ strhash =3D StrHash.new
+ assert_nil strhash.default
+ end
+
+ def test_should_copy_the_default_value_when_converting_to_hash_with_in=
different_access
+ hash =3D Hash.new(3)
+ strhash =3D hash.strhash
+ assert_equal 3, strhash.default
+ end =20
+end
\ No newline at end of file
diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb
index f402da3..c181b19 100644
--- a/test/ruby/test_symbol.rb
+++ b/test/ruby/test_symbol.rb
@@ -1,6 +1,13 @@
require 'test/unit'
=20
class TestSymbol < Test::Unit::TestCase
+ def test_hash
+ assert_instance_of Fixnum, :symbol.hash
+ assert_equal 'symbol'.hash, :symbol.hash
+ assert_equal :"!".hash, :"!".hash
+ assert_not_equal :"$1".hash, :"@@1".hash
+ end
+ =20
# [ruby-core:3573]
=20
def assert_eval_inspected(sym)