summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-10-25 17:05:09 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-10-25 17:05:09 +0000
commit012b58b121ff499a6c811a3e7498e9a50145109b (patch)
treeb917ee642de298a2a30ae86cfd10206ceaae7529 /hash.c
parentd9ff0a6c2279d7329438686a73b25b07d06067c4 (diff)
* hash.c (rb_hash_s_create): check and convert argument hash
using #to_hash. * hash.c (rb_hash_s_create): Hash#[] now takes assocs as source of hash conversion. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13776 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/hash.c b/hash.c
index 1cd41bc6d4..821bfcbb8a 100644
--- a/hash.c
+++ b/hash.c
@@ -21,6 +21,8 @@
#include <crt_externs.h>
#endif
+static VALUE rb_hash_s_try_convert(VALUE, VALUE);
+
#define HASH_DELETED FL_USER1
#define HASH_PROC_DEFAULT FL_USER2
@@ -315,18 +317,34 @@ rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
static VALUE
rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
{
- VALUE hash;
+ VALUE hash, tmp;
int i;
- if (argc == 1 && TYPE(argv[0]) == T_HASH) {
- hash = hash_alloc(klass);
- if (RHASH(argv[0])->ntbl) {
- RHASH(hash)->ntbl = st_copy(RHASH(argv[0])->ntbl);
- }
+ if (argc == 1) {
+ tmp = rb_hash_s_try_convert(Qnil, argv[0]);
+ if (!NIL_P(tmp)) {
+ hash = hash_alloc(klass);
+ if (RHASH(argv[0])->ntbl) {
+ RHASH(hash)->ntbl = st_copy(RHASH(argv[0])->ntbl);
+ }
+ return hash;
+ }
- return hash;
+ tmp = rb_check_array_type(argv[0]);
+ if (!NIL_P(tmp)) {
+ long i;
+
+ hash = hash_alloc(klass);
+ for (i = 0; i < RARRAY_LEN(tmp); ++i) {
+ VALUE v = rb_check_array_type(RARRAY_PTR(tmp)[i]);
+
+ if (NIL_P(v)) continue;
+ if (RARRAY_LEN(v) < 1 || 2 < RARRAY_LEN(v)) continue;
+ rb_hash_aset(hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
+ }
+ return hash;
+ }
}
-
if (argc % 2 != 0) {
rb_raise(rb_eArgError, "odd number of arguments for Hash");
}