diff --git a/ChangeLog b/ChangeLog index e1cefaecd7..65d1cea4ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Jan 24 12:58:41 2012 Yukihiro Matsumoto + + * object.c (rb_Hash): add Kernel#Hash conversion method like + Array() or Float(). a patch from Run Paint Run Run. Fix #3131 + Tue Jan 24 11:38:05 2012 NARUSE, Yui * lib/uri/common.rb (URI.encode_www_form_component): initialize on diff --git a/include/ruby/intern.h b/include/ruby/intern.h index fbc9c49cfb..7a7eee0662 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -559,6 +559,7 @@ VALUE rb_to_float(VALUE); VALUE rb_Float(VALUE); VALUE rb_String(VALUE); VALUE rb_Array(VALUE); +VALUE rb_Hash(VALUE); double rb_cstr_to_dbl(const char*, int); double rb_str_to_dbl(VALUE, int); /* parse.y */ diff --git a/object.c b/object.c index e3302d153e..1632a46e3a 100644 --- a/object.c +++ b/object.c @@ -2594,6 +2594,39 @@ rb_f_array(VALUE obj, VALUE arg) return rb_Array(arg); } +VALUE +rb_Hash(VALUE val) +{ + if (NIL_P(val)) return rb_hash_new(); + VALUE tmp = rb_check_hash_type(val); + if (NIL_P(tmp)) { + if (TYPE(val) == T_ARRAY && RARRAY_LEN(val) == 0) + return rb_hash_new(); + rb_raise(rb_eTypeError, "can't convert %s into Hash", rb_obj_classname(val)); + } + return tmp; +} + +/* + * call-seq: + * Hash(arg) -> hash + * + * Converts arg to a Hash by calling + * arg.to_hash. Returns an empty Hash when + * arg is nil or []. + * + * Hash([]) #=> {} + * Hash(nil) #=> nil + * Hash(key: :value) #=> {:key => :value} + * Hash([1, 2, 3]) #=> TypeError + */ + +static VALUE +rb_f_hash(VALUE obj, VALUE arg) +{ + return rb_Hash(arg); +} + /* * Document-class: Class * @@ -2839,6 +2872,7 @@ Init_Object(void) rb_define_global_function("String", rb_f_string, 1); rb_define_global_function("Array", rb_f_array, 1); + rb_define_global_function("Hash", rb_f_hash, 1); rb_cNilClass = rb_define_class("NilClass", rb_cObject); rb_define_method(rb_cNilClass, "to_i", nil_to_i, 0); diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index b05375ebba..15e7b72e35 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -197,6 +197,19 @@ class TestObject < Test::Unit::TestCase assert_equal([o], Array(o)) end + def test_convert_hash + assert_equal(Hash(nil), {}) + assert_equal(Hash([]), {}) + assert_equal(Hash(key: :value), {key: :value}) + assert_raise(TypeError) { Hash([1,2]) } + assert_raise(TypeError) { Hash(Object.new) } + o = Object.new + def o.to_hash; {a: 1, b: 2}; end + assert_equal(Hash(o), {a: 1, b: 2}) + def o.to_hash; 9; end + assert_raise(TypeError) { Hash(o) } + end + def test_to_integer o = Object.new def o.to_i; nil; end