diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | include/ruby/intern.h | 1 | ||||
-rw-r--r-- | object.c | 34 | ||||
-rw-r--r-- | test/ruby/test_object.rb | 13 |
4 files changed, 53 insertions, 0 deletions
@@ -1,3 +1,8 @@ +Tue Jan 24 12:58:41 2012 Yukihiro Matsumoto <matz@ruby-lang.org> + + * 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 <naruse@ruby-lang.org> * 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 */ @@ -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 <i>arg</i> to a <code>Hash</code> by calling + * <i>arg</i><code>.to_hash</code>. Returns an empty <code>Hash</code> when + * <i>arg</i> is <tt>nil</tt> or <tt>[]</tt>. + * + * 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 |